我正在尝试训练一个简单的卷积神经网络,它由以下部分组成:
- 卷积层过滤器(5×5)x 8,步长为2。
- 最大池化25×25(图像细节较少)
- 将输出展平为(2x2x8)向量
- 使用逻辑回归的分类器
整个网络的权重少于1000个。
文件: nn.py
#!/bin/python import tensorflow as tfimport create_batch# 准备数据batch = create_batch.batchx = tf.reshape(batch[0], [-1,100,100,3])y_ = batch[1]# 卷积网络# 初始化函数def weight_variable(shape): initial = tf.truncated_normal(shape, stddev=0.3) return tf.Variable(initial)def bias_variable(shape): initial = tf.constant(0.2, shape=shape) return tf.Variable(initial)# 步长为1的卷积def conv2d(x, W): return tf.nn.conv2d(x, W, strides=[1, 2, 2, 1], padding='SAME')def max_pool_25x25(x): return tf.nn.max_pool(x, ksize=[1, 25, 25, 1], strides=[1, 25, 25, 1], padding='SAME')# 第一层W_conv1 = weight_variable([5, 5, 3, 8])b_conv1 = bias_variable([8])x_image = tf.reshape(x, [-1,100,100,3])# 第一层卷积h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)h_pool1 = max_pool_25x25(h_conv1)# 密集连接层# 将数据展平W_fc1 = weight_variable([2 * 2 * 8, 2])b_fc1 = bias_variable([2])h_pool1_flat = tf.reshape(h_pool1, [-1, 2*2*8])y_conv = tf.nn.softmax(tf.matmul(h_pool1_flat, W_fc1) + b_fc1)#学习cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices=[1]))train_step = tf.train.GradientDescentOptimizer(0.001).minimize(cross_entropy)correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))# 会话sess = tf.Session()sess.run(tf.initialize_all_variables())# 启动输入入队线程coord = tf.train.Coordinator()threads = tf.train.start_queue_runners(sess=sess, coord=coord)for i in range(200): if i%10 == 0: train_accuracy = accuracy.eval(session=sess) print("第%d步,训练准确率%g"%(i, train_accuracy)) train_step.run(session=sess)
文件: create_batch.py
#!/bin/pythonimport tensorflow as tfPATH1 = "../dane/trening/NK/"PATH2 = "../dane/trening/K/"def create_labeled_image_list(): filenames = [(PATH1 + "nk_%d.png" % i) for i in range(300)] labels = [[1,0] for i in range(300)] filenames += [(PATH2 + "kulki_%d.png" % i) for i in range(300)] labels += [[0,1] for i in range(300)] return filenames, labelsdef read_images_from_disk(input_queue): label = input_queue[1] file_contents = tf.read_file(input_queue[0]) example = tf.image.decode_png(file_contents, channels=3) example.set_shape([100, 100, 3]) example = tf.to_float(example) print ("读取,标签:") print(label) return example, label# 开始image_list, label_list = create_labeled_image_list()# 创建适当的张量用于命名images = tf.convert_to_tensor(image_list, dtype=tf.string)labels = tf.convert_to_tensor(label_list, dtype=tf.float32)input_queue = tf.train.slice_input_producer([images, labels], shuffle=True)image, label = read_images_from_disk(input_queue)batch = tf.train.batch([image, label], batch_size=600)
我正在处理100×100的图像,每个类别有300张图像。基本上,随机初始化的网络在第0步的准确率比训练后的网络还要高。网络在达到0.5的准确率(相当于抛硬币)后停止学习。图像包含蓝色斑点状物体(类别1)或草地(类别2)。
我一次性使用整个图像集(600张图像)来训练网络,损失函数是交叉熵。
我哪里做错了?
回答:
好的,我找到了解决方法,有两个错误,现在网络可以学习了。
- 尽管我在TensorFlow中声明图像为RGB,但实际上它们是RGBA格式的
- 我没有将图像归一化到
[-1,1] float32
范围内。
在TensorFlow中,应该像这样进行处理:
# 我使用"im"表示图像tf.image.convert_image_dtype(im, dtype=float32)im = tf.sub(im, -0.5)im = tf.mul(im, 2.0)
对所有机器学习新手来说,请谨慎准备你的数据!
谢谢。