智慧系統實驗 4
阿新 • • 發佈:2022-05-07
實驗 4 指南 -- by wtyang
點選 這裡 下載資料集,然後執行下面的命令解壓到 /home 資料夾。
unzip -o -d /home/ sample.zip
切換路徑後依次執行下面的命令。
python3 build.py
python3 test_build.py
python3 train.py
python3 test.py
python3 simulation.py
可以直接在本頁面複製程式碼或帶 U 盤過去。建議提前學習一下程式碼。
build.py
''' 程式碼 1: 構建樣本集 ''' import numpy as np import cv2 m1 = 70 # train_set num m2 = 30 # test_set num l = 128 # 輸入長寬設定為 128 success_mark = 0 train_set = np.zeros(m1 * 2 * l * l * 3) train_set = np.reshape(train_set, (m1 * 2, 3, l, l)) test_set = np.zeros(m2 * 2 * l * l * 3) test_set = np.reshape(test_set, (m2 * 2, 3, l, l)) for i in range(m1): path1 = f'./sample/cat.{i}.jpg' path2 = f'./sample/dog.{i}.jpg' img1 = cv2.imread(path1) img2 = cv2.imread(path2) img1 = cv2.resize(img1, (l, l)) img2 = cv2.resize(img2, (l, l)) train_set[i, 0, :, :] = img1[:, :, 0] train_set[i, 1, :, :] = img1[:, :, 1] train_set[i, 2, :, :] = img1[:, :, 2] success_mark += 1 train_set[m1+i, 0, :, :] = img2[:, :, 0] train_set[m1+i, 1, :, :] = img2[:, :, 1] train_set[m1+i, 2, :, :] = img2[:, :, 2] success_mark += 1 for i in range(m2): path1 = f'./sample/cat.{m1+i}.jpg' path2 = f'./sample/dog.{m1+i}.jpg' img1 = cv2.imread(path1) img2 = cv2.imread(path2) img1 = cv2.resize(img1, (l, l)) img2 = cv2.resize(img2, (l, l)) test_set[i, 0, :, :] = img1[:, :, 0] test_set[i, 1, :, :] = img1[:, :, 1] test_set[i, 2, :, :] = img1[:, :, 2] success_mark += 1 test_set[m2+i, 0, :, :] = img2[:, :, 0] test_set[m2+i, 1, :, :] = img2[:, :, 1] test_set[m2+i, 2, :, :] = img2[:, :, 2] success_mark += 1 if success_mark == 200: np.save('cat_train_set.npy', train_set) np.save('cat_test_set.npy', test_set) print('Built success!')
test_build.py
''' 程式碼 2: 測試樣本集是否正常 ''' import numpy as np import cv2 train_set = np.load('cat_train_set.npy') test_set = np.load('cat_test_set.npy') img1 = train_set[69, 0, :, :] img2 = test_set[30, 0, :, :] img1 = img1.astype(np.uint8) img2 = img2.astype(np.uint8) cv2.imshow('cat.69.jpg', img1) cv2.imshow('dog.70.jpg', img2) cv2.waitKey(3000) # 等待 3 s
net_model.py
''' 程式碼 3: 構建分類網路 ''' import torch.nn as nn class ICNET(nn.Module): def __init__(self): super(ICNET, self).__init__() self.ConvNet = nn.Sequential( # 搭建卷積網路 nn.Conv2d(in_channels=3, out_channels=8, kernel_size=3, \ stride=1, padding=1, bias=False), # size: 128, 128, 8 nn.ReLU(inplace=True), nn.Conv2d(in_channels=8, out_channels=8, kernel_size=3, \ stride=1, padding=1, bias=False), # size: 128, 128, 8 nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2, stride=2, padding=0), # size: 64, 64, 8 ) self.LinNet = nn.Sequential( # 搭建網路 nn.Linear(64 * 64 * 8, 1000), # 全連線層 nn.ReLU(inplace=True), 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
train.py
'''
程式碼 4: 訓練網路+視覺化訓練過程
'''
from net_model import ICNET
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
net = ICNET().cuda() # 網路傳入 GPU
x = np.load(file='cat_train_set.npy') / 255
x = torch.tensor(x).type(torch.FloatTensor).cuda()
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).cuda()
y0 = torch.tensor(y0).type(torch.LongTensor).cuda()
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
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='r', marker='x')
plt.title(f'epoch:{epoch}, loss:{loss}')
plt.pause(0.1)
plt.ioff()
plt.show()
torch.save(net, 'net.pkl')
test.py
'''
程式碼 5: 測試網路
'''
import numpy as np
import torch
net = torch.load('net.pkl')
x = np.load(file='cat_train_set.npy') / 255
x = torch.tensor(x).type(torch.FloatTensor).cuda()
y1 = torch.zeros(70)
y2 = torch.ones(70)
y0 = torch.cat((y1, y2))
y = net(x)
a1 = torch.max(y, 1)[1].cpu().data.numpy()
a2 = y0.data.numpy()
print(a1)
print(f'準確率: {sum(a1 == a2) / 140}')
simulation.py
'''
程式碼 6: 模擬實際運用
'''
import numpy as np
import torch
import cv2
net = torch.load('net.pkl')
img = cv2.imread('./sample/dog.20.jpg')
img0 = cv2.resize(img, (128, 128))
x = np.zeros(128 * 128 * 3)
x = np.reshape(x, (1, 3, 128, 128))
x[0, 0, :, :] = img0[:, :, 0] / 255
x[0, 1, :, :] = img0[:, :, 1] / 255
x[0, 2, :, :] = img0[:, :, 2] / 255
x = torch.tensor(x).type(torch.FloatTensor).cuda()
y = net(x)
max_num = torch.max(y, 1)[1]
if max_num == 0:
print('識別結果:圖片中是貓')
str = 'cat'
else:
print('識別結果:圖片中是狗')
str = 'dog'
cv2.imshow(f'{str}', img)
cv2.waitKey(3000)