100天搞定机器学习|day40-42 Tensorflow Keras识别猫狗

100天搞定机器学习|day40-42 Tensorflow Keras识别猫狗,第1张

概述"100天搞定机器学习|1 38天" "100天搞定机器学习|day39 Tensorflow Keras手写数字识别" 前文我们用keras的Sequenti

100天搞定机器学习|1-38天
100天搞定机器学习|day39 Tensorflow Keras手写数字识别

前文我们用keras的Sequential 模型实现mnist手写数字识别,准确率0.9713。今天我们完成day40-42的课程,实现猫、狗的识别。

本文数据集下载地址
https://download.microsoft.com/download/3/E/1/3E1C3F21-ECDB-4869-8368-6DEBA77B919F/kagglecatsanddogs_3367a.zip

本文需要用到OpenCV和Tqdm。OpenCV是跨平台计算机视觉库,可以实现了图像处理和计算机视觉方面的很多通用算法。Tqdm是用来显示进度条的,使用很直观(在循环体里边加个tqdm),基本不影响原程序效率。安装都很简单,只需要pip install即可:

1、数据预处理

数据集各有12501张猫和狗的图像,先对这些图像进行尺寸统一和颜色处理。

导入库

import numpy as npimport matplotlib.pyplot as pltimport osimport cv2from tqdm import tqdm

看一张转换后的图片

DATADIR = "...\Petimages" # 数据集的路径,请根据需要修改CATEGORIES = ["Dog", "Cat"]for category in CATEGORIES:         path = os.path.join(DATADIR,category)  # 创建路径        for img in os.Listdir(path):  # 迭代遍历每个图片        img_array = cv2.imread(os.path.join(path,img) ,cv2.IMREAD_GRAYSCALE)  # 转化成array        plt.imshow(img_array, cmap='gray')  # 转换成图像展示        plt.show()  # display!        break  # 我们作为演示只展示一张,所以直接break了    break  #同上

看下array中存储的图像数据:

print(img_array)

[[117 117 119 … 133 132 132]
[118 117 119 … 135 134 134]
[119 118 120 … 137 136 136]

[ 79  74  73 …  80  76  73]
[ 78  72  69 …  72  73  74]
[ 74  71  70 …  75  73  71]]
看下array的形状:

print(img_array.shape)

(375,500)
我们可以看到这是一张很大的图片,并且拥有RGB3个通道,这并不是我们想要的,所以接下来我们将要进行的 *** 作会使图像变小,并且只剩下灰度:

img_SIZE = 50new_array = cv2.resize(img_array, (img_SIZE, img_SIZE))plt.imshow(new_array, cmap='gray')plt.show()

SIZE设置成50有一些模糊,尝试下100:

img_SIZE = 100new_array = cv2.resize(img_array, cmap='gray')plt.show()

接下来,我们将要创建所有这些培训数据,但是,首先,我们应该留出一些图像进行最终测试。我将手动创建一个名为Testing的目录,然后在其中创建2个目录,一个用于Dog,一个用于Cat。从这里开始,我将把Dog和Cat的前15张图像移到训练版本中。确保移动它们,而不是复制。我们将使用它进行最终测试。

training_data = []def create_training_data():    for category in CATEGORIES:          path = os.path.join(DATADIR,category)          class_num = CATEGORIES.index(category)  # 得到分类,其中 0=dog 1=cat        for img in tqdm(os.Listdir(path)):              try:                img_array = cv2.imread(os.path.join(path,cv2.IMREAD_GRAYSCALE)                  new_array = cv2.resize(img_array, img_SIZE))  # 大小转换                training_data.append([new_array, class_num])  # 加入训练数据中            except Exception as e:  # 为了保证输出是整洁的                pass            #except OSError as e:            #    print("OSErrroBad img most likely", e, os.path.join(path,img))            #except Exception as e:            #    print("general exception",img))create_training_data()print(len(training_data))

100%|██████████| 12501/12501 [00:36<00:00,342.82it/s]
100%|██████████| 12501/12501 [00:39<00:00,320.35it/s]
24946
我们有大约25,000张图片。
我们要做的一件事是确保我们的数据是平衡的。在这个数据集的情况下,我可以看到数据集开始时是平衡的。平衡,我的意思是每个班级都有相同数量的例子(相同数量的狗和猫)。如果不平衡,要么将类权重传递给模型,以便它可以适当地测量误差,或者通过将较大的集修剪为与较小集相同的大小来平衡样本。
现在数据集中要么全是dog要么全是cat,因此接下来要引入随机:

import randomrandom.shuffle(training_data)

我们的training_data是一个列表,这意味着它是可变的,所以它现在很好地改组了。我们可以通过迭代几个初始样本并打印出类来确认这一点:

for sample in training_data[:10]:    print(sample[1])

0
1
0
1
1
0
1
0
1
0
现在可以看到已经是0、1交替了,我们可以开始我们的模型了:

X = []y = []for features,label in training_data:    X.append(features)    y.append(label)print(X[0].reshape(-1, img_SIZE, 1))X = np.array(X).reshape(-1, 1)

让我们保存这些数据,这样我们就不需要每次想要使用神经网络模型时继续计算它:

import picklepickle_out = open("...\X.pickle","wb")pickle.dump(X, pickle_out)pickle_out.close()pickle_out = open("...\y.pickle","wb")pickle.dump(y, pickle_out)pickle_out.close()# We can always load it in to our current script, or a totally new one by doing:pickle_in = open("...\X.pickle","rb")X = pickle.load(pickle_in)pickle_in = open("...\y.pickle","rb")y = pickle.load(pickle_in)

现在我们已经拿出了数据集,我们已经准备好覆盖卷积神经网络,并用我们的数据进行分类。
以上就是这次的关于数据集 *** 作的全部任务。

2、训练模型

基础知识
基本的CNN结构如下:Convolution(卷积) -> Pooling(池化) -> Convolution -> Pooling -> Fully Connected Layer(全连接层) -> Output

Convolution(卷积)是获取原始数据并从中创建特征映射的行为。Pooling(池化)是下采样,通常以“max-pooling”的形式,我们选择一个区域,然后在该区域中取最大值,这将成为整个区域的新值。Fully Connected Layers(全连接层)是典型的神经网络,其中所有节点都“完全连接”。卷积层不像传统的神经网络那样完全连接。

卷积:我们将采用某个窗口,并在该窗口中查找要素,该窗口的功能现在只是新功能图中的一个像素大小的功能,但实际上我们将有多层功能图。接下来,我们将该窗口滑过并继续该过程,继续此过程,直到覆盖整个图像。

池化:最常见的池化形式是“最大池化”,其中我们简单地获取窗口中的最大值,并且该值成为该区域的新值。

全连接层:每个卷积和池化步骤都是隐藏层。在此之后,我们有一个完全连接的层,然后是输出层。完全连接的层是典型的神经网络(多层感知器)类型的层,与输出层相同。

注意
本次代码中所需的X.pickle和y.pickle为上一篇的输出,路径请根据自己的情况更改!

此篇中文为译者根据原文整理得到,可能有不当之处,可以点击此处查看原文。

import tensorflow as tffrom tensorflow.keras.datasets import cifar10from tensorflow.keras.preprocessing.image import ImageDataGeneratorfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense,Dropout,Activation,Flattenfrom tensorflow.keras.layers import Conv2D,MaxPooling2Dimport picklepickle_in = open("../datasets/X.pickle","rb")X = pickle.load(pickle_in)pickle_in = open("../datasets/y.pickle","rb")y = pickle.load(pickle_in)X = X/255.0model = Sequential()model.add(Conv2D(256,(3,3),input_shape=X.shape[1:]))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Conv2D(256,3)))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Flatten())  # this converts our 3D feature maps to 1D feature vectorsmodel.add(Dense(64))model.add(Dense(1))model.add(Activation('sigmoID'))model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])model.fit(X,y,batch_size=32,epochs=3,valIDation_split=0.3)

Train on 17462 samples,valIDate on 7484 samples
Epoch 1/3
step - loss: 0.6728 - acc: 0.6019 - val_loss: 0.6317 - val_acc: 0.6463
Epoch 2/3
step - loss: 0.6164 - acc: 0.6673 - val_loss: 0.6117 - val_acc: 0.6776
Epoch 3/3
step - loss: 0.5690 - acc: 0.7129 - val_loss: 0.5860 - val_acc: 0.6963

在仅仅三个epoches之后,我们的验证准确率为71%。如果我们继续进行更多的epoches,我们可能会做得更好,但我们应该讨论我们如何知道我们如何做。为了解决这个问题,我们可以使用TensorFlow附带的TensorBoard,它可以帮助在训练模型时可视化模型。3、模型调参

在这一部分,我们将讨论的是TensorBoard。TensorBoard是一个方便的应用程序,允许在浏览器中查看模型或模型的各个方面。我们将TensorBoard与Keras一起使用的方式是通过Keras回调。实际上有很多Keras回调,你可以自己制作。

from tensorflow.keras.callbacks import TensorBoard#创建TensorBoard回调对象name = "Cats-vs-dogs-CNN"tensorboard = TensorBoard(log_dir="logs/{}".format(name))

最终,你会希望获得更多的自定义name,但现在这样做。因此,这将保存模型的训练数据logs/name,然后由TensorBoard读取。

最后,我们可以通过将它添加到.fit方法中来将此回调添加到我们的模型中,例如:

model.fit(X,valIDation_split=0.3,callbacks=[tensorboard])

请注意,这callbacks是一个列表。也可以将其他回调传递到此列表中。我们的模型还没有定义,所以现在让我们把它们放在一起:

import tensorflow as tffrom tensorflow.keras.datasets import cifar10from tensorflow.keras.preprocessing.image import ImageDataGeneratorfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense,MaxPooling2Dfrom tensorflow.keras.callbacks import TensorBoard# more info on callbakcs: https://keras.io/callbacks/ model saver is cool too.import pickleimport timename = "Cats-vs-dogs-CNN"pickle_in = open("../datasets/X.pickle",2)))model.add(Flatten())  # this converts our 3D feature maps to 1D feature vectorsmodel.add(Dense(64))model.add(Dense(1))model.add(Activation('sigmoID'))tensorboard = TensorBoard(log_dir="logs/{}".format(name))model.compile(loss='binary_crossentropy',metrics=['accuracy'],)model.fit(X,callbacks=[tensorboard])

Train on 17462 samples,valIDate on 7484 samples
Epoch 1/3
step - loss: 0.6992 - acc: 0.5480 - val_loss: 0.6900 - val_acc: 0.5274
Epoch 2/3
step - loss: 0.6754 - acc: 0.5782 - val_loss: 0.6685 - val_acc: 0.5885
Epoch 3/3
step - loss: 0.6377 - acc: 0.6483 - val_loss: 0.6217 - val_acc: 0.6625
运行此之后,应该有一个名为的新目录logs。我们现在可以使用tensorboard从这个目录中可视化初始结果。打开控制台,切换到工作目录,然后键入:tensorboard --logdir=logs/。应该看到一个通知:TensorBoard 1.10.0 at http://H-PC:6006 (Press CTRL+C to quit)“h-pc”是机器的名称。打开浏览器并前往此地址。你应该看到类似的东西:

现在我们可以看到我们的模型随着时间的推移。让我们改变模型中的一些东西。首先,我们从未在密集层中添加激活。另外,让我们尝试整体较小的模型:

from tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense,MaxPooling2Dfrom tensorflow.keras.callbacks import TensorBoard# more info on callbakcs: https://keras.io/callbacks/ model saver is cool too.import pickleimport timename = "Cats-vs-dogs-64x2-CNN"pickle_in = open("../datasets/X.pickle","rb")y = pickle.load(pickle_in)X = X/255.0model = Sequential()model.add(Conv2D(64,2)))model.add(Conv2D(64,2)))model.add(Flatten())  # this converts our 3D feature maps to 1D feature vectorsmodel.add(Dense(64))model.add(Activation('relu'))model.add(Dense(1))model.add(Activation('sigmoID'))tensorboard = TensorBoard(log_dir="logs/{}".format(name))model.compile(loss='binary_crossentropy',epochs=10,callbacks=[tensorboard])

除此之外,我还改名为name = "Cats-vs-dogs-64x2-CNN"。不要忘记这样做,否则你会偶然附加到你以前的型号的日志,它看起来不太好。我们现在检查TensorBoard:

看起来更好!但是,可能会立即注意到验证丢失的形状。损失是衡量错误的标准,看起来很明显,在我们的第四个时代之后,事情开始变得糟糕。

有趣的是,我们的验证准确性仍然持续,但我想它最终会开始下降。更可能的是,第一件遭受的事情确实是你的验证损失。这应该提醒你,你几乎肯定会开始过度适应。这种情况发生的原因是该模型不断尝试减少样本损失。

在某些时候,模型不是学习关于实际数据的一般事物,而是开始只记忆输入数据。如果你继续这样做,是的,样本中的“准确性”会上升,但你的样本,以及你试图为模型提供的任何新数据可能会表现得很差。

参考

https://github.com/MLEveryday/100-Days-Of-ML-Code/blob/master/Code/Day 40.ipynb

https://github.com/MLEveryday/100-Days-Of-ML-Code/blob/master/Code/Day 41.ipynb

https://github.com/MLEveryday/100-Days-Of-ML-Code/blob/master/Code/Day 42.ipynb

总结

以上是内存溢出为你收集整理的100天搞定机器学习|day40-42 Tensorflow Keras识别猫狗全部内容,希望文章能够帮你解决100天搞定机器学习|day40-42 Tensorflow Keras识别猫狗所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1189895.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存