[2021]从0开始的tensorflow2.0 (二) huoji AI,机器学习,人工智能,keras,tensorflow 2021-07-06 708 次浏览 2 次点赞 上一节 [[2021]从0开始的tensorflow2.0 (一)](https://key08.com/index.php/2021/07/04/1239.html "[2021]从0开始的tensorflow2.0 (一)") 说了基本的逻辑回归操作,实际上所有的一些东西都能被提取特征然后做文本二分类,基本上都是这个套路,现在来说说常见的图像处理 - 卷积 请注意 我们今天只讨论处理后的图像,实际上,**图像识别部分最难的部分就仅仅是图像处理仅此而已,但是我们今天不讨论图像处理** 一个标准的网络由三个部分组成 卷积层 池化层 全连接层 ## 卷积核 ![](https://key08.com/usr/uploads/2021/07/1974543244.png) 把图像放大到只有RBG的时候,就可以提取图像特征了,提取图像特征就是卷积核干的事情,把一块正方形区域的内容压缩到指定的卷积核大小中.通过向量转换.这样一些物品的边缘线之类的东西的特征 就被提取出来了 **我建议你可以去b站搜 卷积可视化如果你对卷积还是没有概念的话** ## tf.keras.layers.Conv2D 构建卷积层。用于从输入的高维数组中提取特征。卷积层的每个过滤器就是一个特征映射,用于提取某一个特征,过滤器的数量决定了卷积层输出特征个数,或者输出深度。因此,图片等高维数据每经过一个卷积层,深度都会增加,并且等于过滤器的数量。 ```cpp Conv2D(filters, kernel_size, strides, padding, activation=‘relu’, input_shape) filters: 过滤器数量 kernel_size: 指定(方形)卷积窗口的高和宽的数字 strides: 卷积步长, 默认为 1 padding: 卷积如何处理边缘。选项包括 ‘valid’ 和 ‘same’。默认为 ‘valid’ activation: 激活函数,通常设为 relu。如果未指定任何值,则不应用任何激活函数。强烈建议你向网络中的每个卷积层添加一个 ReLU 激活函数 input_shape: 指定输入层的高度,宽度和深度的元组。当卷积层作为模型第一层时,必须提供此参数,否则不需要 ``` ## tf.keras.layers.MaxPooling2D 池化层,别想太多,你就想成,他在缩放图片大小.一方面使特征图变小,简化网络计算复杂度;一方面进行特征压缩,提取主要特征 **池化的作用则体现在降采样、保留显著特征、降低特征维度,增大卷积核的感受视野** ## 下载训练集 这是tensorflow的CIFAR10数据集,都已经帮你整理好了,包含10个分类,并且所有图片都是被标注好label了并且都是32x32大小,**如果是你做的话,你需要有一个数据标注团队来标注图片并且需要自己想办法修正图片大小到你指定的图片大小,这叫数据预处理,以后再讨论** ```cpp import numpy as np import pandas as pd import matplotlib.pyplot as plt import os import tensorflow as tf from sklearn.preprocessing import StandardScaler import random (train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.cifar10.load_data() # 像素值处于 0 到 255 之间, 所以要将像素的值标准化至0到1的区间内。 train_images, test_images = train_images / 255.0, test_images / 255.0 class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'] ``` 验证数据集: ```cpp class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'] plt.figure(figsize=(10,10)) for i in range(25): plt.subplot(5,5,i+1) plt.xticks([]) plt.yticks([]) plt.grid(False) plt.imshow(train_images[i], cmap=plt.cm.binary) # 由于 CIFAR 的标签是 array, # 因此您需要额外的索引(index)。 plt.xlabel(class_names[train_labels[i][0]]) plt.show() ``` ![](https://key08.com/usr/uploads/2021/07/902783845.png) ## 构造模型网络 ```cpp model = models.Sequential() model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3))) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) ``` **停停停,怎么跟官方的一模一样!** 这就坑来了,官方的例子的卷积网络拟合能力压根就不强,正确率实测只有60%多... 让我们改进一下并且详细介绍一下 tf.keras.layers.Conv2D两个卷积, 大小3x3, 128的标准过滤器, 此外他的形状是32x32(图片大小),3(RBG就是3), 激活器是relu,并且填充方式不要是valid,valid是不填充,导致图像转换会出问题,我们用same,填充图片 ```cpp model = tf.keras.layers.Conv2D( 128, (3, 3), input_shape=(32, 32, 3), activation='relu', padding='same')(input) model = tf.keras.layers.Conv2D( 128, (3, 3), input_shape=(32, 32, 3), activation='relu', padding='same')(model) model = tf.keras.layers.MaxPooling2D()(model) ``` 套3层,从128到512,但是记住每一层后都要接一个MaxPooling2D调整图片大小,强化特征提取并且防止过拟合 ```cpp model = tf.keras.layers.Conv2D( 128, (3, 3), input_shape=(32, 32, 3), activation='relu', padding='same')(input) model = tf.keras.layers.Conv2D( 128, (3, 3), input_shape=(32, 32, 3), activation='relu', padding='same')(model) model = tf.keras.layers.MaxPooling2D()(model) model = tf.keras.layers.Conv2D( 256, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.Conv2D( 256, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.MaxPooling2D()(model) model = tf.keras.layers.Conv2D( 512, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.Conv2D( 512, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.MaxPooling2D()(model) ``` MaxPooling2D默认是调整特征为2x2的大小,可以自己定义 平均池化(GlobalAveragePooling2D)跟池化类似,也是缩小图片提取特征用. 之后就是全连接层了,我们可以自定义多个网络,增强拟合能力,官方例子是只有一层的,导致拟合能力不佳: ```cpp model = tf.keras.layers.GlobalAveragePooling2D()(model) model = tf.keras.layers.Dense(256, activation='relu')(model) model = tf.keras.layers.Dense(128, activation='relu')(model) model = tf.keras.layers.Dense(64, activation='relu')(model) ``` 一个标准的图像网络就好了,看起来是这样的: ```cpp def build_network(): input = tf.keras.Input(shape=(32, 32, 3)) model = tf.keras.layers.Conv2D( 128, (3, 3), input_shape=(32, 32, 3), activation='relu', padding='same')(input) model = tf.keras.layers.Conv2D( 128, (3, 3), input_shape=(32, 32, 3), activation='relu', padding='same')(model) model = tf.keras.layers.MaxPooling2D()(model) model = tf.keras.layers.Conv2D( 256, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.Conv2D( 256, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.MaxPooling2D()(model) model = tf.keras.layers.Conv2D( 512, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.Conv2D( 512, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.MaxPooling2D()(model) model = tf.keras.layers.GlobalAveragePooling2D()(model) model = tf.keras.layers.Dense(256, activation='relu')(model) model = tf.keras.layers.Dense(128, activation='relu')(model) model = tf.keras.layers.Dense(64, activation='relu')(model) model = tf.keras.layers.Dense(10, activation='softmax')(model) model = tf.keras.Model(inputs=input, outputs=model) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) return model ``` 由于是多分类任务不是逻辑回归,所以loss函数用sparse_categorical_crossentropy ## 训练、测试 直接训练就行: ```cpp network_model = build_network() network_model.summary() history = network_model.fit( x=train_images, y=train_labels, epochs=15, validation_data=(test_images, test_labels)) plt.plot(history.history['accuracy'], label='accuracy') plt.plot(history.history['val_loss'], label='val_loss') plt.xlabel('Epoch') plt.ylabel('Accuracy') plt.show() ``` 可以看到,官方的网络只有70%(其实自己搭建是60%多)的准确率,而我们的强大的拟合能力的模型有97%的准确率,这已经可以用于生产环境了 ![](https://key08.com/usr/uploads/2021/07/1105743849.png) 关于图片显示,可以直接用谷歌官方的代码: ```cpp def plot_image(i, predictions_array, true_label, img): predictions_array, true_label, img = predictions_array, true_label[i], img[i] plt.grid(False) plt.xticks([]) plt.yticks([]) plt.imshow(img, cmap=plt.cm.binary) predicted_label = np.argmax(predictions_array) if predicted_label == true_label: color = 'blue' else: color = 'red' plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label], 100*np.max(predictions_array), class_names[true_label]), color=color) def plot_value_array(i, predictions_array, true_label): predictions_array, true_label = predictions_array, true_label[i] plt.grid(False) plt.xticks(range(10)) plt.yticks([]) thisplot = plt.bar(range(10), predictions_array, color="#777777") plt.ylim([0, 1]) predicted_label = np.argmax(predictions_array) thisplot[predicted_label].set_color('red') thisplot[true_label].set_color('blue') ...... 训练代码、预测代码 ...... num_rows = 5 num_cols = 3 num_images = num_rows*num_cols plt.figure(figsize=(2*2*num_cols, 2*num_rows)) for i in range(num_images): plt.subplot(num_rows, 2*num_cols, 2*i+1) plot_image(i, predictions[i], test_labels, test_images) plt.tight_layout() plt.show() ``` 结果: ![](https://key08.com/usr/uploads/2021/07/3961609971.png) 完整代码: ```cpp import numpy as np import pandas as pd import matplotlib.pyplot as plt import os import tensorflow as tf from sklearn.preprocessing import StandardScaler import random (train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.cifar10.load_data() train_images, test_images = train_images / 255.0, test_images / 255.0 class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'] def build_network(): input = tf.keras.Input(shape=(32, 32, 3)) model = tf.keras.layers.Conv2D( 128, (3, 3), input_shape=(32, 32, 3), activation='relu', padding='same')(input) model = tf.keras.layers.Conv2D( 128, (3, 3), input_shape=(32, 32, 3), activation='relu', padding='same')(model) model = tf.keras.layers.MaxPooling2D()(model) model = tf.keras.layers.Conv2D( 256, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.Conv2D( 256, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.MaxPooling2D()(model) model = tf.keras.layers.Conv2D( 512, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.Conv2D( 512, (3, 3), activation='relu', padding='same')(model) model = tf.keras.layers.MaxPooling2D()(model) model = tf.keras.layers.GlobalAveragePooling2D()(model) model = tf.keras.layers.Dense(256, activation='relu')(model) model = tf.keras.layers.Dense(128, activation='relu')(model) model = tf.keras.layers.Dense(64, activation='relu')(model) model = tf.keras.layers.Dense(10, activation='softmax')(model) model = tf.keras.Model(inputs=input, outputs=model) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) return model def plot_image(i, predictions_array, true_label, img): global class_names predictions_array, true_label, img = predictions_array, true_label[i][0], img[i] plt.grid(False) plt.xticks([]) plt.yticks([]) plt.imshow(img, cmap=plt.cm.binary) predicted_label = np.argmax(predictions_array) if predicted_label == true_label: color = 'blue' else: color = 'red' plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label], 100*np.max(predictions_array), class_names[true_label]), color=color) def plot_value_array(i, predictions_array, true_label): predictions_array, true_label = predictions_array, true_label[i][0] plt.grid(False) plt.xticks(range(10)) plt.yticks([]) thisplot = plt.bar(range(10), predictions_array, color="#777777") plt.ylim([0, 1]) predicted_label = np.argmax(predictions_array) thisplot[predicted_label].set_color('red') thisplot[true_label].set_color('blue') network_model = None if os.path.exists("huoji.h5") == False: network_model = build_network() network_model.summary() history = network_model.fit( x=train_images, y=train_labels, epochs=15, validation_data=(test_images, test_labels)) plt.plot(history.history['accuracy'], label='accuracy') plt.plot(history.history['val_loss'], label='val_loss') plt.xlabel('Epoch') plt.ylabel('Accuracy') plt.show() network_model.save('huoji.h5') else: network_model = tf.keras.models.load_model("huoji.h5") predictions = network_model.predict(test_images) num_rows = 5 num_cols = 3 num_images = num_rows*num_cols plt.figure(figsize=(2*2*num_cols, 2*num_rows)) for i in range(num_images): plt.subplot(num_rows, 2*num_cols, 2*i+1) plot_image(i, predictions[i], test_labels, test_images) plt.subplot(num_rows, 2*num_cols, 2*i+2) plot_value_array(i, predictions[i], test_labels) plt.tight_layout() plt.show() ``` 至此 一个非常简单的图像分类网络就已经完成了. 本文由 huoji 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。 点赞 2
还不快抢沙发