逻辑回归与多层神经网络的比较

 以下例子用于比较逻辑回归和神经网络在处理分类问题时的差别

 语言:Python

框架:Pytorch

工具:Anaconda 3

import torch
import numpy as np
from torch import nn
from torch.autograd import Variable
import torch.nn.functional as F

import matplotlib.pyplot as plt
%matplotlib inline
#绘图_决策_边界
def plot_decision_boundary(model,x,y):
    #设置最小值和最大值,并给它一些空白
    x_min,x_max=x[:,0].min()-1,x[:,0].max()+1
    y_min,y_max=x[:,1].min()-1,x[:,1].max()+1
    h=0.01
    #生成点的网格,点之间的距离为h
    xx,yy=np.meshgrid(np.arange(x_min,x_max,h),np.arange(y_min,y_max,h))
    #Predict the function value for the whole grid
    z=model(np.c_[xx.ravel(),yy.ravel()])
    z=z.reshape(xx.shape)
    #绘制等高线和训练示例
    plt.contourf(xx,yy,z,cmap=plt.cm.Spectral)
    plt.ylabel('x2')
    plt.xlabel('x1')
    plt.scatter(x[:,0],x[:,1],c=y.reshape(-1),s=40,cmap=plt.cm.Spectral)
np.random.seed(1)
m=400 #样本数量
N=int(m/2)#每一类的点的个数
D=2 #维度
x=np.zeros((m,D))
y=np.zeros((m,1),dtype='uint8')#label向量,0表示红色,1表示蓝色
a=4
for j in range(2):
    ix=range(N*j,N*(j+1))
    t=np.linspace(j*3.12,(j+1)*3.12,N)+np.random.randn(N)*0.2  #角度
    r=a*np.sin(4*t)+np.random.randn(N)*0.2 #半径
    x[ix]=np.c_[r*np.sin(t),r*np.cos(t)]
    y[ix]=j
plt.scatter(x[:,0],x[:,1],c=y.reshape(-1),s=40,cmap=plt.cm.Spectral)

 

 我们可以先尝试用logistic回归来解决这个问题

x=torch.from_numpy(x).float()
y=torch.from_numpy(y).float()
w=nn.Parameter(torch.randn(2,1))
b=nn.Parameter(torch.zeros(1))

optimizer=torch.optim.SGD([w,b],1e-1)

def logistic_regression(x):
    return torch.mm(x,w)+b

criterion=nn.BCEWithLogitsLoss()
for e in range(100):
    out = logistic_regression(Variable(x))
    loss = criterion(out,Variable(y))
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    if(e+1)%20==0:
        print('epoch:{},loss:{}'.format(e+1,loss.item()))

  

epoch:20,loss:0.6744809150695801
epoch:40,loss:0.6731831431388855
epoch:60,loss:0.6731505393981934
epoch:80,loss:0.6731476783752441
epoch:100,loss:0.673146665096283
def plot_logistic(x):
    x=Variable(torch.from_numpy(x).float())
    out=torch.sigmoid(logistic_regression(x))
    out =(out>0.5)*1
    return out.data.numpy()

可以看到,逻辑回归并不能很好的区分开这个复杂的数据集,如果你还记得前面的内容,你就知道逻辑回归是一个线性分类器,这个时候就该我们的神经网络登场了

#定义两层神经网络的参数
w1=nn.Parameter(torch.randn(2,4)*0.01) #隐藏层神经元个数2
b1=nn.Parameter(torch.zeros(4))

w2=nn.Parameter(torch.randn(4,1)*0.01)
b2=nn.Parameter(torch.zeros(1))

#定义模型
def two_network(x):
    x1=torch.mm(x,w1)+b1
    x1=torch.tanh(x1)
    x2=torch.mm(x1,w2)+b2
    return x2

optimizer = torch.optim.SGD([w1,w2,b1,b2],1.)#SGD 随机梯度下降。为了使用torch.optim,需要构建optimizer对象,这个对象能够保持当前参数状态并基于计算得到的梯度进行参数更新
criterion = nn.BCEWithLogitsLoss()
#我们训练10000次
for e in range(10000):
    out =two_network(Variable(x))
    loss = criterion(out,Variable(y))
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    if (e+1)%1000==0:
        print('epoch:{},loss:{}'.format(e+1,loss.item()))

 epoch:1000,loss:0.2922297418117523 epoch:2000,loss:0.2799872159957886 epoch:3000,loss:0.27320700883865356 epoch:4000,loss:0.26808029413223267 epoch:5000,loss:0.26380524039268494 epoch:6000,loss:0.2605781853199005 epoch:7000,loss:0.2581803798675537 epoch:8000,loss:0.2563518285751343 epoch:9000,loss:0.25490668416023254 epoch:10000,loss:0.2537277042865753

def plot_network(x):
    x=Variable(torch.from_numpy(x).float())
    x1=torch.mm(x,w1)+b1
    x1=torch.tanh(x1)
    x2=torch.mm(x1,w2)+b2
    out=torch.sigmoid(x2)
    out=(out>0.5)*1
    return out.data.numpy()

可以看到神经网络能够非常好的分类这个复杂的数据,和前面的逻辑回归相比,神经网络因为有了激活函数的存在,成了一个非线性分类模型,所以神经网络的分类更复杂

猜你喜欢

转载自blog.csdn.net/weixin_51781852/article/details/125684344
今日推荐