1. 程式人生 > 其它 >智慧系統實驗 4

智慧系統實驗 4

實驗 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)