【发布时间】:2018-10-14 22:12:33
【问题描述】:
情境化
我正在构建一个用于多标签分类的神经网络:识别图像中的标签(一个人穿的衣服、颜色等)。我想使用纯 tensorflow(而不是 kears 之类的 API),以便对我的指标有更大的灵活性。
PS:用于此 tensorflow 模型的数据已使用 Keras 构建的模型进行了测试,并没有不要产生我将在这里公开的问题。
数据
我的输入数据是 (X,Y):X 的形状为 (1814,204,204,3),Y 的形状为 (1814,39)。所以基本上 X 是一组图像,Y 是与每个图像相关联的标签,这些标签将用于监督学习过程。
总共有 39 个标签,因此对于每个大小为 (1,204,204,3) 的图像,我们关联一个形状为 (1,39) 的向量:39 个值可以是 0 或 1。1,如果在该图像中识别出相应的标签, 否则。 可以同时识别多个标签,这意味着我们没有使用一种热编码,也不是多类分类的情况!
PS:I已经对我的数据进行了标准化,以便适合 [0,1]
我做了什么
1.我做的第一件事是构建我的分类器的抽象版本(这是一个 CNN):
这是我的 CNN 的结构:
# Convolutional Layer 1
# Dropout layer 1
# Convolutional Layer 2
# Pooling Layer 2
# Dense layer 3
# Dropout layer 3
# Dense layer 4
对于给定大小的数据集 (?,204,204,3):这是通过不同层的数据流:
conv1 OUTPUT shape: (?, 204, 204, 32)
drop1 OUTPUT shape: (?, 204, 204, 32)
conv2 OUTPUT shape: (?, 204, 204, 32)
pool2 OUTPUT shape: (?, 102, 102, 32)
dense3 OUTPUT shape: (?, 512)
drop3 OUTPUT shape: (?, 512)
dense4 OUTPUT shape: (?, 39)
这是构建CNN结构的代码
def create_model(X,Y):
# Convolutional Layer #1
conv1 = tf.layers.conv2d(
inputs=X,
filters=32,
kernel_size=[3, 3],
padding="same",
activation=tf.nn.relu)
print('conv1 OUTPUT shape: ',conv1.shape)
# Dropout layer #1
dropout1 = tf.layers.dropout(
inputs=conv1, rate=0.2, training='TRAIN' == tf.estimator.ModeKeys.TRAIN)
print('drop1 OUTPUT shape: ',dropout1.shape)
# Convolutional Layer #2
conv2 = tf.layers.conv2d(
inputs=dropout1,
filters=32,
kernel_size=[3, 3],
padding="same",
activation=tf.nn.relu)
print('conv2 OUTPUT shape: ',conv2.shape)
# Pooling Layer #2
pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2],strides=2)
print('pool2 OUTPUT shape: ',pool2.shape)
pool2_flat = tf.reshape(pool2, [-1, pool2.shape[1]*pool2.shape[2]*pool2.shape[3]])
# Dense layer #3
dense3 = tf.layers.dense(inputs=pool2_flat, units=512, activation=tf.nn.relu)
print('dense3 OUTPUT shape: ',dense3.shape)
# Dropout layer #3
dropout3 = tf.layers.dropout(
inputs=dense3, rate=0.5, training='TRAIN' == tf.estimator.ModeKeys.TRAIN)
print('drop3 OUTPUT shape: ',dropout3.shape)
# Dense layer #4
Z = tf.layers.dense(inputs=dropout3, units=39, activation=tf.nn.sigmoid)
print('dense4 OUTPUT shape: ',Z.shape)
return Z
2. 现在,我正在定义我的成本函数和我的优化器。
- 对于 成本函数,我使用 cross_entropy_with_logits 并独立计算批次样本中所有输出组件的平均值。例如,如果我有一个大小为 10 的批次,模型的输出形状为 (10,39),所以 对于成本,我们将有一个形状为 (1,39) 的向量 em>(对于每个标签,我们计算批次中不同示例的平均值)
- 对于优化器,我正在使用亚当优化器。
这是计算成本和优化器的代码。
def optimizer_and_cost(output,labels):
# Calculating cost
cost= tf.reduce_mean(labels * - tf.log(output) + (1 - labels) * - tf.log(1 - output),axis=0)
print('cost: shape of cost: ',cost.shape)
cost= tf.reshape(cost, [1, 39])
print('cost reshaped: shape of cost reshaped: ',cost.shape)
#Optimizer
optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(cost)
return optimizer,cost
PS:tf.reduce_mean 中的 'axis=0' 让我可以独立计算每个标签的平均值!
3. 定义占位符,初始化模型和训练。
一旦定义了具有不同参数的抽象模型,我就创建了占位符并构建了计算图,然后我初始化了权重并开始了训练。
问题:随着优化的进行,我开始为不同层中的权重和成本函数中的 NaN 设置 NaN 值。因此,Reflexe 首先尝试调试并了解发生了什么。
我尝试测试一个简单的案例,如下所示:
初始化权重--->计算成本并打印(也打印权重)--->进行优化--->计算成本并打印(也打印权重)。
结果:
第一次打印很好我有真正的价值(很明显)。但是在第一次优化之后:我得到了成本的 NaNs 值。 为什么我的优化器在一个优化步骤后使成本变为 NaN!
这是测试的代码! (X_train 和 Y_train 的形状为 (1269, 204, 204, 3) 和 (1269,39) :我只取每个元素的 4 个元素进行测试)
#clearing the graph
ops.reset_default_graph()
#defining placeholders
X = tf.placeholder(tf.float32, [None, X_train.shape[1],X_train.shape[2],X_train.shape[3]])
Y = tf.placeholder(tf.float32, [None, Y_train.shape[1]])
optimizer, cost=optimizer_and_cost(create_model(X,Y),Y)
# Initialize all the variables globally
init = tf.global_variables_initializer()
# Start the session to compute the tensorflow graph
sess=tf.Session()
sess.run(init)
#printing cost and first layers weights
print('first layer weights ',sess.run(tf.trainable_variables()[0]) )
print('cost: ',sess.run(cost,feed_dict={X:X_train[0:4,:], Y:Y_train[0:4,:]}))
#doing one optimization step
_ ,OK=sess.run([optimizer, cost], feed_dict={X:X_train[0:4,:], Y:Y_train[0:4,:]})
#printing cost and first layers weights
print('first layer weights ',sess.run(tf.trainable_variables()[0]) )
print('cost :',sess.run(cost,feed_dict={X:X_train[0:4,:], Y:Y_train[0:4,:]}))
#closing session
sess.close()
欢迎任何帮助。
【问题讨论】:
-
在创建 CNN 时,您是如何在所需的层(卷积、池化、密集或丢弃)之间做出决定的?你为什么使用一个与另一个?我还注意到,当您打印 drop1 的形状时,您打印了 conv1.shape。在您的 conv1 之前似乎也没有输入层。
-
1.你说的对!我打印了 conv1 而不是 drop1 。我纠正了它。 2. 我正在使用众所周知的构建 CNN 的方法,它从卷积层开始,而不是添加池化以减少输出形状,并添加 dropout 以避免过度拟合问题。 3. 我认为在 conv1 之前不需要有一个输入层,因为在 conv1 的参数中,您正在精确输入 X
标签: python tensorflow machine-learning deep-learning convolutional-neural-network