You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为TensorFlow的Inception模型添加新类别并保留原有1000类?

当然有可行的方案!给TensorFlow的Inception模型扩展类别,本质上是迁移学习的经典应用——我们不需要从头训练整个庞大的模型,只需要微调最后几层来适配新增的类别,同时保留原模型对1000类的识别能力。下面是一步步的实现指南:

核心思路

Inception模型(比如InceptionV3)的前几层是通用的特征提取器,已经在ImageNet的1000类数据上学到了强大的视觉特征。我们只需要替换掉模型最顶层的分类层,将其扩展为1000 + 新类别数的输出维度,然后训练这个新的分类层(甚至微调部分底层),让模型学会把提取到的特征映射到包含新类别的所有类别上。

具体实现步骤

1. 准备数据集

  • 整理你的新类别数据:每个新类别单独放在一个文件夹中(和ImageNet的目录结构一致),每个类别建议至少准备50-100张图片(样本越多,效果越好)。如果想保留原1000类的识别能力,最好能准备原ImageNet中每类的少量样本(比如每类10-20张),防止模型“遗忘”原有知识。
  • 使用TensorFlow的工具加载并预处理数据:
    import tensorflow as tf
    
    # 加载数据集,调整尺寸到InceptionV3要求的299x299
    train_ds = tf.keras.utils.image_dataset_from_directory(
        '你的数据集路径',
        image_size=(299, 299),
        batch_size=32,
        label_mode='int'  # 标签用整数编码,新类别从1000开始编号
    )
    
    # 归一化到InceptionV3要求的[-1, 1]范围
    preprocess_input = tf.keras.applications.inception_v3.preprocess_input
    train_ds = train_ds.map(lambda x, y: (preprocess_input(x), y))
    
  • 可选:添加数据增强,提升模型泛化能力:
    data_augmentation = tf.keras.Sequential([
        tf.keras.layers.RandomFlip('horizontal'),
        tf.keras.layers.RandomRotation(0.1),
        tf.keras.layers.RandomZoom(0.1)
    ])
    train_ds = train_ds.map(lambda x, y: (data_augmentation(x, training=True), y))
    

2. 加载预训练的Inception模型

加载去掉顶层分类层的InceptionV3,并冻结基础层的权重,避免训练时破坏已学到的特征:

base_model = tf.keras.applications.InceptionV3(
    weights='imagenet',  # 加载ImageNet预训练权重
    include_top=False,   # 不包含顶层的分类层
    input_shape=(299, 299, 3)
)
base_model.trainable = False  # 冻结基础模型

3. 构建新的分类头

在基础模型的输出上搭建适配新类别的分类层:

# 获取基础模型的输出
x = base_model.output
# 全局平均池化,把特征图转为一维向量
x = tf.keras.layers.GlobalAveragePooling2D()(x)
# 可选:添加全连接层,学习特征到新类别的映射
x = tf.keras.layers.Dense(1024, activation='relu')(x)
x = tf.keras.layers.Dropout(0.5)(x)  # Dropout防止过拟合

# 输出层:神经元数量 = 原1000类 + 你的新类别数
num_new_classes = 5  # 替换成你的新类别数量
predictions = tf.keras.layers.Dense(1000 + num_new_classes, activation='softmax')(x)

4. 组装并编译模型

把基础模型和新分类头组合起来,然后编译:

model = tf.keras.models.Model(inputs=base_model.input, outputs=predictions)

# 编译模型,选择合适的优化器和损失函数
model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(),
    metrics=['accuracy']
)

5. 训练模型

阶段1:训练新分类头

先只训练我们新增的分类层,让模型学会用已有的特征识别新类别:

model.fit(train_ds, epochs=10)

阶段2:微调基础模型(可选)

如果想让模型效果更好,可以解冻基础模型的最后几层,用更小的学习率继续训练,让底层特征也适配新类别:

# 解冻基础模型的最后20层
base_model.trainable = True
fine_tune_at = len(base_model.layers) - 20
for layer in base_model.layers[:fine_tune_at]:
    layer.trainable = False

# 重新编译,用更小的学习率
model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=1e-5),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(),
    metrics=['accuracy']
)

# 继续训练
model.fit(train_ds, epochs=20, initial_epoch=model.epoch)

6. 标签映射与推理

  • 准备一个包含原1000类和新类别的标签字典:原ImageNet的标签可以参考tf.keras.applications.inception_v3.decode_predictions对应的类别,然后把新类别从1000开始追加进去。
  • 推理时,预测结果的索引对应到这个字典即可:
    # 示例:预测一张图片
    img = tf.keras.utils.load_img('测试图片路径', target_size=(299, 299))
    img_array = tf.keras.utils.img_to_array(img)
    img_array = preprocess_input(img_array)
    img_array = tf.expand_dims(img_array, 0)
    
    predictions = model.predict(img_array)
    predicted_class_idx = tf.argmax(predictions[0]).numpy()
    # 用你的标签字典获取类别名称
    predicted_class = your_label_dict[predicted_class_idx]
    
关键注意事项
  • 样本数量:新类别样本越多,模型效果越稳定。如果样本少,优先用数据增强和过采样。
  • 防止遗忘:如果要保留原1000类的识别能力,训练时最好加入少量原ImageNet样本,或者用知识蒸馏的方式让新模型继承原模型的输出。
  • 学习率控制:微调基础层时一定要用极小的学习率,否则容易破坏预训练的特征。

内容的提问来源于stack exchange,提问作者kanishka chandra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:32:21