tensorflow学习-- 使用卷积神经网络进行对fashion-mnist数据集进行分类

    xiaoxiao2025-07-13  11

    # 引入相关的包 import tensorflow as tf import numpy as np from tensorflow import keras # 自定义one_hot编码 def to_onehot(y,num): lables = np.zeros([num,len(y)]) for i in range(len(y)): lables[int(y[i]),i] = 1 return lables.T # 数据预处理 mnist = keras.datasets.fashion_mnist (train_images,train_lables),(test_images,test_lables) = mnist.load_data() # 数据归一化,使得训练更加容易 train_images = train_images / 255.0 test_images = test_images / 255.0 # 标签的one_hot编码 train_lables = to_onehot(train_lables,10) test_lables = to_onehot(test_lables,10) # 增加一个维度,因为卷积神经网络中可以处理多个channel,fashion-mnist数据集的channel=1 [batch,28,28,28] -> [batch,28,28,1] train_images_exp = np.expand_dims(train_images,axis=3) test_images_exp = np.expand_dims(test_images,axis=3) input_nodes = 784 # 图片的width*height output_nodes = 10 # 输出的标签数 image_size = 28 # 图片的宽度(=长度) channels = 1 labels = 10 conv1_deep = 32 # 第一个卷积层的深度,前一层的输入经过卷积之后会变成[*,*,32] conv1_size = 5 # 卷积核的大小 conv2_deep = 64 conv2_size = 5 fc_size = 512 # 全连接层的节点数 # 前向传播 def inference(input_tensor,train,regularizer): with tf.variable_scope('layer1_conv1',reuse=tf.AUTO_REUSE): conv1_weights = tf.get_variable('weight',[conv1_size,conv1_size,channels,conv1_deep],initializer=tf.truncated_normal_initializer(stddev=0.1)) conv1_bias = tf.get_variable('bias',[conv1_deep],initializer=tf.constant_initializer(0.0)) conv1 = tf.nn.conv2d(input_tensor,conv1_weights,strides=[1,1,1,1],padding="SAME") # 问题1 :strides的参数中1,4的参数是定的(在这里为啥是1,有待进一步研究),中间的参数表示向右和向下的滑动距离 relu1 = tf.nn.relu((tf.nn.bias_add(conv1,conv1_bias))) with tf.variable_scope('layer2_pool1',reuse=tf.AUTO_REUSE): pool1 = tf.nn.max_pool(relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME") #下采样层,问题2:padding = same与上面卷积中的padding具体怎么操作的有待进一步研究一下 #ksize=[1,2,2,1] 表示池化的核是2*2的 with tf.variable_scope('layer3_conv2',reuse=tf.AUTO_REUSE): conv2_weights = tf.get_variable("weights",[conv2_size,conv2_size,conv1_deep,conv2_deep],initializer=tf.truncated_normal_initializer(stddev = 0.1)) conv2_bias = tf.get_variable("bias",[conv2_deep],initializer=tf.constant_initializer(0.0)) conv2 = tf.nn.conv2d(pool1,conv2_weights,strides=[1,1,1,1],padding="SAME") relu2 = tf.nn.relu(tf.nn.bias_add(conv2,conv2_bias)) with tf.variable_scope('layer4_pool2',reuse=tf.AUTO_REUSE): pool2 = tf.nn.max_pool(relu2,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME") pool2_shape = pool2.get_shape().as_list() nodes = pool2_shape[1] * pool2_shape[2] * pool2_shape[3] # 展开所有的节点 shape[0] 是样本的个数 reshaped = tf.reshape(pool2,[-1,nodes]) with tf.variable_scope('layer5_fc1',reuse=tf.AUTO_REUSE): fc1_weights = tf.get_variable("weights",[nodes,fc_size],initializer=tf.truncated_normal_initializer(stddev=0.1)) # 问题3 :为什么正则化项只加在全连接层 if regularizer!=None: tf.add_to_collection("losses",regularizer(fc1_weights)) fc1_bias = tf.get_variable("bias",[fc_size],initializer=tf.constant_initializer(0.0)) fc1 = tf.nn.relu(tf.matmul(reshaped,fc1_weights) + fc1_bias) if train: fc1 = tf.nn.dropout(fc1,0.2) with tf.variable_scope('layer6_fc2',reuse=tf.AUTO_REUSE): fc2_weights = tf.get_variable("weight",[fc_size,labels],initializer=tf.truncated_normal_initializer(stddev=0.1)) # 为什么正则化项只加在全连接层 if regularizer!=None: tf.add_to_collection('losses',regularizer(fc2_weights)) fc2_bias = tf.get_variable("bias",[labels],initializer=tf.constant_initializer(0.0)) logit = tf.matmul(fc1,fc2_weights) + fc2_bias # 此时并没有进行softmax操作,因为此时已经可以使用logit来做出预测了,如果是想要概率的话,需要使用softmax来操作 return logit epchos = 1000 # 训练的论次数 learning_rate = 0.001 batch_size = 128 model_save_path = "model_conv_1/model.ckpt" def train_model(data,train=True): trX,trY,teX,teY = data X = tf.placeholder(tf.float32,[None,image_size,image_size,channels],name="x_input") Y_ = tf.placeholder(tf.float32,[None,labels],name = 'y_input') regularizer = tf.contrib.layers.l2_regularizer(0.0000001) y_hat = inference(X,train,regularizer) # 训练模型 if train: #交叉熵函数,logits 必须为未经过softmax处理的,因为这个函数首先会进行softmax操作,labels 各分量的和必须是1(概率) cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=y_hat,labels=Y_)) loss = cross_entropy + tf.add_n(tf.get_collection("losses")) train_step = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(loss) acc = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(Y_,1),tf.argmax(y_hat,1)),tf.float32)) saver = tf.train.Saver() with tf.Session() as sess: tf.global_variables_initializer().run() for i in range(epchos): total_loss = 0 for j in range(int(trX.shape[0] / batch_size + 1)): # 这个如何打乱顺序 x_batch = trX[j*batch_size:min(trX.shape[0],(j+1)*batch_size),:] y_batch = trY[j*batch_size:min(trY.shape[0],(j+1)*batch_size),:] batch_loss,_=sess.run([cross_entropy,train_step],feed_dict={X:x_batch,Y_:y_batch}) total_loss+=batch_loss total_loss /= int(trX.shape[0] / batch_size + 1) test_acc = sess.run(acc,feed_dict={X:teX,Y_:teY}) print("test acc:",test_acc) if i % 100 == 0: saver.save(sess,model_save_path) print("保存模型成功!") train_model((train_images_exp,train_lables,test_images_exp,test_lables))

    在实际按照书上编写代码的时候,博主遇到了一下4个问题没有解决,先放在代码下面,进一步研究后,将解答更新一下,欢迎小伙伴们在评论区留下你们的见解:

    strides的参数中1,4位置的参数是定的,在这里为啥是1,类似的还有其他参数如池化层的ksize。padding的“same” 是跟谁same,以及卷积层和池化层的padding具体是怎么操作的。为什么正则化项只加在全连接层,其他的参数可以正则化嘛?如何打乱每次batch内和batch之间的数据的顺序,来实现随机性?
    最新回复(0)