本文是tensorflow学习的第二篇笔记,内容接上一篇笔记
6.pyplot——python作图工具
本例中使用matplotlib的交互模式进行动态更新图片,显示数据变化情况。
pyplot.figure():见代码
pyplot.figure().add_subplot():见代码
pyplot.ion():开启matplotlib的交互模式。此时python解释器解释完所有命令后出张图,但不会结束会话,如果你继续往代码中加入语句,run之后,你会实时看到图形的改变。当绘图语句中加入plt.ioff()时或不添加plt.ion()时,表示关了交互模式。此时要加入plt.show()才能显示图片。python解释器解释完所有命令后出张图,同时结束会话。如果你继续往代码中加入语句,再不会起作用。
- plt.pause():绘制完暂停指定的时间。参数为暂停的秒数,接受float型。
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt #python绘图工具包
def add_layer(A_prev,n_prev,n,activation_function = None):
#initialize parameters
W = tf.Variable(tf.random_normal([n,n_prev]))
b = tf.Variable(tf.zeros([n,1])+0.1)
#forward propagation
Z = tf.matmul(W,A_prev) + b
if activation_function == None:
A = Z
else:
A = activation_function(Z)
return A
#create data
#X.shape=Y.shape=Noise.shape=(1,300)
X = np.linspace(-1,1,300)[np.newaxis,:]
Noise = np.random.normal(0,0.05,X.shape)
Y = X**2-0.5+Noise
#placeholder
Xs = tf.placeholder(tf.float32,[1,None])
Ys = tf.placeholder(tf.float32,[1,None])
#propagation
layer1_out = add_layer(Xs,1,10,tf.nn.relu)
prediction = add_layer(layer1_out,10,1)
loss = tf.reduce_mean((Ys-prediction)**2)
#train step
train = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
#start optimize
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)
#plot setting
fig = plt.figure() #用figure()函数画图
ax = fig.add_subplot(1,1,1) #向fig中添加一张子图,3个参数表示一共有1x1张子图,ax是第1张子图
ax.scatter(X,Y) #先看看数据的分布。根据X,Y绘制散点图
plt.ion() #开启交互模式
for i in range(1000):
#训练一次网络
sess.run(train,feed_dict={Xs:X,Ys:Y})
if i % 50 == 0:
#用remove方法抹去刚画的那条lines,保证图像中时刻只有一条线
#由于第一次还没定义lines,所以要做异常处理
try:
ax.lines.remove(lines[0])
except Exception:
pass
#获取预测值
prediction_value = sess.run(prediction,feed_dict={Xs:X})
#根据X和预测值绘制连续曲线lines,红色,宽度=5
lines = ax.plot(X.reshape(300), prediction_value.reshape(300), 'r-', lw=5)
plt.pause(0.2) #暂停0.2s
结果类似下图:
7.tensorboard——神经网络可视化
tensorflow提供一个可视化工具——tensorboard。通过使用这个工具我们可以很直观的看到整个神经网络的结构、框架和一些变量的变化情况。
(1)网络结构可视化
用tf.name_scope()
对各个层次、变量进行名字域封装,方便tensorboard构建网络框架图。
在之前双层神经网络的基础上做以下修改:
定义各个层的name scope
使用
tf.summary.FileWriter("log/",sess.graph)
将之前的绘图收集并保存到指定目录log/
下打开terminal进入log的父目录,输入
tensorboard --logdir=logs/
运行后结果:
copy上面的地址到浏览器打开查看结果(见下方)
(2)变量可视化
tf.histogram_summary()
方法记录tensorflow变量信息tf.summary.scalar()
方法记录loss- 合并打包:
tf.summary.merge_all()
方法将所有的summaries
合并到一起 - 以上这些仅仅可以记录很绘制出训练的图表, 但是不会记录训练的数据。训练过程中使用
writer.add_summary()
记录训练过程中每个参数的变化(filewriter定义见上) - 同上打开terminal输入命令,打开浏览器查看结果
import tensorflow as tf
import numpy as np
def add_layer(A_prev,n_prev,n,n_layer,activation_function = None):
#initialize parameters
layer_name = 'layer%s'%n_layer #第几层
with tf.name_scope('layer'): #定义隐层的name scope
with tf.name_scope('weights'): #定义W的name scope
W = tf.Variable(tf.random_normal([n,n_prev]),name = 'W')
#用histogram()函数添加要记录的变量
#histogram()函数第一个参数是图表的名称, 第二个参数是图表要记录的变量
tf.summary.histogram(layer_name+'/weights',W)
with tf.name_scope('biases'):
b = tf.Variable(tf.zeros([n,1])+0.1,name = 'b')
#同上
tf.summary.histogram(layer_name+'/biases',b)
#forward propagation
with tf.name_scope('Z'):
Z = tf.matmul(W,A_prev) + b
if activation_function == None:
A = Z
else:
A = activation_function(Z)
#同上,记录A的值
tf.summary.histogram(layer_name+'/A',A)
return A
#create data
#X.shape=Y.shape=Noise.shape=(1,300)
X = np.linspace(-1,1,300)[np.newaxis,:]
Noise = np.random.normal(0,0.05,X.shape)
Y = X**2-0.5+Noise
#placeholder
'''
使用with tf.name_scope('inputs')可以将Xs和Ys包含进来,形成一个大的图层,图层的名字就是
with tf.name_scope()方法里的参数
'''
with tf.name_scope('inputs'):
#这里指定的name将来会在可视化的图层inputs中显示出来
Xs = tf.placeholder(tf.float32,[1,None],name = 'x_input')
Ys = tf.placeholder(tf.float32,[1,None],name = 'y_input')
#propagation
layer1_out = add_layer(Xs,1,10,1,tf.nn.relu)
prediction = add_layer(layer1_out,10,1,2)
with tf.name_scope('loss'): #loss作同样处理
loss = tf.reduce_mean((Ys-prediction)**2)
#scalar方法记录loss
tf.summary.scalar('loss',loss)
#train step
with tf.name_scope('train'): #train作同样处理
train = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
#start optimize
sess = tf.Session()
merged = tf.summary.merge_all() #合并所有summary
writer = tf.summary.FileWriter("log/",sess.graph) #定义writer,这一步要定义在session开启后
init = tf.global_variables_initializer()
sess.run(init)
for i in range(1000):
sess.run(train,feed_dict={Xs:X,Ys:Y})
if i%50 == 0:
#merge需要run才有效,run时需喂入相关data
result = sess.run(merged,feed_dict={Xs:X,Ys:Y})
writer.add_summary(result,i)#记录训练后变量的结果
8.softmax——多分类预测激活函数
多分类问题的输出不是一个值,而是一个向量。softmax激活函数可以将输入映射为一个概率向量(属于每个分类的可能性)。例子中使用MNIST手写图片集作为训练样本。网络结构是这样的:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data #数据集
#read in data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) #one_hot参数表示如果还没下载数据先下载
def add_layer(A_prev,n_prev,n,activation_function = None):
#initialize parameters
W = tf.Variable(tf.random_normal([n,n_prev]))
b = tf.Variable(tf.zeros([n,1])+0.1)
#forward propagation
Z = tf.matmul(W,A_prev) + b
if activation_function == None:
A = Z
else:
#这里有个问题,Z必须先转置才能作为softmax的参数
#因为tf.nnsoftmax处理的矩阵是这样的shape=(样本数,每个样本特征长度)
A = activation_function(tf.transpose(Z))
A = tf.transpose(A)
return A
#计算准确率的函数
def compute_accuracy(X_test,Y_test):
#要声明prediction为全局变量,因为是外部定义的
global prediction
pre = prediction #获取prediction
#预测准确分布
#tf.argmax(X,axis)就是求X矩阵在axis维度最大值的index
#tf.equal(A,B)求A,B矩阵每个元素是否相等,等于的位置取ture,否则取false
correct_pre = tf.equal(tf.argmax(pre,0),tf.argmax(Y_test,0))
#统计准确率
#tf.cast()表示将矩阵映射为某一dtype
accuracy = tf.reduce_mean(tf.cast(correct_pre,tf.float32))
result = sess.run(accuracy,feed_dict={Xs:X_test})
return result
#placeholder
Xs = tf.placeholder(tf.float32,[784,None])
Ys = tf.placeholder(tf.float32,[10,None])
#add output layer
#使用softmax进行多分类预测
prediction = add_layer(Xs,784,10,tf.nn.softmax)
#loss定义为prediction和labels的交叉熵
loss = tf.reduce_mean(-tf.reduce_sum(Ys*tf.log(prediction),0))
#train step
train = tf.train.GradientDescentOptimizer(0.5).minimize(loss)
#start session
sess = tf.Session()
sess.run(tf.global_variables_initializer())
#train
for i in range(1000):
batch_X,batch_Y = mnist.train.next_batch(100) #每次取100个训练集
sess.run(train,feed_dict={Xs:batch_X.T,Ys:batch_Y.T})
if i%100 == 0:
#每100step输出准确率
print(compute_accuracy(mnist.test.images.T,mnist.test.labels.T))
可以看到准确率不断提升
9.dropot——解决overfitting的问题
- step1:define keep_prob placeholder
- step2:train step时引入keep_prob参数(feed_dict的方式)
- step3:具体的dropout是
Z =
这一步,意思是随机保留keep_prob的结果(其余置0)
tf.nn.dropout(Z,keep_prob)
import tensorflow as tf
#从sklearn库import数据集
from sklearn.datasets import load_digits #data set
from sklearn.model_selection import train_test_split #切割数据集为训练集和测试集
from sklearn.preprocessing import LabelBinarizer
def add_layer(A_prev,n_prev,n,layer_name,activation_function = None):
#initialize parameters
W = tf.Variable(tf.random_normal([n,n_prev]))
b = tf.Variable(tf.zeros([n,1])+0.1)
#forward propagation
Z = tf.matmul(W,A_prev) + b
#dropout step
#保留keep_prob的结果
Z = tf.nn.dropout(Z,keep_prob)
if activation_function == None:
A = Z
else:
A = activation_function(tf.transpose(Z))
A = tf.transpose(A)
tf.summary.histogram(layer_name+'/outputs',A)
return A
#import data
#这个数据集是手写数字集,样本labels是0-9这10个数字
digits = load_digits()
X = digits.data #X=特征数据
y = digits.target #y=样本标签
y = LabelBinarizer().fit_transform(y) #标签二值化,每个标签值转化成0/1表示的向量
#split data set into train and test
#test set占0.3的比例
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.3)
#placeholder
Xs = tf.placeholder(tf.float32,[64,None]) #输入特征维度64
Ys = tf.placeholder(tf.float32,[10,None]) #输出维度10
#define placeholder for dropout
keep_prob = tf.placeholder(tf.float32)
#propagation
layer1_out = add_layer(Xs,64,50,'L1',tf.nn.tanh)
prediction = add_layer(layer1_out,50,10,'L2',tf.nn.softmax)
#define loss
loss = tf.reduce_mean(-tf.reduce_sum(Ys*tf.log(prediction),reduction_indices=[0]))
#记录loss
tf.summary.scalar('loss',loss)
#train step
train = tf.train.GradientDescentOptimizer(0.6).minimize(loss)
#start Session
sess = tf.Session()
#summary writer goes in here
merged = tf.summary.merge_all()
#record results of train set and test set
#使用两个writer记录训练集和测试集的loss
train_writer = tf.summary.FileWriter("log/train",sess.graph)
test_writer = tf.summary.FileWriter("log/test",sess.graph)
#initialize variables
init = tf.global_variables_initializer()
sess.run(init)
#train and record
for i in range(500):
#train with train set data
#置信度keep_prob为0.5
sess.run(train,feed_dict={Xs:X_train.T,Ys:y_train.T,keep_prob:0.5})
#record every 50 steps
if i % 50 == 0:
#记录 train set的loss
train_result = sess.run(merged,feed_dict={Xs:X_train.T,Ys:y_train.T,keep_prob:1})
#记录 test set的loss
test_result = sess.run(merged,feed_dict={Xs:X_test.T,Ys:y_test.T,keep_prob:1})
train_writer.add_summary(train_result,i)
test_writer.add_summary(test_result,i)
未dropout:
dropout后:
可以看到overfitting情况减轻得很明显
10.tf.train.Saver()——保存读取tensorflow变量
tensorflow提供保存变量读取变量的方法,方便重新构建网络时不用再训练,或是将变量给下一层网络使用时调用。
- Variable初始化时需要指定变量的name
tf.train.Saver()
:创建一个saversaver.save(sess,"my_net/save_net.ckpt")
:将各变量存入指定目录的.ckpt
文件中- 读取:定义相同的shape和dtype的Variable
- 同样define一个saver
saver.restore(sess,"my_net/save_net.ckpt")
:从刚才的文件中读取变量
#tensorflow只能保存变量,下次构建时可以导入使用,神经网络框架需要重新定义
import tensorflow as tf
#save#########################
#这部分是save,先去掉注释运行后,再注释掉,运行后面的restore部分代码
##W = tf.Variable([[1,2,3],[4,5,6]],dtype=tf.float32,name="weights")
##b = tf.Variable([[6,6,6]],dtype=tf.float32,name="biases")
##
###define saver
##saver = tf.train.Saver()
##with tf.Session() as sess:
## sess.run(tf.global_variables_initializer())
## #保存路径,保存为后缀为ckpt的文件
## #save()返回值为保存路径
## #第一个参数sess意思是保存当前会话的graph和variables
## save_path = saver.save(sess,"my_net/save_net.ckpt")
##
## print("Save to path:",save_path)
#restore######################
#读取数据的时候需要定义相同的shape和dtype的Variable
W = tf.Variable(tf.zeros([2,3]),tf.float32,name="weights")
b = tf.Variable(tf.zeros([1,3]),tf.float32,name="biases")
#这里不需要init variables
#也是define一个saver
saver = tf.train.Saver()
with tf.Session() as sess:
#saver.restore导入变量
saver.restore(sess,"my_net/save_net.ckpt")
print("W:",sess.run(W))
print("b:",sess.run(b))
保存:
读取:
11.LSTM网络分类例子
LSTM(Long Short-term Memory)是一个RNN模型,tensorflow提供了构建lstm的API,可以直接使用。本例对MNIST手写图片集进行分类。
- 确定网络结构:input==>hidden layer1(in layer)==>LSTM layer==>hidden layer2(out layer)==>output
- 定义超参数
- 定义placeholder for input和output
- 参数初始化:in layer,out layer的W,b
- 定义RNN结构
- 定义loss,train step,准确率
- 训练
#让RNN从每张图片的第一行像素读到最后一行, 然后再进行分类判断
#data流动方向如下
#data==>input==>input hidden layer==>lstm cell==>output hidden layer==>output
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 导入数据
#MNIST手写图片集
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
#define 超参数
lr = 0.001 #learning rate要尽量小,避免梯度爆炸问题
training_iters = 100000 #训练迭代次数
batch_size = 100 #每次取训练样本数
n_input = 28 # MNIST data input(img shape:28*28)
n_step = 28 # 时序持续长度为28,即每做一次预测,需要先输入28行,也就是一张图片的行数
n_hidden_unit = 100 #输入输出隐层单元数
n_lstm_hidden_unit = 128 #lstm层单元数
n_class = 10 #分类的种类数,MNIST是手写数字集(0-9),有10种类别
#placeholder for input,output
X = tf.placeholder(tf.float32,[None,n_step,n_input])
Y = tf.placeholder(tf.float32,[None,n_class])
#initialize weight bias
#in(输入) out(输出)层的参数
W = {
#shape(输入维度,隐层单元数)
'in':tf.Variable(tf.random_normal([n_input,n_hidden_unit])),
#shape(lstm隐层单元数,输出类别数)
'out':tf.Variable(tf.zeros([n_lstm_hidden_unit,n_class]))
}
b = {
#shape(1,隐层单元数)
'in':tf.Variable(tf.zeros([1,n_hidden_unit])),
#shape(1,输出类别数)
'out':tf.Variable(tf.zeros([1,n_class]))
}
#define function for LSTM
def RNN(X, W, b):
#input layer#######################################################
#shape:(batch_size,n_row,n_col)==>(batch_size*n_row,n_col)
X = tf.reshape(X,[-1,n_input])
#输入的input样本先经过一个linear hidden layer
#X_in.shape=(batch_size*n_row,n_hidden_unit)
X_in = tf.matmul(X,W['in'])+b['in']
#chage shape for lstm cell
X_in = tf.reshape(X_in,[-1,n_step,n_hidden_unit])
#rnn layer##########################################################
#定义一层LSTM_cell只需要说明 hidden_size,它会自动匹配输入的 X 的维度
#这步构建了一个hidden units数目指定的lstm cell
#BasicLSTMCell()有几个默认参数,见官方api
#state_is_tuple:该参数默认为True,此时输入和输出的states为c(cell状态)和h(输出)的二元组
lstm_cell = tf.contrib.rnn.BasicLSTMCell(n_lstm_hidden_unit)
#用全零来初始化lstm cell的state
#init_state.shape=(batch_size*state_size),state_size就是lstm隐层单元数
init_state = lstm_cell.zero_state(batch_size,dtype=tf.float32)
#调用dynamic_rnn()来让我们构建好的网络运行起来
# dynamic_rnn receive Tensor (batch, steps, inputs) or (steps, batch, inputs) as X_in
# outputs就是n_step步里所有的输出,shape=(batch_size, n_step, output_size)
# state是最后一步的隐状态,shape=(batch_size, state_size)
#time_major默认=False,表示X_in的shape是(batch, steps, inputs) 这样的
output,final_state = tf.nn.dynamic_rnn\
(lstm_cell,X_in,initial_state=init_state,time_major=False)
#output layer#######################################################
#final_state[1]即h(输出),shape=(batch_size,output_size)
result = tf.matmul(final_state[1], W['out']) + b['out']
return result
pred = RNN(X,W,b)
#tf.nn.softmax_cross_entropy_with_logits()函数:将pred做一个softmax处理,然后与labels求交叉熵
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=Y,logits=pred))
#train step 这里使用AdamOptimizer
train = tf.train.AdamOptimizer(lr).minimize(loss)
#准确率
correct = tf.equal(tf.argmax(pred,1),tf.argmax(Y,1))
accuracy = tf.reduce_mean(tf.cast(correct,tf.float32))
sess = tf.Session()
sess.run(tf.global_variables_initializer())
step = 0
while step*batch_size < training_iters: #训练10W张图片,训练1000次
batch_X, batch_Y = mnist.train.next_batch(batch_size) #每次训练取100张图片
batch_X = batch_X.reshape([batch_size, n_step, n_input])
sess.run(train,feed_dict={X: batch_X, Y: batch_Y})
if step % 100 == 0:
print(sess.run(accuracy,feed_dict={X:batch_X,Y:batch_Y}))
step += 1