北京大学人工智能实践(2)

一、基于tensorflow的NN

——定义:用张量表示数据,用计算图搭建神经网络,用会话执行计算图,优化线上的权 重(参数),得到模型

——张量(tensor):多维数组(列表)
0阶张量称作标量,表示一个单独的数;

举例 S=123

1阶张量称作向量,表示一个一维数组
举例 V=[1,2,3]

2阶张量称作矩阵,表示一个二维数组,它可以有i行j列个元素,每个元素可以用行号和列号共同索引到;
举例 m=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

判断张量是几阶的,就通过张量右边的方括号数,0个是0阶,n个是n阶,张量可以表示0阶到n阶数组(列表);
举例 t=[ [ [… ] ] ]为3阶。

在这里插入图片描述

——:张量的维数

——数据类型:Tensorflow的数据类型有tf.float32、tf.int32等。

实现Tensorflow的加法

#引入模块
import tensorflow as tf
#定义一个张量等于[1.0,2.0]
a=tf.constant([1.0,2.0])
#定义一个张量等于[3.0,4.0]
b=tf.constant([3.0,4.0])
#实现a加b的加法 
result=a+b
#打印出结果 可以打印出这样一句话:
#Tensor(“add:0”, shape=(2, ), dtype=float32)
#意思为result是一个名称为add:0的张量,shape=(2,)表示一维数组长度为2,dtype=float32表示数据类型为浮点型。 
print result

——计算图(Graph):搭建神经网络的计算过程,是承载一个或多个计算节点的一张图,只搭建网络,不运算。
在这里插入图片描述
x1、x2表示输入,w1、w2分别是x1到y和x2到y的权重,y=x1w1+x2w2。

#引入模块
import tensorflow as tf

#定义一个2阶张量等于[[1.0,2.0]]  (一行两列)
x = tf.constant([[1.0, 2.0]])    

#定义一个2阶张量等于[[3.0],[4.0]]  (两行一列)
w = tf.constant([[3.0], [4.0]])    (一行一列的张量)

#实现xw矩阵乘法
y=tf.matmul(x,w)

#打印出结果 可以打印出这样一句话:Tensor(“matmul:0”, shape(1,1), dtype=float32),
print y

#执行会话并打印出执行后的结果 

#可以打印出这样的结果:[[11.]] 
with tf.Session() as sess:
    print sess.run(y)

print的结果显示y是一个张量,只搭建承载计算过程的计算图,并没有运算,如果我们想得到运算结果就要用到“会话Session()”了。

——会话(Session):执行计算图中的节点运算。我们用with结构实现

with tf.Session() as sess:
    print sess.run(y)

在vim编辑器中运行Session()会话时,有时会出现“提示warning”,是因为有的电脑可以支持加速指令,但是运行代码时并没有启动这些指令。可以把这些“提示warning”暂时屏蔽掉。屏蔽方法为进入主目录下的bashrc文件,在bashrc 文件中加入这样一句 export TF_CPP_MIN_LOG_LEVEL=2,从而把“提示 warning”等级降低。source 命令用于重新执行修改的初始化文件,使之立即生效,而不必注销并重新登录。

vim ~/.bashrc

source ~/.bashrc

——参数
即神经网络线上的权重w,用变量表示,随机给初值

生成参数的方法是让w等于tf.Variable,把生成的方式写在括号里。

w= tf.Variable(tf.random_normal([2,3],stddev=2,mean=0,seed=1))

在这里插入图片描述
注意:

1、随机种子如果去掉每次生成的随机数将不一致。
2、如果没有特殊要求标准差、均值、随机种子是可以不写的

在这里插入图片描述


二、神经网络实现过程

当我们知道张量、计算图、会话和参数后,我们可以讨论神经网络的实现过程了。

(步骤1~3是训练过程 步骤4是使用过程)

1、准备数据集,提取特征,作为输入喂给神经网络(Neural Network,NN)

2、搭建NN结构,从输入到输出(先搭建计算图,再用会话执行)

   ( NN前向传播算法 -----> 计算输出) 

3、大量特征数据喂给NN,迭代优化NN参数

   ( NN反向传播算法 -----> 优化参数训练模型)

4、使用训练好的模型预测和分类

由此可见,基于神经网络的机器学习主要分为两个过程,即训练过程和使用过程。

训练过程是第一步、第二步、第三步的循环迭代,使用过程是第四步,一旦参数优化完成就可以固定这些参数,实现特定应用了。很多实际应用中,我们会先使用现有的成熟网络结构,喂入新的数据,训练相应模型,判断是否能对喂入的从未见过的新数据作出正确响应,再适当更改网络结构,反复迭代,让机器自动训练参数找出最优结构和参数,以固定专用模型。

三、前向传播:

搭建神经网络模型,让神经网络NN实现推理过程
在这里插入图片描述

这块引用拿来详细讲解下上图的前向传播例子:

Eg NN:生产一批零件,将体积x1和重量x2位特征,把它们喂入神经网络,当体积和重量这组数据输入神经网络后会得到一个输出。

Input:以输入的特征值是:体积0.7 重量0.5为例。

Output:由搭建的神经网络可得,隐藏层节点a11=x1w11+x2w21=0.14+0.15=0.29,同理算得节点a12=0.32,a13=0.38,最终计算得到输出层Y=-0.015,这便实现了前向传播过程。

推导

神经网络共有几层(或当前是第几层网络)都是指的计算层,输入层不是计算层,所以a为第一层网络,第一层 X是输入为1X2矩阵 用x表示输入,是一个1行2列矩阵,表示一次输入一组特征,这组特征包含了 体积和重量两个元素。

W 前节点编号,后节点编号(层数) 为待优化的参数
对于第一层的w 前面有两个节点,后面有三个节点 w应该是个两行三列矩阵,
我们这样表示:
在这里插入图片描述
所以a为第一层网络,a是一个一行三列矩阵。
我们这样表示:a(1)=[a11, a12, a13]=XW(1)
第二层参数要满足前面三个节点,后面一个节点,所以W(2) 是三行一列矩阵。 我们这样表示:
在这里插入图片描述

输入层:

x是输入为1X2矩阵;表示一次输入一组特征,这组特征包含了 “体积” 和 “重量” 两个元素。
下编号(节点),上编号(层数) 为待优化的参数

参数w的确定:

输入层到第一层,参数要满足前面两个节点,后面三个节点 ;因此应该是个两行三列矩阵2x3;运算后得到的a是一个一行三列矩阵1x3。
第一层到输出层,参数要满足前面三个节
点,后面一个节点;所以 是三行一列矩阵3x1。 隐藏层:
隐藏层的计算;我们把每层输入与线上的权重进行矩阵乘法,这样用矩阵乘法可以计算出输出y了。
a= tf.matmul(X,)
y= tf.matmul(a, )

输出层:

想要输出结果,就需要用到Session会话,利用with结构来实现。把所有的所有变量初始化过程、计算过程都要放到 sess.run 函数中 前向传播就是搭建模型的计算过程,让模型具有推理能力,可以针对输入给出相应的输出。

①用placeholder实现输入定义(sess.run中喂入一组数据)的情况 第一组喂体积0.7、重量0.5

 #coding:utf-8
    #两层简单神经网络(全连接)
    
    import tensorflow as tf
    #定义输入和参数
    
    #用placeholder实现输入定义 (sess.run中喂一组数据)
    x = tf.placeholder(tf.float32, shape=(1, 2))    (一行两列)
    w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
    w2= tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
     
    #定义前向传播过程
    a = tf.matmul(x, w1)
    y = tf.matmul(a, w2)
     
    #用会话计算结果
    with tf.Session() as sess:
        init_op = tf.global_variables_initializer()
        sess.run(init_op)       (执行计算)
        print "y in tf3_4.py is:\n" , sess.run(y, feed_dict={x: [[0.7,0.5]]}) 将x的一组特征喂入)

`

②用placeholder实现输入定义(sess.run中喂入多组数据)的情况第一组喂体积0.7、重量0.5,第二组喂体积0.2、重量0.3,第三组喂体积0.3 、重量0.4,第四组喂体积0.4、重量0.5.

#coding:utf-8
#两层简单神经网络(全连接)
import tensorflow as tf
#定义输入和参数
#用placeholder定义输入(sess.run喂多组数据)(不知道喂入多少组,shap的第一个参数为none)
x = tf.placeholder(tf.float32, shape=(None, 2))   
w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
w2= tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
 
#定义前向传播过程
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
 
#调用会话计算结果
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()  
    sess.run(init_op)
    print "the result of tf3_5.py is:\n",sess.run(y, feed_dict={x: [[0.7,0.5],[0.2,0.3],[0.3,0.4],[0.4,0.5]]})
    print "w1:\n", sess.run(w1)
    print "w2:\n", sess.run(w2)

以输入的特征值是:体积0.7 重量0.5 的例子的实现整体代码如下

#!/user/bin/env python3
# -*- coding: utf-8 -*-
# 定义两层简单神经网络(全连接)
 
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
 
#导入TensorFlow模块,并简写为tf
import tensorflow as tf
 
# 定义神经网络的输入和神经元上的参数权重
x = tf.constant([[0.7,0.5]]) #定义体积为0.7 重量为0.5
w1 = tf.Variable(tf.random_normal([2,3],stddev=1,seed=1)) #定义一个2x3随机矩阵作为w1参数
w2 = tf.Variable(tf.random_normal([3,1],stddev=1,seed=1)) #定义一个3x1随机矩阵作为w2参数
 
# 定义前向传播过程
a = tf.matmul(x,w1)
y = tf.matmul(a,w2)

# 到此为止 神经网络创建完成
 
#用会话Session来计算结果
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()          (i把初始化所有的函数,简写为初始化为节点nit_op)
    sess.run(init_op)        
    print(sess.run(y))
 
'''
[[ 3.0904665]]
'''

这条引用拿来归纳TensorFlow神经网络的几个基本点:

在 TensorFlow 中,数据不是以整数、浮点数或者字符串形式存储的。这些值被封装在一个叫做 tensor的对象中;tf.constant 返回的 tensor 是一个常量 tensor,因为这个 tensor 的值不会变

  • 操作(Op/operation):在 TensorFlow 的运行时中,它是一种类似 add 或 matmul 或 concat的运算

  • 张量(Tensor):表示数据。Tensor是一种特定的多维数组。每一个tensor值在graph上都是一个op

  • 计算图(Graph):描述运算任务。把运算任务描述成一个直接的无环图形(DAG),图表中的节点(node)代表必须要实现的一些操作。图中的边代表数据或者可控的依赖。

  • 会话(Session):运行Tensorflow操作的类,Session 提供在图中执行操作的一些方法。Session封装了被执行操作和Tensor计算的环境,运行session.run()可以获得你要进行运算的结果。启动图的第一步是创建一个Session
    对象。

  • tf.placeholder(dtype,shape=None,name=None) 在实际应用中,我们可以一次喂入一组或多组输入,先用tf.placeholder给输入占位,方便输入的处理。dtype:数据类型,喂给TensorFlow的张量元素的类型;

  • shape:数据形状[x,y];表示有x组输入,y表示每组输入有y个特征。name:名称;返回值:张量Tensor类型

四、反向传播

一、反向传播

反向传播:训练模型参数,在所有参数上用梯度下降,使NN模型在训练数据上的损失函数最小。
损失函数(loss):计算得到的预测值y与已知答案y_的差距

损失函数的计算有很多方法,均方误差MSE是比较常用的方法之一。

均方误差MSE:求前向传播计算结果与已知答案之差的平方再求平均。

  用tensorflow函数表示为: loss_mse =tf.reduce_mean(tf.square(y_ - y))

反向传播训练方法:

以减小loss值为优化目标,有梯度下降、momentum优化器、adam优化器等优化方法。

在TensorFlow中代码表示分别如下:

train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
 
train_step=tf.train.MomentumOptimizer(learning_rate, momentum).minimize(loss)
 
train_step=tf.train.AdamOptimizer(learning_rate).minimize(loss)

学习率:决定参数每次更新的幅度

代码(背)

#加入编码兼容格式utf-8
#coding:utf-8

#0导入模块numpy(python 的科学计算模块),生成模拟数据集。
import tensorflow as tf
import numpy as np

#BATCH一次喂入神经网络多少组数据,seed随机生成
BATCH_SIZE = 8
SEED = 23455
 
#基于seed产生随机数
rdm = np.random.RandomState(SEED)

#随机数返回32行2列的矩阵 表示32组 体积和重量 作为输入数据集
X = rdm.rand(32,2)

#从X这个32行2列的矩阵中 取出一行 判断如果和小于1 给Y赋值1 如果和不小于1 给Y赋值0 

#作为输入数据集的标签(正确答案) 
Y_ = [[int(x0 + x1 < 1)] for (x0, x1) in X]
print "X:\n",X
print "Y_:\n",Y_
 
#1定义神经网络的输入、参数和输出,定义前向传播过程。
x = tf.placeholder(tf.float32, shape=(None, 2))    (输入)
y_= tf.placeholder(tf.float32, shape=(None, 1))  (标准答案)
 
w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))  (对应x)
w2= tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))    (对应y)

#用矩阵乘法实现 
a = tf.matmul(x, w1)   
y = tf.matmul(a, w2)
 
#2定义损失函数loss及反向传播方法。
loss_mse = tf.reduce_mean(tf.square(y-y_))       (使用均方误差计算loss)

#使用梯度下降实现训练过程,学习率为0.001
train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss_mse) 

#train_step = tf.train.MomentumOptimizer(0.001,0.9).minimize(loss_mse)    (Momentum优化方法)
#train_step = tf.train.AdamOptimizer(0.001).minimize(loss_mse)     (Adam优化方法)
 
#3生成会话,训练STEPS轮
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()        (初始化参数)
    sess.run(init_op)
    
    # 输出目前(未经训练)的参数取值。
    print "w1:\n", sess.run(w1)
    print "w2:\n", sess.run(w2)
    print "\n"
    
    # 训练模型。

  #训练三千轮
    STEPS = 3000
    for i in range(STEPS):
        start = (i*BATCH_SIZE) % 32
        end = start + BATCH_SIZE
        # //从x的数据集和y的标签里面抽取相应的数据和标签喂入神经网络,用sess.run执行训练过程
        sess.run(train_step, feed_dict={x: X[start:end], y_: Y_[start:end]})  
        //每500轮打印loss值
        if i % 500 == 0:  
            total_loss = sess.run(loss_mse, feed_dict={x: X, y_: Y_})
            print("After %d training step(s), loss_mse on all data is %g" % (i, total_loss))
    
    # 输出训练(优化后的)后的参数取值。
    print "\n"
    print "w1:\n", sess.run(w1)
    print "w2:\n", sess.run(w2)

由神经网络的实现结果,我们可以看出,总共训练3000轮,每轮从X的数据集 和Y的标签中抽取相对应的从start开始到end结束个特征值和标签,喂入神经网络,用sess.run求出loss,每500轮打印一次loss值。经过3000轮后,我们打印出最终训练好的参数w1、w2。

可以修改BATCH_SIZE 看看对loss的影响,可以训练次数增大来观察loss的减少过程,更改优化器来看看哪一个效果更好

五、搭建神经网络的八股

  1. 准备

  2. 前向传播

  3. 反向传播

  4. 迭代循环

1、准备

import
常量定义
生成或导入数据集

2、前向传播:定义输入、参数以及输出

x=定义输入Input 对应的组数和每组特征数
y_=定义标签Lable 对应的组数和标签特征数

w1=定义输入层到第一层的权重参数 行号要于输入的每组特征数一致
w2=定义第一层到输出层的权重参数 列号要于输出的标签特征数一致

a=第一层得到的结果 传递给下一层
y=输出层得到的结果

3、反向传播 :定义损失函数、反向传播方法

loss=
train_step=

4、迭代循环:生成会话,迭代训练STEPS轮

with tf.session() as sess
    Init_op=tf. global_variables_initializer()
    sess_run(init_op)  
    STEPS=3000 for i in range(STEPS):
    start=   end=
    sess.run(train_step, feed_dict:) 

`

猜你喜欢

转载自blog.csdn.net/qq_44716817/article/details/89186834