栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

机器学习之Logistic&Sofmax回归模型--python实现

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

机器学习之Logistic&Sofmax回归模型--python实现

Logistic回归 & Softmax回归
    • 概述:
    • Logistic回归
      • 线性分类器
      • logistic函数
        • 概率意义
        • 对数概率函数
        • 一阶导数
      • Logistic回归模型
      • 极大似然法估计参数
      • 梯度下降更新
    • Softmax回归
      • Sotfmax函数
      • 梯度下降更新公式

——《 Python机器学习算法:原理,实现与案例》读书笔记

相关数据集:
链接:https://pan.baidu.com/s/1fBNk7mbqCczKawmOyk491Q
提取码:niz2

概述:

Logistic回归虽然名为回归,实为分类算法,用于处理二分类问题


Sotfmax回归是在Logistic回归的基础上推广得到的,用于处理多元分类问题

Logistic回归
线性分类器

先从简单的二维平面的二分类问题开始


如下图所示:
在二维平面内存在两种类别的样本,我们可以找到一条直线,将这两种样本尽可能好得划分开
假 设 直 线 方 程 为 : 假设直线方程为: 假设直线方程为:
w T x + b = 0 w , b ∈ R w^{T}x+b=0 qquad w,bin R wTx+b=0w,b∈R

直 线 上 方 的 点 都 满 足 : w T x + b > k 直线上方的点都满足:w^{T}x+b>k 直线上方的点都满足:wTx+b>k
而 直 线 下 方 的 点 都 满 足 : w T x + b < k 其 中 k 为 常 数 而直线下方的点都满足:w^{T}x+b

这意味着,我们可以根据找出的这条直线,判断样本的类别
设 z 为 样 本 的 类 别 ( 0 , 1 ) 设z为样本的类别(0,1) 设z为样本的类别(0,1)
z = { 0 , w T x + b = < k 1 , w T x + b = > k z=begin{cases} 0,w^{T}x+b=k end{cases} z={0,wTx+b=k​

对于多维空间的分类问题,类似上述问题,我们只需要找到一个超平面,可以将所有样本尽可能好得划分开(类似SVM)

假 设 超 平 面 方 程 为 : 假设超平面方程为: 假设超平面方程为:
w T x + b = 0 w ∈ R n , b ∈ R w^{T}x+b=0 qquad win R^{n},bin R wTx+b=0w∈Rn,b∈R
类似的,根据此函数的输出函数值,我们可以实现对样本的分类

logistic函数

对于二维平面的二分类问题,最理想的分类函数显然为单位阶跃函数:
H ( z ) = { 1 , z ≥ 0 0 , z ≤ 0 H(z) = begin{cases} 1,qquad z ge 0\ 0, qquad z le 0 end{cases} H(z)={1,z≥00,z≤0​
但此函数有一个严重的缺点:不连续–>不是处处可微(有些算法就不可以运用)


logistic函数便是一直常用的替代函数
σ ( z ) = 1 1 + e − z sigma (z) = frac{1}{1+e^{-z}} σ(z)=1+e−z1​

概率意义

logistic是一种sigmoid函数,其值域在(0,1)之间连续

函数的输出可以视为x条件下样本分类为y=1的条件概率
P ( y = 1 ∣ x ) = σ ( g ( x ) ) = 1 1 + e w T + b P(y=1|x)=sigma(g(x)) = frac{1}{1+e^{w^{T}+b}} P(y=1∣x)=σ(g(x))=1+ewT+b1​

对数概率函数

在统计学中,几率(odds) 定义为:事件发生的概率与事件不发生概率的比值

几率表示的是样本作为正例的相对可能性

对数几率:
l o g p 1 − p log frac{p}{1-p} log1−pp​对数几率大于0表明正例的概率大,大于0表明负例的概率大

logistic回归模型假设一个实例为正例的对数几率是 输入(x)的线性函数

l o g p 1 − p = w T x + b log frac{p}{1-p} = w^{T}x+b log1−pp​=wTx+b
反求p得:
p = σ ( g ( x ) ) = 1 1 + e − ( w T + b ) p = sigma (g(x)) = frac {1}{1+e^{-(w^{T}+b)}} p=σ(g(x))=1+e−(wT+b)1​

一阶导数

d σ ( z ) d z = σ ( z ) ( 1 − σ ( z ) ) frac{mathrm{d} sigma (z)}{mathrm{d} z} = sigma(z)(1-sigma(z)) dzdσ(z)​=σ(z)(1−σ(z))

Logistic回归模型

Logistic回归模型假设函数为:
h w , b ( x ) = σ ( g ( x ) ) = 1 1 + e − ( w T x + b ) h_{w,b}(x) = sigma (g(x)) = frac{1}{1+e^{-(w^{T}x+b)}} hw,b​(x)=σ(g(x))=1+e−(wTx+b)1​

通常将b作为w0纳入权向量w,同时为输入向量添加常数1作为x0:
w = ( b , w 1 , w 2 , . . . , w n ) T x = ( 1 , x 1 , x 2 , . . . , x n ) T w = (b,w_{1},w_{2},...,w_{n})^{T} \ x = (1,x_{1},x_{2},...,x_{n})^{T} w=(b,w1​,w2​,...,wn​)Tx=(1,x1​,x2​,...,xn​)T
此时,logistic函数为:
h w ( x ) = σ ( g ( x ) ) = 1 1 + e − ( w T x ) h_{w}(x) = sigma (g(x)) = frac{1}{1+e^{-(w^{T}x)}} hw​(x)=σ(g(x))=1+e−(wTx)1​

h w ( x ) 的 输 出 为 预 测 x 为 正 例 的 概 率 , 通 过 训 练 可 以 确 定 模 型 参 数 w , 构 建 二 元 分 类 函 数 : h_{w}(x)的输出为 预测x 为正例的概率,通过训练可以确定模型参数w,构建二元分类函数: hw​(x)的输出为预测x为正例的概率,通过训练可以确定模型参数w,构建二元分类函数:
H ( h w ( x ) ) = { 1 , h w ( x ) ≥ 0.5 0 , h w ( x ) ≤ 0.5 H(h_{w}(x)) = begin{cases} 1,qquad h_{w}(x)ge 0.5 \ 0,qquad h_{w}(x)le 0.5 end{cases} H(hw​(x))={1,hw​(x)≥0.50,hw​(x)≤0.5​

极大似然法估计参数

对于给定的包含m个样本的数据集D,可以使用极大似然法估计w
易 知 , 模 型 将 输 入 实 例 x i 预 测 为 y i 的 概 率 为 : 易知,模型将输入实例x_{i}预测为y_{i}的概率为: 易知,模型将输入实例xi​预测为yi​的概率为:

P ( y = y i ∣ x i ; w ) = h w ( x i ) y i ( 1 − h w ( x i ) 1 − y i ) y i = 0 , 1 P(y=y_{i}|x_{i};w) = h_{w}(x_{i})^{y_{i}}(1-h_{w}(x_{i})^{1-y_{i}})qquad y_{i}=0,1 P(y=yi​∣xi​;w)=hw​(xi​)yi​(1−hw​(xi​)1−yi​)yi​=0,1

定 义 似 然 函 数 为 : href{https://www.zhihu.com/question/54082000}{定义似然函数为:} 定义似然函数为:

L ( w ) = ∏ i = 1 m P ( y = y i ∣ x i ; w ) L(w) = prod_{i=1}^{m} P(y=y_{i}|x_{i};w) L(w)=i=1∏m​P(y=yi​∣xi​;w)

比 较 L o w 的 写 法 : L ( w ) = h w ( x i ) k ( 1 − h w ( x i ) ) n − k n , 抽 样 总 次 数 , k , 抽 样 为 y = 1 的 次 数 比较Low的写法:L(w)=h_{w}(x_{i})^{k}(1-h_{w}(x_{i}))^{n-k}qquad n ,抽样总次数,k, 抽样为y=1 的次数 比较Low的写法:L(w)=hw​(xi​)k(1−hw​(xi​))n−kn,抽样总次数,k,抽样为y=1的次数

极大似然法估计参数w的核心思想:已知x,y(样本分布),选择w,使得观测的数据(样本分布)出现的概率最大

(个人理解:不同的w,直接导致样本的分布不同,根据已知的分布,选择合适的参数(w),使得对任意样本集的分布 近似为 已知样本集的分布)
参 考 − − 极 大 似 然 估 计 href{https://www.cnblogs.com/softlin/p/6219372.html}{参考--极大似然估计} 参考−−极大似然估计
参 考 − − 极 大 似 然 估 计 href{https://zhuanlan.zhihu.com/p/26614750}{参考--极大似然估计} 参考−−极大似然估计

w ^ = a r g   m a x w   L ( w ) hat{w} = underset{w}{arg max} L(w) w^=warg max​ L(w)

为了简化模型,我们将目标函数转化为:
w ^ = a r g   m a x w   l n ( L ( w ) ) hat{w} = underset{w}{arg max} ln(L(w)) w^=warg max​ ln(L(w))对数似然函数(对数函数:积变和,单调递增函数)
l ( w ) = l n ( L ( w ) ) = ∑ i = 1 m y i l n ( h w ( x i ) ) + ( 1 − y i ) l n ( 1 − h w ( x i ) ) l(w) = ln(L(w)) = sum_{i=1}^{m} y_{i}ln(h_{w}(x_{i})) + (1-y_{i})ln(1-h_{w}(x_{i})) l(w)=ln(L(w))=i=1∑m​yi​ln(hw​(xi​))+(1−yi​)ln(1−hw​(xi​))

梯度下降更新

对于Logistic回归模型,定义其损失函数为:
J ( w ) = − 1 m ∑ i = 1 m y i l n ( h w ( x i ) ) + ( 1 − y i ) l n ( 1 − h w ( x i ) ) J(w) = -frac{1}{m} sum_{i=1}^{m} y_{i}ln(h_{w}(x_{i})) + (1-y_{i})ln(1-h_{w}(x_{i})) J(w)=−m1​i=1∑m​yi​ln(hw​(xi​))+(1−yi​)ln(1−hw​(xi​))
损失函数最小值与对数似然函数最大值等价


计算损失函数梯度:
计 算 J ( w ) 对 分 量 w i 的 偏 导 数 计算J(w)对分量w_{i}的偏导数 计算J(w)对分量wi​的偏导数
∂ J ( w ) ∂ w j = − 1 m ∂ ∂ w j ∑ i = 1 m y i l n ( h w ( x i ) ) + ( 1 − y i ) l n ( 1 − h w ( x i ) ) frac{partial J(w)}{partial w_{j}} = -frac{1}{m} frac{partial }{partial w_{j}} sum_{i=1}^{m} y_{i}ln(h_{w}(x_{i})) + (1-y_{i})ln(1-h_{w}(x_{i})) ∂wj​∂J(w)​=−m1​∂wj​∂​i=1∑m​yi​ln(hw​(xi​))+(1−yi​)ln(1−hw​(xi​))
= − 1 m ∑ i = 1 m y i ∂ ∂ w j l n ( h w ( x i ) ) + ( 1 − y i ) ∂ ∂ w j l n ( 1 − h w ( x i ) ) = -frac{1}{m} sum_{i=1}^{m} y_{i}frac{partial }{partial w_{j}}ln(h_{w}(x_{i})) + (1-y_{i})frac{partial }{partial w_{j}}ln(1-h_{w}(x_{i})) =−m1​i=1∑m​yi​∂wj​∂​ln(hw​(xi​))+(1−yi​)∂wj​∂​ln(1−hw​(xi​))
= − 1 m ∑ i = 1 m y i 1 h w ( x i ) ∂ h w ( x i ) z i ∂ z i w j + ( 1 − y i ) 1 1 − h w ( x i ) − ∂ h w ( x i ) z i ∂ z i w j = -frac{1}{m} sum_{i=1}^{m} y_{i}frac{1}{h_{w}(x_{i})} frac{partial h_{w}(x_{i})}{z_{i}} frac{partial z_{i}}{w_{j}} + (1-y_{i})frac{1}{1-h_{w}(x_{i})} frac{-partial h_{w}(x_{i})}{z_{i}} frac{partial z_{i}}{w_{j}} =−m1​i=1∑m​yi​hw​(xi​)1​zi​∂hw​(xi​)​wj​∂zi​​+(1−yi​)1−hw​(xi​)1​zi​−∂hw​(xi​)​wj​∂zi​​
= − 1 m ∑ i = 1 m ( y i − h w ( x i ) ) ∂ z i ∂ w j =-frac{1}{m} sum _{i=1}^{m} (y_{i}-h_{w}(x_{i}))frac{partial z_{i}}{partial w_{j}} =−m1​i=1∑m​(yi​−hw​(xi​))∂wj​∂zi​​
= 1 m ∑ i = 1 m ( h w ( x i ) − y i ) x i =frac{1}{m} sum _{i=1}^{m} (h_{w}(x_{i})-y_{i})x_{i} =m1​i=1∑m​(hw​(xi​)−yi​)xi​

h w ( x i ) − y i 可 解 释 为 模 型 预 测 x i 为 正 例 的 概 率 与 实 际 类 别 之 间 的 误 差 h_{w}(x_{i})-y_{i}可解释为模型预测x_{i}为正例的概率与实际类别之间的误差 hw​(xi​)−yi​可解释为模型预测xi​为正例的概率与实际类别之间的误差

对于随机梯度下降算法,相应的梯度计算公式为:

▽ J ( w ) = ( h w ( x i ) − y i ) x i bigtriangledown J(w) = (h_{w}(x_{i})-y_{i})x_{i} ▽J(w)=(hw​(xi​)−yi​)xi​

模 型 参 数 w 的 更 新 公 式 为 : w : = w − η ▽ J ( w ) , η 为 学 习 率 模型参数w的更新公式为:w := w - eta bigtriangledown J(w), eta 为学习率 模型参数w的更新公式为:w:=w−η▽J(w),η为学习率

算法流程:

数据处理

循环

计算内积
概率转换
计算损失
求解梯度
更新参数

判断条件

import numpy as np

class LogisticRegression:
    def __init__(self, n_iter=200, eta=1e-3, tol=None):
        # 训练迭代次数
        self.n_iter = n_iter
        #学习率
        self.eta = eta
        #误差变化阈值
        self.tol = tol
        #模型参数
        self.w = None
    
    def _preprocess_data_X(self, X):
        '''数据预处理 '''
        
        m, n = X.shape
        X_ = np.empty((m, n+1))
        X_[:, 0] = 1 
        X_[:, 1:] = X
        
        return X_
    
    def _z(self, X, w):
        '''g(x)函数,计算内积(x与w)'''
        return np.dot(X, w)
    
    def _sigmod(self, z):
        '''Logistic函数'''
        return 1./(1. + np.exp(-z))
    
    def _predict_proba(self, X, w):
        '''h(x)函数,预测y=1的概率'''
        z = self._z(X, w)    
        return self._sigmod(z)
    
    def _loss(self, y, y_proba):
        '''计算损失'''
        m = y.size
        p = y_proba * (2 * y - 1) + (1 - y) 
        return -np.sum(np.log(p)) / m 
    
    def _gradient(self, X, y, y_proba):
        '''计算梯度'''  
        return np.matmul(y_proba-y, X) / y.size
    
    def _gradient_descent(self, w, X, y):
        '''梯度下降算法'''
        if self.tol is not None:
            loss_old = np.inf 
            
        for step_i in range(self.n_iter):
            y_proba = self._predict_proba(X, w) 
            
            loss = self._loss(y, y_proba)
            print('%4i Loss: %s' % (step_i, loss))
            
            if self.tol is not None:
                if loss_old - loss < self.tol:
                    break
                
            loss_old = loss 
        
            grad = self._gradient(X, y, y_proba)

            w -= self.eta * grad
            
    def train(self, X_train, y_train):
        '''训练'''
        #预处理
        X_train = self._preprocess_data_X(X_train)
        
        #初始化参数向量
        _, n = X_train.shape
        self.w = np.random.random(n) * 0.5
        
        #梯度下降训练
        self._gradient_descent(self.w, X_train, y_train)
    
    def predict(self, X): 
        '''预测''' 
        X = self._preprocess_data_X(X) 
        
        y_pred = self._predict_proba(X, self.w)
        
        # p>0.5 y=1
        return np.where(y_pred >= 0.5, 1, 0)
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 数据导入
X = np.genfromtxt('wine.data', delimiter=',', usecols=range(1, 14))
y = np.genfromtxt('wine.data', delimiter=',', usecols=0)
idx = (y != 3)
X = X[idx]
y = y[idx]
y -= 1

#划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

#标准化
ss = StandardScaler()
ss.fit(X_train)
StandardScaler(copy=True, with_mean=True, with_std=True)
X_train_std = ss.transform(X_train)
X_test_std = ss.transform(X_test)

# 模型处理
clf = LogisticRegression(n_iter=2000, eta=0.01, tol=0.0001)
clf.train(X_train_std, y_train)
# 模型检验
from sklearn.metrics import accuracy_score

y_pred = clf.predict(X_test_std)
accuracy = accuracy_score(y_test, y_pred)
accuracy
0.9743589743589743
Softmax回归

Logistic回归只能处理二元分类问题,在此基础上推广得到的Sotfmax回归可以处理多元分类问题。Sotfmax回归也被称为多元Logistic回归。

Sotfmax函数

假设有k个分类,Sotfmax对实例x的类别进行预测时,需分别计算x属于每一个类别的概率,因此每个类别拥有各自独立的线性函数:
z j = g j ( x ) = w j T x z_{j} = g_{j}(x) = w_{j}^{T}x zj​=gj​(x)=wjT​x

W = [ w 1 T w 2 T ⋮ w k T ] W=begin{bmatrix} w_{1}^{T}\ w_{2}^{T} \ vdots \ w_{k}^{T}\ end{bmatrix} W=⎣⎢⎢⎢⎡​w1T​w2T​⋮wkT​​⎦⎥⎥⎥⎤​


定 义 S o t f m a x 回 归 的 g ( x ) 函 数 为 : 定义Sotfmax回归的g(x)函数为: 定义Sotfmax回归的g(x)函数为:
z = g ( x ) = W x = [ z 1 z 2 ⋮ z k ] z = g(x) = Wx = begin{bmatrix} z_{1}\ z_{2} \ vdots \ z_{k}\ end{bmatrix} z=g(x)=Wx=⎣⎢⎢⎢⎡​z1​z2​⋮zk​​⎦⎥⎥⎥⎤​

定义Softmax函数为:
σ ( z ) j = e z j ∑ k = 1 K e z k sigma (z)_{j} = frac{e^{z_{j}}}{sum_{k=1}^{K} e^{z_{k}}} σ(z)j​=∑k=1K​ezk​ezj​​
Softmax函数的输出为:
σ ( z ) = [ σ ( z ) 1 σ ( z ) 2 ⋮ σ ( z ) k ] sigma (z) = begin{bmatrix} sigma (z)_{1}\ sigma (z)_{2}\ vdots \ sigma (z)_{k} end{bmatrix} σ(z)=⎣⎢⎢⎢⎡​σ(z)1​σ(z)2​⋮σ(z)k​​⎦⎥⎥⎥⎤​


Sotfmax回归模型假设函数为:
h w ( x ) = σ ( g ( x ) ) = 1 ∑ k = 1 K e w k T x [ e w 1 T x e w 2 T x ⋮ e w K T x ] h_{w}(x) = sigma(g(x)) = frac {1}{sum_{k=1}^{K}e^{w_{k}^{T}x}}begin{bmatrix} e^{w_{1}^{T}x}\ e^{w_{2}^{T}x}\ vdots \ e^{w_{K}^{T}x} end{bmatrix} hw​(x)=σ(g(x))=∑k=1K​ewkT​x1​⎣⎢⎢⎢⎢⎡​ew1T​xew2T​x⋮ewKT​x​⎦⎥⎥⎥⎥⎤​

Sotfmax函数的输出是预测x为各类别的概率,通过训练确定了模型参数W,便可构建多元分类函数:
H ( h w ( x ) ) = a r g   m a x k   h W ( x ) k = a r g   m a x k ( W k T x ) H(h_{w}(x)) = underset{k}{arg max} h_{W}(x)_{k} = underset{k}{arg max}({W}_{k}^{T}x) H(hw​(x))=karg max​ hW​(x)k​=karg max​(WkT​x)

梯度下降更新公式

Sotfmax回归模型的损失函数为:
J ( w ) = − 1 m ∑ i = 1 m ∑ j = 1 K I ( y i = j ) l n   h W ( x i ) J(w) = -frac{1}{m} sum_{i=1}^{m} sum_{j=1}^{K} I(y_{i}=j)ln h_{W}(x_{i}) J(w)=−m1​i=1∑m​j=1∑K​I(yi​=j)ln hW​(xi​)

I 为 指 示 函 数 , 当 y i = j 时 , I = 1 , 否 则 I = 0 I为指示函数,当y_{i}= j时,I=1,否则I=0 I为指示函数,当yi​=j时,I=1,否则I=0

这里直接给出梯度的计算公式:
▽ w j J ( W ) = 1 m ∑ i = 1 m ( h W ( x i ) j − I ( y i = j ) ) x i bigtriangledown _{w_{j}}J(W) = frac{1}{m} sum _{i=1}^{m}(h_{W}(x_{i})_{j}-I(y_{i}=j))x_{i} ▽wj​​J(W)=m1​i=1∑m​(hW​(xi​)j​−I(yi​=j))xi​

h W ( x i ) j − I ( y i = j ) 可 以 解 释 为 模 型 预 测 x i 为 第 j 类 别 的 概 率 与 其 是 否 为 第 j 类 别 之 间 的 误 差 h_{W}(x_{i})_{j}-I(y_{i}=j)可以解释为模型预测x_{i}为第j类别的概率与其是否为第j类别之间的误差 hW​(xi​)j​−I(yi​=j)可以解释为模型预测xi​为第j类别的概率与其是否为第j类别之间的误差

对于随机梯度下降算法,每次只使用一个样本来计算梯度,相应梯度计算公式为:
▽ w j J ( W ) = ∑ i = 1 m ( h W ( x i ) j − I ( y i = j ) ) x i bigtriangledown _{w_{j}}J(W) = sum _{i=1}^{m}(h_{W}(x_{i})_{j}-I(y_{i}=j))x_{i} ▽wj​​J(W)=i=1∑m​(hW​(xi​)j​−I(yi​=j))xi​

w j 的 更 新 公 式 为 : w j : = w j − η ▽ w j J ( W ) w_{j}的更新公式为:w_{j}:=w_{j}-eta bigtriangledown _{w_{j}}J(W) wj​的更新公式为:wj​:=wj​−η▽wj​​J(W)
即:
W : = W − η [ ▽ w 1 J ( w ) T ▽ w 2 J ( w ) T ⋮ ▽ w k J ( w ) T ] W:=W-eta begin{bmatrix} bigtriangledown _{w_{1}}J(w)^{T}\ bigtriangledown _{w_{2}}J(w)^{T}\ vdots\ bigtriangledown _{w_{k}}J(w)^{T}\ end{bmatrix} W:=W−η⎣⎢⎢⎢⎡​▽w1​​J(w)T▽w2​​J(w)T⋮▽wk​​J(w)T​⎦⎥⎥⎥⎤​

import numpy as np
import random

class SoftmaxRegression:
    def __init__(self, n_iter=200, eta=1e-3, tol=None):
        # 训练迭代次数
        self.n_iter = n_iter
        # 学习率
        self.eta = eta
        # 误差变化阈值
        self.tol = tol
        # 模型参数W
        self.W = None
        
    def _z(self, X, W):
        '''g(x)函数:计算X与W内积'''
        if X.ndim == 1 :
            return np.dot(W, X) 
        return np.matmul(X, W.T)
    
    def _softmax(self, Z):
        '''softmax函数'''
        E = np.exp(Z) 
        if Z.ndim == 1:
            return E / np.sum(E) 
        return E / np.sum(E, axis=1, keepdims=True)
    
    def _predict_proba(self, X, W): 
        '''h(x)函数,预测y为各类别的概率'''
        Z = self._z(X, W)
        return self._softmax(Z)
    
    def _loss(self, y, y_proba):
        '''计算损失'''
        m = y.size 
        # 获取每个样本对应种类的概率,如果这个样本为1类,就选取其对应1类的概率
        p = y_proba[range(m), y]
        return -np.sum(np.log(p)) / m 
    
    def _gradient(self, xi, yi, yi_proba):
        '''计算梯度'''
        K = yi_proba.size
        y_bin = np.zeros(K)
        # 对应样本类型为1
        y_bin[yi] = 1 
        
        return (yi_proba - y_bin)[:,None] * xi
    
    def _stochastic_gradient_descent(self, W, X, y): 
        '''随机梯度下降算法''' 
        if self.tol is not None:
            loss_old = np.inf
            end_count = 0
            
        # 核心代码
        m = y.size
        idx = np.arange(m)
        for step_i in range(self.n_iter):
            # 计算损失
            y_proba = self._predict_proba(X, W) 
            loss = self._loss(y, y_proba)
            print('%4i Loss: %s '%(step_i, loss)) 
            
            if self.tol is not None:
                # 随机梯度下降的loss曲线起伏较大,连续多次低于阈值,停止算法
                if loss_old - loss < self.tol:
                    end_count += 1 
                    if end_count == 5:
                        break
                else:
                    end_count = 0
                
                loss_old = loss 
            
            # 每一轮迭代前,打乱数据集
            np.random.shuffle(idx) 
            for i in idx: 
                yi_proba = self._predict_proba(X[i], W)
                
                grad = self._gradient(X[i], y[i], yi_proba)
                # 根据每一个样本更新梯度
                W -= self.eta * grad
                
    def _preprocess_data_X(self, X): 
        m, n = X.shape
        X_ = np.empty((m, n+1)) 
        X_[:, 0] = 1 
        X_[:, 1:] = X
        
        return X_ 
    
    def train(self, X_train, y_train):
        
        X_train = self._preprocess_data_X(X_train) 
        
        k = np.unique(y_train).size
        
        _, n = X_train.shape
        self.W = np.random.random((k, n)) * 0.05
        
        self._stochastic_gradient_descent(self.W, X_train, y_train)
        
    def predict(self, X): 
        X = self._preprocess_data_X(X) 
        Z = self._z(X, self.W)
        return np.argmax(Z, axis=1) 
X = np.genfromtxt('wine.data', delimiter=',', usecols=range(1, 14))
y = np.genfromtxt('wine.data', delimiter=',', usecols=0)
y -= 1 
y=y.astype(np.int32)

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
ss = StandardScaler()
ss.fit(X_train)
StandardScaler(copy=True, with_std=True, with_mean=True)
X_train_std = ss.transform(X_train)
X_test_std = ss.transform(X_test)
clf = SoftmaxRegression(n_iter=2000, eta=0.01, tol=0.0001)
clf.train(X_train_std, y_train)

# 模型检验
from sklearn.metrics import accuracy_score
y_pred = clf.predict(X_test_std)
accuracy_score(y_test, y_pred)

Python机器学习算法:原理,实现与案例 – 刘硕

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/293641.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号