目录
1.构建样本集
样本集来自kaggle,读者可以自行下载
因为创建的矩阵要把猫和狗的数据全部存进去,所以通道数要乘2
为了获取更多的特征,让网络得到更好的训练,采用三个通道得彩色图像作为训练集和测试集,所以创建的张量的第二个维度应该为3
import cv2 as cv
import numpy as np
import os
if __name__=='__main__':
l_x=128
m=200#样本数量
m1=70#训练集数量
m2=30#测试集
train_set=np.zeros(m1*2*l_x*l_x*3)
train_set=np.reshape(train_set,(m1*2,3,l_x,l_x))
test_set = np.zeros(m2 * 2 * l_x * l_x * 3)
test_set = np.reshape(test_set, (m2 * 2, 3, l_x, l_x))
sucess_mark=0
#print(sucess_mark)
#构建训练集
for i in range(m1):
path1=f'./images/training_set/training_set/cats/cat.{i+1}.jpg'
path2 = f'./images/training_set/training_set/dogs/dog.{i+1}.jpg'
print(sucess_mark)
if os.path.exists(path1) & os.path.exists(path2):
img1=cv.imread(path1)
img2 = cv.imread(path2)
img1=cv.resize(img1,(l_x,l_x))
img2 = cv.resize(img2, (l_x, l_x))
#猫的图像赋值给矩阵
train_set[i,0,:,:]=img1[:,:,0]
train_set[i, 1, :, :] = img1[:, :, 1]
train_set[i, 2, :, :] = img1[:, :, 2]
sucess_mark+=1
# 狗的图像赋值给矩阵
train_set[m1+i, 0, :, :] = img2[:, :, 0]
train_set[m1+i, 1, :, :] = img2[:, :, 1]
train_set[m1+i, 2, :, :] = img2[:, :, 2]
sucess_mark += 1
print("\r"+f'训练集总数:{m1*2},当前第{(i+1)*2}个',end=' ',flush=True)
else:
print(f'路径{path1}或{path2}不存在!')
break
print('')
#print(sucess_mark)
#构建测试集
for i in range(m2):
path1=f'./images/test_set/test_set/cats/cat.{4000+i+1}.jpg'
path2 = f'./images/test_set/test_set/dogs/dog.{4000+i+1}.jpg'
if os.path.exists(path1) & os.path.exists(path2):
img1 = cv.imread(path1)
img2 = cv.imread(path2)
img1 = cv.resize(img1, (l_x, l_x))
img2 = cv.resize(img2, (l_x, l_x))
# 猫的图像赋值给矩阵
test_set[i, 0, :, :] = img1[:, :, 0]
test_set[i, 1, :, :] = img1[:, :, 1]
test_set[i, 2, :, :] = img1[:, :, 2]
sucess_mark += 1
# 狗的图像赋值给矩阵
test_set[m2 + i, 0, :, :] = img2[:, :, 0]
test_set[m2 + i, 1, :, :] = img2[:, :, 1]
test_set[m2 + i, 2, :, :] = img2[:, :, 2]
sucess_mark += 1
print("\r" + f'测试集总数:{m2 * 2},当前第{(i + 1) * 2}个', end=' ', flush=True)
else:
print(f'路径{path1}或{path2}不存在!')
break
print('')
#print(sucess_mark)
if sucess_mark==200:
np.save('cat_train_set.npy',train_set)
np.save('cat_test_set.npy', test_set)
2.构建网络
import torch.nn as nn
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.ConvNet=nn.Sequential(
nn.Conv2d(in_channels=3,out_channels=8,kernel_size=3,stride=1,padding=1,bias=False),
nn.ReLU(inplace=True),
nn.Conv2d(in_channels=8, out_channels=8, kernel_size=3, stride=1, padding=1, bias=False),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2,stride=2,padding=0)
)
self.LinNet=nn.Sequential(
nn.Linear(64*64*8,1000),
nn.ReLU(inplace=True),#每次进行ReLU函数的时候都进行覆盖
nn.Linear(1000, 1000),
nn.ReLU(inplace=True),
nn.Linear(1000, 2),
nn.Softmax(dim=1)#Softmax分类激活函数
)
def forward(self,x):
x=self.ConvNet(x)#将x传入卷积神经网络
x=x.view(x.size(0),64*64*8)#展成一维数组
out=self.LinNet(x)#通过全连接层
return out
网络在每次训练的时候,数据通过Relu函数都会得到一个新的值,给inplace赋值为True就会直接覆盖赋值,不会申请新的内存空间,从而大大节省了内存空间
3.训练网络
采用小批次训练的方法,因为样本数量较大,一次性全部送入网络中进行训练,可能会导致系统内存不足或者训练效果不佳
同时可视化训练过程
from net import Net
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
net=Net()
x=np.load(file="cat_train_set.npy")/255
x=torch.tensor(x).type(torch.FloatTensor)
y1=torch.zeros(70)
y2=torch.ones(70)
y=torch.cat((y1,y2)).type(torch.LongTensor)
optimizer=torch.optim.SGD(net.parameters(),lr=0.03)
loss_func=nn.CrossEntropyLoss()
samplenum=140#样本总数
minibatch=35#小批次样本大小
w_HR=128#样本尺寸
x0=np.zeros(minibatch*3*w_HR*w_HR)
x0=np.reshape(x0,(minibatch,3,w_HR,w_HR))
y0=np.zeros(minibatch)
x0=torch.tensor(x0).type(torch.FloatTensor)
y0=torch.tensor(y0).type(torch.LongTensor)
plt.ion()
x_plt = [0]
y_plt = [0]
for epoch in range(1000):
for iterations in range(int(samplenum/minibatch)):
k=0
for i in range(iterations*minibatch,iterations*minibatch+minibatch):
x0[k,0,:,:]=x[i,0,:,:]
x0[k, 1, :, :] = x[i, 1, :, :]
x0[k, 2, :, :] = x[i, 2, :, :]
y0[k]=y[i]
k=k+1
out=net(x0)
loss=loss_func(out,y0)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch%50==0:
plt.cla()
plt.xlim((0, 1000))
plt.xlabel('epoch')
plt.ylim((0, 1))
plt.ylabel('loss')
x_plt.append(epoch)
y_plt.append(loss.data)
plt.plot(x_plt,y_plt,c='red',marker='x')
print(f'epoch:{epoch},loss:{loss}')
plt.pause(0.1)
plt.ioff()
plt.show()
torch.save(net,'net.pkl')
4.测试网络
import torch
import numpy as np
net=torch.load('net.pkl')
x=np.load(file="cat_test_set.npy")/255
x=torch.tensor(x).type(torch.FloatTensor)
y1=torch.zeros(30)
y2=torch.ones(30)
y0=torch.cat((y1,y2)).type(torch.LongTensor)
y=net(x)
a1=torch.max(y,1)[1].data.numpy()#返回数字较大的坐标
a2=y0.data.numpy()
print(f'准确率:{sum(a1==a2)/60}')
参考书籍:《python神经网络入门与实战》王凯