课程简介
课程链接: https://www.bilibili.com/video/BV1B7411L7Qt
主讲老师: 北京大学软件与微电子学院曹健老师
源代码: https://pan.baidu.com/s/19XC28Hz_TwnSQeuVifg1UQ 提取码:mocm
0. 开篇----Tensorflow2.1.0 安装及测试
Tensorflow2.1.0安装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 conda create --name TF2.1 python=3.7 conda activate TF2.1 conda install cudatoolkit=10.1 conda install cudnn=7.6 pip install tensorflow==2.1 python >>> import tensorflow as tf>>> tf.__version__'2.1.0'
配置Pycharm
略
测试代码
1 2 3 4 5 6 7 8 9 10 11 import tensorflow as tftensorflow_version = tf.__version__ gpu_available = tf.test.is_gpu_available() print ("tensorflow version:" , tensorflow_version, "\tGPU available:" , gpu_available)a = tf.constant([1.0 , 2.0 ], name="a" ) b = tf.constant([1.0 , 2.0 ], name="b" ) result = tf.add(a, b, name="add" ) print (result)
若返回下面的代码, 则说明配置成功
1 tf.Tensor([2. 4. ], shape=(2 ,), dtype=float32)
测试报错
1 RuntimeError: cudaGetDevice() failed. Status: CUDA driver version is insufficient for CUDA runtime version
报错原因
CUDA驱动版本不适合CUDA运行时版本
输入nvidia-smi
查看驱动版本, 在虚拟环境中输入conda list cuda
查看cudatoolkit
的版本号
在英伟达GPU驱动和CUDA的版本对应关系 中查看对应的版本号
解决方案1——降低cuda的版本
参考博客tensorflow的CUDA driver version is insufficient for CUDA runtime version 问题解决方案
解决方案2——升级nvidia显卡驱动
查看显卡型号, Win
+R
, 输入dxdiag
, 在display
中查看显卡型号
此电脑的显卡型号为NVIDA GeForce GTX 1060
在InVidia GeForce Drivers 中下载对应版本的显卡驱动并安装
1.1 人工智能三学派
1.2 神经网络设计过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import tensorflow as tfw = tf.Variable(tf.constant(5 , dtype=tf.float32)) lr = 0.2 epoch = 40 for epoch in range (epoch): with tf.GradientTape() as tape: loss = tf.square(w + 1 ) grads = tape.gradient(loss, w) w.assign_sub(lr * grads) print ("After %s epoch,w is %f,loss is %f" % (epoch, w.numpy(), loss))
1.3 张量的生成
Tensorflow的数据类型
tf.int
: tf.int32
tf.float
: tf.float32
, tf.float64
tf.bool
: tf.constant([True,False])
tf.string
: tf.constant("Hello,world!")
创建一个Tensor
1 tf.constant(张量内容, dtype=数据类型(可选参数))
1 2 3 4 5 6 import tensorflow as tfa = tf.constant([1 , 5 ], dtype=tf.int64) print (a)print (a.dtype)print (a.shape)
1 2 3 4 tf.Tensor([1 5 ], shape=(2 ,), dtype=int64) <dtype: 'int64' > (2 ,)
将Numpy数据类型转换为Tensor数据类型
1 tf.convert_to_tensor(数据名, dtype=数据类型(可选参数))
1 2 3 4 5 6 import tensorflow as tfimport numpy as npa = np.arange(0 ,5 ) b = tf.convert_to_tensor(a, dtype=tf.int64) print (a)print (b)
1 2 3 [0 1 2 3 4 ] tf.Tensor([0 1 2 3 4 ], shape=(5 ,), dtype=int64)
创建指定值的Tensor
1 2 3 4 5 6 7 import tensorflow as tfa = tf.zeros([2 ,3 ]) b = tf.ones(4 ) c = tf.fill([2 ,2 ],9 ) print (a)print (b)print (c)
1 2 3 4 5 6 7 8 9 10 tf.Tensor( [[0. 0. 0. ] [0. 0. 0. ]], shape=(2 , 3 ), dtype=float32) tf.Tensor([1. 1. 1. 1. ], shape=(4 ,), dtype=float32) tf.Tensor( [[9 9 ] [9 9 ]], shape=(2 , 2 ), dtype=int32)
生成正太分布的随机数
创建正太分布的随机数, 默认均值为0, 标准差为1
1 tf.random.normal(维度, mean=均值, stddev=标准差, dtype=数据类型)
1 tf.random.truncated_normal(维度, mean=均值, stddev=标准差)
生成的值服从具有指定平均值和标准偏差的正态分布, 如果生成的值大于平均值2个标准偏差的值则丢弃重新选择, 即落在( μ − 2 σ , μ + 2 σ ) (\mu-2\sigma,\mu+2\sigma) ( μ − 2 σ , μ + 2 σ ) 之外的数据会被丢弃, 保证生成的值在均值附近.
3 σ 3\sigma 3 σ 原则
横轴区间(μ-σ,μ+σ)内的概率为68.268949%。
横轴区间(μ-2σ,μ+2σ)内的概率为95.449974%。
横轴区间(μ-3σ,μ+3σ)内的概率为99.730020%。
1 2 d = tf.random.normal([2 , 2 ], mean=0.5 , stddev=1 ) print (d)
1 2 3 4 tf.Tensor( [[ 0.30043095 0.7326505 ] [-0.86194825 0.5580075 ]], shape=(2 , 2 ), dtype=float32)
1 2 e = tf.random.truncated_normal([2 , 2 ], mean=0.5 , stddev=1 ) print (e)
1 2 3 4 tf.Tensor( [[ 1.0384454 0.40930927 ] [-0.28229052 -0.44121146 ]], shape=(2 , 2 ), dtype=float32)
生成均匀分布的随机数
1 tf.random.uniform(维度, minval=最小值, maxval=最大值, dtype=数据类型)
1 2 f = tf.random.uniform([2 ,3 ], minval=0 , maxval=1 ) print (f)
1 2 3 4 tf.Tensor( [[0.78726804 0.81395364 0.9172931 ] [0.7733567 0.35996556 0.23103678 ]], shape=(2 , 3 ), dtype=float32)
1.4 常用函数1
强制类型转换和最大最小值
1 tf.cast(张量名, dtype=数据类型)
1 2 3 4 5 6 7 8 x1 = tf.random.uniform([2 , 3 ], minval=0 , maxval=100 , dtype=tf.float64) print (x1)x2 = tf.cast(x1, tf.int32) print (x2)print (tf.reduce_min(x2))print (tf.reduce_max(x2))
1 2 3 4 5 6 7 8 9 10 11 tf.Tensor( [[64.38174971 13.3164515 77.12602053 ] [70.67317952 83.79160795 52.05179418 ]], shape=(2 , 3 ), dtype=float64) tf.Tensor( [[64 13 77 ] [70 83 52 ]], shape=(2 , 3 ), dtype=int32) tf.Tensor(13 , shape=(), dtype=int32) tf.Tensor(83 , shape=(), dtype=int32)
理解axis
axis = 0
是对第一个维度进行操作
axis = 1
是对第二个维度进行操作
不指定默认是对所有元素进行操作
1 tf.reduce_mean(张量名, axis=维度)
1 tf.reduce_sum(张量名, axis=维度)
1 2 3 4 5 6 7 8 9 10 11 x = tf.constant( [[[1 , 2 , 3 , 4 ], [2 , 2 , 3 , 5 ], [3 , 4 , 5 , 6 ]], [[4 , 5 , 6 , 7 ], [5 , 6 , 7 , 8 ], [6 , 7 , 8 , 9 ]]]) print (x)print (tf.reduce_mean(x))print (tf.reduce_sum(x, axis=1 ))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 tf.Tensor( [[[1 2 3 4 ] [2 2 3 5 ] [3 4 5 6 ]] [[4 5 6 7 ] [5 6 7 8 ] [6 7 8 9 ]]], shape=(2 , 3 , 4 ), dtype=int32) tf.Tensor(4 , shape=(), dtype=int32) tf.Tensor( [[ 6 8 11 15 ] [15 18 21 24 ]], shape=(2 , 4 ), dtype=int32)
tf.Variable
tf.Variavle()
将变量标记为"可训练", 被标记的变量会在反向传播中记录梯度信息. 神经网络训练中, 常用该函数标记待训练的参数.
1 2 w = tf.Variable(tf.random.normal([2 , 2 ], mean=0 , stddev=1 ))
数学运算
注意: 只有维度相同的元素才能进行四则运算
1 2 3 4 5 6 7 8 tf.add(张量1 , 张量2 ) tf.subtract(张量1 , 张量2 ) tf.multiply(张量1 , 张量2 ) tf.divide(张量1 , 张量2 )
1 2 3 4 5 6 tf.square(张量名) tf.sqrt(张量名) tf.pow (张量名, n次方数)
注意: 参与运算的两个矩阵的维度要符合矩阵乘法的规则
读入数据
切分传入张量的第一维度, 生成输入( 特征 , 标签 ) (特征, 标签) ( 特征 , 标签 ) 对, 构建数据集
(Numpy和Tensor格式都可用该语句读入数据)
1 data = tf.data.Dataset.from_tensor_slices((输入特征, 标签))
1 2 3 4 5 6 7 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 <TensorSliceDataset shapes: ((), ()), types: (tf.int32, tf.int32)> (<tf.Tensor: shape=(), dtype=int32, numpy=12 >, <tf.Tensor: shape=(), dtype=int32, numpy=0 >) (<tf.Tensor: shape=(), dtype=int32, numpy=23 >, <tf.Tensor: shape=(), dtype=int32, numpy=1 >) (<tf.Tensor: shape=(), dtype=int32, numpy=10 >, <tf.Tensor: shape=(), dtype=int32, numpy=1 >) (<tf.Tensor: shape=(), dtype=int32, numpy=17 >, <tf.Tensor: shape=(), dtype=int32, numpy=0 >)
1.5 常用函数2
tf.GradientTape()
with结构记录计算过程, gradient求出张量的梯度
1 2 3 with tf.GradientTape() as tape: 若干计算过程 grad=tape.gradient(函数, 对谁求导)
∂ w 2 ∂ w = 2 w \frac{\partial w^2}{\partial w} = 2w
∂ w ∂ w 2 = 2 w
1 2 3 4 5 6 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 tf.Tensor(6.0 , shape=(), dtype=float32)
enumerate()
enumerate是python的内建函数, 它可遍历每个元素(如列表, 元组, 或字符串), 组合为: 索引 元素, 常在for循环中使用.
1 2 3 seq = ['one' , 'two' , 'three' ] for i, element in enumerate (seq): print (i, element)
tf.one_hot()
独热编码(one-hot encoding): 在分类问题中, 常用独热码做标签, 标记类别1/0
tf.one_hot()
将待转换数据转换为one-hot形式的数据输出.
1 tf.one_hot(待转换数据, depth=几分类)
1 2 3 4 5 6 classes = 3 labels = tf.constant([1 , 0 , 2 ]) output = tf.one_hot(labels, depth=classes) print (output)
1 2 3 4 5 tf.Tensor( [[0. 1. 0. ] [1. 0. 0. ] [0. 0. 1. ]], shape=(3 , 3 ), dtype=float32)
tf.nn.softmax()
tf.nn.softmax
函数使输出符合概率分布
y = { 1.01 2.01 − 0.66 s o f t m a x ( y ) = { e y 0 e y 0 + e y 1 + e y 2 = 2.75 10.73 = 0.256 e y 1 e y 0 + e y 1 + e y 2 = 7.46 10.73 = 0.695 e y 2 e y 0 + e y 1 + e y 2 = 0.52 10.73 = 0.048 y=
\begin{cases}
1.01 \\ 2.01 \\ -0.66
\end{cases}
\qquad
softmax(y) =
\begin{cases}
\frac{e^{y_0}}{e^{y_0}+e^{y_1}+e^{y_2}} = \frac{2.75}{10.73} = 0.256\\
\frac{e^{y_1}}{e^{y_0}+e^{y_1}+e^{y_2}} = \frac{7.46}{10.73} = 0.695\\
\frac{e^{y_2}}{e^{y_0}+e^{y_1}+e^{y_2}} = \frac{0.52}{10.73} = 0.048\\
\end{cases}
y = ⎩ ⎨ ⎧ 1.01 2.01 − 0.66 so f t ma x ( y ) = ⎩ ⎨ ⎧ e y 0 + e y 1 + e y 2 e y 0 = 10.73 2.75 = 0.256 e y 0 + e y 1 + e y 2 e y 1 = 10.73 7.46 = 0.695 e y 0 + e y 1 + e y 2 e y 2 = 10.73 0.52 = 0.048
1 2 3 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 After softmax, y_pro is : tf.Tensor([0.25598174 0.69583046 0.0481878 ], shape=(3 ,), dtype=float32)
assign_sub()
赋值操作, 更新参数的值并返回.
调用assign_sub
前, 先用tf.Variable
定义变量w
为可训练(可自更新)
1 2 3 w = tf.Variable(4 ) w.assign_sub(1 ) print (w)
1 2 <tf.Variable 'Variable:0' shape=() dtype=int32, numpy=3 >
tf.argmax() & tf.argmin()
1 2 3 4 5 6 7 8 9 10 11 12 13 import tensorflow as tfimport numpy as nptest = np.array([ [1 , 2 , 3 ], [2 , 3 , 4 ], [5 , 6 , 7 ], [8 , 9 , 2 ] ]) print (test)print (tf.argmax(test, axis=0 )) print (tf.argmin(test, axis=0 )) print (tf.argmax(test, axis=1 )) print (tf.argmin(test, axis=1 ))
1 2 3 4 5 6 7 8 9 [[1 2 3 ] [2 3 4 ] [5 6 7 ] [8 9 2 ]] tf.Tensor([3 3 2 ], shape=(3 ,), dtype=int64) tf.Tensor([0 0 3 ], shape=(3 ,), dtype=int64) tf.Tensor([2 2 2 1 ], shape=(4 ,), dtype=int64) tf.Tensor([0 0 0 2 ], shape=(4 ,), dtype=int64)
1.6 鸢尾花数据集(Iris)
数据集介绍
共有150组数据, 每组包括花萼长,花萼宽,花瓣长,花瓣宽4个输入特征. 同时给出了这一组特征对应的鸢尾花类别. 类别包括Setosa Iris(狗尾草鸢尾), Versicolour Iris(杂色鸢尾), Virginica Iris(弗吉尼亚鸢尾)三种类别, 分别用数字0,1,2表示.
数据集的导入
从sklearn.datasets读入Iris数据集
1 2 3 from sklearn.datasets import load_irisx_data = datasets.load_iris().data y_data = datasets.load_iris().target
1 2 3 4 5 6 from sklearn import datasetsx_data = datasets.load_iris().data y_data = datasets.load_iris().target print ("x_data from datasets: \n" , x_data)print ("y_data from datasets: \n" , y_data)
1 2 3 4 5 6 7 8 9 x_data from datasets: [[5.1 3.5 1.4 0.2 ] [4.9 3. 1.4 0.2 ] ...... [5.9 3. 5.1 1.8 ]] y_data from datasets: [0 0 ... 0 1 1 ... 1 2 2 ...2 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from sklearn import datasetsfrom pandas import DataFrameimport pandas as pdx_data = datasets.load_iris().data y_data = datasets.load_iris().target x_data = DataFrame(x_data, columns=['花萼长度' , '花萼宽度' , '花瓣长度' , '花瓣宽度' ]) pd.set_option('display.unicode.east_asian_width' , True ) print ("x_data add index: \n" , x_data)x_data['类别' ] = y_data print ("x_data add a column: \n" , x_data)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 x_data add index: 花萼长度 花萼宽度 花瓣长度 花瓣宽度 0 5.1 3.5 1.4 0.2 1 4.9 3.0 1.4 0.2 .. ... ... ... ... 149 5.9 3.0 5.1 1.8 [150 rows x 4 columns] x_data add a column: 花萼长度 花萼宽度 花瓣长度 花瓣宽度 类别 0 5.1 3.5 1.4 0.2 0 1 4.9 3.0 1.4 0.2 0 .. ... ... ... ... ... 149 5.9 3.0 5.1 1.8 2 [150 rows x 5 columns]
1.7 神经网络实现鸢尾花分类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 import tensorflow as tffrom sklearn import datasetsfrom matplotlib import pyplot as pltimport numpy as npx_data = datasets.load_iris().data y_data = datasets.load_iris().target 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 :] x_train = tf.cast(x_train, tf.float32) x_test = tf.cast(x_test, tf.float32) 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 ) 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 )) lr = 0.1 train_loss_results = [] test_acc = [] epoch = 500 loss_all = 0 for epoch in range (epoch): for step, (x_train, y_train) in enumerate (train_db): with tf.GradientTape() as tape: y = tf.matmul(x_train, w1) + b1 y = tf.nn.softmax(y) y_ = tf.one_hot(y_train, depth=3 ) loss = tf.reduce_mean(tf.square(y_ - y)) loss_all += loss.numpy() 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 )) train_loss_results.append(loss_all / 4 ) loss_all = 0 total_correct, total_number = 0 , 0 for x_test, y_test in test_db: y = tf.matmul(x_test, w1) + b1 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 test_acc.append(acc) print ("Test_acc:" , acc) print ("--------------------------" ) plt.title('Loss Function Curve' ) plt.xlabel('Epoch' ) plt.ylabel('Loss' ) plt.plot(train_loss_results, label="$Loss$" ) plt.legend() plt.show() plt.title('Acc Curve' ) plt.xlabel('Epoch' ) plt.ylabel('Acc' ) plt.plot(test_acc, label="$Accuracy$" ) plt.legend() plt.show()