逻辑回归python实现

逻辑回归

  • 逻辑回归是一种分类模型:
    z = W T X = w 0 + w 1 x 1 + w 2 x 2 + ⋯ + w n x n z=W^{T}X=w^{0}+w^{1}x^{1}+w^{2}x^{2}+\cdots+w^{n}x^{n} z=WTX=w0+w1x1+w2x2++wnxn
  • 逻辑回归是通过sigmoid函数将输入值映射到 [ 0 , 1 ] [0,1] [0,1]的区间范围
    p = s ( z ) = 1 1 + e − z p=s(z)=\frac{1}{1+e^{-z}} p=s(z)=1+ez1`

目标函数

  • 逻辑回归的目标函数为:
    J ( W ) = − ∑ i = 1 n [ y ( i ) l o g ( s ( z ( i ) ) ) + ( 1 − y ( i ) ) l o g ( 1 − s ( z ( i ) ) ) ] J(W)=-\sum_{i=1}^{n}[y^{(i)}log(s(z^{(i)}))+(1-y^{(i)})log(1-s(z^{(i)}))] J(W)=i=1n[y(i)log(s(z(i)))+(1y(i))log(1s(z(i)))]
    因此,目标函数最小时, W W W的值就是我们要求的最终权重值

代码实现

1.数据预处理

import numpy as np
import pandas as pd
data=pd.read_csv(r"F:\数据集\Iris数据集\iris.csv")
#将Unnamed: 0列名改为id
data=data.rename(columns={"Unnamed: 0":"id"})
data
#去掉不需要的id列
data.drop("id",axis=1,inplace=True)
#删除重复的值
data.drop_duplicates(inplace=True)
#三个类别:setosa   versicolor    virginica
#实现映射操作
data["Species"]=data["Species"].map({"versicolor":0,"setosa":1,"virginica":2})
#只选取类别为0和1 的鸢尾花数据,进行逻辑回归的而分类
data=data[data["Species"]!=2]
#len(data)

2.编写逻辑回归的类

class LogisticRegression:
    
    """
    使用python语言实现逻辑回归算法
    """
    def __init__(self,alpha,times):
        """
        初始化方法
        Parameters:
        _____________
        alpha:float
            学习率
        times:int
            迭代次数
        """
        self.alpha=alpha
        self.times=times
        
    def sigmoid(self,z):
        """
        sigmoid函数的实现
        Parameters:
        ______________
        z:float
          自变量,值为z=w.T*x
        Returns:
        ————————
        p:float,值为[0,1]之间。
          返回样本属于类别1的概率值,用来作为结果的预测
          当s>=0.5(z>=0)时,判定为类别1,否则判定为类别0.
        """
        return 1.0/(1.0+np.exp(-z))
    
    def fit(self,X,y):
        """
        根据提供的训练数据,对模型进行训练
        Parameters:
        ------------
        X:类数组类型,形状:[样本数量,特征数量]
           待训练的样本特征属性
        y:类数组类型,形状:[样本数量]
          每个样本的目标值。(标签)
        """
        X=np.asarray(X)
        y=np.asarray(y)
        #创建权重的向量,初始值为0,长度比特征数多1。(多出来的一个是截距)
        self.w_=np.zeros(1+X.shape[1])
        #创建损失值列表,用来保存每次迭代后的损失值
        self.loss_=[]
        for i in range(self.times):
            z=np.dot(X,self.w_[1:])+self.w_[0]
            #计算概率值(结果判定为1的概率值)
            p=self.sigmoid(z)
            #根据逻辑回归的代价函数(目标函数)计算损失值。
            #逻辑回归的损失函数(目标函数):
            #J(w)=-sum(yi*log(s(zi))+(1-yi)*log(1-s(zi))),[i从1到n,n为样本数量]
            cost=-np.sum(y*np.log(p)+(1-y)*np.log(1-p))
            self.loss_.append(cost)
            #调整权重值,根据公式调整为调整为  权重(j列)=权重(j列)+学习率*sum((y-s(z)) *x(j))
            self.w_[0]+=self.alpha*np.sum(y-p)
            self.w_[1:]+=self.alpha*np.dot(X.T,y-p)
            
    def predict_proba(self,X):
        """
        根据参数传递的样本对样本数据进行预测
        Parameters:
        ___________
        X:类数组类型,形状:[样本数量,特征数量]
          待测试的样本特征(属性)
        Returns:
        -------------
        result:数组类型
              预测的结果(概率值)
        """
        X=np.asarray(X)
        z=np.dot(X,self.w_[1:])+self.w_[0]
        p=self.sigmoid(z)
        #将预测结果变成二维数组(结构),便于后续拼接。因为一维结构是没办法拼接的
        p=p.reshape(-1,1)
        #将两个数组进行拼接。方向为横拼接(axis=1)
        return np.concatenate([1-p,p],axis=1)
    def predict(self,X):
        """
        根据参数传递的样本,对样本数据进行预测
        Parameters:
        ------------
        X:类数组类型,形状:[样本数量,特征数量]
           待测试的样本特征(属性)
        Returns:
        ------------
        result:数组类型。
            预测的结果(分类值)
        """
        #返回数组中值比较大的索引即可,横向
        return np.argmax(self.predict_proba(X),axis=1)
            
    

3.测试逻辑回归的类

#提取出0和1两个类别
t1=data[data["Species"]==0]
t2=data[data["Species"]==1]
#对两个类别进行洗牌
t1=t1.sample(len(t1),random_state=0)
t2=t2.sample(len(t2),random_state=0)
#拼接构建训练集,拼接方向为纵向
train_X=pd.concat([t1.iloc[:40,:-1],t2.iloc[:40,:-1]],axis=0)
train_y=pd.concat([t1.iloc[:40,-1],t2.iloc[:40,-1]],axis=0)
test_X=pd.concat([t1.iloc[40:,:-1],t2.iloc[40:,:-1]],axis=0)
test_y=pd.concat([t1.iloc[40:,-1],t2.iloc[40:,-1]],axis=0)

#鸢尾花的特征列都在同一个数量级,我们这里可以不用进行标准化处理
lr=LogisticRegression(alpha=0.01,times=20)
lr.fit(train_X,train_y)
#预测属于哪个类别的概率值
#lr.predict_proba(test_X)
result=lr.predict(test_X)
#计算准确性
#np.sum(result==test_y)
#计算准确率
np.sum(result==test_y)/len(test_y)
1.0

可视化

import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rcParams["font.family"]="SimHei"
mpl.rcParams["axes.unicode_minus"]=False
#绘制预测值
plt.plot(result,"ro",ms=15,label="预测值")
#绘制真实值
plt.plot(test_y.values,"go",label="真实值")
plt.title("逻辑回归")
plt.xlabel("样本序号")
plt.ylabel("类别")
plt.legend()
plt.show()

在这里插入图片描述

#绘制目标函数损失值
plt.plot(range(1,lr.times+1),lr.loss_,"go-")
[<matplotlib.lines.Line2D at 0x562b4bbe48>]

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值