python-基于softmax方法的简单神经网络(程序)

以下内容笔记出自‘跟着迪哥学python数据分析与机器学习实战’,外加个人整理添加,仅供个人复习使用。


softmax分类器可以说是在线性的SVM分类上,将wx+b的分值进行了转化(指数函数、归一化),将分值转化为概率值,还是线性分类。

首先构造需要的数据

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['figure.figsize']=(8,6)
plt.rcParams['image.interpolation']='nearest'
#plt.rcParams['image.cmap']='gray'

np.random.seed(0)
N=100 #每个类别的点个数
D=2 #维度 2维数据
K=3 #类别数
X=np.zeros((N*K,D))
y=np.zeros(N*K,dtype='uint8')
for j in range(K):
    ix=range(N*j,N*(j+1))
    r = np.linspace(0.0,1,N) # radius
    t = np.linspace(j*4,(j+1)*4,N) + np.random.randn(N)*0.2 # theta
    X[ix] = np.c_[r*np.sin(t), r*np.cos(t)]
    y[ix] = j
fig=plt.figure()
plt.scatter(X[:,0],X[:,1],c=y,s=40,cmap=plt.cm.Spectral)
plt.xlim([-1,1])
plt.ylim([-1,1])
plt.show()

在这里插入图片描述

首先看一下仅softmax分类器的分类效果

W=0.01*np.random.randn(D,K)  #随机初始化
b=np.zeros((1,K))    #初始化为1
#也就是随机初始化了3个方程?就是和神经网络同样的道理

step_size=1e-0  #1
reg=1e-3  #好像参数调整步长 0.001

num_examples=X.shape[0]
for i in range(1000):
    scores=np.dot(X,W)+b  #300*3  因为是3个方程式
    #print(scores.shape)  300*3
    #计算分类的概率
    exp_scores=np.exp(scores)  #300*3
    #归一化
    probs=exp_scores/np.sum(exp_scores,axis=1,keepdims=True)
      #[N*K] 300*3
    #print(probs.shape)  #每个方程式求出的每个点的类别概率  300*3
    
    #计算损失函数,
    #损失函数是预测为正确类别的归一化概率再取对数求负值
    corect_logprobs=-np.log(probs[range(num_examples),y])  #找出预测正确的概率
    #print(corect_logprobs.shape)  #300*1
    data_loss=np.sum(corect_logprobs)/num_examples #平均化
    reg_loss=0.5*reg*np.sum(W*W)  #L2正则化项(前面乘以参数0.001)
    #总的损失
    loss=data_loss+reg_loss
    if i %100==0:
        print('iteration %d: loss %f' % (i,loss))
    
    #计算梯度
    dscores=probs  #概率
    dscores[range(num_examples),y]-=1  #概率值减去1
    dscores/=num_examples   #除以个数平均化  300*3
    
    #反向传播梯度并调整参数
    dW=np.dot(X.T,dscores)  
         #(300*2).T * (300*3) ->(2*300) * (300*3)=2*3 
         #得出的是3个方程的两个参数 矩阵
    db=np.sum(dscores,axis=0,keepdims=True)
    
    dW+=reg*W  #初始参数值W
    
    #进行参数迭代
    W+=-step_size*dW
    b+=-step_size *db
    scores=np.dot(X,W)+b
predicted_class=np.argmax(scores,axis=1)
print('training accuracy:%.2f' %(np.mean(predicted_class==y)))

在这里插入图片描述

h = 0.02
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                     np.arange(y_min, y_max, h))
Z = np.dot(np.c_[xx.ravel(), yy.ravel()], W) + b
Z = np.argmax(Z, axis=1)
Z = Z.reshape(xx.shape)
fig = plt.figure()
plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.Spectral)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.show()

在这里插入图片描述
可知线性分类器对这种图形的分类效果不是很好

基于softmax方法的神经网络

h=100 #一个隐藏层,这一层中有100个单元
W=0.01 * np.random.randn(D,h)  #100个单元对应100组参数组合 数据x:300*2 
  #因此初始参数为2*100
b=np.zeros((1,h)) #初始截距为1 1*100
W2=0.01*np.random.randn(h,K)  #100*3  3个方程,自变量是100个单元,所以是100个参数
b2=np.zeros((1,K)) #初始截距为1 1*3

step_size=1e-0
reg=1e-3

num_examples=X.shape[0]
for i in range(2000):
    #分类得分N*K  300*3
    hidden_layer=np.maximum(0,np.dot(X,W)+b)  #Relu 激活函数
    # x:300*2  W:2*100  上面结果300*100 样本数量*隐藏层单元个数
    scores=np.dot(hidden_layer,W2)  #再对隐藏层的单元进行组合
    #(300*100)*(100*3)=(300*3) 每一个样本属于每一类的得分
    #计算每一类概率
    exp_scores=np.exp(scores)  #300*3  #得分要向概率转化
    probs=exp_scores/np.sum(exp_scores,axis=1,
                           keepdims=True) #归一化得出概率300*3
    
    #计算损失:就是softmax思想,平均交叉熵损失
    corect_logprobs=-np.log(probs[range(num_examples),y]) #300*1
       #对预测为正确的概率取对数再求负值
        
    data_loss=np.sum(corect_logprobs)/num_examples  #除以样本数量,
      #本轮参数运行的平均损失
    reg_loss=0.5*reg*np.sum(W*W)+0.5*reg*np.sum(W2*W2) #惩罚项
    loss=data_loss+reg_loss
    if i%100==0:
        print('iteration %d: loss %f' % (i,loss))
    
    #计算梯度
    dscores=probs  #300*3
    dscores[range(num_examples),y]-=1 
    dscores/=num_examples
    
    #反向传播调整参数
    #第一次传播是到W2
    dW2=np.dot(hidden_layer.T,dscores)  #(300*100).T*(300*3)=100*3
    #每一个单元对300个样本的预测,乘以最后每一个样本属于每类的概率
    db2=np.sum(dscores,axis=0,keepdims=True)
    #第二次传播是到了隐藏层
    dhidden=np.dot(dscores,W2.T)
    #激活函数是Relu函数
    dhidden[hidden_layer<=0]=0
    #最后是到输入层
    dW=np.dot(X.T,dhidden)
    db=np.sum(dhidden,axis=0,keepdims=True)
    
    #调节
    dW2 += reg*W2
    dW += reg *W
    
    #参数更新
    W+=-step_size*dW
    b+=-step_size*db
    W2+=-step_size*dW2
    b2+=-step_size*db2
    
hidden_layer = np.maximum(0, np.dot(X, W) + b)
scores = np.dot(hidden_layer, W2) + b2
predicted_class = np.argmax(scores, axis=1)
print ('training accuracy: %.2f' % (np.mean(predicted_class == y)))

在这里插入图片描述
作图:

h = 0.02
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                     np.arange(y_min, y_max, h))
Z = np.dot(np.maximum(0, np.dot(np.c_[xx.ravel(), yy.ravel()], W) + b), W2) + b2
Z = np.argmax(Z, axis=1)
Z = Z.reshape(xx.shape)
fig = plt.figure()
plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.Spectral)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.show()

在这里插入图片描述
看,神经网络能够比较合适的分类

猜你喜欢

转载自blog.csdn.net/qq_43165880/article/details/108574589