
在当今的在线旅游平台(如携程、飞猪)上,一张优质的图片胜过千言万语。当用户在浏览酒店、餐厅或景点时,首先映入眼帘的主图往往在几秒钟内就决定了其点击意愿,并最终影响预订决策。为了帮助商家在海量图片中自动筛选出最具吸引力的"门面",一套基于机器学习的智能主图推荐系统应运而生。本文将深入剖析该系统的构建原理,并结合国内业务场景,提供简化的PyTorch实现方案。
一、为何主图选择至关重要
图片是驱动在线业务增长的核心引擎。根据国内互联网行业报告,高质量的视觉内容能显著提升用户参与度和转化率。以国内领先的在线旅游平台为例,其平台汇聚了数亿张由商家和用户上传的图片,且每年仍在以极高的速度增长。
对于用户而言,主图是他们对一个陌生酒店或餐厅的第一印象。一张光线绝佳、构图精美的酒店外景图,能瞬间激发用户的兴趣;反之,一张昏暗、杂乱的普通客房照片,则很可能让用户直接划走。正如一位用户在预订后评论道:"我就是被照片吸引才决定预订的。"
然而,面对数以百万计的图片,依赖人工筛选不仅效率低下,而且标准难以统一,无法实现规模化。因此,开发一套能够自动、高效、精准地选出最佳主图的系统,成为了提升平台体验和商家效率的关键。
二、技术核心思路:从模式识别到模型构建
"美"虽然主观,但在受欢迎的图片中,客观规律依然存在。无论是北京的故宫还是上海的东方明珠,那些获得高点击率的照片往往具备共同点:良好的光线、独特的视角、对核心特征的清晰展现。该系统的核心思路,正是将"视觉吸引力"与"业务相关性"这两个关键指标进行量化与融合。
整个方案包含两大核心模块:
1.吸引力评分模型:一个深度学习模型,用于量化评估单张图片的视觉吸引力。
2.主图选择逻辑:一套将吸引力评分与业务规则相结合的决策引擎,最终选出最合适的主图。
2.1 吸引力评分模型的设计与实现
直接定义"美"的绝对标准是极其困难的。因此,我们采用了一种更可靠的"成对比较"学习方法。模型学习的目标不是"这张图片的吸引力是8.5分",而是"在这两张图片中,哪一张更吸引人?"。这种相对比较的方式,让模型能更稳定地学习人类的审美偏好。
该模型架构借鉴了经典的RankNet思想(排序学习中的经典方法),使用孪生神经网络。它由两个共享权重的相同子网络组成,分别处理一对图片,最终输出各自的吸引力评分,通过比较这两个评分来学习用户的偏好。
吸引力评分模型
以下提供一个简化的PyTorch实现思路,用于构建和训练这个吸引力评分模型,在具体实现时可以增加一些模块,比如利用图像模型提取图片的embedding等。
import torchimport torch.nn as nnimport torch.optim as optimfrom torchvision import models, transformsfrom torch.utils.data import Dataset, DataLoader
# 1. 定义模型骨干网络# 使用预训练的ResNet作为特征提取器,这是一个常用且高效的选择class AttractivenessModel(nn.Module): def __init__(self): super(AttractivenessModel, self).__init__() # 加载预训练的ResNet18,并去掉最后的分类层 backbone = models.resnet18(pretrained=True) self.features = nn.Sequential(*list(backbone.children())[:-1]) # 添加一个全连接层来输出单一的吸引力评分 self.fc = nn.Linear(backbone.fc.in_features, 1)
def forward(self, x): x = self.features(x) x = torch.flatten(x, 1) score = self.fc(x) return score
# 2. 定义孪生网络结构class SiameseNetwork(nn.Module): def __init__(self): super(SiameseNetwork, self).__init__() # 创建一个共享的吸引力模型实例 self.attractiveness_model = AttractivenessModel()
def forward(self, img1, img2): # 将两张图片分别通过共享模型 score1 = self.attractiveness_model(img1) score2 = self.attractiveness_model(img2) return score1, score2
# 3. 定义成对比较的损失函数 (基于RankNet)# 如果img1比img2更受欢迎,label为1;否则为0class PairwiseLoss(nn.Module): def forward(self, score1, score2, label): # 计算概率,即模型认为img1比img2好的概率 prob = torch.sigmoid(score1 - score2) # 使用二元交叉熵损失 loss_fn = nn.BCELoss() loss = loss_fn(prob, label.float()) return loss
# 4. 模拟训练过程# 假设我们已经有了成对的图片数据和标签# class PairwiseImageDataset(Dataset): ... (此处省略数据集加载代码)
# 初始化模型、损失函数和优化器siamese_net = SiameseNetwork()criterion = PairwiseLoss()optimizer = optim.Adam(siamese_net.parameters(), lr=0.0001)
# 模拟一个训练批次# img1_batch, img2_batch, label_batch = ... (从DataLoader中获取)# img1_batch, img2_batch = torch.randn(4, 3, 224, 224), torch.randn(4, 3, 224, 224)# label_batch = torch.randint(0, 2, (4, 1))
# optimizer.zero_grad()# score1, score2 = siamese_net(img1_batch, img2_batch)# loss = criterion(score1, score2, label_batch)# loss.backward()# optimizer.step()
# print(f"Training Loss: {loss.item()}")
通过大规模成对数据的训练,该模型能够为任何一张图片输出一个可靠的吸引力评分,为后续的排序打下基础。
2.2 数据构建策略
为了训练上述模型,需要为酒店、餐厅、景点等不同业务线构建大规模的成对比较数据集。人工标注成本高昂且效率低下。一个高效的策略是利用大语言模型(如文心一言、通义千问)进行辅助标注。通过精心设计的提示词,可以让LLM对成对的图片进行快速、大规模的偏好判断,生成高质量的训练标签,极大地加速了模型迭代。
三、主图选择逻辑:融合业务规则的智慧
视觉吸引力最高的图片,并不总是最合适的商业主图。例如,一张灯光璀璨的酒店浴室照片可能得分很高,但它对于展示酒店的整体风貌和核心价值(如大堂、外观、特色客房)贡献有限。因此,必须在模型的吸引力评分之上,叠加一层业务逻辑,实现"智能"与"智慧"的结合。
业务逻辑示例:
-
酒店
:优先展示"酒店外观"、"大堂"、"特色套房"等能促进预订的场景,降低"浴室"、"走廊"等场景的权重。
-
景点
:对于故宫这类历史景点,优先展示"太和殿"、"午门"等标志性建筑;对于自然风光,则优先展示"全景"、"最佳观景点"。
-
餐厅
:优先展示"招牌菜"、"特色环境"或"热闹的氛围",以激发用户的食欲和体验欲。
实现:主图选择逻辑
以下是一个规则函数的设计思路,模拟了如何结合吸引力评分和业务规则来选择最终的主图。
def select_primary_photo(photo_candidates): """ 根据吸引力评分和业务规则选择最佳主图。
:param photo_candidates: 包含图片信息的字典列表。 每个字典应包含: - 'path': 图片路径 (str) - 'attractiveness_score': 模型预测的吸引力评分 - 'category': 图片场景类别 :return: 选出的最佳主图信息字典 """ # 定义不同场景类别的业务权重 # 权重 > 1.0 表示优先,< 1.0 表示抑制 business_weights = { '酒店外观': 1.5, '大堂': 1.2, '特色套房': 1.3, '标准客房': 1.0, '餐厅': 1.1, '健身房': 0.6, '浴室': 0.4, '其他': 0.8 }
best_photo = None max_final_score = -1
for photo in photo_candidates: # 获取吸引力评分和业务权重 attractiveness = photo.get('attractiveness_score', 0) category = photo.get('category', '其他') weight = business_weights.get(category, 0.8)
# 计算最终得分 = 吸引力评分 * 业务权重 final_score = attractiveness * weight
print(f"图片: {photo['path']}, 类别: {category}, 吸引力: {attractiveness:.2f}, 权重: {weight}, 最终得分: {final_score:.2f}")
# 更新最高分和最佳图片 if final_score > max_final_score: max_final_score = final_score best_photo = photo
return best_photo
# 模拟一批候选图片candidates = [ {'path': 'hotel_view.jpg', 'attractiveness_score': 0.85, 'category': '酒店外观'}, {'path': 'lobby.jpg', 'attractiveness_score': 0.78, 'category': '大堂'}, {'path': 'deluxe_room.jpg', 'attractiveness_score': 0.92, 'category': '特色套房'}, {'path': 'bathroom.jpg', 'attractiveness_score': 0.88, 'category': '浴室'}, {'path': 'gym.jpg', 'attractiveness_score': 0.75, 'category': '健身房'},]
# 执行选择逻辑chosen_primary = select_primary_photo(candidates)print("\n-------------------------")print(f"最终选择的主图是: {chosen_primary['path']} (类别: {chosen_primary['category']})")
在这个例子中,尽管"浴室"照片的吸引力评分(0.88)很高,但由于其业务权重(0.4)被抑制,最终得分(0.352)很低。而"特色套房"虽然吸引力评分(0.92)最高,但"酒店外观"凭借更高的业务权重(1.5),其最终得分(1.275)可能成为最高,从而被选为主图。这完美体现了AI与业务规则的融合。
四、系统评估与验证
一个可靠的系统需要多维度的评估来确保其效果。
1.模型指标评估:在测试集上,通过准确率和AUC等指标,衡量模型在成对比较任务上的基础性能。这确保了模型本身的有效性。
2.大模型辅助评估:利用大语言模型作为"评判者",让其对比系统推荐的主图与原始主图,从吸引力、代表性等维度进行二选一,从而量化推荐效果的提升。
3.人工质量审核:组织内部评审团队,对精选的代表性样本(如不同城市的连锁酒店、热门餐厅)进行A/B测试,人工评估新旧主图的优劣,为系统优化提供最直接的反馈。
通过这套"模型+规则+评估"的闭环体系,智能主图推荐系统不仅能为商家提供自动化决策支持,还能在提升用户点击率和预订转化率方面取得显著成效,真正实现技术赋能业务。