目录 引言 1.什么是卷积神经网络? 1.1什么是神经网络? 1.2什么是卷积? 2.准备工作 2.1一些知识: 2.2keras 2.3Conv2D 2.4 MaxPooling2D 3.基于卷积神经网络的猫狗识别 3.1导入必要库 3.2模型定义 3.3实例化模型并训练 3.4获取验证的图片 3.5进行验证 3.6显示预测结果 4.总结 5.代码及数据集
引言 首先,我们看几张图片: 编辑 编辑 编辑 作为人类,我们很轻松就能识别出第一张是猫,后两张是狗。为什么我们知道呢?因为从小我们的爸妈,我们的老师,周围的所有人都指着狗对我们说它是狗,指着猫对我们说它是猫。换句话来说,是别人教我们的,所以我们现在才能识别出猫狗。而对于计算机呢?没有人教它,这些丰富多彩的图片在它眼里,无非都是一个个像素点构成的数字矩阵。该怎么让他识别出来呢?这就是今天所用的卷积神经网络。
1.什么是卷积神经网络? 1.1什么是神经网络? 顾名思义,神经网络是类似于人脑神经元的一种东西。学过生物的我们都知道,神经元彼此之间相互联系,传入一个信号后,可以在神经元之间不断传递,最终促使肌体做出反应,比如被针扎了之后会马上缩手。你也可以笼统的认为神经网络就是一个函数,传入一个或多个参数后,经过一系列变换,输出一个或多个参数。最简单的以y=x+1为例,传入一个值就能输出一个值,当传入x=2的时候输出3,x=3的时候输出4。不过,真正的神经网络要复杂的多。这里以BP神经网络为例: 编辑 目前,你只需要知道神经网络是一个大函数就行,传入输入,传出输出。 想要继续深入学习可以参考:到底什么是神经网络?
1.2什么是卷积? 首先,给出卷积的公式: 编辑 积看出来了,f(t)和g(t)的积,那卷在哪里呢?笔者认为,卷在两个方面: 第一卷是如果将f(t)和g(t)的图像放在同一垂直面上,对应点之间的连线是相互交织在一起的,如果将g函数翻转一下,是不是就舒服很多了呢? 编辑 编辑 第二卷是g函数不等于卷积核,g函数要旋转180度之后才是卷积核。 可参考:卷积神经网络卷在哪里? 强烈推荐:从“卷积”、到“图像卷积操作”、再到“卷积神经网络”,“卷积”意义的3次改变
2.准备工作 2.1一些知识: 1.眼睛只完成图像的摄取功能,识别的关键在于人脑。而人脑对图像的识别是层层抽像的。 2.人工神经元及神经网络模拟了大脑的神经元及其连接。 3.计算机看到的图片是一个个代表明暗的数字。彩色图片是由RGB三色组成的。 4.神经网络需要训练来得到最佳的模型参数。 5.卷积神经网络主要的设计思想是更好的利用图片的性质。
图片的模式比图片小的多
图片中的模式出现在图像的不同区域
缩放不影响图片中的物体
6.卷积层就是在图片中扫描特征 7.最大池化层就是在缩放图片,减少参数。 8.多次的卷积和池化后,再经过flatten连接一个全连接层
2.2keras
keras是一个用python编写的高级神经网络APL
sequential模型
1 2 3 4 5 6 7 import kerasfrom keras import layersmodel = keras.Sequential() model.add(layers.Dense(20 ,activation="relu" ,input_shape=(10 ,))) model.add(layers.Dense(20 ,activation="relu" )) model.add(layers.Dense(10 ,activation="softmax" )) model.fit(x,y,epochs=10 ,batch_size=32 )
keras. Sequential() 建立函数
model.add() 添加层
model.fit() 训练模型
2.3Conv2D 1 keras.layers.Conv2D(filters,kernel_size,strides=(1 ,1 ),padding="valid" ,data_formt=None ))
filters:整数,输出空间的维度,卷积核的数量
kernel_size:一个整数,或者2个整数代表的元组或列表,指明2D卷积窗口的宽度和高度,可以是一个整数,为所有空间维度指定相同的值。
strides:一个整数,或者2个整数代表的元组或列表,指明卷积沿宽度和高度方向的步长。可以是一个整数,为所有空间维度指定相同的值。
padding:"valid"或者"same",大小写敏感,用于边缘处理部分。
2.4 MaxPooling2D 1 keras.layers.MaxPooling2D(pool_size=(2 ,2 ),strides=None ,padding="valid" ,data_format =None )
pool_size:整数,或者2个整数表示的元组,沿(垂直,水平)方向缩小比例的因数。(2,2)会把输入张量的两个维度都缩小一半。如果只使用一个整数,那么两个维度都会使用同样的窗口长度。
strides:整数,2个整数表示的元组,或者是None。表示步长值。如果是None,那么默认值是pool_size。
padding:"valid"或者“same"
3.基于卷积神经网络的猫狗识别 3.1导入必要库 1 2 3 4 5 6 7 8 9 10 11 12 13 import sysfrom matplotlib import pyplotfrom keras.utils import to_categoricalfrom keras.models import Sequentialfrom keras.layers import Conv2Dfrom keras.layers import MaxPool2Dfrom keras.layers import Densefrom keras.layers import Flattenfrom keras.optimizers import SGDfrom keras.preprocessing.image import ImageDataGeneratorfrom keras.models import load_modelimport tensorflow as tftf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
这一部分自己安装就可以,pip install 对应库名,受网络问题可能会有点慢。
3.2模型定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def define_cnn_model (): model = Sequential() model.add(Conv2D(32 ,(3 ,3 ),activation="relu" ,padding="same" ,input_shape=(200 ,200 ,3 ))) model.add(MaxPool2D((2 ,2 ))) model.add(Flatten()) model.add(Dense(128 ,activation="relu" )) model.add(Dense(1 ,activation="sigmoid" )) opt = SGD(lr= 0.001 ,momentum=0.9 ) model.compile (optimizer=opt,loss="binary_crossentropy" ,metrics=["accuracy" ]) return model
首先创建一个Sequential模型 添加一个卷积层,第一个参数是卷积核的数量,第二个是卷积核的规格,(3,3)即为33的,第三个参数是激活函数类型,第四个是边缘的处理办法,第五个因为第一层即为卷积层,要定义输入图片的规格(200,200,3)即为200 200,3说明是彩色图片。 再添加一个池化层,(2,2)说明每2*2化作一个窗格。 再添加一个Flatten层,将池化后的结果展开; 再添加一个全连接层,第一个参数是神经元个数,第二个参数是激活函数的类型; 最后再添加一个全连接层输出结果,注意我们的结果需判断猫狗就行,因此一个神经元就行。 最后用随机梯度编译模型,这一块感兴趣的同学可以自己查阅资料学习。
3.3实例化模型并训练 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def train_cnn_model (): model = define_cnn_model() datagen = ImageDataGenerator(rescale=1.0 /255.0 ) train_it = datagen.flow_from_directory( "./ma1ogo3ushu4ju4ji2/dogs_cats/data/train/" , class_mode="binary" , batch_size=64 , target_size=(200 , 200 )) model.fit_generator(train_it, steps_per_epoch=len (train_it), epochs=5 , verbose=1 ) model.save("my_model.h5" )
首先调用3.2的函数实例化模型,紧接着创建图片生成器:这个作用就是把文件夹中的图片传入模型中训练,知道就行。里面的参数batch_size是规定一次只能传入64张图片,这样可以有效地避免内存的问题。训练模型中一个重要参数epochs,这里设置为5,说明传入的图片他要学习5次。比如,这里我总共传入了2500张图片,它学习了五次,也就是12500张图片。这样的重复学习,可以有效提高进度,但是当你值调整比较大时,会非常耗时。最后将训练好的模型保存到项目文件夹下。
3.4获取验证的图片 1 2 3 4 5 def read_random_image (): folder = r"./ma1ogo3ushu4ju4ji2/dogs_cats/data/test/" file_path = folder + random.choice(os.listdir(folder)) pil_im = Image.open (file_path, 'r' ) return pil_im
3.5进行验证 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 def get_predict (pil_im,model ): name = '' pil_im = pil_im.resize((200 ,200 )) array_im = np.asarray(pil_im) array_im = array_im[np.newaxis,:] result = model.predict([[array_im]]) if result[0 ][0 ]>0.5 : name = "它是狗!" print ("预测结果是:狗" ) else : name = "它是猫!" print ("预测结果是:猫" ) return name
注意一行代码: array_im = array_im[np.newaxis,:] 上一行的array_im 是一个三维数组,不符合运行规范,这里要将其转化为四位数组,否则会报错!
3.6显示预测结果 1 2 3 4 pil_im =read_random_image() imshow(np.asarray(pil_im)) plt.title(get_predict(pil_im,model)) pylab.show()
到这里就大功告成啦!看一下我们的预测结果: 编辑 编辑 编辑 编辑 总体来看,预测效果还是不错的,学习次数在5次的情况下,准确度可以达到70%,感兴趣的话,也可以将学习次数调大一点,看看效果!红色警告是由于GPU和CPU的处理问题,你可以暂时忽略。
4.总结 这个猫狗项目只是一个入门项目,但是它的思想很重要。想想看,只要我们有数据,有模型是不是就能让计算机认识任何我们想要认识的东西。手机的人脸识别,支付宝的人脸支付,甚至在未来有没有可能在无人机上装个摄像头去帮我们抓捕犯罪嫌疑人?人工智能的世界很开阔,未来等着我们去探索! 笔者为入门初学者,所以难免会有错误,欢迎大家指正,感兴趣的话可以在评论区一起交流!
5.代码及数据集 第一部分代码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 """ @Project :神经网络猫狗识别 @File :CNN.py @IDE :PyCharm @Author :咋 @Date :2022/10/2 10:37 """ import sysfrom matplotlib import pyplotfrom keras.utils import to_categoricalfrom keras.models import Sequentialfrom keras.layers import Conv2Dfrom keras.layers import MaxPool2Dfrom keras.layers import Densefrom keras.layers import Flattenfrom keras.optimizers import SGDfrom keras.preprocessing.image import ImageDataGeneratorfrom keras.models import load_modelimport tensorflow as tftf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR) def define_cnn_model (): model = Sequential() model.add(Conv2D(32 ,(3 ,3 ),activation="relu" ,padding="same" ,input_shape=(200 ,200 ,3 ))) model.add(MaxPool2D((2 ,2 ))) model.add(Flatten()) model.add(Dense(128 ,activation="relu" )) model.add(Dense(1 ,activation="sigmoid" )) opt = SGD(lr= 0.001 ,momentum=0.9 ) model.compile (optimizer=opt,loss="binary_crossentropy" ,metrics=["accuracy" ]) return model def train_cnn_model (): model = define_cnn_model() datagen = ImageDataGenerator(rescale=1.0 /255.0 ) train_it = datagen.flow_from_directory( "./ma1ogo3ushu4ju4ji2/dogs_cats/data/train/" , class_mode="binary" , batch_size=64 , target_size=(200 , 200 )) model.fit_generator(train_it, steps_per_epoch=len (train_it), epochs=5 , verbose=1 ) model.save("my_model.h5" ) train_cnn_model()
第二部分代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 """ @Project :神经网络猫狗识别 @File :CNN_test.py @IDE :PyCharm @Author :咋 @Date :2022/10/2 12:12 """ import os,randomimport matplotlib.pyplot as pltfrom keras.models import load_modelfrom matplotlib.pyplot import imshowimport numpy as npfrom PIL import Imagemodel_path = "my_model.h5" model = load_model(model_path) import pylabplt.rcParams['font.sans-serif' ]=['SimHei' ] def read_random_image (): folder = r"./ma1ogo3ushu4ju4ji2/dogs_cats/data/test/" file_path = folder + random.choice(os.listdir(folder)) pil_im = Image.open (file_path, 'r' ) return pil_im def get_predict (pil_im,model ): name = '' pil_im = pil_im.resize((200 ,200 )) array_im = np.asarray(pil_im) array_im = array_im[np.newaxis,:] result = model.predict([[array_im]]) if result[0 ][0 ]>0.5 : name = "它是狗!" print ("预测结果是:狗" ) else : name = "它是猫!" print ("预测结果是:猫" ) return name pil_im =read_random_image() imshow(np.asarray(pil_im)) plt.title(get_predict(pil_im,model)) pylab.show()
数据集下载链接:猫狗数据集 视频教学连接:基于卷积神经网络的猫狗识别