当前位置:   article > 正文

Python深度学习03——Keras卷积神经网络(CNN)实现_from keras.layers import

from keras.layers import

参考书目:陈允杰.TensorFlow与Keras——Python深度学习应用实战.北京:中国水利水电出版社,2021

本系列基本不讲数学原理,只从代码角度去让读者们利用最简洁的Python代码实现深度学习方法。


卷积神经网络

卷积神经网络其实是做互相关运算,和概率论里面的卷积公式不是一个东西。理论就不过多介绍了,记住卷积神经网络是用于图像处理的,并且接受的输入不再是机器学习或者多层感知机里面的二维输入,由于图片本身就是二维数据了,再加上样本的个数这个维度,图片起码都是三维数据,并且考虑颜色通道不一样,四维的数据也很常见。

Keras里面的卷积层主要是Conv1(一维卷积层),Conv2(二维卷积层),UpSampling2D(1D)上采样层,MaxPooling2D(1D)最大池化层,AveragePooling2D(1D)平均池化层。

一般的卷积案例都采用MNIST手写数字集,这个数据集是黑白的,而且太简单了,MLP就能取得很好的分类效果。因此本次案例采用Cifar-10彩色数据集,其官网为:https://www.cs.toronto.edu/~kriz/cifar.html

该数据集为10分类的问题,物品为飞机汽车鸟狗青蛙等.......下面开始案例


卷积神经网络Python案例

Keras内置数据集,导入包导入数据:(若是有同学想学怎么把图片变成数据,可以看后面章节)

  1. from keras.datasets import cifar10
  2. import matplotlib.pyplot as plt
  3. # 载入 Cifar10 数据集, 如果是第一次载入会自行下载数据集
  4. (X_train, Y_train), (X_test, Y_test) = cifar10.load_data()
  5. print("X_train.shape: ", X_train.shape)
  6. print("Y_train.shape: ", Y_train.shape)
  7. print("X_test.shape: ", X_test.shape)
  8. print("Y_test.shape: ", Y_test.shape)

 

 

展示结果为训练数据为5w张,测试集数据为1w。每个数据都是32*32的图片,并且*3表示是三种颜色,下面打印前9张图片看看

  1. #绘出9张图片
  2. sub_plot= 330
  3. for i in range(0, 9):
  4. ax = plt.subplot(sub_plot+i+1)
  5. ax.imshow(X_train[i], cmap="binary")
  6. ax.set_title("Label: " + str(Y_train[i]))
  7. ax.axis("off")
  8. plt.subplots_adjust(hspace = .5)
  9. # 显示数字图片
  10. plt.show()

 

下面开始构建神经网络,首先将数据归一化,y是10分类问题,所以要独热编码

  1. import numpy as np
  2. import pandas as pd
  3. from keras.models import Sequential
  4. from keras.layers import Dense
  5. from keras.layers import Flatten
  6. from keras.layers import Conv2D
  7. from keras.layers import MaxPooling2D
  8. from keras.layers import Dropout
  9. from tensorflow.keras.utils import to_categorical
  10. # 指定随机数种子
  11. seed = 10
  12. np.random.seed(seed)
  13. # 因为是固定范围, 所以执行正规化, 从 0-255 至 0-1
  14. X_train = X_train.astype("float32") / 255
  15. X_test = X_test.astype("float32") / 255
  16. # One-hot编码
  17. Y_train = to_categorical(Y_train)
  18. Y_test = to_categorical(Y_test)

定义卷积模型

  1. # 定义模型
  2. model = Sequential()
  3. model.add(Conv2D(32, kernel_size=(3, 3), padding="same",input_shape=X_train.shape[1:], activation="relu"))
  4. model.add(MaxPooling2D(pool_size=(2, 2)))
  5. model.add(Dropout(0.25))
  6. model.add(Conv2D(64, kernel_size=(3, 3), padding="same",activation="relu"))
  7. model.add(MaxPooling2D(pool_size=(2, 2)))
  8. model.add(Dropout(0.25))
  9. model.add(Flatten())
  10. model.add(Dense(512, activation="relu"))
  11. model.add(Dropout(0.5))
  12. model.add(Dense(10, activation="softmax"))
  13. model.summary() #显示模型摘要资讯

 

32表示卷积核的格式,kernel_size表示卷积核大小,padding表示补零为相同尺寸(填充),strides表示填充步幅。最大池化层里面的pool_size=(2, 2)表示缩小比例。

编译模型,然后开始训练拟合,因为数据太大,只训练个20轮吧

  1. # 编译模型
  2. model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
  3. # 训练模型
  4. history = model.fit(X_train, Y_train, validation_split=0.2, epochs=20, batch_size=128, verbose=2)

 在训练集和测试集上评估模型

  1. # 评估模型
  2. print("\nTesting ...")
  3. loss, accuracy = model.evaluate(X_train, Y_train)
  4. print("训练数据集的准确度 = {:.2f}".format(accuracy))
  5. loss, accuracy = model.evaluate(X_test, Y_test)
  6. print("测试数据集的准确度 = {:.2f}".format(accuracy))

储存模型

  1. #存储Keras模型
  2. print("Saving Model: cifar10.h5 ...")
  3. model.save("cifar10.h5")

 画出损失变化

  1. # 显示训练和验证损失
  2. loss = history.history["loss"]
  3. epochs = range(1, len(loss)+1)
  4. val_loss = history.history["val_loss"]
  5. plt.plot(epochs, loss, "bo-", label="Training Loss")
  6. plt.plot(epochs, val_loss, "ro--", label="Validation Loss")
  7. plt.title("Training and Validation Loss")
  8. plt.xlabel("Epochs")
  9. plt.ylabel("Loss")
  10. plt.legend()
  11. plt.show()

 画出准确率变化

  1. # 显示训练和验证准确度
  2. acc = history.history["accuracy"]
  3. epochs = range(1, len(acc)+1)
  4. val_acc = history.history["val_accuracy"]
  5. plt.plot(epochs, acc, "bo-", label="Training Acc")
  6. plt.plot(epochs, val_acc, "ro--", label="Validation Acc")
  7. plt.title("Training and Validation Accuracy")
  8. plt.xlabel("Epochs")
  9. plt.ylabel("Accuracy")
  10. plt.legend()
  11. plt.show()

 计算预测结果的评价

  1. # 计算分类的预测值
  2. print("\nPredicting ...")
  3. predict=model.predict(X_test)
  4. Y_pred=np.argmax(predict,axis=1)
  5. #重新加载Y_test
  6. (X_train, Y_train), (X_test, Y_test) = cifar10.load_data()
  7. #计算混淆矩阵
  8. #显示混淆矩阵
  9. tb = pd.crosstab(Y_test.astype(int).flatten(),
  10. Y_pred.astype(int),
  11. rownames=["label"], colnames=["predict"])
  12. print(tb)

 画热力图

  1. import seaborn as sns
  2. sns.heatmap(tb,cmap='Blues',fmt='.20g',annot=True)
  3. #fmt='.20g'不使用科学计数法,annot=True表示增加注释
  4. plt.tight_layout()

 随便选一个图片,看模型预测其概率准不准

  1. #重新归一化
  2. X_train = X_train.astype("float32") / 255
  3. X_test = X_test.astype("float32") / 255
  4. #选第10张图片
  5. i = 10
  6. img = X_test[i]
  7. # 将图片转换成 4D 张量
  8. X_test_img = img.reshape(1, 32, 32, 3).astype("float32")
  9. # 绘出图表的预测结果
  10. plt.figure()
  11. plt.subplot(1,2,1)
  12. plt.title("Example of Image:" + str(Y_test[i]))
  13. plt.imshow(img, cmap="binary")
  14. plt.axis("off")

这是个飞机

看模型预测的种类概率

  1. #预测结果的概率
  2. print("Predicting ...")
  3. probs = model.predict(X_test_img, batch_size=1)
  4. plt.subplot(1,2,2)
  5. plt.title("Probabilities for Each Image Class")
  6. plt.bar(np.arange(10), probs.reshape(10), align="center")
  7. plt.xticks(np.arange(10),np.arange(10).astype(str))
  8. plt.show()

 

 模型几乎38%认为是飞机,35%认为是鹿....(差点就错了)

下面查看分类错误对象的记录

  1. Y_probs=model.predict(X_test) # 概率
  2. Y_pred=np.argmax(predict,axis=1)# 分类
  3. # 建立分类错误的 DataFrame 物件
  4. Y_test = Y_test.flatten()
  5. df = pd.DataFrame({"label":Y_test, "predict":Y_pred})
  6. df = df[Y_test!=Y_pred] # 筛选出分类错误的资料
  7. print(df.shape)
  8. print(df.head())

有2568个分类错误了

随机选一张看看

  1. #随机选 1 个错误分类的数字索引
  2. i = df.sample(n=1).index.values.astype(int)[0]
  3. print("Index: ", i)
  4. img = X_test[i]
  5. # 绘出图表的预测结果
  6. plt.figure()
  7. plt.subplot(1,2,1)
  8. plt.title("Example of Image:" + str(Y_test[i]))
  9. plt.imshow(img, cmap="binary")
  10. plt.axis("off")
  11. plt.subplot(1,2,2)
  12. plt.title("Probabilities for Each Image Class")
  13. plt.bar(np.arange(10), Y_probs[i].reshape(10), align="center")
  14. plt.xticks(np.arange(10),np.arange(10).astype(str))
  15. plt.show()

 这是一个船,但是模型几乎90%认为它是一个汽车....

再选一个看看

  这是一个猫,但是模型几乎60%认为它是一只马....

还是很有意思的,同学们可以调整模型参数让其准确率更高,再来进行测评

下一章介绍自编码器去处图片噪声。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/103858
推荐阅读
相关标签
  

闽ICP备14008679号