神经网络代码入门解析
import torch
import matplotlib.pyplot as plt
import random
def create_data(w, b, data_num): # 数据生成
x = torch.normal(0, 1, (data_num, len(w)))
y = torch.matmul(x, w) + b # 矩阵相乘再加b
noise = torch.normal(0, 0.01, y.shape) # 为y添加噪声
y += noise
return x, y
num = 500
true_w = torch.tensor([8.1, 2, 2, 4])
true_b = 1.1
X, Y = create_data(true_w, true_b, num)
plt.scatter(X[:, 3], Y, 1) # 画散点图 对X取全部的行的第三列,标签Y,点大小
plt.show()
def data_provider(data, label, batchsize): # 每次取batchsize个数据
length = len(label)
indices = list(range(length))
# 这里需要把数据打乱
random.shuffle(indices)
for each in range(0, length, batchsize):
get_indices = indices[each: each+batchsize]
get_data = data[get_indices]
get_label = label[get_indices]
yield get_data, get_label # 有存档点的return
batchsize = 16
for batch_x, batch_y in data_provider(X, Y, batchsize):
print(batch_x, batch_y)
break
定义模型
def fun(x, w, b):
pred_y = torch.matmul(x, w) + b
return pred_y
定义loss
def maeLoss(pre_y, y):
return torch.sum(abs(pre_y-y))/len(y)
sgd(梯度下降)
def sgd(paras, lr):
with torch.nograd(): # 这部分代码不计算梯度
for para in paras:
para -= para.grad lr # 不能写成 para = para - paras.grad lr !!!! 这句相当于要创建一个新的para,会导致报错
para.grad.zero() # 将使用过的梯度归零
lr = 0.01
w_0 = torch.normal(0, 0.01, true_w.shape, requires_grad=True)
b_0 = torch.tensor(0.01, requires_grad=True)
print(w_0, b_0)
epochs = 50
for epoch in range(epochs):
data_loss = 0
for batch_x, batch_y in data_provider(X, Y, batchsize):
pred_y = fun(batch_x, w_0, b_0)
loss = maeLoss(pred_y, batch_y)
loss.backward()
sgd([w_0, b_0], lr)
data_loss += loss
print("epoch %03d: loss: %.6f" % (epoch, data_loss))
print(“真实函数值:”, true_w, true_b)
print(“训练得到的函数值:”, w_0, b_0)
idx = 0
plt.plot(X[:, idx].detach().numpy(), X[:, idx].detach().numpy()*w_0[idx].detach().numpy()+b_0.detach().numpy())
plt.scatter(X[:, idx].detach().numpy(), Y, 1)
plt.show()