news 2026/6/4 3:38:36

别再只用欧氏距离了!用Keras孪生网络做商品图去重,我的实战踩坑与调优记录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再只用欧氏距离了!用Keras孪生网络做商品图去重,我的实战踩坑与调优记录

电商场景下的商品图像去重实战:从传统方法到孪生网络的深度优化

在电商平台的实际运营中,商品图像管理一直是个令人头疼的问题。同一款商品往往会有多张主图——不同角度拍摄的、不同背景的、不同光线条件下的,甚至还有带水印和不带水印的版本。当商品数量达到百万级别时,人工审核变得不切实际,而简单的哈希比对又难以应对复杂的图像变换。这就是为什么我们需要更智能的解决方案。

1. 为什么传统图像去重方法在电商场景中失效

1.1 图像哈希方法的局限性

大多数工程师首先会尝试传统的图像哈希方法,比如:

  • 感知哈希(pHash):对图像进行DCT变换后取低频分量
  • 差异哈希(dHash):基于相邻像素灰度值比较
  • 平均哈希(aHash):计算像素平均值后二值化
import cv2 import numpy as np # 典型的dHash实现 def dhash(image, hash_size=8): resized = cv2.resize(image, (hash_size + 1, hash_size)) diff = resized[:, 1:] > resized[:, :-1] return sum([2 ** i for (i, v) in enumerate(diff.flatten()) if v])

这些方法在理想情况下表现尚可,但面对电商图像的特殊性时就会暴露问题:

图像变化类型哈希方法效果孪生网络效果
亮度调整失效保持稳定
添加文字水印失效保持稳定
背景替换失效部分保持
商品角度变化失效保持稳定
分辨率压缩可能失效保持稳定

1.2 特征点匹配的适用边界

OpenCV的SIFT/SURF/ORB等特征点匹配方法在特定场景下表现更好,但也有其局限性:

import cv2 def match_features(img1, img2): orb = cv2.ORB_create() kp1, des1 = orb.detectAndCompute(img1, None) kp2, des2 = orb.detectAndCompute(img2, None) bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) matches = bf.match(des1, des2) return len(matches)

在实际测试中我们发现:

  • 对纹理丰富的商品(如纺织品)效果较好
  • 对光滑表面商品(如手机)效果很差
  • 计算复杂度随图像数量呈指数增长
  • 难以设定统一的匹配阈值

2. 孪生网络在电商图像去重中的独特优势

2.1 网络架构设计要点

我们的Keras实现采用了改进的孪生网络结构:

from keras.models import Model from keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense, Lambda import keras.backend as K def create_base_network(input_shape): """共享权重的基网络""" input = Input(shape=input_shape) x = Conv2D(32, (3,3), activation='relu')(input) x = MaxPooling2D((2,2))(x) x = Conv2D(64, (3,3), activation='relu')(x) x = MaxPooling2D((2,2))(x) x = Flatten()(x) x = Dense(128, activation='relu')(x) return Model(input, x) def build_siamese(input_shape): img_a = Input(shape=input_shape) img_b = Input(shape=input_shape) base_network = create_base_network(input_shape) feat_a = base_network(img_a) feat_b = base_network(img_b) distance = Lambda(lambda x: K.abs(x[0]-x[1]))([feat_a, feat_b]) prediction = Dense(1, activation='sigmoid')(distance) return Model(inputs=[img_a, img_b], outputs=prediction)

关键改进点:

  1. 使用更轻量级的卷积结构,适应电商图像特点
  2. 在特征比较层使用L1距离而非传统的欧氏距离
  3. 输出层采用sigmoid激活直接得到相似概率

2.2 数据准备的特殊技巧

电商图像数据集构建需要特别注意:

  • 正样本对生成

    • 同一商品的不同主图
    • 应用仿射变换生成增强样本
    • 调整亮度、对比度等模拟不同拍摄条件
  • 负样本对生成

    • 不同商品的随机组合
    • 特别注意外观相似的不同商品(如不同颜色的同款衣服)
    • 加入部分困难负样本提升模型辨别力

我们开发了专门的DataGenerator:

from keras.utils import Sequence import numpy as np import cv2 class SiameseGenerator(Sequence): def __init__(self, image_dict, batch_size=32): self.image_dict = image_dict self.batch_size = batch_size self.categories = list(image_dict.keys()) def __len__(self): return int(np.ceil(len(self.image_dict) / self.batch_size)) def __getitem__(self, idx): batch_pairs = [] batch_labels = [] for _ in range(self.batch_size): # 50%概率生成正样本对 if np.random.random() > 0.5: category = np.random.choice(self.categories) img1, img2 = np.random.choice(self.image_dict[category], 2, replace=False) label = 1 else: cat1, cat2 = np.random.choice(self.categories, 2, replace=False) img1 = np.random.choice(self.image_dict[cat1]) img2 = np.random.choice(self.image_dict[cat2]) label = 0 # 图像增强处理 img1 = self.augment_image(img1) img2 = self.augment_image(img2) batch_pairs.append([img1, img2]) batch_labels.append(label) return [np.array([x[0] for x in batch_pairs]), np.array([x[1] for x in batch_pairs])], np.array(batch_labels) def augment_image(self, img): # 实现各种图像增强 if np.random.random() > 0.5: img = cv2.flip(img, 1) # 其他增强操作... return img

3. 损失函数选择与模型训练策略

3.1 Contrastive Loss vs Triplet Loss

我们对比了两种主流的损失函数:

Contrastive Loss实现

def contrastive_loss(y_true, y_pred, margin=1): square_pred = K.square(y_pred) margin_square = K.square(K.maximum(margin - y_pred, 0)) return K.mean(y_true * square_pred + (1 - y_true) * margin_square)

Triplet Loss实现

def triplet_loss(anchor, positive, negative, alpha=0.2): pos_dist = K.sum(K.square(anchor - positive), axis=-1) neg_dist = K.sum(K.square(anchor - negative), axis=-1) basic_loss = pos_dist - neg_dist + alpha return K.mean(K.maximum(basic_loss, 0))

实际测试结果对比:

指标Contrastive LossTriplet Loss
训练稳定性较低
收敛速度较快较慢
困难样本区分度一般优秀
计算资源消耗较低较高

提示:对于商品图像去重任务,当数据量较大时(>100万图片),Triplet Loss的采样策略会成为性能瓶颈

3.2 困难样本挖掘策略

我们发现以下策略能显著提升模型性能:

  1. 动态困难负样本挖掘

    • 每训练几个epoch后,用当前模型筛选出被误判的样本
    • 将这些样本加入后续训练
  2. 半硬负样本选择

    • 选择那些距离正样本较近,但尚未超过正样本距离的负样本
    • 避免选择极端困难样本导致训练不稳定

实现代码示例:

def get_hard_negatives(model, datagen, num_samples=1000): hard_negatives = [] for _ in range(num_samples): # 获取一批正常样本 (anchor, pos), _ = datagen.__getitem__(0) # 获取预测结果 preds = model.predict([anchor, pos]) # 找出预测相似度高的负样本对 if preds.mean() > 0.7: hard_negatives.append((anchor, pos)) return hard_negatives

4. 生产环境部署与性能优化

4.1 模型轻量化方案

原始模型在线上环境可能过大,我们采用以下优化:

  1. 知识蒸馏

    • 用训练好的大模型指导小模型训练
    • 保持90%准确率的同时减少70%参数量
  2. 量化感知训练

    import tensorflow_model_optimization as tfmot model = build_siamese(input_shape) quantized_model = tfmot.quantization.keras.quantize_model(model)
  3. 特征预计算

    • 预先计算所有商品图像的特征向量
    • 线上只需计算查询图像特征后进行相似度匹配

4.2 服务化部署架构

我们的生产部署方案:

商品图片入库 → 特征提取Worker → 特征向量存储(FAISS/Pinecone) ↑ 用户查询图片 → API服务 → 相似度计算 → 返回去重结果

关键组件:

  • 使用FAISS进行高效相似度搜索
  • 特征存储采用分层设计(热数据/冷数据)
  • 异步更新机制处理新增商品

4.3 实际业务指标

在百万级商品库中的表现:

场景准确率召回率QPS
同商品不同角度98.2%97.5%1200
同商品不同背景96.8%95.3%1100
相似但不同商品92.1%90.7%1000
带水印vs无水印94.5%93.2%1150

这套系统在实际业务中帮助我们减少了30%的重复商品展示,同时降低了40%的人工审核成本。最令人惊喜的是,在一些垂直品类(如服装、电子产品)中,模型的准确率甚至超过了人工审核的水平。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/4 3:36:57

2026-御网杯-逆向-chacha20

前言 这个题目,比赛的时候是AI一把梭的。 这个比赛有三题比赛时候没做出来。当时感觉题目缺材料,还有就是服务器有待提高的感觉,好几次连上就断。 一整个AI大战现在,感觉现在入门的速度应该没有AI成长的快。 但是但是,…

作者头像 李华
网站建设 2026/6/4 3:31:00

从一道CTF题深入理解PHP Session反序列化:以HarekazeCTF Easy Notes为例

从PHP Session机制到反序列化漏洞实战:以HarekazeCTF为例的深度解析在Web安全领域,PHP的Session机制一直是安全研究的重点对象。当开发者对Session处理器的差异理解不足时,就可能为系统埋下严重的安全隐患。本文将以HarekazeCTF2019中的"…

作者头像 李华
网站建设 2026/6/4 3:26:16

STCTS语义编解码:语音通信的80bps革命

1. STCTS系统架构解析:从波形到语义的范式转变在传统语音通信领域,Opus等波形编解码器通过时频变换和感知编码实现音频压缩,其优化空间已接近理论极限。STCTS(Speech-to-Text-to-Speech)系统采用颠覆性的语义编解码架构…

作者头像 李华