卷积神经网络-猫狗识别(附源码)

news2024/11/24 14:30:00

一,项目描述

该项目将使用卷积神经网络算法,识别图片中的动物是还是

数据集地址:https://momodel.cn/explore/5efc77dbc018c95e69fb2a81?type=dataset

其中,训练用的图片数据集在 dogs_cats/data 文件夹下,整个数据集分为训练集和测试集,其中训练集在 dogs_cats/data/train 文件夹内,有 25000 张图片,猫狗各 12500 张。 而测试集在dogs_cats/data/test 文件夹内有 12500 张,没有标明是猫还是狗

部分数据展示如下:

二,神经网络

(1)神经网络结构

可以通过下图进行理解神经网络的基本构成:

(2)图片在计算机内的储存

  图片在计算机储存由像素点矩阵组成,黑白图片的像素点是0-255或者0-1之间的数值,代表明暗程度;彩色图片是RGB图像,RGB表示红,绿,蓝三原色,计算机里所有的颜色都是三原色不同比例组成的,即三色通道

(3)图像的传递

将二维图像经过flatten 展开成一维输入全连接网络中

(4)训练数据

输入一组照片,通过全连接层的处理输出预测值和损失,损失越小越接近真实结果,因此需要找到最好的参数,即让所有的损失和最小,那么如何找到最好的参数呢?

现在选用的方法是梯度下降:

通过梯度下降不断迭代,调整初始参数,找到总损失比较小的最佳参数

三,卷积神经网络

(1)图片的特质
  1. 图片的一些模式比整张图片小的多

  比如说要识别猫,可以只通过猫的一部分特征去进行识别,即一个神经元不需要看到整个图像去发现模式,可以通过较少的参数连接到小区域

  1. 同样的模式可能出现在图像的不同区域

相同的猫耳检测器可以共享参数

  1. 对图像进行缩放不会改变图像中的物体

当图片很大时,图片的像素点也会很多,那么图片传入神经网络后连接数就会很多,参数就会多。缩放后可以使参数减少,简化问题

(2)CNN模型
  1. 卷积层

  卷积核在原始图片中起到探测模式的作用。可以发现卷积核的维度比原始图像要小,实现卷积的过程就是开始时,让卷积核从原始图像左上角对齐,对应每个小格子位置相乘,再将所有的结果相加,得到卷积结果矩阵的第一个值;再将卷积核向右移动,遍历原始图像,以此类推

不同的卷积核有不同的效果,而其中的值都是需要学习的参数

例:原始图片是8x8像素的,卷积核是3x3像素的,卷积结果是多少像素的?

答:6x6像素,8x8矩阵减去边缘一圈,即8-2=6

 (1)边界处理

有两种边界处理方式,Full PaddingSame Padding

(2)Stride: 卷积核每次移动的步长

  1. 最大池化层

在每个小区域内最大值取出来组合,起到图像缩放的作用,减少参数

  1. Flatten层

将二维图像经过flatten 展开成一维输入全连接层中

(3)keras

Sequential 模型:非常简单,只支持单输入,单输出的模型,适用于70%的应用场景

函数式API:支持多输入,多输出模型,适用于95%的应用场景

建立一个全连接层:

import keras
from keras import layers#导入层结构

model = 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'))

# 训练模型
# x-样本数据即图片,y-图片标签,epochs=处理图片的次数,batch_size=一次性处理几张图片
model.fit(x, y, epochs=10, batch_size=32)

建立一个卷积层:

keras.layers.Conv2D(filters, kernel_size, strides=(1,1), padding='valid', data_format=None)
# filters: 输出空间的维度
# kernel_size: 1个整数或2个整数表示的元组,2D卷积窗口的宽度和高度
# strides: 2个整数表示的元组,卷积沿宽度和高度方向的步长
# padding: 边界处理的方法,"valid"或"same"

建立一个最大池化层:

keras.layers.MaxPooling2D(pool_size=(2,2), strides=None, padding='valid', data_format=None )
# pool_size: 沿(垂直,水平)方向缩小比例的因数,如果只有一个整数,则两个维度使用相同窗口长度
# strides: 2个整数表示的元组,步长值,None表示默认值pool_size
# padding: 边界处理的方法,"valid"或"same"
四,代码实现

完整代码在末尾,所有的文件路径都需要修改成自己的文件路径喔!

(1)定义一个基础CNN模型

其中卷积层的卷积核数量为32,卷积核尺寸为3x3,激活函数为ReLU,padding设置为same,最大池化层的尺寸为2x2

#todo:创建一个cnn模型
def define_cnn_model():
    #使用序列模型
    model = Sequential()
    #卷积层
    model.add(Conv2D(32, (3,3), activation="relu",
                    kernel_initializer='he_uniform',
                    padding="same",
                    input_shape=(200,200,3)))
    '''卷积核数量,卷积核维度,激活函数,padding,图片像素200x200,3代表彩色图片'''
    #最大池化层
    model.add(MaxPooling2D((2,2)))
    #Flatten 层
    model.add(Flatten())
    #全连接层
    model.add(Dense(128, activation="relu",kernel_initializer='he_uniform' ))
    model.add(Dense(1, activation="sigmoid"))#输出层0,1,sigmoid模型实现输出值0~1之间,分别代表猫狗

    #编译模型
    opt = SGD(lr=0.001, momentum=0.9)#优化器,随机梯度下降,为模型找到最佳的参数
    model.compile(optimizer=opt,
                   loss='binary_crossentropy',
                   metrics=['accuracy'])
    return model
#打印模型图片
from keras.utils import plot_model
model = define_cnn_model()
plot_model(model,
           to_file='cnn_model.png',
           dpi = 100,
           show_shapes=True,
           show_layer_names=True)

打印出卷积神经网络模型图为:

训练模型:

#训练模型
def train_cnn_model():
    #实例化模型
    model = define_cnn_model()
    #创建图片生成器,产生图片并输入
    datagen = ImageDataGenerator(rescale=1.0 / 225.0)
    train_it = datagen.flow_from_directory(
        'C:\\Users\\Alixy\\Desktop\\ma1ogo3ushu4ju4ji2\\dogs_cats\\data\\train',
        class_mode='binary',
        batch_size=64,  #一次产生并输入64张图片
        target_size=(200, 200)  #缩放图片为200x200,和输入图片大小相同!!!
        )
   #训练模型
    model.fit_generator(train_it,
                        steps_per_epoch=len(train_it),
                        epochs=20,
                        verbose=1 )
    #把模型保存到文件夹,basic_cnn_result.h5是提前就创建好的,用来保存模型的
    model.save("D:\\python\\python\\MCM\\Data_clean\\basic_cnn_result.h5")

运行训练模型:

if __name__ == "__main__":
   train_cnn_model()

这个构建的CNN模型在迭代20个epoch时,可以达到约95%的准确率,是一个不错的结果

使用训练好的模型做一些预测:

从测试文件夹中随机读取一张照片,并进行判断

#定义函数读取测试文件夹中的照片
def read_random_image():
    folder = r'C:\\Users\\Alixy\Desktop\\ma1ogo3ushu4ju4ji2\\dogs_cats\\data\\test\\'
    file_path = folder + random.choice(os.listdir(folder))
    print(file_path)
    pil_im = Image.open(file_path, 'r')
    return pil_im

#对一个使用模型对读取出的图片进行预测
def get_predict(pil_im, model):
    #对图片进行缩放
    pil_im = pil_im.resize((200,200)) #这里很重要,要符合后面输入图片规定的大小
    #将格式转换为 numpy array 格式
    array_im = np.asarray(pil_im)
    array_im = np.expand_dims(array_im, axis=0)
    #对图片进行预测
    result = model.predict(array_im)
    if result[0][0] > 0.5:
        print("预测结果是:狗")
    else:
        print("预测结果是:猫")

pil_im = read_random_image()
get_predict(pil_im, model)
pil_im.show(np.asarray(pil_im)) #显示随机选取的照片

输出结果:

(2)完整代码

  1. CNN_train.py

#导入需要的包
import sys
from matplotlib import pyplot
from keras.utils import to_categorical
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Dense
from keras.layers import Flatten
from keras.optimizers import SGD
from keras.preprocessing.image import ImageDataGenerator
import tensorflow as tf
tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)

#todo:创建一个cnn模型
def define_cnn_model():
    #使用序列模型
    model = Sequential()
    #卷积层
    model.add(Conv2D(32, (3,3), activation="relu",
                    kernel_initializer='he_uniform',
                    padding="same",
                    input_shape=(200,200,3)))
    '''卷积核数量,卷积核维度,激活函数,padding,图片像素200x200'''
    #最大池化层
    model.add(MaxPooling2D((2,2)))
    #Flatten 层
    model.add(Flatten())
    #全连接层
    model.add(Dense(128, activation="relu",kernel_initializer='he_uniform' ))
    model.add(Dense(1, activation="sigmoid"))#输出层0,1,sigmoid模型实现输出值0~1之间,分别代表猫狗

    #编译模型
    opt = SGD(lr=0.001, momentum=0.9)#优化器,随机梯度下降,为模型找到最佳的参数
    model.compile(optimizer=opt,
                   loss='binary_crossentropy',
                   metrics=['accuracy'])
    return model
#打印模型图片
from keras.utils import plot_model
model = define_cnn_model()
plot_model(model,
           to_file='cnn_model_basic.png',
           dpi = 100,
           show_shapes=True,
           show_layer_names=True)

#训练模型
def train_cnn_model():
    #实例化模型
    model = define_cnn_model()
    #创建图片生成器,产生图片并输入
    datagen = ImageDataGenerator(rescale=1.0 / 225.0)
    train_it = datagen.flow_from_directory(
        'C:\\Users\\Alixy\\Desktop\\ma1ogo3ushu4ju4ji2\\dogs_cats\\data\\train',
        class_mode='binary',
        batch_size=64,  #一次产生并输入64张图片
        target_size=(200, 200)  #缩放图片为200x200,和输入图片大小相同
        )
   #训练模型
    model.fit_generator(train_it,
                        steps_per_epoch=len(train_it),
                        epochs=20,
                        verbose=1 )
    #把模型保存到文件夹
    model.save("D:\\python\\python\\MCM\\Data_clean\\basic_cnn_result.h5")

if __name__ == "__main__":
   train_cnn_model()
  1. CNN_predict.py

from keras.models import load_model
#模型地址
model_path = 'D:\\python\\python\\MCM\\Data_clean\\basic_cnn_result.h5'
#载入模型
model = load_model(model_path)

import os, random
import numpy as np
from PIL import Image
#定义函数读取测试文件夹中的照片
def read_random_image():
    folder = r'C:\\Users\\Alixy\Desktop\\ma1ogo3ushu4ju4ji2\\dogs_cats\\data\\test\\'
    file_path = folder + random.choice(os.listdir(folder))
    print(file_path)
    pil_im = Image.open(file_path, 'r')
    return pil_im

#对一个使用模型对读取出的图片进行预测
def get_predict(pil_im, model):
    #对图片进行缩放
    pil_im = pil_im.resize((200,200))
    #将格式转换为 numpy array 格式
    array_im = np.asarray(pil_im)
    array_im = np.expand_dims(array_im, axis=0)
    #对图片进行预测
    result = model.predict(array_im)
    if result[0][0] > 0.5:
        print("预测结果是:狗")
    else:
        print("预测结果是:猫")

pil_im = read_random_image()
get_predict(pil_im, model)
pil_im.show(np.asarray(pil_im)) #显示随机选取的照片

有错误欢迎指正!😃

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/169601.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机视觉Computer Vision课程学习笔记六之Fourier Analysis傅里叶分析

第六章 傅里叶分析 处理图像频率信息 图像的频率是表征图像中灰度变化剧烈程度的指标,是灰度在平面空间上的梯度。 从纯粹的数学意义上看,傅立叶变换是将一个函数转换为一系列周期函数来处理的。从物理效果看,傅立叶变换是将图像从空间域转换…

LinkedList链表知识点概括(一)

作者:爱塔居的博客_CSDN博客-JavaSE,数据结构领域博主 专栏:数据结构 作者简介:大三学生,希望2023年迎来更优秀的自己!希望跟大家一同进步~ 文章目录 前言 一、链表的基本概念 二、面试题实战 前言 顺序表/ArrayList:…

vue2中keepalive手动清理内存,存在子路由内存无法回收的问题

起因 近期客户经常反馈系统崩溃的问题,尤其是在下午最频繁,经过自己的自测,发现系统tab关闭后内存并没有回收掉,目前我已经处理了,tab页签关闭后,手动清理keep-alive内的缓存,应该不存在内存泄…

Qt+C++自定义标题栏最大最小化关闭堆叠切换美化

程序示例精选 QtC自定义标题栏最大最小化关闭堆叠切换美化 如需安装运行环境或远程调试&#xff0c;见文章底部个人微信名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<QtC自定义标题栏最大最小化关闭堆叠切换美化>>编写代码&#xff0c…

这几个办公技巧竟还不知道

技巧一&#xff1a;压缩文件大小 我们可以通过压缩文件大小的方法来减少电脑内存&#xff0c;正好Windows就有自带的压缩包可以操作。 首先我们可以用鼠标右击文件&#xff0c;选择“添加到压缩文件”&#xff0c;最后系统即可帮我们自动压缩文件大小。技巧二&#xff1a;定时清…

C++封装对MySQL的基本操作

1.环境搭建在这里&#xff0c;我将使用vscode来搭建MySQL的编程环境。首先&#xff0c;下载MySQL&#xff0c;配置好系统环境变量并运行MySQL数据库。接着&#xff0c;vscode扩展中搜索并下载MySQL与MySQL Syntax插件。安装完成后&#xff0c;在资源管理器的MySQL栏中点击号&am…

从0到1完成一个Node后端(express)项目(五、session、token)

往期 从0到1完成一个Node后端&#xff08;express&#xff09;项目&#xff08;一、初始化项目、安装nodemon&#xff09; 从0到1完成一个Node后端&#xff08;express&#xff09;项目&#xff08;二、下载数据库、navicat、express连接数据库&#xff09; 从0到1完成一个Nod…

“暗黑天使”降临:DarkAngels勒索病毒全解密

恶意文件分析 恶意文件描述 近期&#xff0c;深信服深盾终端实验室在运营工作中发现了一种 ELF 格式的勒索软件&#xff0c;该勒索软件近期开始出现&#xff0c;其释放的勒索信中的 Onion 链接似乎已关闭&#xff0c;这表明该勒索软件可能仍在开发中。 经过分析&#xff0c;…

AtCoder Beginner Contest 281 (A-F,口胡G)青大acmer 日常vp

A - Count Down 输出小于等于nnn的数 代码 B - Sandwich Number 题意 问字符串是否是第一个和最后一个字符是大小写&#xff0c;中间的字符是100000−99999100000-99999100000−99999之间的数字。 暴力模拟即可&#xff0c;需要注意的例子是A0100000AA0100000AA0100000A 代码 …

day14-常用API

1.API 1.1 API概述【理解】 什么是API ​ API (Application Programming Interface) &#xff1a;应用程序编程接口 java中的API ​ 指的就是 JDK 中提供的各种功能的 Java类&#xff0c;这些类将底层的实现封装了起来&#xff0c;我们不需要关心这些类是如何实现的&#xff…

VScode-git提交 无法推送refs到远端

在将代码同步到远端仓库时&#xff0c;弹窗提醒”无法推送refs到远端。您可以试着运行”拉取”功能&#xff0c;整合您的更改“ 但尝试后发现“拉取”功能也无法解决问题&#xff0c;最后是因为文件过大原因&#xff0c;在这里记录一下解决方法&#xff0c;并整理了另一种可能…

传输层协议:套接字Socket

介绍 socket是一种操作系统提供的进程间通信机制。 在操作系统中&#xff0c;通常会为应用程序提供一组应用程序接口&#xff08;API&#xff09;&#xff0c;称为套接字接口&#xff08;英语&#xff1a;socket API&#xff09;。应用程序可以通过套接字接口&#xff0c;来使…

大数据分析案例-基于决策树算法构建金融反欺诈分类模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

春节期间外贸老鸟们都会掌握的那些事(内含祝福话术及邮件模板)

中国外贸规模在长期疫情的大环境下&#xff0c;外贸业界克服诸多困难&#xff0c;实现了量稳质升。随着我们迈入2023年&#xff0c;外贸人除了需要继续“强身健体”外&#xff0c;同时也将面临更多的挑战&#xff0c;本期Boom将从四个维度给大家分享临近中国春节期间&#xff0…

入门PostgreSQL,pg的历史,为什么说pg是国产化的方向,与mysql的比较

目录一、PG简介1、PG的历史2、PG的社区3、PostgreSQL与MySQL的比较一、PG简介 PostgreSQL 是一个免费的对象-关系数据库服务器(ORDBMS)&#xff0c;在灵活的BSD许可证下发行。 PostgreSQL 开发者把它念作 post-gress-Q-L。 PostgreSQL 的 Slogan 是 “世界上最先进的开源关系…

python-MySQL数据库基础(三)MySQL与python交互

MySQL与python交互 用python代码来连接数据库&#xff0c;执行SQL语句&#xff0c;来查询到数据库中的数据。 当一张表中的数据量比较多时&#xff0c;而我们只需要查询其中的某个字段数据&#xff0c;直接查询会导致效率降低&#xff0c;此时就需要建立分表。 python操作MySQ…

君乐宝,高端之路不好走

文|螳螂观察 作者|kinki 近日&#xff0c;奶粉巨头雅培发表声明称&#xff0c;将逐步停止中国大陆市场的婴幼儿和儿童营养产品的运营和销售&#xff0c;一直以来&#xff0c;雅培都是中国奶粉市场前十名的“常客”&#xff0c;但近年却跌出了“前十”的位置。 雅培的退出&am…

2023年DataWhale 1月Free Excel 第三次打卡

第三章 Excel的表合并 Excel的合并计算工具可以快速完成多个表的行列记录合并。 1.多表行合并 问题&#xff1a;在3个消费表格中&#xff0c;每个客户的消费金额不同&#xff0c;使用多表合并功能统计每个客户消费的总金额。 具体步骤&#xff1a; 1.选择需要汇总的单元格…

ZooKeeper 技术内幕|Leader 选举是一个什么样的过程

几个问题&#xff0c;引发思考&#xff1a; 什么时候 leader 选举&#xff1f; 选举的过程&#xff1f; 选举过程中&#xff0c;是否能提供服务&#xff1f; 选举结果&#xff0c;是否会丢失数据&#xff1f; 服务器角色 2 个小问题&#xff1a; 服务器节点有多少角色&…

如何实现连杆码垛机械臂的逆解计算?

1. 连杆码垛机械臂介绍 连杆码垛机器人是工业应用场景中常用的一种机械臂&#xff0c;常用于简单的大负载搬运作业场景。常见的连杆码垛机械臂都是4个自由度&#xff0c;相较于6轴和7轴的机械臂成本较低。 连杆码垛机械臂的运动特性是&#xff1a;末端始终平行于地面。第一个平…