Advertisement

cnn图像识别python代码_【PyTorch】CNN图像识别分类模型

阅读量:

import numpy as np

import pandas as pd

导入sklearn.metrics模块中的准确率计算(accuracy_score)、混淆矩阵(confusion_matrix)及分类报告(classification_report)

import matplotlib.pyplot as plt

import seaborn as sns

import copy

import time

import torch

import torch.nn as nn

from torch.optim import Adam

import torch.utils.data as Data

from torchvision import transforms

from torchvision.datasets import FashionMNIST

#读取数据

train_data=FashionMNIST(

root="./data/FashionMNIST",

train=True,

transform=transforms.ToTensor(),

download=False

)

#定义数据加载器

train_loader=Data.DataLoader(

dataset=train_data,

batch_size=64,

shuffle=False,

num_workers=0,

)

print("train_loader的batch数量为:",len(train_loader))

#可视化一个batch的图像

#获取一个batc的数据

for step,(b_x,b_y) in enumerate(train_loader):

if step>0:

break

#可视化一个batch的图像

batch_x=b_x.squeeze().numpy()

batch_y=b_y.numpy()

class_label=train_data.classes

class_label[0]="T-shirt"

plt.figure(figsize=(12,5))

for ii in np.arange(len(batch_y)):

plt.subplot(4,16,ii+1)#4行16列

plt.imshow(batch_x[ii,:,:],cmap=plt.cm.gray)

plt.title(class_label[batch_y[ii]],size=9)

plt.axis("off")

plt.subplots_adjust(wspace=0.05)

plt.show()

#测试集数据处理

test_data=FashionMNIST(

root="./data/FashionMNIST",

train=False,

transform=transforms.ToTensor(),

download=False

)

test_data_x=test_data.data.type(torch.FloatTensor)/255.0#归一化

test_data_x=torch.unsqueeze(test_data_x,dim=1)#添加一个通道维度

test_data_y=test_data.targets

print("test_data_x.shape:",test_data_x.shape)

print("test_data_y.shape:",test_data_y.shape)

class MyConvNet(nn.Module):

def init(self):

super(MyConvNet,self).init()

#第一个卷积层

self.conv1=nn.Sequential(

nn.Conv2d(

in_channels=1,

out_channels=16,#162828

kernel_size=3,

stride=1,#步长

padding=1,

),#12828-->162828 正常会变成2626但两侧有填充 所以还是2828

nn.ReLU(),

nn.AvgPool2d(

kernel_size=2,

stride=2,

),#162828-->161414

)

第2个卷积层

self.conv2=nn.Sequential(

nn.Conv2d(16,32,3,1,0),#161414-->321212

nn.ReLU(),

nn.AvgPool2d(2,2)#321212-->3266

)

#分类层

self.classifier=nn.Sequential(

nn.Linear(3266,256),#展平

nn.ReLU(),

nn.Linear(256,128),

nn.ReLU(),

nn.Linear(128,10)

)

def forward(self,x):

x=self.conv1(x)

x=self.conv2(x)

x=x.view(x.size(0),-1)

output=self.classifier(x)

return output

myConvnet=MyConvNet()

print(myConvnet)

def train_learning_algorithm(model(training_data_loader), training_rate, loss_function, optimiser, number_of_epochs=25):

'''

:param model: 网络模型

:param traindataloader: 训练数据集 训练集和测试集

:param train_rate: 训练集batchsize百分比 用于划分训练集和测试集

:param criterion: 损失函数

:param optimizer: 优化器

:param num_epochs: 训练轮数

:return: 训练好的模型和训练过程

'''

batch_num=len(traindataloader)

training batch number = rounding function of (batch number * train rate).# round() method returns the rounded value of x.

best_model_wts=copy.deepcopy(model.state_dict())#复制模型参数

best_acc=0.0

train_loss_all=[]

train_acc_all=[]

val_loss_all=[]

val_acc_all=[]

since=time.time()

for epoch in range(num_epochs):

print('epoch {}/{}'.format(epoch,num_epochs-1))

print('-'*10)

train_loss=0.0

train_corrects=0

train_num=0

val_loss=0.0

val_corrects=0

val_num=0

for step,(b_x,b_y) in enumerate(traindataloader):

if step

model.train()

output=model(b_x)

pre_lab=torch.argmax(output,1)#返回指定维度最大值的序号下标

print(pre_lab)

loss=criterion(output,b_y)#

optimizer.zero_grad()

loss.backward()

optimizer.step()

train_loss+=loss.item()*b_x.size(0)

train_corrects+=torch.sum(pre_lab==b_y.data)

train_num+=b_x.size(0)

else:

model.eval()

output = model(b_x)

pre_lab = torch.argmax(output, 1) # 返回指定维度最大值的序号下标

loss = criterion(output, b_y) #

val_loss += loss.item() * b_x.size(0)

val_corrects += torch.sum(pre_lab == b_y.data)

val_num += b_x.size(0)

train_loss_all.append(train_loss/train_num)

train_acc_all.append(train_corrects.double().item()/train_num)

val_loss_all.append(val_loss/val_num)

val_acc_all.append(val_corrects.double().item()/val_num)

print('{} train loss:{:.4f} train acc:{:.4f}'.format(epoch,train_loss_all[-1],train_acc_all[-1]))

print('{} test loss:{:.4f} test acc:{:.4f}'.format(epoch, val_loss_all[-1], val_acc_all[-1]))

if val_acc_all[-1]>best_acc:

best_acc=val_acc_all[-1]

best_model_wts=copy.deepcopy(model.state_dict())

time_user=time.time()-since

print("train and val complete in{:.0f}m {:.0f}s".format(time_user//60,time_user%60))

model.load_state_dict(best_model_wts)

train_process=pd.DataFrame(

data={

"epoch":range(num_epochs),

"train_loss_all":train_loss_all,

"val_loss_all":val_loss_all,

"train_acc_all":train_acc_all,

"val_acc_all":val_acc_all

}

)

return model,train_process

#训练模型

optimizer=torch.optim.Adam(myConvnet.parameters(),lr=0.01)

criterion=nn.CrossEntropyLoss()

conv_net; training_process = TrainingModel(
conv_net,
train_loader,
0.8; eighty%;
criterion;
OptimizationAlgorithm;
Number_Epochs=25
);

#可视化

plt.figure(figsize=(12,4))

plt.subplot(1,2,1)

调用matplotlib.pyplot模块中的plot函数来绘制训练过程中epoch与损失值的变化曲线图,并为该图形添加标签为'train loss'

plt.plot(train_process.epoch,train_process.val_loss_all,"ro-",label="val loss")

plt.legend()

plt.xlabel("epoch")

plt.ylabel("loss")

plt.subplot(1,2,2)

使用pyplot模块绘制训练过程中各 epoch 的训练准确率曲线

plt.plot(train_process.epoch,train_process.val_acc_all,"ro-",label="val acc")

plt.legend()

plt.xlabel("epoch")

plt.ylabel("acc")

plt.show()

#预测

myConvnet.eval()

output=myConvnet(test_data_x)

pre_lab=torch.argmax(output,1)

acc=accuracy_score(test_data_y,pre_lab)

print("测试集上的预测精度:",acc)

#混淆矩阵热力图

conf_mat=confusion_matrix(test_data_y,pre_lab)

df_cm=pd.DataFrame(conf_mat,index=class_label,columns=class_label)

heatmap=sns.heatmap(df_cm,annot=True,fmt="d",cmap="YlGnBu")

Set the tick labels on the y-axis of the heatmap to be rotated and aligned to the right by calling the set_ticklabels method with the retrieved tick labels as arguments, specifying rotation=0 and horizontal alignment='right'.

设置刻度标签为get_ticklabels()并对其进行旋转45度和水平对齐到右侧

plt.xlabel("true label")

plt.ylabel("predicted label")

plt.show()

全部评论 (0)

还没有任何评论哟~