作业15
补交:6.逻辑回归 https://www.cnblogs.com/Roromiya/p/13088857.html
一、手写数字数据集
- from sklearn.datasets import load_digits
- digits = load_digits()
1 # 1 - Load dataset 2 digits = load_digits() 3 X = digits['images'] 4 Y = digits['target']
二、图片数据预处理
- x:归一化MinMaxScaler()
- y:独热编码OneHotEncoder()或to_categorical
- 训练集测试集划分
- 张量结构
使用自定义归一化函数normalization(),与独立热编码函数onehot_encode()
1 # 2.1 - Reshape the images, from (8, 8) to (8, 8, 1) 2 def img_reshape(images): 3 return [tf.reshape(image, (8, 8, 1)).numpy() for image in images] 4 X = img_reshape(X) 5 6 # 2.2 - Normalize the images, scale the value to 0.0 ~ 1.0 7 def normalization(data): 8 _range = np.max(data) - np.min(data) 9 return (data - np.min(data)) / _range 10 X = normalization(X) 11 12 # 2.3 - Onehot encoding on labels 13 def onehot_encode(labels): 14 onehot_labels = [] 15 for y in labels: 16 label = [0. for i in range(10)] 17 label[y] = 1. 18 onehot_labels.append(label) 19 return onehot_labels 20 def onehot_decode(labels): 21 return np.array([label.index(True) for label in labels.tolist()]) 22 Y = onehot_encode(Y) 23 Y = np.array(Y) 24 25 # 2.4 - Split the train-set and test-set 26 X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0) 27 28 print('Images shape: ', X.shape) 29 print('Labels shape: ', Y.shape) 30 print('Images: ', X) 31 print('Labels: ', Y)
处理后的数据集尺寸(数量, 高度, 宽度, 通道数):

处理后的标签集尺寸(数量, 类别个数):

查看数据集:

查看标签集:

三、设计卷积神经网络结构
- 绘制模型结构图,并说明设计依据。
网络结构:

设计依据:
1)数据尺寸太小,特征较少,没必要使用过深的网络提取特征,三层就够了。
2)由于图像尺寸较小,故卷积核尺寸设置为2×2,三个卷积-池化层的卷积核数量分别设置为32、64、128。
3)该模型不使用Dropout,因为在使用小卷积核时Dropout丢弃过多特征会导致准确率变差。
4)在卷积层后使用BatchNormalization替代Dropout,BN同样可以起到防止过拟合的作用,还可以加速模型收敛。
5)池化前使用ReLu而不是sigmod作为激活函数,目的是避免“梯度消失”。
6)由于这是一个用于分类的神经网络,独热编码值介于0.0~1.0之间,故全连接之后使用Softmax激活函数进行分类。
创建模型:
设置初始学习率为1e-4,优化器为Adam,损失函数为交叉熵损失
1 def CNN(): 2 nn = models.Sequential() 3 # 1st Convolution->BN->ReLu->Pool 4 nn.add(layers.Conv2D(filters=32, kernel_size=(2, 2), input_shape=(8, 8, 1))) 5 nn.add(layers.BatchNormalization()) 6 nn.add(layers.ReLU()) 7 nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=1)) 8 9 # 2nd Convolution->BN->ReLu->Pool 10 nn.add(layers.Conv2D(filters=64, kernel_size=(2, 2))) 11 nn.add(layers.BatchNormalization()) 12 nn.add(layers.ReLU()) 13 nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=1)) 14 15 # 3rd Convolution->Convolution->BN->ReLu->Pool 16 nn.add(layers.Conv2D(filters=128, kernel_size=(2, 2))) 17 nn.add(layers.Conv2D(filters=128, kernel_size=(2, 2))) 18 nn.add(layers.BatchNormalization()) 19 nn.add(layers.ReLU()) 20 nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=2)) 21 22 # Flatten->Dense->Softmax 23 nn.add(layers.Flatten()) 24 nn.add(layers.Dense(units=10)) 25 nn.add(layers.Softmax()) 26 27 # Compile and ready to use 28 nn.compile( 29 optimizer=optimizers.Adam(learning_rate=0.0001), 30 loss=losses.categorical_crossentropy, 31 metrics=['accuracy'] 32 ) 33 return nn
四、模型训练
设置batch_size为4,epoch为80轮。
创建回调函数TensorBoard(),用于记录loss下降曲线。
创建回调函数ReduceLROnPlateau(),当验证集超过10个epoch不下降时自动降低学习率。
def train(nn, train_image, train_label, test_image, test_label, batch_size, epoch, log_path): # Create Tensorboard callback tb = tf.keras.callbacks.TensorBoard(log_dir=log_path, histogram_freq=1) # Create learning rate reducer reduce_lr = ReduceLROnPlateau(monitor='val_loss', patience=10, mode='auto') history = nn.fit(train_image, train_label, batch_size=batch_size, epochs=epoch, validation_data=(test_image, test_label), callbacks=[tb, reduce_lr]) return history log_dir = "./logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") train(model, X_train, Y_train, X_test, Y_test, batch_size=4, epoch=80, log_path=log_dir) model.save("./weights.hdf5") # Save the weights
训练过程:

Linux终端内启动tensorboard

打开Tensorboard网页界面,观察loss_epoch曲线、accuracy_epoch曲线:
打开Tensorboard网页界面,观察全连接层的张量直方图:

五、模型评价
- model.evaluate()
- 交叉表与交叉矩阵
- pandas.crosstab
- seaborn.heatmap
使用model.evaluate()进行模型评估:
1 # 5.1 - model.evaluate() 2 model.load_weights(args.weights) 3 print("\nModel Evaluate:") 4 model.evaluate(X_test, Y_test, batch_size=128)
评估结果——模型在测试集上的准确率为 99.72%

绘制交叉表:
1 # 5.2 - pandas.crosstab() 2 pred = model.predict_classes(X_test) 3 table = pandas.DataFrame(pandas.crosstab(onehot_decode(Y_test), pred, rownames=['true'], colnames=['pred'])) 4 heatmap(table, annot=True, cmap="Reds", linewidths=0.2, linecolor='G') 5 plt.show()

完整代码:
Python版本:3.8.3
Tensorflow版本:2.2.0
Tensorboard版本:2.2.2
1 import datetime 2 import argparse 3 from sklearn.datasets import load_digits 4 from sklearn.model_selection import train_test_split 5 import tensorflow as tf 6 from tensorflow.keras import layers, models, optimizers, losses 7 import numpy as np 8 import os 9 import pandas 10 from seaborn import heatmap 11 from matplotlib import pyplot as plt 12 13 # From [9] to [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.] 14 from tensorflow.python.keras.callbacks import ReduceLROnPlateau 15 16 17 def onehot_encode(labels): 18 onehot_labels = [] 19 for y in labels: 20 label = [0. for i in range(10)] 21 label[y] = 1. 22 onehot_labels.append(label) 23 return onehot_labels 24 25 # From [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.] to [9] 26 def onehot_decode(labels): 27 return np.array([label.index(True) for label in labels.tolist()]) 28 29 # Scale to 0. ~ 1. 30 def normalization(data): 31 _range = np.max(data) - np.min(data) 32 return (data - np.min(data)) / _range 33 34 # From (n, 8, 8) to (n, 8, 8, 1) 35 def img_reshape(images): 36 return [tf.reshape(image, (8, 8, 1)).numpy() for image in images] 37 38 def CNN(): 39 nn = models.Sequential() 40 # 1st Convolution->BN->ReLu->Pool 41 nn.add(layers.Conv2D(filters=32, kernel_size=(2, 2), input_shape=(8, 8, 1))) 42 nn.add(layers.BatchNormalization()) 43 nn.add(layers.ReLU()) 44 nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=1)) 45 46 # 2nd Convolution->BN->ReLu->Pool 47 nn.add(layers.Conv2D(filters=64, kernel_size=(2, 2))) 48 nn.add(layers.BatchNormalization()) 49 nn.add(layers.ReLU()) 50 nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=1)) 51 52 # 3rd Convolution->Convolution->BN->ReLu->Pool 53 nn.add(layers.Conv2D(filters=128, kernel_size=(2, 2))) 54 nn.add(layers.Conv2D(filters=128, kernel_size=(2, 2))) 55 nn.add(layers.BatchNormalization()) 56 nn.add(layers.ReLU()) 57 nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=2)) 58 59 # Flatten->Dense->Softmax 60 nn.add(layers.Flatten()) 61 nn.add(layers.Dense(units=10)) 62 nn.add(layers.Softmax()) 63 64 # Compile and ready to use 65 nn.compile( 66 optimizer=optimizers.Adam(learning_rate=0.0001), 67 loss=losses.categorical_crossentropy, 68 metrics=['accuracy'] 69 ) 70 return nn 71 72 def train(nn, train_image, train_label, test_image, test_label, batch_size, epoch, log_path): 73 # Create Tensorboard callback 74 tb = tf.keras.callbacks.TensorBoard(log_dir=log_path, histogram_freq=1) 75 # Create learning rate reducer 76 reduce_lr = ReduceLROnPlateau(monitor='val_loss', patience=10, mode='auto') 77 history = nn.fit(train_image, train_label, 78 batch_size=batch_size, epochs=epoch, validation_data=(test_image, test_label), callbacks=[tb, reduce_lr]) 79 return history 80 81 82 if __name__ == '__main__': 83 parser = argparse.ArgumentParser() 84 parser.add_argument('--cpu', type=bool, default=False) 85 parser.add_argument('--weights', type=str, default=None) 86 args = parser.parse_args() 87 88 # Force CPU or GPU 89 os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" 90 os.environ["CUDA_VISIBLE_DEVICES"] = "-1" if args.cpu else "0" 91 if not args.cpu: 92 # Fix CUDNN_STATUS_INTERNAL_ERROR 93 gpu_devices = tf.config.experimental.list_physical_devices('GPU') 94 for device in gpu_devices: 95 tf.config.experimental.set_memory_growth(device, True) 96 97 # 1 - Load dataset 98 digits = load_digits() 99 X = digits['images'] 100 Y = digits['target'] 101 102 # 2 - Pretreatment 103 # 2.1 - Reshape the images, from (8, 8) to (8, 8, 1) 104 X = img_reshape(X) 105 # 2.2 - Normalize the images, scale the value to 0.0 ~ 1.0 106 X = normalization(X) 107 # 2.3 - Onehot encoding on labels 108 Y = onehot_encode(Y) 109 Y = np.array(Y) 110 # 2.4 - Split the train-set and test-set 111 X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0) 112 print('Images shape: ', X.shape) 113 print('Labels shape: ', Y.shape) 114 print('Images: ', X) 115 print('Labels: ', Y) 116 117 # 3 - Create model 118 model = CNN() 119 model.summary() 120 121 # 4 - Training 122 if not args.weights: 123 log_dir = "./logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") 124 train(model, X_train, Y_train, X_test, Y_test, batch_size=4, epoch=80, log_path=log_dir) 125 model.save("./weights.hdf5") # Save the weights 126 127 # 5 - Evaluate 128 # 5.1 - model.evaluate() 129 if args.weights: 130 model.load_weights(args.weights) 131 print("\nModel Evaluate:") 132 model.evaluate(X_test, Y_test, batch_size=4) 133 # 5.2 - pandas.crosstab() 134 pred = model.predict_classes(X_test) 135 table = pandas.DataFrame(pandas.crosstab(onehot_decode(Y_test), pred, rownames=['true'], colnames=['pred'])) 136 heatmap(table, annot=True, cmap="Reds", linewidths=0.2, linecolor='G') 137 plt.show()

浙公网安备 33010602011771号