Numpy实现简单神经元进行逻辑回归对糖尿病数据集二分类

本文介绍了一个简单的神经元模型用于逻辑回归,通过Sigmoid激活函数处理糖尿病数据集的二分类问题。作者展示了从神经元方程、损失函数、梯度下降法到代码实现的全过程,并在实验中遇到模型发散问题,分析了可能的原因。最终,模型在测试集上的准确率为0.6429。
摘要由CSDN通过智能技术生成

神经元(也可以叫感知机,本质没有太大区别),是神经网络的基本组成单位,这里实现一个简单的神经元进行逻辑回归,并利用sigmoid函数看看对糖尿病数据集二分类的处理效果如何。

基本流程可以先看看这篇,感知机

完整工程代码点击这里

一、神经元方程式

在这里插入图片描述

其中x是我们输入的数据向量,x=[x1,x2,x3,x4,…,xn],n为特征数目。
w为我们神经元的参数,b是常数项。
拆开看为

z=w1x1 + w2x2 + w3x3 + ... + wnxn + b

其中
在这里插入图片描述
为激活函数,激活函数有很多,比如tanh双曲正切函数,ReLu函数,Sigmoid函数,这里入门使用了Sigmoid函数。点击这里查看常见激活函数和对应的函数表达式。

其中y是数据的正确标签,是已知值 ,a为预测的答案。

这里的损失函数L(a,y)采用的是交叉熵损失函数。

二、导函数求解进行反向计算

这里如何更新参数w涉及梯度下降法,导函数的计算涉及链式法则,下面我将进行关于损失函数L和我们的求解目标参数w的导数计算,最后再使用梯度下降法进行参数优化求解。

导数求解证明过程如下:
在这里插入图片描述

注意这里的w和x都是向量,w=[w1,w2,w3,…,wn] , x=[x1,x2,x3,…,xn]
所以根据梯度下降法更新时,

w1=w1 - lr * (a-y)x1
w2=w2 - lr * (a-y)x2
....
wn=wn - lr * (a-y)xn
b=b - lr*(a-y)#关于dZ/db=1

三、代码实现

这里使用了糖尿病数据集diabetes.txt
在这里插入图片描述
数据集包含8个特征,标签Outcome表示是否患有糖尿病(1表示患病,0表示没患病)。

是比较典型的二分类问题,我们直接用来训练我们的单个神经元,看看效果。

代码如下

import pandas as pd
import numpy as np
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
N=8#特征数目
lr=0.0001#学习率
step=10000#迭代次数
w = np.random.rand(1,N+1)[0]*0.01#随机初始化参数,w[N]看成是b

def function(w,x):
    return np.sum(w[0:N]*x)+w[N]

def Sigmoid(z):#激活函数
    return 1/(1+np.e**(-z))

def Loss(w,x,y):#损失函数
    loss=0
    for i in range(len(x)):
        a=Sigmoid(function(w,x[i]))
        loss+=(-(y[i]*np.log(a)+(1-y[i])*np.log(1-a)))
    return loss/len(x)#取平均

def derivative_function(w,x,y):#导数
    derivative=[]
    for j in range(N):
        averge=0
        for i in range(len(x)):
            averge+=Sigmoid(function(w,x[i]))*x[i][j]
        averge/=len(x)#取平均
        derivative.append(averge)#储存下每个参数wj的平均下降梯度
    averge=0
    for i in range(len(x)):#针对参数b
        averge+=Sigmoid(function(w,x[i]))
    averge/=len(x)
    derivative.append(averge)
    return np.array(derivative)
def Predict_function(w,x):
    pred=[]
    for i in range(len(x)):
        res=Sigmoid(function(w,x[i]))
        if res>=0.5:
            pred.append(1)
        else:
            pred.append(0)
    return np.array(pred)
data=pd.read_csv('download/diabetes.txt',header=None).values
M=len(data)#数据集大小
x=data[:,0:N]
x=x/(np.max(x)-np.min(x))#归一化
y=data[:,-1]

train_x=x[0:int(M*0.8)]
train_y=y[0:int(M*0.8)]
#按8:2划分训练集和验证集
test_x=x[int(M*0.8):]
test_y=y[int(M*0.8):]

los=[]
best_w=w.copy()
best_loss=1e9
for i in range(step):
    loss=Loss(w,train_x,train_y)
    if i%10==0:
        print('step=',i,'   loss=',loss)
    if loss<best_loss:#找最优参数
        best_loss=loss
        best_w=w.copy()
    los.append(loss)
    f=derivative_function(w,x,y)
    w=w-lr*f#乘上学习率,开始梯度下降法

y_pre = Predict_function(best_w,test_x)
print("accuracy_score: %.4lf" % accuracy_score(test_y,y_pre))

plt.plot(los)
plt.show()


运行结果
在这里插入图片描述

最后准确率为0.6429,尽力了,因为单个神经元的学习能力实在很弱,这里主要演示下单个神经元如何实现,主要找不到合适的数据集,糖尿病数据集8个特征信息,已经算是比较复杂的数据信息了。

PS:实验中,模型存在发散现象,一开始模型不断拟合,损失降低,但是逐渐到达某个峰值后开始发散,损失不断增大,我反复做了实验对比,思考原因可能是学习率不够小,其次数据集也存在问题,因为我没有分批次训练,而是整个数据集导入训练取梯度平均,这样的过程很容易带来很大的误差,导致模型拟合到一定结果时因为这个细微的误差开始出现发散,其次的原因还有就是,虽然我们尽可能让数据误差呈现凸函数方便使用梯度下降法求解,但实际中数据呈现的函数形式可能更复杂,不是标准的凸函数形式,这样模型迭代就容易陷入这种局部危险中。

希望我的分享对你的学习有所帮助,如果有问题请及时指出,谢谢~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值