Python 演算法 Day 18 - Tensorflow 后续思考

Chap.III 深度学习与模型优化

Part 3: Tensorflow - 续

上一篇章简介了 tensorflow 的程式码,同时也留下了几个后续思考的问题。
这边就以同样是 mnist 的资料集 fashion 来展开讨论。

# Datasetsimport tensorflow as tfmnist = tf.keras.datasets.fashion_mnist(x_train, y_train),(x_test, y_test) = mnist.load_data()# Feature Engineeringx_train_n, x_test_n = x_train / 255.0, x_test / 255.0# Modelmodel = tf.keras.models.Sequential([    tf.keras.layers.Flatten(input_shape=(28, 28)),    tf.keras.layers.Dense(128, activation='relu'),    tf.keras.layers.Dropout(0.2),    tf.keras.layers.Dense(10, activation='softmax')])model.compile(optimizer='adam',              loss='sparse_categorical_crossentropy',              metrics=['accuracy'])# Training modelhis = model.fit(x_train_n, y_train, epochs=5, validation_split=0.2, steps_per_epoch=800)# Score modelscore = model.evaluate(x_test, y_test)score>>  [54.680458068847656, 0.8521999716758728]

1. 最后一层参数总数算法?

我们可以透过 mdoel_load.summary() 指令来获得参数量。

mdoel.summary()>>  Model: "sequential_1"    _________________________________________________________________    Layer (type)                 Output Shape              Param #       =================================================================    flatten_1 (Flatten)          (None, 784)               0             _________________________________________________________________    dense_2 (Dense)              (None, 128)               100480        _________________________________________________________________    dropout_1 (Dropout)          (None, 128)               0             _________________________________________________________________    dense_3 (Dense)              (None, 10)                1290          =================================================================    Total params: 101,770    Trainable params: 101,770    Non-trainable params: 0    _________________________________________________________________

为什么是 1290?

最后一层的 input 是 128 个权重,那么我们可以把其一的迴归线写作:
http://img2.58codes.com/2024/20138527R87SOhEEmO.png
总共有 128 个权重 W 与 1 个偏差项 b,共 129 个参数。
再来, output 共输出了 10 条迴归线,故总参数量就是 129*10 = 1290!

以 GPT-3(一种自迴归语言模型)来说,含有高达 1750 亿个参数呢!

2. 哪些品项容易混淆?

要查看哪些品项容易误判,这时候我们就可利用先前说过的混淆矩阵来帮忙了。

# 如何画出「好看的」混淆矩阵import sklearn.metrics as skmimport numpy as nppre = np.argmax(mdoel_load.predict(x_test_n), axis=1)  # 预测资料,并且每一列取最大值(最有可能)cm = skm.confusion_matrix(y_true=y_test, y_pred=pre)# 用 seaborn 画import matplotlib.pyplot as pltimport seaborn as snsplt.figure(figsize=(10, 6))labels=np.arange(10)sns.heatmap(    cm, xticklabels=labels, yticklabels=labels,    annot=True, linewidths=0.1, fmt='d', cmap='YlGnBu')plt.title('Confusion Matrix', fontsize=15)plt.ylabel('Actual label')plt.xlabel('Predict label')

http://img2.58codes.com/2024/20138527QgQOqfssXa.png
这样一来,很清楚可以看到

有 110 个品项 0(T-shirt)被预测成 品项 6(Shirt)有 154 个品项 4(Coat)被预测成 品项 2(Trouser)有 117 个品项 6(Shirt)被预测成 品项 0(T-shirt)有 152 个品项 6(Shirt)被预测成 品项 2(Pullover)

看来衣服真的很容易预测错误呢(笑)

3. Dense 的参数?

我们可以参考Keras 官网:

units: 正整数,输出空间维度。activation: 激励函数。若不指定,则不使用激活函数 (即「线性」: a(x) = x)。use_bias: 偏差项。即 y=wx + b 中的 b。initializers
4-1. kernel_initializer: w 的初始化器。
4-2. bias_initializer: b 的初始化器。regularizers https://keras.io/zh/regularizers/
5-1. kernel_regularizer: w 的正则化函数。
5-2. bias_regularizer: b 的正则化函数。activity_regularizer: 正则化函数。constraint
7-1. kernel_constraint: 限制 w 的範围。
7-2. bias_constraint: 限制 b 的範围。

4. Activate function 要选用哪个?

在前篇我们已经有讨论过,依照现有的研究指出,ReLU(可接受 0)及 LeakyReLU(不可接受 0)在大部分情况下效果会最好。
其他还有像是早期使用的 Sigmoid、tanh,以及专门用来归一化的 softmax...等。

更多激励函数可参考维基百科

5. Ragularization 的作用?

比起以往的演算法,神经网路特徵更多,以数字辨识为例,就有 28*28 = 784 个特徵。
过多的特徵将导致 overfitting 的问题,因此会在神经层中加入 penalty 惩罚项,以简化 Loss function。
让新的损失函数会变成如下:
http://img2.58codes.com/2024/20138527F6Cy5l1ceS.png

其中,我们最常使用的就是 L1 penalty & L2 penalty。
http://img2.58codes.com/2024/20138527rZGPSerMoM.png
数学上来看,L1 就是直接删去较高的权重,只针对较小的权重寻找最小的损失函数。
http://img2.58codes.com/2024/20138527MBqwOMyBJ8.png
而不同于 L1,L2 不使任何权重归零,但会将所有的权重调整,以达到简化模型的目的。

6. Dropout 是甚么? 该摆放在哪一层? 比例又该如何选择?

Dropout 层就是随机将特定比例的资料抛弃,以达到矫正 overfitting 简化模型的目的。
基本上可以将每一层 Dense 后方都设定一层 Dropout 层。
至于 Dropout 的比例如何拿捏...那就是黑箱科学的部分了 XD!
要根据经验,资料类型及属性等去判断,并没有一定的比例是最好的~

7. 损失函数有哪些? 个别有甚么影响?

可以参考Keras 官网中其他的损失函数。
我们目前有接触到的两样如下:

MSECross Entropy

然而,直接将上面的程式码直接改成 MSE 会发现:

# Modelmodel = tf.keras.models.Sequential([    tf.keras.layers.Flatten(input_shape=(28, 28)),    tf.keras.layers.Dense(128, activation='relu'),    tf.keras.layers.Dropout(0.2),    tf.keras.layers.Dense(10, activation='softmax')])model.compile(optimizer='adam',              loss='mse',              metrics=['accuracy'])# Training modelhis = model.fit(x_train_n, y_train, epochs=5, validation_split=0.2, steps_per_epoch=800)# Score modelscore = model.evaluate(x_test, y_test)score>>  [27.61042594909668, 0.10019999742507935]

居然结果只有 10% 準确率,这是怎么回事?

其实,这是因原本损失函数 "sparse_categorical_crossentropy" 里,偷偷包含了一个 sparse categorical。
这个所谓的「稀疏分类」,其实就是我们熟知的「One-hot encoding」。

简单地说,若分类结果有 10 种,他会将 y 自动拆分成 10 个栏位,
若某一样的预测结果是「9」,那么在「0~8」栏位里面都会是 False,而第 9 栏位是 True。

然而 MSE 的损失函数运算并没有这个功能,因此我们必须手动作业:

# Datasetsimport tensorflow as tfmnist = tf.keras.datasets.fashion_mnist(x_train, y_train),(x_test, y_test) = mnist.load_data()x_train_n, x_test_n = x_train / 255.0, x_test / 255.0# One-hot encodingy_train = tf.keras.utils.to_categorical(y_train)y_train[0:1]>>  array([9], dtype=uint8)

查看一下是不是有成功

y_train[0:1]>>  array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]], dtype=float32)

接着 Training,就可以发现準确率回到了原先的 87% 啰!

*注记: One-hot encoding 又分 Ordinal(有序,有大小顺序之分)与 Nominal(名目,仅有 True/False 之分)
.
.
.
.
.

Homework Answer:

请使用以下网站的资料(日文辨识),作为机器学习的对象。

https://github.com/rois-codh/kmnist

将四个档案下载完成后,机器学习程式码如下:

Dataset
注:.npz档: numpy 提供的压缩档模式。
import numpy as npfilename = './k49-train-imgs.npz'arr = np.load(filename)X_train = arr['arr_0']filename = './k49-test-imgs.npz'arr = np.load(filename)X_test = arr['arr_0']filename = './k49-train-labels.npz'arr = np.load(filename)y_train = arr['arr_0']filename = './k49-test-labels.npz'arr = np.load(filename)y_test = arr['arr_0']X_train.shape, X_test.shape, y_train.shape, y_test.shape>> ((232365, 28, 28), (38547, 28, 28), (232365,), (38547,))

*随意取出一笔资料图片:

import matplotlib.pyplot as pltdata_one = X_train[1]plt.imshow(data_one.reshape(28, 28), cmap='gray')plt.axis('off')plt.savefig('tf Japan 01')plt.show()

http://img2.58codes.com/2024/201385271cXhlUCQD5.png
看起来是日文字"と(To)"

Feture Engineering 常态化
X_train_n, X_test_n = X_train / 255.0, X_test / 255.0
建立 Model
要注意的是,在最后一层 Dense 全连接层须将 output 数量改为 49。
model = tf.keras.models.Sequential([  tf.keras.layers.Flatten(input_shape=(28, 28)),  tf.keras.layers.Dense(128, activation='relu'),  tf.keras.layers.Dropout(0.2),  tf.keras.layers.Dense(49, activation='softmax')])# 选用优化器(此处选择 'adam')model.compile(optimizer='adam',              loss='sparse_categorical_crossentropy',              metrics=['accuracy'])
训练 Model
依然用 validation_split 把训练资料拆出 20%,作训练过程中的验证
model.fit(X_train_n, y_train, epochs=5, validation_split=0.2)
Score Model
score = model.evaluate(X_test_n, y_test)print(score)>> [0.9463422894477844, 0.7574648857116699]
Use Model predict
取用测试资料进行测试,取出前 20 笔对答案。
import numpy as nppre = np.argmax(model.predict(X_test_n), axis=1)  # 预测资料,每一列取最大值(最有可能的数字)print("Predict:", pre[0:20])print("Actual:", y_test[0:20])>>  Predict: [19  4 10  3 26 12 25  9 24  8 19  5 12 46 28  4  9 10  7 13]    Actual: [19 23 10 31 26 12 24  9 24  8 19  5 12 46 28  4  9 10 18 13]

调出第 4 笔错误图片

X_3 = X_test_n[3,:,:]plt.imshow(X_3.reshape(28,28), cmap='gray')plt.axis('off')plt.savefig('tf Japan test 03')plt.show()

http://img2.58codes.com/2024/20138527JUICZcIfGK.png
预测为"え(E)",实际上是"み(Mi)"

结论:看来预测文字的精準度远远不及预测数字呢...


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章