一、创建训练集
为了保证后续过程中产生的随机数都是一致的(方便测试),我们首先种下一颗随机种子。
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np
def setup_seed(seed):
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
setup_seed(50)
在[-10, 10]区间上随机生成1000个离散点,并将其可视化。
#create trainning set
batch_n = 1000
x = torch.linspace(-10, 10, batch_n).reshape(batch_n, 1)
y = torch.randn(batch_n, 1)
plt.figure()
plt.scatter(x.data.numpy(), y.data.numpy())
plt.show()
创造两个非线性函数,这里用y=0.5cos(x)+0.4sin(2x)+0.3sin(3x)和y=0.002*x^3+0.02*x^2吧。将其可视化在图像上。
def Myfunc(x):
y = 0.5*np.cos(x) + 0.4*np.sin(2*x) + 0.3*np.sin(3*x)
return y
def Myfunc2(x):
y = 0.002*np.power(x, 3) + 0.01*np.power(x-3, 2)
return y
plt.figure()
plt.scatter(x.data.numpy(), y.data.numpy())
plt.plot(x.data.numpy(), Myfunc(x.data.numpy()), 'g-')
plt.plot(x.data.numpy(), Myfunc2(x.data.numpy()), 'g-')
plt.show()
我想做什么?我想利用这两个非线性函数,将平面分成四个区域。如果一个点同时位于两条直线之上,我们认为他处于区域[0];同时位于两条直线之下,处于区域[1];还有一上一下的情形……。
我们将(x, y)合并为训练集trainning set,然后为这些点贴上相应区域的标签。那么平面上这1000个离散点就被分为了四类。
train_set = torch.tensor(torch.cat((x, y), 1), dtype=torch.float32)
label = torch.tensor(torch.zeros(batch_n), dtype=torch.int64)
for i in range(batch_n):
_y = Myfunc(x[i].data) - y[i].data
__y = Myfunc2(x[i].data) - y[i].data
if _y > 0 and __y > 0:
label[i] = 0
elif _y > 0 and __y <= 0:
label[i] = 1
elif _y <= 0 and __y > 0:
label[i] = 2
else:
label[i] = 3
plt.figure()
plt.title('Training Set:%d Samples' % batch_n)
plt.plot(x.data.numpy(), Myfunc(x.data.numpy()), 'b-', label='split-line')
plt.plot(x.data.numpy(), Myfunc2(x.data.numpy()), 'b-')
colors = label.data.numpy()
plt.scatter(train_set.data.numpy()[:, 0], train_set.data.numpy()[:, 1], c=label.data.numpy(), s=20, lw=0, cmap='RdYlGn')
plt.legend()
plt.show()
到此,训练集创建完毕。
二、搭建神经网络
输入给神经网络的是一个“点”,有(x, y)两个参数,所以神经网络输入层维度是2;神经网络要将这个些点分为四类,输出层维度是4;隐藏层我们使用30个神经元,选用sigmoid激活函数。
使用CrossEntropyLoss(交叉熵)损失函数,Adam优化器,初始化学习率0.3
class Net(torch.nn.Module):
def __init__(self, in_dim, hidden_dim, out_dim):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(in_dim, hidden_dim)
self.predict = torch.nn.Linear(hidden_dim, out_dim)
def forward(self, x):
x = self.hidden(x)
x = F.sigmoid(x)
x = self.predict(x)
return x
net = Net(2, 30, 4)
loss_func = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.3)
三、训练神经网络
用for循环做1500次迭代训练。
for i in range(1500):
pre_y = net(train_set)
loss = loss_func(pre_y, label)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("loss:{}".format(loss))
四、创建测试集验证模型
我们已经用训练集对神经网络完成了训练。接下来我们创建一个含有2000个样本的测试集来验证我们的训练成果。
重新种下一颗随机数种子,确保创建的测试集是新的。
#create test set
batch_n = 2000
setup_seed(100)
x = torch.linspace(-10, 10, batch_n).reshape(batch_n, 1)
y = torch.randn(batch_n, 1)
test_set = torch.tensor(torch.cat((x, y), 1), dtype=torch.float32)
label = torch.tensor(torch.zeros(batch_n), dtype=torch.int64) #初始化
for i in range(batch_n):
_y = Myfunc(x[i].data) - y[i].data
__y = Myfunc2(x[i].data) - y[i].data
if _y > 0 and __y > 0:
label[i] = 0
elif _y > 0 and __y <= 0:
label[i] = 1
elif _y <= 0 and __y > 0:
label[i] = 2
else:
label[i] = 3
放进神经网络前向传播,并得到预测的标签。
pre_y = net(test_set)
pre_label = torch.max(pre_y, 1)[1]
计算准确率
#calculate accuracy
cnt = 0
for i in range(batch_n):
if pre_label[i] == label[i]:
cnt = cnt + 1
accuracy = float(cnt)/float(batch_n)*100
可视化训练成果。
五、总代码及训练成果
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np
#random seed
def setup_seed(seed):
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
setup_seed(50)
#create trainning set
batch_n = 1000
x = torch.linspace(-10, 10, batch_n).reshape(batch_n, 1)
y = torch.randn(batch_n, 1)
def Myfunc(x):
y = 0.5*np.cos(x) + 0.4*np.sin(2*x) + 0.3*np.sin(3*x)
return y
def Myfunc2(x):
y = 0.002*np.power(x, 3) + 0.01*np.power(x-3, 2)
return y
train_set = torch.tensor(torch.cat((x, y), 1), dtype=torch.float32)
label = torch.tensor(torch.zeros(batch_n), dtype=torch.int64)
for i in range(batch_n):
_y = Myfunc(x[i].data) - y[i].data
__y = Myfunc2(x[i].data) - y[i].data
if _y > 0 and __y > 0:
label[i] = 0
elif _y > 0 and __y <= 0:
label[i] = 1
elif _y <= 0 and __y > 0:
label[i] = 2
else:
label[i] = 3
plt.figure()
plt.subplot(1, 2, 1)
plt.title('Training Set:%d Samples' % batch_n)
plt.plot(x.data.numpy(), Myfunc(x.data.numpy()), 'b-', label='split-line')
plt.plot(x.data.numpy(), Myfunc2(x.data.numpy()), 'b-')
colors = label.data.numpy()
plt.scatter(train_set.data.numpy()[:, 0], train_set.data.numpy()[:, 1], c=label.data.numpy(), s=20, lw=0, cmap='RdYlGn')
plt.legend()
#network
class Net(torch.nn.Module):
def __init__(self, in_dim, hidden_dim, out_dim):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(in_dim, hidden_dim)
self.predict = torch.nn.Linear(hidden_dim, out_dim)
def forward(self, x):
x = self.hidden(x)
x = F.sigmoid(x)
x = self.predict(x)
return x
net = Net(2, 30, 4)
loss_func = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.3)
#trainning
for i in range(1500):
pre_y = net(train_set)
loss = loss_func(pre_y, label)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("loss:{}".format(loss))
#create test set
batch_n = 2000
setup_seed(100)
x = torch.linspace(-10, 10, batch_n).reshape(batch_n, 1)
y = torch.randn(batch_n, 1)
test_set = torch.tensor(torch.cat((x, y), 1), dtype=torch.float32)
label = torch.tensor(torch.zeros(batch_n), dtype=torch.int64)
for i in range(batch_n):
_y = Myfunc(x[i].data) - y[i].data
__y = Myfunc2(x[i].data) - y[i].data
if _y > 0 and __y > 0:
label[i] = 0
elif _y > 0 and __y <= 0:
label[i] = 1
elif _y <= 0 and __y > 0:
label[i] = 2
else:
label[i] = 3
#forward
pre_y = net(test_set)
pre_label = torch.max(pre_y, 1)[1]
#calculate accuracy
cnt = 0
for i in range(batch_n):
if pre_label[i] == label[i]:
cnt = cnt + 1
accuracy = float(cnt)/float(batch_n)*100
plt.subplot(1, 2, 2)
plt.title('Prediction:%d Samples' % batch_n)
plt.plot(x.data.numpy(), Myfunc(x.data.numpy()), 'b--', label='split-line')
plt.plot(x.data.numpy(), Myfunc2(x.data.numpy()), 'b--')
plt.scatter(test_set.data.numpy()[:, 0], test_set.data.numpy()[:, 1], c=pre_label.data.numpy(), s=20, lw=0, cmap='RdYlGn')
plt.legend()
plt.text(6.5, -3.3, 'Accuracy=%.2f %%' % accuracy, fontdict={'size': 10, 'color': 'red'})
plt.text(-10, -3.3, 'Supervised Learning - Classification', fontdict={'size': 12, 'color': 'black'})
plt.show()