基本使用( 三 )


利于Lenet做三分类任务
#coding=utf-8import os#图像读取库from PIL import Image#矩阵运算库import numpy as npimport tensorflow as tf# 数据文件夹data_dir = "data"#_test# 训练还是测试train =False# True## 模型文件路径model_path = "model/image_model"data_test = 'data_test'def read_test(x):global fpathtest = []for fname in os.listdir(x):fpath = os.path.join(x, fname)image = Image.open(fpath)fname = np.array(image) / 255.0test.append(fname)# test = np.append(test)return testdeta_test = read_test (data_test)# 从文件夹读取图片和标签到numpy数组中# 标签信息在文件名中,例如1_40.jpg表示该图片的标签为1'''定义三个列表:图片,标签,图片文件os.listdir(data_dir) 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表 。s.path.join。自动加上/data/0_6.jpgPIL.Image.open()专接图片路径,用来直接读取该路径指向的图片 。要求路径必须指明到哪张图,不能只是所有图所在的文件夹;'''def read_data(data_dir):datas = []labels = []fpaths = []for fname in os.listdir(data_dir):fpath = os.path.join(data_dir, fname)#data/0_6.jpgfpaths.append(fpath)#拥有了data下所有的图片文件的位置image = Image.open(fpath)#读取所有图片的位置,这里返回的是JPEG图像文件图像模式=RGB,大小=32x32data = http://www.kingceram.com/post/np.array(image) / 255.0#将图像矩阵32*32,转换为np的数据格式并做归一化label = int(fname.split("_")[0]) #从_中分割,0位置为图片的labeldatas.append(data)#将矩阵图片添加进datas列表中labels.append(label)#加lable添加进labels列表走datas = np.array(datas)#转换np格式labels = np.array(labels)#转换np格式print(r"shape aof dtas: {}\tshape of labels: {}".format(datas.shape, labels.shape))return fpaths, datas, labelsfpaths, datas, labels = read_data(data_dir)# 计算有多少类图片num_classes = len(set(labels))# 定义Placeholder,存放输入和标签datas_placeholder = tf.placeholder(tf.float32, [None, 32, 32, 3])labels_placeholder = tf.placeholder(tf.int32, [None])# 存放DropOut参数的容器,训练时为0.25,测试时为0dropout_placeholdr = tf.placeholder(tf.float32)'''tf.layers.conv2d是tf.nn.conv2d更高级的api这里只需要定义输入,卷积核通道数,卷积核大小,激活函数'''# 定义卷积层, 20个卷积核, 卷积核大小为5,用Relu激活conv0 = tf.layers.conv2d(datas_placeholder, 20, 5, activation=tf.nn.relu)#28*28*20print(conv0)# 定义max-pooling层,pooling窗口为2x2,步长为2x2pool0 = tf.layers.max_pooling2d(conv0, [2, 2], [2, 2])#14*14*20print(pool0)# 定义卷积层, 40个卷积核, 卷积核大小为4,用Relu激活conv1 = tf.layers.conv2d(pool0, 40,5, activation=tf.nn.relu) #10*10*40print(conv1)# 定义max-pooling层,pooling窗口为2x2,步长为2x2pool1 = tf.layers.max_pooling2d(conv1, [2, 2], [2, 2])#5*5*40print(pool1)# 将3维特征转换为1维向量(扁平化)flatten = tf.layers.flatten(pool1)# 全连接层,转换为长度为100的特征向量fc = tf.layers.dense(flatten, 400, activation=tf.nn.relu)# 加上DropOut,防止过拟合dropout_fc = tf.layers.dropout(fc, dropout_placeholdr)# 全连接层,转换为长度为nun_classes的特征向量,这一步不定义激活函数softmax的原因是:下面我们应用tf.nn.softmax_cross_entropy_with_logits函数 。logits = tf.layers.dense(dropout_fc, num_classes)predicted_labels = tf.arg_max(logits, 1)#测试输出概率最大的一个类别print(predicted_labels)'''tf.nn.softmax_cross_entropy_with_logits函数:tf.one_hot:(热编码)函数,如果Yj为第一类那么其独热编码为: [1,0,0,0,0],如果是第二类那么独热编码为:[0,1,0,0,0],'''# 利用交叉熵定义损失losses = tf.nn.softmax_cross_entropy_with_logits(labels=tf.one_hot(labels_placeholder, num_classes), #真实label是分类的概率,比如说[0.2,0.3,0.5].我们设置了函数tf.one_hot之后就会输出[1,0],或者[0,1]logits=logits#预测时的labels ,返回的是[0.2,0.3,0.5]概率值,加起来=1)# 平均损失mean_loss = tf.reduce_mean(losses)#将[0.2,0.3,0.5]相加之后除以数量求平均!这就是我们要缩小的loss值,越小越好 。# 定义优化器,指定要优化的损失函数optimizer = tf.train.AdamOptimizer(learning_rate=1e-2).minimize(losses)#定义优化器缩小loss# 用于保存和载入模型saver = tf.train.Saver()with tf.Session() as sess: #创建会话if train:#假如多true则进行训练模式print("训练模式")# 如果是训练,初始化参数sess.run(tf.global_variables_initializer()) #全局变量初始化# sess.run:执行优化器和打印出loss 。定义输入和Label以填充容器,训练时dropout为0.25for step in range(1500):_, mean_loss_val = sess.run([optimizer, mean_loss], feed_dict={datas_placeholder: datas,labels_placeholder: labels,dropout_placeholdr: 0.25})if step % 10 == 0: #每训练10次就打印出一次lossprint(r"step = {}\tmean loss = {}".format(step, mean_loss_val))saver.save(sess, model_path)#保存模型文件#image_model.meta保存模型#image_model.data保存变量print("训练结束,保存模型到{}".format(model_path))else:print("测试模式")# 如果是测试,载入参数saver.restore(sess, model_path)#saver.restore:载入数据,因为模型上面已经定义好了,所以只需要读书数据就好 。需要读取模型就用tf.train.import_meta_graphprint("从{}载入模型".format(model_path))# label和名称的对照关系label_name_dict = {0: "飞机",1: "汽车",2: "鸟"}# 定义输入和Label以填充容器,测试时dropout为0predicted_labels_val = sess.run(predicted_labels, feed_dict={datas_placeholder: deta_test,dropout_placeholdr: 0})# print('鸟', predicted_labels_val)# 真实label与模型预测labelfor i in predicted_labels_val:if i == 1:print('汽车',)elif i == 0:print('飞机')else:print('鸟')