当前位置: 首页 > 后端技术 > Python

100天搞定机器学习-day40-42TensorflowKeras识别猫狗

时间:2023-03-26 02:05:09 Python

100天搞定机器学习|1-38天,100天搞定机器学习|day39TensorflowKeras手写数字识别上一篇我们使用keras的Sequential模型实现mnist手写数字识别,准确率为0.9713。今天我们完成day40-42课程,实现猫狗识别。本文数据集下载地址为https://download.microsoft.co...本文需要使用到OpenCV和Tqdm。OpenCV是一个跨平台的计算机视觉库,它实现了许多图像处理和计算机视觉的通用算法。tqdm用于显示进度条。使用起来非常直观(在循环体内加了一个tqdm),基本不影响原程序的运行效率。安装非常简单,只需要pipinstall即可:1.数据预处理数据集有12501张猫狗图片。首先,这些图像的大小和颜色是统一的。importlibraryimportnumpyasnpimportmatplotlib.pyplotaspltimportosimportcv2fromtqdmimporttqdm看一张转换后的图片DATADIR="...\\PetImages"#数据集的路径,请修改CATEGORIES=["Dog","Cat"]forcategoryinCATEGORIES:path=os.path.join(DATADIR,category)#在os.listdir(path)中为img创建一个路径:#遍历每个图像img_array=cv2.imread(os.path.join(path),img),cv2.IMREAD_GRAYSCALE)#转换为数组plt.imshow(img_array,cmap='gray')#转换为图像显示plt.show()#显示!break#我们只展示一个作为demo,所以直接break吧break#同上?查看数组中存储的图像数据:print(img_array)[[117117119…133132132][118117119…135134134][119118120...137136136]...[797473...807673][787269...727374][747170...757371]]看形状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,(IMG_SIZE,IMG_SIZE))plt.imshow(new_array,cmap='gray')plt.show()接下来,我们将创建所有这些训练数据,但是,首先我们应该留出一些图像用于最终测试我将手动创建一个名为Testing的目录,然后在其中创建2个目录,一个用于Dog,一个用于Cat。从这里开始,我会将狗和猫的前15张图像移到训练版本中。确保移动它们,而不是复制它们。我们将使用它进行最终测试。training_data=[]defcreate_training_data():forcategoryinCATEGORIES:path=os.path.join(DATADIR,category)class_num=CATEGORIES.index(category)#获取分类,其中d0ingforimq(d0ing=dog1=catOs.listdir(Path):尝试:Img_array=cv2.imread(os.path.join(PATH,IMG),CV2.imream_grale)New_ARRAY=cv2.ReSize(img_array,(img_size,img_size)).Append([new_array,class_num]#AddtotheExceptExceptionasE:#toensuretheoutputisacleanPass#exceptOSERRORAsE:#Print("OSERRRROROBADIMGMOSTLIKly",E,OS.Path.Join复制代码(OS.PATH.JOIN路径,img))#exceptExceptionase:#print("generalexception",e,os.path.join(path,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张图像。我们所做的其中一件事就是确保我们的数据是平衡的。对于这个数据集,我可以看到数据集一开始就是平衡的。通过平衡,我的意思是每个班级都有相同数量的例子(相同数量的狗和猫)。如果不平衡,要么将类别权重传递给模型,以便它可以适当地测量误差,要么通过将较大的集合修剪为与较小的集合大小相同来平衡样本。现在数据集不是全是狗就是全是猫,所以接下来我们引入随机:我们可以通过迭代几个初始样本并打印出类来确认这一点:forsampleintraining_data[:10]:print(sample[1])0101101010现在我们可以看到0和1是交替的,我们可以开始我们的模型:X=[]y=[]forfeatures,labelintraining_data:X.append(features)y.append(label)print(X[0].reshape(-1,IMG_SIZE,IMG_SIZE,1))X=np.array(X).reshape(-1,IMG_SIZE,IMG_SIZE,1)让我们保存这些数据,这样我们就不需要在每次要使用神经网络模型时都继续计算它:importpicklepickle_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()#我们总是可以将它加载到我们当前的脚本中,或者一个全新的脚本: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->FullyConnectedLayer(全连接层)->OutputConvolution(卷积)是获取行为原始数据并从中创建特征图。Pooling就是降采样,通常是“max-pooling”的形式,我们选择一个区域,然后取该区域的最大值,这将成为整个区域的新值。全连接层是典型的神经网络,其中所有节点都是“全连接”的。卷积层不像传统的神经网络那样完全连接。卷积:我们将获取一些窗口并在该窗口中寻找特征,该窗口的特征现在只是新特征图中的一个像素大小的特征,但实际上我们会有多层特征图。接下来,我们将那个窗口滑过并继续这个过程,继续这个过程,直到覆盖整个图像。池化:最常见的池化形式是“最大池化”,我们只需在一个窗口中取最大值,该值就成为该区域的新值。全连接层:每个卷积和池化步骤都是一个隐藏层。在此之后,我们有一个完全连接的层,然后是一个输出层。全连接层是典型的神经网络(多层感知器)类型的层,与输出层相同。注意这段代码中需要的X.pickle和y.pickle是上一篇文章的输出,请根据自己的情况更改路径!本文由译者根据原文整理而成,可能有不妥之处。您可以点击此处查看原文。从tensorflow.keras.datasets导入tensorflowastf从tensorflow.keras.preprocessing.image导入cifar10从tensorflow.keras.models导入ImageDataGenerator从tensorflow.keras.layers导入Sequential从tensorflow.keras.layers导入Dense,Dropout,Activation,Flatten从tensorflow.keras.layers导入Conv2D,MaxPooling2Dimportpicklepickle_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,3)))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Flatten())#这将我们的3D特征映射转换为1D特征向量model.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)Trainon17462samples,validateon7484samplesEpoch1/3step-loss:0.6728-acc:0.6019-val_loss:0.6317-val_acc:0.6463Epoch2/3step-loss:0.6164-acc:0.6673-val_loss:0.6117-val_acc:0.6776Epoch3/3step-loss:0.5690-acc:0.7129-val_loss:0.586只有三个时代之后,我们有71%的验证准确率如果我们继续进行更多的epoch,我们可能会做得更好,但我们应该讨论我们如何知道我们在做什么。为了解决这个问题,我们可以使用TensorFlow自带的TensorBoard,它有助于在训练模型的同时可视化模型。3.模型调优在这一部分,我们将讨论TensorBoard。TensorBoard是一个方便的应用程序,允许在浏览器中查看模型或模型的各个方面。我们将TensorBoard与Keras结合使用的方式是通过Keras回调。实际上有很多Keras回调,您可以自己制作。fromtensorflow.keras.callbacksimportTensorBoard#CreateTensorBoardcallbackobjectNAME="Cats-vs-dogs-CNN"tensorboard=TensorBoard(log_dir="logs/{}".format(NAME))最后,你会想要更多的自定义名称对于,但现在就这样做。所以这将保存模型的训练数据日志/名称,然后由TensorBoard读取。最后,我们可以将此回调添加到我们的模型中,方法是将其添加到.fit方法中,例如:model.fit(X,y,batch_size=32,epochs=3,validation_split=0.3,callbacks=[tensorboard])注意回调是一个列表。其他回调也可以传递到这个列表中。我们的模型还没有确定的权利,所以现在让我们把它放一起:importtensorflowastffromtensorflow.keras.datasetsimportcifar10fromtensorflow.keras.preprocessing.imageimportImageDataGeneratorfromtensorflow.keras.modelsimportSequentialfromtensorflow.keras.layersimportDense,Dropout,Activation,Flattenfromtensorflow.keras.layersimportConv2D,MaxPooling2Dfromtensorflow.keras.callbacksimportTensorBoard#更多关于callbakcs的信息:https://keras.io/callbacks/modelsaver也很酷。importpickleimporttimeNAME="Cats-vs-dogs-CNN"pickle_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,3)))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Flatten())#这会转换我们的3D特征e映射到一维特征向量model.add(Dense(64))model.add(Dense(1))model.add(Activation('sigmoid'))tensorboard=TensorBoard(log_dir="logs/{}".format(NAME))model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'],)model.fit(X,y,batch_size=32,epochs=3,validation_split=0.3,callbacks=[tensorboard])在17462个样本上训练,在7484个样本上验证Epoch1/3step-loss:0.6992-acc:0.5480-val_loss:0.6900-val_acc:0.5274Epoch2/3step-loss:0.6754-acc:0.5_ac-0.5_ac-60.5885Epoch3/3step-loss:0.6377-acc:0.6483-val_loss:0.6217-val_acc:0.6625运行后,应该有一个名为logs的新目录我们现在可以使用tensorboard可视化来自该目录的初始结果。打开控制台,切换到工作目录,然后键入:tensorboard--logdir=logs/。您应该会看到一条通知:TensorBoard1.10.0athttp://H-PC:6006(按CTRL+C退出)“h-pc”是机器的名称。打开浏览器并转到此地址。您应该会看到类似这样的内容:现在我们可以看到我们的模型随时间的变化。让我们改变模型中的一些东西。首先,我们从不在密集层中添加激活。另外,让我们试试整体比较小的模型:fromtensorflow.keras.modelsimportSequentialfromtensorflow.keras.layersimportDense,Dropout,Activation,Flattenfromtensorflow.keras.layersimportConv2D,MaxPooling2Dfromtensorflow.keras.callbacksimportTensorBoard#more关于callbakcs的信息:https://keras.io/callbacks/modelsaver也很酷。importpickleimporttimeNAME="Cats-vs-dogs-64x2-CNN"pickle_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()模型.add(Conv2D(64,(3,3),input_shape=X.shape[1:]))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Conv2D(64,(3,3)))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Flatten())#这将我们的3D特征图转换为1D特征向量=TensorBoard(log_dir="logs/{}".format(NAME))model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'],)model.fit(X,y,batch_size=32,epochs=10,validation_split=0.3,callbacks=[tensorboard])除此之外,我还重命名了NAME="Cats-vs-dogs-64x2-CNN"不要忘记这样做,否则你会不小心附上你以前模型的日志,看起来不太好。现在让我们检查一下TensorBoard:它看起来更好!但是,您可能会立即注意到验证损失的形状。损失是错误的衡量标准,似乎很明显,在我们的第四个时代之后,事情开始变糟。有趣的是,我们的验证准确性仍然保持稳定,但我想它最终会开始下降。更有可能的是,首先遭受的确实是您的验证损失。这应该提醒您,您几乎肯定会开始过度拟合。发生这种情况是因为模型一直在尝试减少样本损失。在某个时候,模型不再学习有关实际数据的一般知识,而是开始只记住输入数据。如果你继续这样做,是的,样本内的“准确度”会上升,但你的样本,以及你试图提供给模型的任何新数据都可能表现不佳。参考https://github.com/MLEveryday...https://github.com/MLEveryday...https://github.com/MLEveryday...