下面进行全连接网络的学习,对于全连接网络的简单理解,可以认为是多个线性分类的组合,当直线不能完成复杂分类任务的时候,我们可以将非线性边缘分解为多个线性边缘的组合,推荐一个网站,可以直观的感受到多个线性分类器组合后的分类效果:
https://playground.tensorflow.org/
hidden layer中仅有一个 node的时候,相当于仅有一个线性分类器,所以最后的分类效果边界是直线:
当有两个node的时候,相当于两个线性分类器,进行组合,最后可以看到基本是两个线性边界
有3个node的时候:就可以正确分类的,似乎是比较符合我们的预期的
然后是pytorch代码的演示,
首先生成数据,我们也生成如上图一样的数据,中心在一起的两类:
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets
n_pt=500
x,y=datasets.make_circles(n_pt,random_state=123,noise=0.1,fator=0.2)
def scatter_plot(x,y):
plt.scatter(x[y==0,0],x[y==1,1],10,label='0')
plt.scatter(x[y==1,0],x[y==1,1],10,label='1')
plt.legend()
scatter_plot(x,y)
x_data=torch.Tensor(x)
y_data=torch.Tensor(y).view(n_pt,1)
数据图为:
然后建立一个全连接网路,网络结构为 输入-> hidden layer->输出, 其中书输入 2,隐藏层 4,输出1
class Model(nn.Module):
def __init__(self,input_size,h1,output_size):
super().__init__()
self.linear1=nn.Linear(input_size,h1)
self.linear2=nn.Linear(h1,output_size)
def forward(self,x):
pred1=torch.sigmoid(self.linear1(x))
pred2=torch.sigmoid(self.linear2(pred1))
return pred2
model=Model(2,4,1)
最后进行训练,训练的过程和linear regression都是一致的
criterion=nn.BCELoss()
optimizer=torch.optim.Adam(model.parameters(),lr=0.01)
epochs=1000
losses=[]
for i in range(epochs):
y_pred=model.forward(x_data)
loss=criterion(y_pred,y_data)
if i%50==0:
print('epoch:',i,'loss:',loss.item())
losses.append(loss)
optimizer.zero_grad()
loss.backward()
optimizer.step()
plt.plot(losses)
最后我们画一下分类的边界:
def plot_decision_boundary(x,y):
x_span=np.linspace(min(x[:,0]),max(x[:,1]))
y_span=np.linspace(min(y[:,0]),max(y[:,1]))
xx,yy=np.meshgrid(x_span,y_span)
grid=torch.Tensor(np.c_[xx.ravel(),yy.ravel()])
pred_func=model.forward(grid)
z=pred_func.view(xx.shape).detach().numpy()
plt.contourf(xx,yy,z)
plot_decision_boundary(x,y)
scatter_plot(x,y)