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()
