Tensorflow入门--用tensorflow实现一个三层的神经网络

前言

       这段时间在学习吴恩达的深度学习视频,前面博客中一直在利用numpy自己构造网络框架实现前向传播、损失函数、反向传播、优化等,在这一篇博客中将实现利用tensorflow库里的函数直接实现上面所说的功能,使整个程序更加简洁。

       最后,如果有写得不对的地方,希望大家不吝赐教,谢谢!

Tensorflow入门

一、怎样实现Tensorflow代码步骤

(1)创建Tensorflow变量

(2)实现Tensorflow变量之间的操作定义

(3)初始化Tensorflow变量

(4)创建Session

(5)运行Session

二、整个过程

此次任务是检测手势0-5六个数字,即一共6个类别,C=6,训练集一共有1080张图片,测试集一共有120张图片

1、编写独热编码

2、加载数据

3、分割数据集

4、创建placeholders

5、初始化w和b参数

6、前向传播

7、损失函数

8、反向传播与优化

9、模型

10、结果与测试

三、导入的包

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import time
from tensorflow.python.framework import ops
import math
import h5py

1、独热编码

独热编码即0、1编码,如下所示:

y=[0   1     3     2]      \Rightarrow     y^{'}=\begin{bmatrix} 0 &0 &0 &0 \\ 0 & 1& 0& 0\\ 0 &0 & 0 &1 \\ 0& 0 & 1 & 0 \end{bmatrix}  \left.\begin{matrix} \leftarrow class=0\\\leftarrow class=1 \\ \leftarrow class=2 \\ \leftarrow class=3 \end{matrix}\right\}

维度变化:y:1 \times n_y     \Rightarrow       y':#classes \times n_y (#classes:是类别数量)

以上即是独热编码(one-hot encoding),在Tensorflow中一行代码可以搞定:

tf.one_hot(labels,depth,axis)

当我们不用Tensorflow库函数时,我们也可以这样写:

#使用独热编码
    
def covert_to_one_hot(Y,C):
    
    Y=np.eye(C)[Y.reshape(-1)].T
    
    return Y

测试一下:

Y=np.array([0,1,3,2])
#使用自己编写的one_hot函数
one_hot=covert_to_one_hot(Y,4)
'''
#使用Tensorflow库的one_hot函数
one_hot=tf.one_hot(Y,4)
sess=tf.Session()
one_hot=sess.run(one_hot)
'''
print('Y:',Y)
print('one_hot:')
print(one_hot)

结果:

 Y: [0 1 3 2]
one_hot:
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 0. 1.]
 [0. 0. 1. 0.]]

 2、加载数据

数据下载地址:链接:https://pan.baidu.com/s/1szOSCBaS0naPicXu3nOlng      提取码:twn8 
 

#加载数据集
def load_datasets():
    
    train_data=h5py.File('F:\\PythonProgram\\第三周\\datasets\\train_signs.h5','r')
    train_x=np.array(train_data['train_set_x'][:])
    train_y=np.array(train_data['train_set_y'][:])
    
    test_data=h5py.File('F:\\PythonProgram\\第三周\\datasets\\test_signs.h5','r')
    test_x=np.array(test_data['test_set_x'][:])
    test_y=np.array(test_data['test_set_y'][:])
    
    classes=np.array(test_data['list_classes'][:])
    
    train_x=train_x.reshape(train_x.shape[0],-1).T
    train_x=train_x/255
    
    test_x=test_x.reshape(test_x.shape[0],-1).T
    test_x=test_x/255
    
    train_y=train_y.reshape((1,train_y.shape[0]))
    test_y=test_y.reshape((1,test_y.shape[0]))
    
    train_y=covert_to_one_hot(train_y,6)
    test_y=covert_to_one_hot(test_y,6)
    
    print('train_x_shape:',train_x.shape)
    print('train_y_shape:',train_y.shape)
    print('test_x_shape:',test_x.shape)
    print('test_y_shape:',test_y.shape)
    
    return train_x,train_y,test_x,test_y,classes

测试一下:

train_x,train_y,test_x,test_y,classes=load_datasets()

结果:

train_x_shape: (12288, 1080)
train_y_shape: (6, 1080)
test_x_shape: (12288, 120)
test_y_shape: (6, 120)

 3、分割数据集

#分割数据
def random_mini_batches(X,Y,mini_batches_size=64,seed=0):
    
    np.random.seed(seed)
    m=Y.shape[1]
    mini_batches=[]
    
    #第一步:打乱顺序
    permutation =list(np.random.permutation(m))
    X_random=X[:,permutation]
    Y_random=Y[:,permutation].reshape(Y.shape[0],m)
    
    #第二步:分割
    num_competed=math.floor(m/mini_batches_size)
    
    for i in range(num_competed):
        
        mini_batch_x=X_random[:,i*mini_batches_size:(i+1)*mini_batches_size]
        mini_batch_y=Y_random[:,i*mini_batches_size:(i+1)*mini_batches_size]
        mini_batch=(mini_batch_x,mini_batch_y)
        mini_batches.append(mini_batch)
        
    if m%mini_batches_size!=0:
        
        mini_batch_x=X_random[:,num_competed*mini_batches_size:]
        mini_batch_y=Y_random[:,num_competed*mini_batches_size:]
        mini_batch=(mini_batch_x,mini_batch_y)
        mini_batches.append(mini_batch)
        
    return mini_batches

4、创建placeholders

为X和Y创建占位符,后面会话时再向里面传递数据

#创建placeholders
'''
函数功能:为train_x和train_y创建占位符
输入:n_x:图片的大小为64*64*3,n_y:类别数,在这里为6
输出:X:一个数据集的占位符,维度:[n_x,None],Y:对应标签的占位符,维度:[n_y,None]
'''
def crate_placeholders(n_x,n_y):
    
    X=tf.placeholder(tf.float32,[n_x,None],name='X')#None:表示这值不确定,可以改变
    Y=tf.placeholder(tf.float32,[n_y,None],name='Y')
    
    return X,Y

5、初始化w和b参数

#初始化w和b参数
'''
函数功能:初始化w和b参数
输入:net_dims:网络维度信息
输出:parms:初始化好的w和b
'''
def init_w_b(net_dims):
    
    L=len(net_dims)
    parms={}
    tf.set_random_seed(1)
    
    for i in range(1,L):
        
        parms['W'+str(i)]=tf.get_variable('W'+str(i),[net_dims[i],net_dims[i-1]],
             initializer=tf.contrib.layers.xavier_initializer(seed=1))
        parms['b'+str(i)]=tf.get_variable('b'+str(i),[net_dims[i],1],initializer=tf.zeros_initializer())
        
    return parms

6、前向传播

在Tensorflow中,W和X矩阵相乘是:tf.matmul(W,X),相加:tf.add(a,b) 也可以直接是a+b

#前向传播
'''
函数功能:实现前向传播
输入:X:训练集数据,parms:w和b参数,net_dims:网络维度信息
输出:Z[L-1]:最后一层的Z值,在tensorflow中是用Z[L-1]作为计算损失值的输入
'''   
def forward(X,parms,net_dims):
    
    L=len(net_dims)
    Z={}
    A={}
    
    Z[1]=tf.matmul(parms['W1'],X)+parms['b1']
    A[1]=tf.nn.relu(Z[1])
    
    for i in range(2,L-1):
        
        Z[i]=tf.matmul(parms['W'+str(i)],A[i-1])+parms['b'+str(i)]
        A[i]=tf.nn.relu(Z[i])
        
    Z[L-1]=tf.matmul(parms['W'+str(L-1)],A[L-2])+parms['b'+str(L-1)]
    
    return Z[L-1]

7、损失函数

在Tensorflow中,计算损失值可以直接用:

cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits= ... ,labels= ... ))

#损失函数
'''
函数功能:计算损失值
输入:ZL:最后一层的线性输出,Y:训练集的标签
输出:cost:损失值
'''   
def cost_function(ZL,Y):
    
    logit=tf.transpose(ZL) #转置
    label=tf.transpose(Y)
    
    cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logit,labels=label))
   
    return cost

 8、反向传播与优化

在Tensorflow中,优化不需要通过迭代去一步步更新w和b,直接选用自己需要的优化器直接通过一行代码即可实现优化,所以也不需要一步步求导,在这里我们选用Adam优化器进行优化:

#反向传播,利用Adam优化
optimizier=tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

9、模型

#模型
'''
函数功能:构造整个训练与测试模型
输入:train_x:训练集,train_y:训练集标签,test_x:测试集,test_y:测试集标签
     learning_rate:学习速率,iterations:迭代次数,mini_batch_size:分割数据的大小
     print_flag:是否打印损失值,is_plot:是否绘制损失值
输出:parms:更新好的w和b值
'''    
def model(train_x,train_y,test_x,test_y,learning_rate=0.0001,iterations=1500,
          mini_batch_size=32,print_flag=False,is_plot=False):
    
    ops.reset_default_graph() #能够重新运行而不覆盖tf变量
    
    tf.set_random_seed(1)
    
    seed=3
    
    (n_x,m)=train_x.shape
    n_y=train_y.shape[0]
    net_dims={0:n_x,1:25,2:12,3:6}
    costs=[]
    
    #给X和Y创建placeholders
    X,Y=crate_placeholders(n_x,n_y)
    
    #初始化w和b参数
    parms=init_w_b(net_dims)
    
    #前向传播
    ZL=forward(X,parms,net_dims)
    
    #计算损失值
    cost=cost_function(ZL,Y)
    
    #反向传播,利用Adam优化
    optimizier=tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
    
    #初始化所有的变量
    init=tf.global_variables_initializer()
    
    #开启会话并计算
    with tf.Session() as sess:
        #初始化
        sess.run(init)
        
        #训练更新
        for i in range(iterations):
            
            epoch_cost=0
            num=int(m/mini_batch_size)
            seed+=1
            mini_batches=random_mini_batches(train_x,train_y,mini_batch_size,seed)
            
            for mini_batch in mini_batches:
                
                #选择一个mini_batch
                (mini_x_batch,mini_y_batch)=mini_batch
                
                #数据已准备好,开始运行sess
                _,mini_batch_cost=sess.run([optimizier,cost],feed_dict={X:mini_x_batch,Y:mini_y_batch})
                
                #计算这一个mini_batch在这一代中所占的误差
                epoch_cost=epoch_cost+mini_batch_cost/num
                
            if i%5==0:
                costs.append(epoch_cost)
                
            if (print_flag) and (i%100==0):
                
                print('epoch=%d,epoch cost=%f'% (i,epoch_cost))
                
        if is_plot:
            
            plt.plot(np.squeeze(costs))
            plt.ylabel('cost')
            plt.xlabel('iterations (per tens)')
            plt.title('learning rate='+str(learning_rate))
          
        parms=sess.run(parms)
        
        #计算当前预测结果
        predict_y=tf.equal(tf.argmax(ZL),tf.argmax(Y))
        
        #计算准确性
        accuracy=tf.reduce_mean(tf.cast(predict_y,'float'))
        
        print('训练集的准确性:',accuracy.eval({X:train_x,Y:train_y}))
        print('测试集准确性:',accuracy.eval({X:test_x,Y:test_y}))
        
    return parms

10、结果与测试

train_x,train_y,test_x,test_y,classes=load_datasets()

#开始时间
start_time = time.clock()
#开始训练
parameters = model(train_x, train_y, test_x, test_y,print_flag=True,is_plot=True)
#结束时间
end_time = time.clock()
#计算时差
print("CPU的执行时间 = " + str(end_time - start_time) + " 秒" )

train_x_shape: (12288, 1080)
train_y_shape: (6, 1080)
test_x_shape: (12288, 120)
test_y_shape: (6, 120)
epoch=0,epoch cost=1.855702
epoch=100,epoch cost=1.017255
epoch=200,epoch cost=0.733184
epoch=300,epoch cost=0.573071
epoch=400,epoch cost=0.468573
epoch=500,epoch cost=0.381228
epoch=600,epoch cost=0.313815
epoch=700,epoch cost=0.253708
epoch=800,epoch cost=0.203900
epoch=900,epoch cost=0.166454
epoch=1000,epoch cost=0.146636
epoch=1100,epoch cost=0.107279
epoch=1200,epoch cost=0.086698
epoch=1300,epoch cost=0.059342
epoch=1400,epoch cost=0.052289
训练集的准确性: 0.9990741
测试集准确性: 0.725
CPU的执行时间 = 335.2098427000001 秒

                                                                                    图1 迭代次数与损失值关系

  • 4
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烊萌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值