1.Tensorflow的简单网络。
#coding:utf-8
#0导入模块 ,生成模拟数据集
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
BATCH_SIZE = 100
TOTAL_SIZE = 1000
LEARNING_RATE_BASE = 0.1 #最初学习率
LEARNING_RATE_DECAY = 0.5 #学习率衰减率
LEARNING_RATE_STEP = 1000 #喂入多少轮BATCH_SIZE后,更新一次学习率,一般设为:总样本数/BATCH_SIZE
seed = 10
#基于seed产生随机数
rdm = np.random.RandomState(seed)
#随机数返回300行2列的矩阵,表示300组坐标点(x0,x1)作为输入数据集
X = rdm.randn(TOTAL_SIZE,2)
#从X这个300行2列的矩阵中取出一行,判断如果两个坐标的平方和小于2,给Y赋值1,其余赋值0
#作为输入数据集的标签(正确答案)
Y_ = np.array([[int(x0*x0 + x1*x1 <2)] for (x0,x1) in X])
#遍历Y中的每个元素,1赋值'red'其余赋值'blue',这样可视化显示时人可以直观区分
Y_c = [['red' if y else 'blue'] for y in Y_]
#对数据集X和标签Y进行shape整理,第一个元素为-1表示,随第二个参数计算得到,第二个元素表示多少列,把X整理为n行2列,把Y整理为n行1列
#X = np.vstack(X).reshape(-1,2)
#Y_ = np.vstack(Y_).reshape(-1,1)
#print(X)
#print(Y_)
#print(Y_c)
#用plt.scatter画出数据集X各行中第0列元素和第1列元素的点即各行的(x0,x1),用各行Y_c对应的值表示颜色(c是color的缩写)
plt.scatter(X[:, 0], X[:, 1], c=np.squeeze(Y_c))# np.squeeze(Y_c)去掉Y_c.shape中为1的维度
#plt.show()# 显示图
x = tf.placeholder(tf.float32, shape=(None, 2))# 输入占位
y_ = tf.placeholder(tf.float32, shape=(None, 1))# 标签中输出占位
w1 = tf.Variable(tf.random_normal([2, 11]), dtype=tf.float32)# 第一层,2行11列
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(0.01)(w1))# 将w1的正则化加入‘losses’中
b1 = tf.Variable(tf.constant(0.01, shape=[11]))# 第一层偏置
y1 = tf.nn.relu(tf.matmul(x, w1)+b1)# 激活函数relu,y1为神经网络第一层的输出
w2 = tf.Variable(tf.random_normal([11, 1]), dtype=tf.float32)# 第二层,11行1列
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(0.01)(w2))# w2的正则化
b2 = tf.Variable(tf.constant(0.01, shape=[1]))# w2的偏置
y = tf.matmul(y1, w2)+b2# 网络的输出
global_step = tf.Variable(0, trainable=False)# 迭代步数,计数器
#定义指数下降学习率
learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE, global_step, LEARNING_RATE_STEP, LEARNING_RATE_DECAY, staircase=True)# 学习率的衰减方式为指数方式
loss_mse = tf.reduce_mean(tf.square(y-y_))# 误差平均差,损失函数
loss_total = loss_mse + tf.add_n(tf.get_collection('losses'))# 总的损失函数
train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss_total, global_step=global_step)# 定义每一步迭代,使用的优化器为Adam,
with tf.Session() as sess:
init_op = tf.global_variables_initializer()# 初始化变量
sess.run(init_op)
for i in range(10000):# 开始迭代
start = (i * BATCH_SIZE)% TOTAL_SIZE# BATCH_SIZE下,计算每一次迭代的数据的BATCH的第一个位置
end = start + BATCH_SIZE# 每一次迭代的结尾,配合start
sess.run(train_step, feed_dict={x: X[start:end], y_: Y_[start:end]})# 执行训练一次,需要feed的参数为训练集的x,和标签。
if i % 500 == 0:# 每迭代500次执行一次
print("step: ",i," global_step: ",sess.run(global_step)," learning_rate ",sess.run(learning_rate)," loss: ",sess.run(loss_mse, feed_dict={x: X[start:end], y_: Y_[start:end]}))
#xx在-3到3之间以步长为0.01,yy在-3到3之间以步长0.01,生成二维网格坐标点
xx, yy = np.mgrid[-5:5:.01, -5:5:.01]# 实际上就是将网格切分,xx和yy中记录的都是[-5,5]步长为0.01的10000个数,
#print("xx.shape: ",xx.shape)
# 将xx , yy拉直,并合并成一个2列的矩阵,得到一个网格坐标点的集合
grid = np.c_[xx.ravel(), yy.ravel()]# 形成类似于[xx,yy]的二维矩阵。np.c_将两个矩阵横向相加,要求行数相等。纵向相加的对应的是np.r_
#print("grid.shape: ",grid.shape)
# 将网格坐标点喂入神经网络 ,probs为输出
probs = sess.run(y, feed_dict={x: grid})
#print("probs.shape: ",probs.shape)
# probs的shape调整成xx的样子
probs = probs.reshape(xx.shape)
#print("w1:\n", sess.run(w1))
#print("b1:\n", sess.run(b1))
#print("w2:\n", sess.run(w2))
#print("b2:\n", sess.run(b2))
a = plt.contourf(xx, yy, probs, 100, cmap=plt.cm.Spectral)# 把输出划分为100个等级,填充颜色
plt.scatter(X[:, 0], X[:, 1], c=np.squeeze(Y_c))# 画原数据点
b = plt.contour(xx, yy, probs, levels=[.5])# 画等高线
plt.colorbar(a, ticks=[0, 0.5, 1, 1.5, 2.0, 2.5])# 右侧数据条
plt.clabel(b, inline=True, fontsize=10)# 显示等高线
plt.show()# 显示
10000次迭代后输出结果:
2.训练mnist数据集(不用卷积)
训练代码:
import numpy as np
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import os
BATCH_SIZE = 200
LEARNING_RATE_BASE = 0.1
LEARNING_RATE_DECAY = 0.99
MOVING_AVERAGE_DECAY = 0.99
STEPS = 50000
REGULARIZER = 0.0001
OUTPUT_NODE = 10
INPUT_NODE = 784
HIDDEN_NODE = 500
MODEL_SAVE_PATH = "./models/"# 模型保存的路径
MODEL_NAME = "mnist_model"# 模型保存名字
DATA_PATH = "/home/yjh/Tensorflow-learning/Tensorflow5fc1/data"# 数据集路径
def get_weight(shape, regularizer):# 添加一个w层
w = tf.Variable(tf.truncated_normal(shape, stddev=0.1))# 生成随机数方式为截断正态分布
if regularizer != None:# 判断是否带正则化
tf.add_to_collection("losses", tf.contrib.layers.l2_regularizer(regularizer)(w))
return w
def get_bias(shape):# 生成一个偏置项
b = tf.Variable(tf.zeros(shape))# 偏置初始化为0
return b
mnist = input_data.read_data_sets(DATA_PATH, one_hot=True)# 获取数据集
x = tf.placeholder(tf.float32, [None, INPUT_NODE])# 输入占位,长度为一个一个数据的长度。
y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE])# 标签的占位,长度为10分类
w1 = get_weight([INPUT_NODE, HIDDEN_NODE], REGULARIZER)# 网络的第一层
b1 = get_bias([HIDDEN_NODE])# 第一层的偏置
y1 = tf.nn.relu(tf.matmul(x, w1) + b1)# 第一层的输出
w2 = get_weight([HIDDEN_NODE, OUTPUT_NODE], REGULARIZER)# 第二层
b2 = get_bias([OUTPUT_NODE])# 第二层偏置
y = tf.matmul(y1, w2) + b2# 输出
global_step = tf.Variable(0, trainable=False)# 迭代步数计数器
ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))# 对网络最后一层的输出y做softmax,在根据标签求交叉熵
cem = tf.reduce_mean(ce)# 均值loss
loss = cem + tf.add_n(tf.get_collection("losses"))# 总loss,加上了正则化
learning_rate = tf.train.exponential_decay(
LEARNING_RATE_BASE,
global_step,
mnist.train.num_examples / BATCH_SIZE,
LEARNING_RATE_DECAY,
staircase=True
)# 学习率的衰减方式为指数形式
train_step = tf.train.MomentumOptimizer(learning_rate, 0.9).minimize(loss, global_step=global_step)# 优化器为Mumentum
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)# 指数滑动平均
ema_op = ema.apply(tf.trainable_variables())# 使用滑动平均
with tf.control_dependencies([train_step, ema_op]):# 依赖
train_op = tf.no_op(name='train')# 当sess.run(train_op)时,会同时run上边两个[train_step, ema_op]
saver = tf.train.Saver()# 建立一个保存模型的存储器
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
for i in range(STEPS):
xs, ys = mnist.train.next_batch(BATCH_SIZE)# 在训练集中提取一个BATCH
_, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys})
if (i + 1) % 1000 == 0:
print("after %d steps, ;loss is %f" % (step, loss_value))
if (i + 1) % 5000 == 0:
saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)
pycharm运行结果:
after 1000 steps, ;loss is 0.170276
after 2000 steps, ;loss is 0.136261
after 3000 steps, ;loss is 0.115604
after 4000 steps, ;loss is 0.105963
after 5000 steps, ;loss is 0.088661
after 6000 steps, ;loss is 0.081842
after 7000 steps, ;loss is 0.073383
after 8000 steps, ;loss is 0.068116
after 9000 steps, ;loss is 0.064231
after 10000 steps, ;loss is 0.061444
after 11000 steps, ;loss is 0.054349
after 12000 steps, ;loss is 0.049520
after 13000 steps, ;loss is 0.050399
after 14000 steps, ;loss is 0.046730
after 15000 steps, ;loss is 0.046526
after 16000 steps, ;loss is 0.042283
after 17000 steps, ;loss is 0.043034
after 18000 steps, ;loss is 0.039838
after 19000 steps, ;loss is 0.038359
after 20000 steps, ;loss is 0.039458
after 21000 steps, ;loss is 0.036007
after 22000 steps, ;loss is 0.037945
after 23000 steps, ;loss is 0.035751
after 24000 steps, ;loss is 0.037602
after 25000 steps, ;loss is 0.035550
after 26000 steps, ;loss is 0.036474
after 27000 steps, ;loss is 0.032806
after 28000 steps, ;loss is 0.033995
after 29000 steps, ;loss is 0.032326
after 30000 steps, ;loss is 0.031818
after 31000 steps, ;loss is 0.035270
after 32000 steps, ;loss is 0.035549
after 33000 steps, ;loss is 0.030204
after 34000 steps, ;loss is 0.033483
after 35000 steps, ;loss is 0.032387
after 36000 steps, ;loss is 0.032469
after 37000 steps, ;loss is 0.031001
after 38000 steps, ;loss is 0.033947
after 39000 steps, ;loss is 0.031707
after 40000 steps, ;loss is 0.029635
after 41000 steps, ;loss is 0.030342
after 42000 steps, ;loss is 0.029521
after 43000 steps, ;loss is 0.032588
after 44000 steps, ;loss is 0.028240
after 45000 steps, ;loss is 0.031453
after 46000 steps, ;loss is 0.031022
after 47000 steps, ;loss is 0.028289
after 48000 steps, ;loss is 0.031529
after 49000 steps, ;loss is 0.029671
after 50000 steps, ;loss is 0.030248
3.使用Lenet5卷积神经网络,实现手写图数字识别,包括训练和单张测试函数
import tensorflow as tf
import numpy as np
import os
import time
from PIL import Image
from tensorflow.examples.tutorials.mnist import input_data
BATCH_SIZE = 1
IMAGE_SIZE = 28# 图像的WH都是38
IMAGE_CHANNELS = 1# 输入图像为单通道图像
KERNEL_SIZE1 = 5# 第一个卷积核的长宽
CONV1_CHANNEL_NUM = 32# 第一次卷积后的特征图通道个数
KERNEL_SIZE2 = 5# 第二次卷积卷积核的大小
CONV2_CHANNEL_NUM = 64# 第二次卷积后的特征图通道数
OUTPUT_NODE = 10# 输出10类
FC_SIZE = 512# 全连接层的大小
REGULARIZER = 0.0001# 正则化参数
LEARNING_RATE_DECAY = 0.99# 学习率的衰减率
LEARNING_RATE_BASE = 0.005# 基础学习率
MOVING_AVERAGE_DECAY = 0.99# 滑动平均的参数
MODEL_SAVE_PATH = "./model/"# 模型保存路径
MODEL_NAME = "mnist_model"# 模型保存名称
def net_build(x_size):# 构建网络
# 第一层
x = tf.placeholder(tf.float32, [x_size,
IMAGE_SIZE,
IMAGE_SIZE,
IMAGE_CHANNELS])# 输入占位,
conv1_w = tf.Variable(tf.truncated_normal([KERNEL_SIZE1,
KERNEL_SIZE1,
IMAGE_CHANNELS,
CONV1_CHANNEL_NUM], stddev=0.1))# 定义第一个卷积核
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(REGULARIZER)(conv1_w))# 添加正则化
conv1_b = tf.Variable(tf.zeros([CONV1_CHANNEL_NUM]))# 第一层卷积偏置
conv1 = tf.nn.conv2d(x, conv1_w, strides=[1, 1, 1, 1], padding='SAME')# 卷积,步长为1,方式为全padding
relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_b))# 添加偏置后,进行激活函数
pool1 = tf.nn.max_pool(relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')# 最大池化层,核大小为2,步长为2
# 第二层
conv2_w = tf.Variable(tf.truncated_normal([KERNEL_SIZE2,
KERNEL_SIZE2,
CONV1_CHANNEL_NUM,
CONV2_CHANNEL_NUM], stddev=0.1))#第二次卷积核
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(REGULARIZER)(conv2_w))# 正则化
conv2_b = tf.Variable(tf.zeros([CONV2_CHANNEL_NUM]))# 偏置
conv2 = tf.nn.conv2d(pool1, conv2_w, strides=[1, 1, 1, 1], padding='SAME')# 卷积,步长为1,padding
relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_b))# 卷积后加偏置并激活
pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')# 最大池化层
pool_shape = pool2.get_shape().as_list()# 得到第二次卷积后的特征图shape,放到一个列表中,列表的0、1、2、3个分别是,B,H,W,C(不确定顺序)
nodes = pool_shape[1] * pool_shape[2] * pool_shape[3]# 得到一个特征图的像素点数量
reshaped = tf.reshape(pool2, [pool_shape[0], nodes])# 将卷基层输出的所有特征图都拉直,得到的维度为[一个特征图像素点数,BATCH]
fc1_w = tf.Variable(tf.truncated_normal([nodes, FC_SIZE], stddev=0.1))# 第一层全连接层
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(REGULARIZER)(fc1_w))# 正则化
fc1_b = tf.Variable(tf.zeros([FC_SIZE]))# 第一层全连接的偏置
fc1 = tf.matmul(reshaped, fc1_w) + fc1_b# 计算
fc1_rule = tf.nn.relu(fc1)#激活
fc1_dropout = tf.nn.dropout(fc1_rule, 0.5)# dropout,概率为0.5
fc2_w = tf.Variable(tf.truncated_normal([FC_SIZE, OUTPUT_NODE], stddev=0.1))# 第二层全连接
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(REGULARIZER)(fc2_w))# 正则化
fc2_b = tf.Variable(tf.zeros([OUTPUT_NODE]))# 第二层偏置
y = tf.matmul(fc1_dropout, fc2_w) + fc2_b# 输出
return x, y# 返回输入和输出
def train():# 训练过程
mnist_data = input_data.read_data_sets("./data/", one_hot=True)# 读取mnist的数据集
x_ph, y_ph = net_build(BATCH_SIZE)# 建立网络,定义前向传播过程
y_label = tf.placeholder(tf.float32, [None, OUTPUT_NODE])# 训练集标签的占位
global_step = tf.Variable(0, trainable=False)# 总的训练计数器
ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y_ph, labels=tf.argmax(y_label, 1))# 对前向传播的结果y_ph做softmax(求出分类的概率),并求出交叉熵
cem = tf.reduce_mean(ce)# 求平均值
loss = cem + tf.add_n(tf.get_collection('losses'))# 计算损失函数
learning_rate = tf.train.exponential_decay(
LEARNING_RATE_BASE,
global_step,
mnist_data.train.num_examples / BATCH_SIZE,
LEARNING_RATE_DECAY,
staircase=True)# 学习率指数衰减
# train_step = tf.train.MomentumOptimizer(learning_rate, 0.9).minimize(loss, global_step=global_step)# 选择优化器
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)# 指数滑动平均
ema_op = ema.apply(tf.trainable_variables())# 应用滑动平均
with tf.control_dependencies([train_step, ema_op]):# train_step和ema_op合并到以一个列表,合成一个操作
train_op = tf.no_op(name='train')
with tf.Session() as sess:
init_op = tf.global_variables_initializer()# 初始化变量
sess.run(init_op)
ckpt = tf.train.get_checkpoint_state(MODEL_SAVE_PATH)# 加载检查点
saver = tf.train.Saver()# 模型的存储器
if ckpt and ckpt.model_checkpoint_path:# 检查是否存在训练的检查点
saver.restore(sess, ckpt.model_checkpoint_path)# 有的话加载存贮的模型的检查点,一会继续训练
print("ckpt done.")
time.sleep(1)# 暂停一秒。为的是让人看清楚上面打印的话
for i in range(50000):# 开始训练迭代50000次
xs, ys = mnist_data.train.next_batch(BATCH_SIZE) #取一个BATCH
reshaped_xs = np.reshape(xs, (
BATCH_SIZE,
IMAGE_SIZE,
IMAGE_SIZE,
IMAGE_CHANNELS)) # 把训练集输入拉直
_, loss_value, step, lr = sess.run([train_op, loss, global_step, learning_rate], feed_dict={x_ph: reshaped_xs, y_label: ys})# 训练
if (i+1) % 10000 == 0: # 每迭代10000次保存一次结果
print("After %d training step(s),lr %f; loss on training batch is %g." % (step, lr, loss_value))
saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)
if (i+1) % 100 == 0:
print("After %d training step(s),lr %f; loss on training batch is %g." % (step, lr, loss_value))
# 预处理图片
def pre_pic(picName): # 图片预处理,预处理自己的图片
img = Image.open(picName) # 打开图片,用的是PIL
reIm = img.resize((28, 28), Image.ANTIALIAS) # 将图片拉伸为28*28大小,质量为Image.ANTIALIAS
im_arr = np.array(reIm.convert('L')) # 转化为灰度图
threshold = 50 # 定义一个阈值,低于阈值的将被省略
for i in range(28): # 遍历图像,进行二值化
for j in range(28):
im_arr[i][j] = 255 - im_arr[i][j]
if (im_arr[i][j] < threshold):
im_arr[i][j] = 0
else: im_arr[i][j] = 255
# 将图片转换为需要的四个张量
nm_arr = im_arr.reshape([1,
IMAGE_SIZE,
IMAGE_SIZE,
IMAGE_CHANNELS]) # 将二值化的图片转化为张量
nm_arr = nm_arr.astype(np.float32) # 张量转为float32形式
img_ready = np.multiply(nm_arr, 1.0/255.0) # 像素值限定到0-1
return img_ready # 最后返回的是一个28*28*1的二值化图
def test(): # 测试训练结果的函数
with tf.Graph().as_default() as g: # 在默认图下建立网络
x_ph, y_ph = net_build(1) # 定义网络,生成前向传播
preSotfmax = tf.nn.softmax(y_ph) # 对结果进行非极大值抑制,得出分类结果
preValue = tf.argmax(preSotfmax, 1) # 找出top1,即可能性最大的结果
pic_array = pre_pic('./5.jpg') # 进行图片预处理,得出可供训练的图片数据格式
#print(pic_array.shape)
with tf.Session() as sess:
ckpt = tf.train.get_checkpoint_state(MODEL_SAVE_PATH) # 模型路径
saver = tf.train.Saver() # 定义存储器
if ckpt and ckpt.model_checkpoint_path: # 如果模型存在
saver.restore(sess, ckpt.model_checkpoint_path) # 加载模型
out_y, output_val, output_softmax = sess.run([y_ph, preValue, preSotfmax], feed_dict={x_ph: pic_array}) # 将图片喂给网络,进行预测
print('网络的输出out_y: \n',out_y)
print('分类结果output_softmax: \n',output_softmax)
print(output_val)
def main():
print('main')
test()
if __name__ == '__main__':
main()
输入图片:
输出结果:
网络的输出out_y:
[[-6.7819757 -0.47882637 -0.52103394 5.084658 -5.0194373 10.814644
-1.8547115 -1.8722407 5.6790185 0.9596205 ]]
分类结果output_softmax:
[[2.2589280e-08 1.2340278e-05 1.1830261e-05 3.2174783e-03 1.3163231e-07
9.9087030e-01 3.1173508e-06 3.0631813e-06 5.8296579e-03 5.2003736e-05]]
属于类别:output_val:
[5]