[关闭]
@1007477689 2020-03-29T10:35:51.000000Z 字数 7095 阅读 566

50题真 • 一文入门TensorFlow2.x

Python


导入一些必要的库

import numpy as np
import matplotlib.pyplot as plt
import os
import pickle

1.导入TensorFlow库简写为tf,并输出其版本号

import tensorflow as tf
tf.__version__

一、Tensor张量

常量

2. 创建一个3x3的0常量张量

c = tf.zeros([3, 3])

3. 根据上题张量的形状(3x3),创建一个一模一样形状的1常量张量

tf.ones_like(c)

4. 创建一个2x3,数值全为6的常量张量

tf.fill([2, 3], 6)  
# 2x3 全为 6 的常量 Tensor

5. 创建3x3随机的随机数组

tf.random.normal([3,3])

6. 通过二维数组创建一个常量张量

a = tf.constant([[1, 2], [3, 4]])  
# 形状为 (2, 2) 的二维常量
a

7. 取出张量中的numpy数组

a.numpy()

8. 从1.0-10.0中等间距的取出5个数生成一个常量张量

tf.linspace(1.0, 10.0, 5)

9. 从1开始间隔2取1个数字,到大等于10为止

tf.range(start = 1, limit = 10, delta = 2)

运算

10. 将两个张量相加

a + a

11. 将两个张量做矩阵乘法

tf.matmul(a, a)

12. 两个张量做点乘

tf.multiply(a, a)

13. 将一个张量转置

tf.linalg.matrix_transpose(c)

14. 将一个12x1张量变形成3行的张量

b = tf.linspace(1.0, 10.0, 12)
# 方法一
tf.reshape(b, [3, 4])
# 方法二
tf.reshape(b, [3, -1])

二、自动微分

这一部分将会实现 处的导数

变量

15. 新建一个1x1变量,值为1

x = tf.Variable([1.0])
x

16. 新建一个GradientTape追踪梯度,把要微分的公式写在里面

with tf.GradientTape() as tape:  
# 追踪梯度
    y = x * x

17. 求y对于x的导数

grad = tape.gradient(y, x)  
# 计算梯度
grad

三、线性回归案例

这一部分将生成添加随机噪声的沿100个的数据点,再对这些数据点进行拟合。

18. 生成X,Y数据,X为100个随机数,Y = 3X + 2 + noise,noise为100个随机数

X = tf.random.normal([100, 1]).numpy()
noise = tf.random.normal([100, 1]).numpy()

y = 3*X + 2 + noise

# 可视化这些点
plt.scatter(X, y)

19. 创建需要预测的参数W,b(变量张量)

W = tf.Variable(np.random.randn())
b = tf.Variable(np.random.randn())
print(f'W: {W.numpy()}, b: {b.numpy()})

20. 创建线性回归预测模型

def linear_regression(x):
    return W * x + b

21. 创建损失函数,此处采用真实值与预测值的差的平方,公式为:[公式]

def mean_square(y_pred, y_true):
    return tf.reduce_mean(tf.square(y_pred - y_true))

22. 创建GradientTape,写入需要微分的过程

with tf.GradientTape() as tape:
    pred = linear_regression(X)
    loss = mean_square(pred, y)

23. 对loss,分别求关于W,b的偏导数

dW, db = tape.gradient(loss, [W, b])

24. 用最简单朴素的梯度下降更新W,b,learning_rate设置为0.1

W.assign_sub(0.1*dW)
b.assign_sub(0.1*db)
print('W: %f, b: %f'%(W.numpy(), b.numpy()))

25. 以上就是单次迭代的过程,现在我们要继续循环迭代20次,并且记录每次的loss, W , b

for i in range(20):
    with tf.GradientTape() as tape:
        pred = linear_regression(X)
        loss = mean_square(pred, y)

    dW, db = tape.gradient(loss, [W, b])

    W.assign_sub(0.1 * dW)
    b.assign_sub(0.1 * db)

    print("step: %i, loss: %f, W: %f, b: %f" % (i+1, loss, W.numpy(), b.numpy()))

# 画出最终拟合的曲线
plt.plot(X, y, 'ro', label = 'Original data')
plt.plot(X, np.array(W * X + b), label = 'Fitted line')
plt.legend()
plt.show()

四、神经网络案例

这部分将会在CIFAR10数据集上,训练LeNet5模型

模型结构如下所示:

CIFAR10数据集为32x32的3通道图像,标签共10个种类

定义参数

26. 定义第①步:卷积层的参数

输入图片:3×32×32

卷积核大小:5×5

卷积核种类:6

所以需要定义5×5×3×6个权重变量,和6个bias变量

conv1_w = tf.Variable(tf.random.truncated_normal([5,5,3,6], stddev=0.1))
conv1_b = tf.Variable(tf.zeros([6]))

27.定义第③步:卷积层的参数

输入:14×14×6

卷积核大小:5×5

卷积核种类:16

所以需要定义5×5×6×16个权重变量,和16个bias变量

conv2_w = tf.Variable(tf.random.truncated_normal([5, 5, 6, 16], stddev=0.1))
conv2_b = tf.Variable(tf.zeros([16]))

28.定义第第⑤步:全连接层的参数

输入:5×5×16

输出:120

fc1_w = tf.Variable(tf.random.truncated_normal([5*5*16, 120], stddev=0.1))
fc1_b = tf.Variable(tf.zeros([120]))

29.定义第⑥步:全连接层的参数

输入:120

输出:84

fc2_w = tf.Variable(tf.random.truncated_normal([120, 84], stddev=0.1))
fc2_b = tf.Variable(tf.zeros([84]))

30.定义第⑦步:全连接层的参数

输入:84

输出:10

fc3_w = tf.Variable(tf.random.truncated_normal([84, 10], stddev=0.1))
fc3_b = tf.Variable(tf.zeros([10]))

搭模型

def lenet5(input_img):
    ## 31.搭建INPUT->C1的步骤
    conv1_1 = tf.nn.conv2d(input_img, conv1_w, strides=[1,1,1,1], padding="VALID")
    conv1_2 = tf.nn.relu(tf.nn.bias_add(conv1_1,conv1_b))

    ## 32.搭建C1->S2的步骤
    pool1 = tf.nn.max_pool(conv1_2,ksize=[1,2,2,1],strides=[1,2,2,1],padding="VALID")

    ## 33.搭建S2->C3的步骤
    conv2_1 = tf.nn.conv2d(pool1,conv2_w,strides=[1,1,1,1],padding="VALID")
    conv2_2 = tf.nn.relu(tf.nn.bias_add(conv2_1,conv2_b))

    ## 34.搭建C3->S4的步骤
    pool2 = tf.nn.max_pool(conv2_2,ksize=[1,2,2,1],strides=[1,2,2,1],padding="VALID")

    ## 35.将S4的输出扁平化
    reshaped = tf.reshape(pool2,[-1, 16*5*5])

    ## 35.搭建S4->C5的步骤
    fc1 = tf.nn.relu(tf.matmul(reshaped,fc1_w) + fc1_b)

    ## 36.搭建C5->F6的步骤
    fc2 = tf.nn.relu(tf.matmul(fc1,fc2_w) + fc2_b)

    ## 37.搭建F6->OUTPUT的步骤
    OUTPUT = tf.nn.softmax(tf.matmul(fc2,fc3_w) + fc3_b)

    return OUTPUT

38.创建一个Adam优化器,学习率0.02

optimizer = tf.optimizers.Adam(learning_rate=0.02)
验证网络正确性

(随便搞点数据,验证一下能不能跑通) ###39.随机一对x,y数据,x的形状为(1,32,32,3),y的形状为(10,)###

test_x = tf.Variable(tf.random.truncated_normal([1,32,32,3]))
test_y = [1,0,0,0,0,0,0,0,0,0]
将数据送入模型,进行反向传播

with tf.GradientTape() as tape:  
    ## 40.将数据从入模型
    prediction = lenet5(test_x)
    print("第一次预测:", prediction)
    ## 41.使用交叉熵作为损失函数,计算损失
    cross_entropy = -tf.reduce_sum(test_y * tf.math.log(prediction))

42.计算梯度

trainable_variables = [conv1_w, conv1_b, conv2_w, conv2_b, fc1_w, fc1_b, fc2_w, fc2_b, fc3_w, fc3_b]  # 需优化参数列表
grads = tape.gradient(cross_entropy, trainable_variables) 

43.更新梯度

optimizer.apply_gradients(zip(grads, trainable_variables))

print("反向传播后的预测:", lenet5(test_x))
读入数据,预处理

## load_cifar()定义略
train_X, train_Y, test_X, test_Y = load_cifar('/home/kesci/input/cifar10')
classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
train_X.shape, train_X.shape, test_X.shape, test_Y.shape
捞一个数据看看样子

plt.imshow(train_X[0])
plt.show()
print(classes[train_Y[0]])

44.预处理1:将train_y, test_y进行归一化

train_X = tf.cast(train_X, dtype=tf.float32) / 255
test_X = tf.cast(test_X, dtype=tf.float32) / 255
45.预处理2:将train_y, test_y进行onehot编码

train_Y = tf.one_hot(train_Y, depth=10)
test_Y = tf.one_hot(test_Y, depth=10)
训练网络

因为前面实验的时候修改过参数,所以需要重新初始化所有参数

conv1_w = tf.Variable(tf.random.truncated_normal([5,5,3,6], stddev=0.1))
conv1_b = tf.Variable(tf.zeros([6])) 
conv2_w = tf.Variable(tf.random.truncated_normal([5, 5, 6, 16], stddev=0.1))
conv2_b = tf.Variable(tf.zeros([16]))
fc1_w = tf.Variable(tf.random.truncated_normal([5*5*16, 120], stddev=0.1))
fc1_b = tf.Variable(tf.zeros([120]))
fc2_w = tf.Variable(tf.random.truncated_normal([120, 84], stddev=0.1))
fc2_b = tf.Variable(tf.zeros([84]))
fc3_w = tf.Variable(tf.random.truncated_normal([84, 10], stddev=0.1))
fc3_b = tf.Variable(tf.zeros([10]))
然后再重新定义一个优化器

optimizer2 = tf.optimizers.Adam(learning_rate=0.002)
简简单单随便写一个算准确率的函数

def accuracy_fn(y_pred, y_true):
    preds = tf.argmax(y_pred, axis=1)  # 取值最大的索引,正好对应字符标签
    labels = tf.argmax(y_true, axis=1)
    return tf.reduce_mean(tf.cast(tf.equal(preds, labels), tf.float32))

46.把数据送入模型,开始训练,训练集迭代5遍,每遍分成25个batch,数据集每迭代完一遍,输出一次训练集上的准确率

EPOCHS = 5  # 整个数据集迭代次数

for epoch in range(EPOCHS):
    for i in range(25):  # 一整个数据集分为10个小batch训练
        with tf.GradientTape() as tape:
            prediction = lenet5(train_X[i*2000:(i+1)*2000])
            cross_entropy = -tf.reduce_sum(train_Y[i*2000:(i+1)*2000] * tf.math.log(prediction))

        trainable_variables = [conv1_w, conv1_b, conv2_w, conv2_b, fc1_w, fc1_b, fc2_w, fc2_b, fc3_w, fc3_b]  # 需优化参数列表
        grads = tape.gradient(cross_entropy, trainable_variables)  # 计算梯度

        optimizer2.apply_gradients(zip(grads, trainable_variables))  # 更新梯度

    # 每训练完一次,输出一下训练集的准确率    
    accuracy = accuracy_fn(lenet5(train_X), train_Y)
    print('Epoch [{}/{}], Train loss: {:.3f}, Test accuracy: {:.3f}'
              .format(epoch+1, EPOCHS, cross_entropy/2000, accuracy))
使用网络进行预测

47.在测试集上进行预测

test_prediction = lenet5(test_X)
test_acc = accuracy_fn(test_prediction, test_Y)
test_acc.numpy()
取一些数据查看预测结果

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.imshow(test_X[i], cmap=plt.cm.binary)
    title=classes[np.argmax(test_Y[i])]+'=>'
    title+=classes[np.argmax(test_prediction[i])]
    plt.xlabel(title)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)

五、变量保存&读取

这一部分,我们实现最简单的保存&读取变量值

48.新建一个Checkpoint对象,并且往里灌一个刚刚训练完的数据

save = tf.train.Checkpoint()
save.listed = [fc3_b]
save.mapped = {'fc3_b': save.listed[0]}

49.利用save()的方法保存,并且记录返回的保存路径

save_path = save.save('/home/kesci/work/data/tf_list_example')
print(save_path)

50.新建一个Checkpoint对象,从里读出数据

restore = tf.train.Checkpoint()
fc3_b2 = tf.Variable(tf.zeros([10]))
print(fc3_b2.numpy())
restore.mapped = {'fc3_b': fc3_b2}
restore.restore(save_path)
print(fc3_b2.numpy())
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注