代码参考bilibili UP主——小黑黑讲AI
【bilibili】基于pytorch实现一个神经网络,训练非线性的分类模型
本人并不是这位UP。
前言部分记录下总是容易出错的地方
- 总是提示说mat1和mat2的数据类型不符,这个太坑了,numpy的float是float64,要换成torch的float32,或者直接torch.float类型就行了;
- 有关tensor,确实乱七八糟的,一定要自己看看是不是想要的shape
- 变量命名方式,可以参考torch官网来,保证自己代码的风格一致,比如X是feature,y是label啥的,pred是测试的结果。
# 制造数据
import numpy as np
import matplotlib.pyplot as plt
def make_data(num, seed=10):
np.random.seed(seed)
r_rand = np.random.standard_normal(num)*0.3
t_rand = np.random.random(num)*np.pi*2
center = np.array([[0,0]]*num)+np.array([r_rand*np.cos(t_rand),r_rand*np.sin(t_rand)]).T
plt.scatter(center[:,0],center[:,1], c='r')
r_rand = np.random.standard_normal(num)*0.3+2
t_rand = np.random.random(num)*np.pi*2
center1 = np.array([[0,0]]*num)+np.array([r_rand*np.cos(t_rand),r_rand*np.sin(t_rand)]).T
plt.scatter(center1[:,0],center1[:,1], c='g')
r_rand = np.random.standard_normal(num)*0.5
t_rand = np.random.random(num)*np.pi*2
c = 2.5
op =[[c,c],[c,-c],[-c,c],[-c,-c]]*num
np.random.shuffle(op)
corner = np.array(op[:num])+np.array([r_rand*np.cos(t_rand),r_rand*np.sin(t_rand)]).T
plt.scatter(corner[:,0],corner[:,1], c='b')
return center, center1, corner
make_data(100,seed=100)
plt.show()
import torch
import torch.nn as nn
device_label = 'dml' # 这里如果是dml,则需要安装directml库,对amd老显卡使用
if torch.cuda.is_available():
device = 'cuda'
elif device_label == 'dml':
import torch_directml
device = torch_directml.device()
else:
device = 'cpu'
class Network(nn.Module):
def __init__(self):
super().__init__()
# self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(2, 10),
nn.ReLU(),
nn.Linear(10, 3),
nn.ReLU(),
nn.Linear(3, 3),
)
def forward(self, x):
# x = self.flatten(x)
x = self.linear_relu_stack(x)
return x
# 数据处理,以及导入模型
in_dim = 2
hid_dim = 10
out_dim = 3
learning_rate = 1e-3
batch_size = 10
epochs = 1000
def dataset():
c1, c2, c3 = make_data(100)
plt.show()
c1 = torch.tensor(c1,dtype=torch.float).to(device)
c2 = torch.tensor(c2,dtype=torch.float).to(device)
c3 = torch.tensor(c3,dtype=torch.float).to(device)
X = torch.cat((c1, c2, c3), 0).to(device)
y = torch.tensor([0] * len(c1) + [1] * len(c2) + [2] * len(c3)).to(device)
return X, y
model = Network().to(device)
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
def train(model, X, y, epochs, loss_fn, optimizer):
model.train()
for epoch in range(epochs):
pred = model(X)
loss = loss_fn(pred, y)
loss.backward()
optimizer.step()
optimizer.zero_grad()
if (epoch+1) % 100 == 0:
loss, current = loss.item(), (epoch+1) * len(X)
print(f"loss: {loss:>7f} epochs: {current:>5d}")
# 开始迭代训练
X, y = dataset()
train(model, X, y, epochs, loss_fn, optimizer)
import tqdm
# 绘制等高图
def draw_decision_boundary(model, xlim ,ylim):
# 生成网格数据点
xx, yy = np.meshgrid(np.linspace(xlim[0], xlim[1], 100),
np.linspace(ylim[0], ylim[1], 100))
x_pred = xx.ravel()
y_pred = yy.ravel()
z = list()
bar = tqdm.tqdm(zip(x_pred,y_pred))
i =0
for X in bar:
X = torch.FloatTensor([X]).to(device)
with torch.no_grad():
pred = model(X).max(1)[1].item()
z.append(pred)
i+=1
bar.desc = f'{i} / {len(x_pred)}'
z = np.array(z).reshape(xx.shape)
return xx, yy, z
x,y,z = draw_decision_boundary(model, [-4, 4],[-4, 4])
plt.contourf(x, y, z)
make_data(100)
plt.show()
10000 / 10000: 10000it [00:10, 927.89it/s]