TensorFlow学习_note2

本文是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

结果类似下图:

图1

7.tensorboard——神经网络可视化

tensorflow提供一个可视化工具——tensorboard。通过使用这个工具我们可以很直观的看到整个神经网络的结构、框架和一些变量的变化情况。

(1)网络结构可视化

tf.name_scope()对各个层次、变量进行名字域封装,方便tensorboard构建网络框架图。

在之前双层神经网络的基础上做以下修改:

  • 定义各个层的name scope

  • 使用 tf.summary.FileWriter("log/",sess.graph) 将之前的绘图收集并保存到指定目录log/

  • 打开terminal进入log的父目录,输入tensorboard --logdir=logs/

    运行后结果:

    图2

  • 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)#记录训练后变量的结果

图3

图4

8.softmax——多分类预测激活函数

多分类问题的输出不是一个值,而是一个向量。softmax激活函数可以将输入映射为一个概率向量(属于每个分类的可能性)。例子中使用MNIST手写图片集作为训练样本。网络结构是这样的:

图6

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))

图5

可以看到准确率不断提升

9.dropot——解决overfitting的问题

  • step1:define keep_prob placeholder
  • step2:train step时引入keep_prob参数(feed_dict的方式)
  • step3:具体的dropout是Z =
    tf.nn.dropout(Z,keep_prob)
    这一步,意思是随机保留keep_prob的结果(其余置0)
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:

图7

dropout后:

图8

可以看到overfitting情况减轻得很明显

10.tf.train.Saver()——保存读取tensorflow变量

tensorflow提供保存变量读取变量的方法,方便重新构建网络时不用再训练,或是将变量给下一层网络使用时调用。

  • Variable初始化时需要指定变量的name
  • tf.train.Saver() :创建一个saver
  • saver.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))

保存:

图9

读取:

图10

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

图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值