卷积神经网络(CNN)实现图像分类——Python

文章目录

    • 1.代码运行
    • 2.注意事项
    • 3.代码分析
    • 4.源代码

1.代码运行

  1. 输入 1 测试一张图片并预测结果

  1. 输入 2 对测试集整体进行测试,得出准确率(10秒左右)

  2. 输入其他数字自动退出程序

2.注意事项

  1. 本程序包含python库较多,请自行配置(pip),如有需求,请评论或私信

  2. 回复其他数字会自动退出程序

  3. 输入图片要求是28*28像素

  4. 模型训练大概需要2分钟,请耐心等候!

  5. 本代码使用在线MNIST数据库,无需本地MNIST数据库!

  6. 文件会自动在同目录下面生成Model文件夹,里面包含两个文件model.pdoptmodel.pdparams

  7. 如果需要可视化,可以将callbacks行注释去除

  8. 如果需要下图格式,请将上面代码中 verbose=0修改为verbose=1

3.代码分析

  1. 数据预处理,从paddle库得到mnist数据
def data_process():transform = T.Normalize(mean=[127.5], std=[127.5])train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)print('训练样本量:{},测试样本量:{}'.format(len(train_dataset), len(test_dataset)))return train_dataset, test_dataset

2.训练模型

def create_model(train_dataset, test_dataset):print('查找是否存在模型.')# 网络结构代码实现,调用paddle的网络network = paddle.vision.models.LeNet(num_classes=10)model = paddle.Model(network)model.prepare(paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters()),# 优化器paddle.nn.CrossEntropyLoss(),# 损失函数paddle.metric.Accuracy())# 评估指标if not os.path.exists('Model/model.pdopt') or not os.path.exists('Model/model.pdparams'):print('不存在模型,开始训练模型.')# callback = paddle.callbacks.VisualDL(log_dir='visualdl_log_dir_LeNet学习率0.001')# 启动全流程训练model.fit(train_dataset,# 训练数据集test_dataset,# 评估数据集epochs=5,# 训练轮次batch_size=64,# 单次计算数据样本量verbose=0,# callbacks=callback)# 日志展示形式print("模型训练结束")# 进行预测操作# result = model_1.predict(test_dataset)model.save('Model/model')else:model.load('Model/model')print("已经存在训练好的模型!!!")return model

3.测试单张和多张

def Test_one(imgPath, modelPath):model = modelPath# image = preprocessing.StandardScaler().fit_transform(np.array(Image.open(imgPath).convert('L'), dtype='float32'))im = Image.open(imgPath).convert('L')# 为灰度图像,每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。 转换公式:L = R * 299/1000 + G * 587/1000+ B * 114/1000。# im = im.resize((28, 28), Image.ANTIALIAS)im = numpy.array(im).reshape(-1, 1, 28, 28).astype('float32')im = im / 255.0 - 1.0result = model.predict([im], verbose=True)print('预测结果是:', result[0][0].argmax(), '\n')# argmax()得到最大值下标# 测试准确率def Test_all(modelPath):model = modelPathresult = model.evaluate(test_dataset, verbose=1)print('准确率为:', result['acc'])

4.主程序

if __name__ == '__main__':print('训练数据自动使用paddle自带的MINST数据库')print('回复数字1为测试一张图片,回复数字2为测试测试集准确率,回复其他数字自动退出程序!!!\n')train_dataset, test_dataset = data_process()model = create_model(train_dataset, test_dataset)while 1:ans = input('测试一张(1)还是测试集准确率(2):')match (ans):case '1':modelPath = model# 模型文件会生成在本文件同目录下不需要选择,这里Path默认直接加载模型root = tk.Tk()root.withdraw()print('请选择测试图片')imgPath = filedialog.askopenfilename()Test_one(imgPath, modelPath)continuecase '2':modelPath = modelTest_all(modelPath)continuecase _:print('测试结束!!!')exit()

4.源代码

如果是完成大作业需求,请各位自己适配!!!!
#!/usr/bin/env python# -*- coding:utf-8 -*-# @FileName:CNN3.py# @Time:2023/4/24 14:28# @Author:YKWimport osimport paddleimport numpyimport tkinter as tkfrom PIL import Imagefrom tkinter import filedialogimport paddle.vision.transforms as T'protobuf版本建议使用3.20.0,否则会不兼容''训练数据自动使用paddle自带的MINST数据库'# 数据预处理,从paddle库得到mnist数据def data_process():transform = T.Normalize(mean=[127.5], std=[127.5])train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)print('训练样本量:{},测试样本量:{}'.format(len(train_dataset), len(test_dataset)))return train_dataset, test_dataset# 训练模型def create_model(train_dataset, test_dataset):print('查找是否存在模型.')# 网络结构代码实现,调用paddle的网络network = paddle.vision.models.LeNet(num_classes=10)model = paddle.Model(network)model.prepare(paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters()),# 优化器paddle.nn.CrossEntropyLoss(),# 损失函数paddle.metric.Accuracy())# 评估指标if not os.path.exists('Model/model.pdopt') or not os.path.exists('Model/model.pdparams'):print('不存在模型,开始训练模型.')# callback = paddle.callbacks.VisualDL(log_dir='visualdl_log_dir_LeNet学习率0.001')# 启动全流程训练model.fit(train_dataset,# 训练数据集test_dataset,# 评估数据集epochs=5,# 训练轮次batch_size=64,# 单次计算数据样本量verbose=0,# callbacks=callback)# 日志展示形式print("模型训练结束")# 进行预测操作# result = model_1.predict(test_dataset)'''indexs = [5, 20, 48, 210]for idx in indexs:show_img(test_dataset[idx][0], np.argmax(result[0][idx]))'''model.save('Model/model')else:model.load('Model/model')print("已经存在训练好的模型!!!")return model# 测试单张def Test_one(imgPath, modelPath):model = modelPath# image = preprocessing.StandardScaler().fit_transform(np.array(Image.open(imgPath).convert('L'), dtype='float32'))im = Image.open(imgPath).convert('L')# 为灰度图像,每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。 转换公式:L = R * 299/1000 + G * 587/1000+ B * 114/1000。# im = im.resize((28, 28), Image.ANTIALIAS)im = numpy.array(im).reshape(-1, 1, 28, 28).astype('float32')im = im / 255.0 - 1.0result = model.predict([im], verbose=True)print('预测结果是:', result[0][0].argmax(), '\n')# argmax()得到最大值下标# 测试准确率def Test_all(modelPath):model = modelPathresult = model.evaluate(test_dataset, verbose=1)print('准确率为:', result['acc'])if __name__ == '__main__':print('训练数据自动使用paddle自带的MINST数据库')print('回复数字1为测试一张图片,回复数字2为测试测试集准确率,回复其他数字自动退出程序!!!\n')train_dataset, test_dataset = data_process()model = create_model(train_dataset, test_dataset)while 1:ans = input('测试一张(1)还是测试集准确率(2):')match (ans):case '1':modelPath = model# 模型文件会生成在本文件同目录下不需要选择,这里Path默认直接加载模型root = tk.Tk()root.withdraw()print('请选择测试图片')imgPath = filedialog.askopenfilename()Test_one(imgPath, modelPath)continuecase '2':modelPath = modelTest_all(modelPath)continuecase _:print('测试结束!!!')exit()