在TensorFlow的DNNClassifier中,如何输入图像特征(含其他特征列)?
解决DNNClassifier结合图像特征与结构化特征的问题
嘿,这个场景我熟!结合图像特征和结构化特征(比如年龄、类型)用DNNClassifier其实没那么复杂,我给你一步步讲清楚怎么做:
核心思路
DNNClassifier接受的是**特征列(Feature Column)**作为输入,不管是结构化特征还是图像特征,都需要转换成对应的特征列格式。图像本质是高维数值特征,所以我们可以用numeric_column来定义,但要注意先对图像做预处理(比如扁平化或者特征提取)。
步骤1:定义所有特征列
首先把你的结构化特征和图像特征都转换成特征列:
结构化特征列(年龄、类型)
- 年龄是数值型,你已经用了
numeric_column,完全没问题:age_column = tf.feature_column.numeric_column('age') - 类型是分类型的话,需要先转成分类特征列,再用
indicator_column做one-hot编码(适配多分类场景):# 假设你的类型是['cat', 'dog', 'bird']这类离散值 type_category = tf.feature_column.categorical_column_with_vocabulary_list( key='type', vocabulary_list=['cat', 'dog', 'bird'] ) type_column = tf.feature_column.indicator_column(type_category)
图像特征列
图像特征的处理分两种情况,根据你的图像尺寸和任务需求选择:
情况1:直接扁平化图像(适合小尺寸图像,比如MNIST的28x28)
如果图像尺寸不大,直接把二维/三维图像扁平化成长度为宽×高×通道数的一维向量,然后用numeric_column定义,指定shape为向量长度:
# 假设是28x28的灰度图,扁平化后是784维 image_column = tf.feature_column.numeric_column(key='image', shape=(784,))
情况2:用预训练CNN提取特征(适合大尺寸图像,比如224x224的RGB图)
如果图像尺寸大,直接扁平化会导致特征维度太高,训练效率低。这时候可以用预训练的卷积神经网络(比如MobileNetV2、ResNet)提取图像的高层特征向量,再把这个向量作为输入:
# 加载预训练的MobileNetV2,去掉顶层分类层 base_model = tf.keras.applications.MobileNetV2( input_shape=(224, 224, 3), include_top=False, weights='imagenet' ) # 用全局平均池化得到1280维的特征向量 feature_extractor = tf.keras.Model( inputs=base_model.input, outputs=tf.keras.layers.GlobalAveragePooling2D()(base_model.output) ) # 预处理图像(符合预训练模型的要求) def preprocess_image(image): image = tf.image.resize(image, (224, 224)) return tf.keras.applications.mobilenet_v2.preprocess_input(image) # 提取训练集图像的特征向量(提前预处理好,训练时直接用) train_image_features = feature_extractor.predict(preprocess_image(train_images)) # 定义图像特征列,shape是预训练模型输出的特征维度 image_column = tf.feature_column.numeric_column(key='image_feature', shape=(1280,))
步骤2:合并特征列并初始化DNNClassifier
把所有特征列放到一个列表里,传入DNNClassifier:
# 合并所有特征列(根据你选的图像处理方式调整image_column的key) feature_columns = [age_column, type_column, image_column] # 初始化分类器,调整hidden_units和n_classes适配你的任务 classifier = tf.estimator.DNNClassifier( feature_columns=feature_columns, hidden_units=[512, 256, 128], # 隐藏层神经元数量,按需调整 n_classes=3, # 你的任务类别数,比如3分类 model_dir='./my_dnn_model' # 模型保存路径 )
步骤3:构建输入函数
输入函数需要返回一个特征字典(key对应特征列的key,value是对应的张量)和标签张量。举个例子:
对应情况1(直接扁平化图像)的输入函数
def input_fn(images, ages, types, labels, batch_size=32): # 把图像扁平化,注意维度匹配 features = { 'image': tf.reshape(images, [-1, 784]), 'age': ages, 'type': types } # 构建Dataset并做shuffle、batch处理 dataset = tf.data.Dataset.from_tensor_slices((features, labels)) return dataset.shuffle(1000).batch(batch_size).repeat()
对应情况2(预训练特征)的输入函数
def input_fn(image_features, ages, types, labels, batch_size=32): features = { 'image_feature': image_features, 'age': ages, 'type': types } dataset = tf.data.Dataset.from_tensor_slices((features, labels)) return dataset.shuffle(1000).batch(batch_size).repeat()
步骤4:训练模型
调用classifier的train方法,传入输入函数:
# 情况1的训练调用 classifier.train( input_fn=lambda: input_fn(train_images, train_ages, train_types, train_labels), steps=1000 # 训练步数,按需调整 ) # 情况2的训练调用(用提前提取好的图像特征) classifier.train( input_fn=lambda: input_fn(train_image_features, train_ages, train_types, train_labels), steps=1000 )
内容的提问来源于stack exchange,提问作者Park.BJ
相关产品推荐
相关产品推荐

