实验环境准备
Anoconda3.7
TensorFlow2.1
PyCharm
安装Anoconda
官网下载安装,勾选添加到环境变量。
安装TensorFlow2.1
1 打开安装好的Anoconda Prompt
2 创建一个环境
1 2 conda create -n TF2.1 python=3.7 y
3 进入新创建的环境
4 安装所需软件
1 2 3 4 5 6 7 # 安装英伟达SDK10.1版本 conda install cudatoolkit=10.1 # 安装英伟达深度学习软件包7.6版本 conda install cudann=7.6 # 以上两条是为了支持N卡GPU,如果报错,暂时跳过 # 安装TensorFlow,指定版本2.1 pip install tensorflow==2.1
5 验证安装
1 2 3 python import tensorflow as tf tf.__version__
安装PyCharm
官网下载安装
新建工程
打开PyCharm,新建工程,添加创建好的环境TF2.1
右键工程文件夹选择在文件管理器中打开(open in explorer)
将课程代码拷贝进入工程目录
神经网络计算
本讲目标:学会神经网络计算过程,使用基于TF2原生代码搭建你的第一个的神经网络训练模型
当今人工智能主流方向——连接主义
前向传播
损失函数(初体会)
梯度下降(初体会)
学习率(初体会)
反向传播更新参数
Tensorflow2 常用函数
1.1 人工智能三学派
人工智能:让机器具备人的思维和意识。
人工智能三学派:
行为主义:基于控制论,构建感知-动作控制系统。
(控制论,如平衡、行走、避障等自适应控制系统)
符号主义:基于算数逻辑表达式,求解问题时先把问题描述为表达式,再求解表达式。
(可用公式描述、实现理性思维,如专家系统)
连接主义:仿生学,模仿神经元连接关系。本课重点
(仿脑神经元连接,实现感性思维,如神经网络)
1.2 基于连结主义的神经网络设计过程
用计算机仿出神经网络连接关系,让计算机具备感性思维。
准备数据:采集大量“特征/标签”数据
搭建网络:搭建神经网络结构
优化参数:训练网络获取最佳参数(反传)
应用网络:将网络保存为模型,输入新数据,输出分类或预测结果(前传)
1.3 TF2
TensorFlow2
2019年3 月Tensorflow2.0 测试版发布
2019年10月Tensorflow2.0 正式版发布
2020年1 月Tensorflow2.1 发布
张量
张量(Tensor):多维数组(列表)阶:张量的维数
维数
阶
名字
例子
0-D
0
标量 scalar
s=123
1-D
1
向量 vector
v=[1,2,3]
2-D
2
矩阵 matrix
m=[[1,2,3],[4,5,6],[7,8,9]]
3-D
n
张量 tensor
t=[[[…]]]
数据类型
tf.int, tf.float……
tf.int 32, tf.float32, tf.float64
tf.bool
tf.constant([True, False])
tf.string
tf.constant(“Hello, world!”)
如何创建一个Tensor
tf创建一个张量
tf.constant(张量内容,dtype=数据类型(可选))
1 2 3 4 5 import tensorflowas tfa=tf.constant([1 ,5 ],dtype=tf.int64) print (a)print (a.dtype)print (a.shape)
将numpy的数据类型转换为Tensor数据类型
tf. convert_to_tensor(数据名,dtype=数据类型(可选))
1 2 3 4 5 6 import tensorflowas tfimport numpyas npa = np.arange(0 , 5 ) b = tf.convert_to_tensor( a, dtype=tf.int64 ) print (a)print (b)
1 2 3 4 5 6 7 8 9 10 11 12 ''' 维度: 一维直接写个数 二维用[行,列] 多维用[n,m,j,k……] ''' a = tf.zeros([2 , 3 ]) b = tf.ones(4 ) c = tf.fill([2 , 2 ], 9 ) print (a)print (b)print (c)
生成正态分布的随机数,默认均值为0,标准差为1
tf. random.normal(维度,mean=均值,stddev=标准差)
生成截断式正态分布的随机数
tf. random.truncated_normal (维度,mean=均值,stddev=标准差)
在tf.truncated_normal中如果随机生成数据的取值在(μ-2σ,μ+2σ)之外则重新进行生成,保证了生成值在均值附近。
μ:均值,σ:标准差
1 2 3 4 d = tf.random.normal([2 , 2 ], mean=0.5 , stddev=1 ) print (d)e = tf.random.truncated_normal([2 , 2 ], mean=0.5 , stddev=1 ) print (e)
生成均匀分布随机数[ minval, maxval)
tf. random. uniform(维度,minval=最小值,maxval=最大值)
1 2 f = tf.random.uniform([2 , 2 ], minval=0 , maxval=1 ) print (f)
1.4 TF2常用函数
tf.cast(张量名,dtype=数据类型)
tf.reduce_min(张量名)
tf.reduce_max(张量名)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 x1 = tf.constant([1. , 2. , 3. ],dtype=tf.float64) print (x1)x2 = tf.cast(x1, tf.int32) print (x2)print (tf.reduce_min(x2), tf.reduce_max(x2))''' 理解axis 在一个二维张量或数组中,可以通过调整 axis 等于0或1 控制执行维度。 axis=0代表跨行(经度,down),而axis=1代表跨列(纬度,across) 如果不指定axis,则所有元素参与计算。 '''
tf.reduce_mean(张量名,axis=操作轴)
tf.reduce_sum(张量名,axis=操作轴)
1 2 3 4 x=tf.constant( [ [ 1 , 2 , 3 ],[ 2 , 2 , 3 ] ] ) print (x)print (tf.reduce_mean( x ))print (tf.reduce_sum( x, axis=1 ))
tf.Variable() 将变量标记为“可训练”,被标记的变量会在反向传播中记录梯度信息。神经网络训练中,常用该函数标记待训练参数。
tf.Variable(初始值)
w = tf.Variable(tf.random.normal([2, 2], mean=0, stddev=1))
TensorFlow中的数学运算
对应元素的四则运算:tf.add,tf.subtract,tf.multiply,tf.divide
只有维度相同的张量才可以做四则运算
1 2 3 4 5 6 7 8 a = tf.ones([1 , 3 ]) b = tf.fill([1 , 3 ], 3. ) print (a)print (b)print (tf.add(a,b))print (tf.subtract(a,b))print (tf.multiply(a,b))print (tf.divide(b,a))
平方、次方与开方: tf.square,tf.pow,tf.sqrt
1 2 3 4 5 a = tf.fill([1 , 2 ], 3. ) print (a)print (tf.pow (a, 3 ))print (tf.square(a))print (tf.sqrt(a))
1 2 3 4 5 6 ''' tf.matmul(矩阵1,矩阵2) ''' a = tf.ones([3 , 2 ]) b = tf.fill([2 , 3 ], 3. ) print (tf.matmul(a, b))
tf.data.Dataset.from_tensor_slices
1 2 3 4 5 6 7 8 9 10 11 12 ''' 切分传入张量的第一维度,生成输入特征/标签对,构建数据集 data = tf.data.Dataset.from_tensor_slices((输入特征, 标签)) (Numpy和Tensor格式都可用该语句读入数据) ''' features = tf.constant([12 ,23 ,10 ,17 ]) labels = tf.constant([0 , 1 , 1 , 0 ]) dataset = tf.data.Dataset.from_tensor_slices((features, labels)) print (dataset)for element in dataset: print (element)
1 2 3 4 5 6 7 8 9 10 11 ''' with结构记录计算过程,gradient求出张量的梯度 with tf.GradientTape( ) as tape: 若干个计算过程 grad=tape.gradient(函数,对谁求导) ''' with tf.GradientTape( ) as tape: w = tf.Variable(tf.constant(3.0 )) loss = tf.pow (w,2 ) grad = tape.gradient(loss,w) print (grad)
1 2 3 4 5 6 7 8 9 ''' enumerate是python的内建函数,它可遍历每个元素(如列表、元组 或字符串),组合为:索引 元素,常在for循环中使用。 enumerate(列表名) ''' seq = ['one' , 'two' , 'three' ] for i, element in enumerate (seq): print (i, element)
1 2 3 4 5 6 7 8 9 10 ''' 独热编码(one-hot encoding):在分类问题中,常用独热码做标签,标记类别:1表示是,0表示非. tf.one_hot (待转换数据, depth=几分类) ''' classes = 3 labels = tf.constant([1 ,0 ,2 ]) output = tf.one_hot( labels, depth=classes ) print (output)
1 2 3 4 5 6 ''' tf.nn.softmax(x) 使输出符合概率分布 ''' y = tf.constant ( [1.01 , 2.01 , -0.66 ] ) y_pro = tf.nn.softmax(y) print ("After softmax, y_pro is:" , y_pro)
1 2 3 4 5 6 7 8 ''' 赋值操作,更新参数的值并返回。 调用assign_sub前,先用 tf.Variable 定义变量 w 为可训练(可自更新)。 w.assign_sub (w要自减的内容) ''' w = tf.Variable(4 ) w.assign_sub(1 ) print (w)
1 2 3 4 5 6 7 8 ''' 返回张量沿指定维度最大值的索引tf.argmax (张量名,axis=操作轴) ''' import numpy as nptest = np.array([[1 , 2 , 3 ], [2 , 3 , 4 ], [5 , 4 , 3 ], [8 , 7 , 2 ]]) print (test)print ( tf.argmax (test, axis=0 )) print ( tf.argmax (test, axis=1 ))
1.5 神经网络实现鸢尾花分类
数据集介绍
共有数据150组,每组包括花萼长、花萼宽、花瓣长、花瓣宽4个输入特征。同时给出了,这一组特征对应的鸢尾花类别。类别包括Setosa Iris(狗尾草鸢尾),Versicolour Iris(杂色鸢尾),Virginica Iris(弗吉尼亚鸢尾)三类,分别用数字0,1,2表示。
准备数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from sklearn.datasets import datasetsx_data = datasets.load_iris().data 返回iris数据集所有输入特征 y_data = datasets.load_iris().target 返回iris数据集所有标签 np.random.seed(116 ) np.random.shuffle(x_data) np.random.seed(116 ) np.random.shuffle(y_data) tf.random.set_seed(116 ) x_train = x_data[:-30 ] y_train = y_data[:-30 ] x_test = x_data[-30 :] y_test = y_data[-30 :] train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32 ) test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32 )
搭建网络
1 2 3 4 w1 = tf.Variable(tf.random.truncated_normal([ 4 , 3 ], stddev=0.1 , seed=1 )) b1 = tf.Variable(tf.random.truncated_normal([ 3 ], stddev=0.1 , seed=1 ))
参数优化
1 2 3 4 5 6 7 8 9 10 for epoch in range (epoch): for step, (x_train, y_train) in enumerate (train_db): with tf.GradientTape() as tape: 前向传播过程计算y 计算总loss grads = tape.gradient(loss, [ w1, b1 ]) w1.assign_sub(lr * grads[0 ]) b1.assign_sub(lr * grads[1 ]) print ("Epoch {}, loss: {}" .format (epoch, loss_all/4 ))
测试效果
1 2 3 4 5 6 7 8 9 10 11 12 for x_test, y_test in test_db:y = tf.matmul(h, w) + b y = tf.nn.softmax(y) pred = tf.argmax(y, axis=1 ) pred = tf.cast(pred, dtype=y_test.dtype) correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32) correct = tf.reduce_sum (correct) total_correct += int (correct) total_number += x_test.shape [0 ] acc = total_correct / total_number print ("test_acc:" , acc)
acc/loss可视化
1 2 3 4 5 6 7 plt.title('Acc Curve' ) plt.xlabel('Epoch' ) plt.ylabel('Acc' ) plt.plot(test_acc, label="$Accuracy$" ) plt.legend() plt.show()