Task2机器学习入门笔记逻辑回归

逻辑回归与线性回归的区别

线性回归适用于不同类别的训练样例数目相当。如果不同类别的训练样例数目稍有差别,通常影响不大,但若差别很大,则会对学习过程造成困扰。

类别不平衡就是指分类任务中不同类别的训练样例数目差别很大的情况。

例如:

图显示了是否购买玩具和年龄之间的关系,可以用线性回归拟合成一条直线,将购买标注为1,不购买标注为0,拟合后取当0.5值为阈值来划分类别。
在这里插入图片描述
可以看到,在途中,年龄的区分点约为19岁。但当数据点不平衡时,很容易影响到阈值,见以下图:

在这里插入图片描述
可以看到,0值样本的年龄段往高年龄端偏移后,真实的阈值依然是19岁左右,但拟合出来的曲线的阈值往后边偏移了。可以想想,负样本越多,年龄大的人越多,偏移越严重。可是这符合实际情况吗?实际情况是60岁的老人和80岁的老人都不会购买玩具,增加几位80岁的老人,并不会影响可以看到,0值样本的年龄段往高年龄端偏移后,真实的阈值依然是19岁左右,但拟合出来的曲线的阈值往后边偏移了。可以想想,负样本越多,年龄大的人越多,偏移越严重。可是这符合实际情况吗?实际情况是60岁的老人和80岁的老人都不会购买玩具,增加几位80岁的老人,并不会影响20岁以下人群购买玩具的概率。但因为拟合曲线原本的值域为(−∞ ∞)(−∞ ∞)而转换后的值域为[0,1],阈值对变量偏移很敏感。20岁以下人群购买玩具的概率。但因为拟合曲线原本的值域为(−∞ ∞)(−∞ ∞)而转换后的值域为[0,1],阈值对变量偏移很敏感。

逻辑回归的原理

常用的替代函数是对数几率函数,它是一种“Sigmoid”函数,它将z值转化为一个接近0或1的y值,并且其输出值在z=0附近变化很陡。
在这里插入图片描述在这里插入图片描述
我们可以看到,当z大于0时,函数大于0.5;当函数等于0时,函数等于0.5;函数小于0时,函数小于0.5。如果用函数表示目标分到某一类的概率,我们可以采用以下“单位阶跃函数”来判断数据的类别:
在这里插入图片描述
若Z大于0,则判断为正例;若小于0,判断为反例;若等于0,可任意判别。由于Sigmoid函数单调且可导,函数在(0,1)之间程Z字型,可以很好的模拟二分类情况。

正则化与模型评估指标

正则化

可以在损失函数后面,加上正则化函数,即𝜃θ的惩罚项,来抑制过拟合问题。
L1正则:
J ( θ ) = 1 m ∑ i = 1 m y ( i ) h θ ( x ( i ) ) + ( 1 − y ( i ) ) ( 1 − h θ ( x ( i ) ) ) + λ m ∑ i = 1 m ∣ θ i ∣ J(\theta) =\frac{1}{m}\sum^{m}_{i=1} y^{(i)}h_\theta (x^{(i)}) + (1-y^{(i)})(1-h_\theta (x^{(i)})) + \frac{\lambda}{m }\sum^m_{i=1}|\theta_i| J(θ)=m1i=1my(i)hθ(x(i))+(1y(i))(1hθ(x(i)))+mλi=1mθi
Δ θ i l ( θ ) = 1 m ∑ i = 1 m ( y ( i ) − h θ ( x ( i ) ) ) x ( i ) + λ m s g n ( θ i ) \Delta_{\theta_i} l(\theta) = \frac{1}{m}\sum^m_{i=1}(y^{(i)} - h_\theta (x^{(i)}))x^{(i)} + \frac{\lambda}{m}sgn(\theta_i) Δθil(θ)=m1i=1m(y(i)hθ(x(i)))x(i)+mλsgn(θi)
梯度下降法的迭代函数变为,
θ : = θ − K ′ ( θ ) − λ m s g n ( θ ) \theta:=\theta-K'(\theta)-\frac{\lambda}{m}sgn(\theta) θ:=θK(θ)mλsgn(θ)
K(θ)为原来的损失函数,由于最后一项的符号由𝜃决定,可以看到,当𝜃大于零时,更新后的𝜃变小;当𝜃θ小于零时,更新后的𝜃变大。因此,L1正则化调整后的结果会更加稀疏(结果向量中有更多的0值)。(见图示,相当于在等高线上找令菱形最小的点。)
在这里插入图片描述
L2正则
J ( θ ) = 1 m ∑ i = 1 m y ( i ) h θ ( x ( i ) ) + ( 1 − y ( i ) ) ( 1 − h θ ( x ( i ) ) ) + λ 2 m ∑ i = 1 m θ i 2 J(\theta) =\frac{1}{m}\sum^{m}_{i=1} y^{(i)}h_\theta (x^{(i)}) + (1-y^{(i)})(1-h_\theta (x^{(i)})) + \frac{\lambda}{2m}\sum^m_{i=1}\theta_i^2 J(θ)=m1i=1my(i)hθ(x(i))+(1y(i))(1hθ(x(i)))+2mλi=1mθi2
Δ θ i l ( θ ) = 1 m ∑ i = 1 m ( y ( i ) − h θ ( x ( i ) ) ) x ( i ) + λ m θ i \Delta_{\theta_i} l(\theta) = \frac{1}{m}\sum^m_{i=1}(y^{(i)} - h_\theta (x^{(i)}))x^{(i)} + \frac{\lambda}{m}\theta_i Δθil(θ)=m1i=1m(y(i)hθ(x(i)))x(i)+mλθi
梯度下降法的迭代函数变为,
θ : = θ − K ′ ( θ ) − 2 λ m θ \theta:=\theta-K'(\theta)-\frac{2\lambda}{m}\theta θ:=θK(θ)m2λθ
𝐾(𝜃)为原来的损失函数,最有一项的𝜆决定了对参数的惩罚力度,惩罚力度越大,最后的结果向量的参数普遍较小且分散,避免了个别参数对整个函数起较大的影响。(见图示,相当于在等高线上找令圆形最小的点)

在这里插入图片描述

python实现

use skearn

import pandas as pd
import matplotlib.pyplot as plt

df_X = pd.read_csv('./logistic_x.txt', sep='\ +', header=None, engine='python')  # 读取X值
ys = pd.read_csv('./logistic_y.txt', sep='\ +', header=None, engine='python')  # 读取y值
ys = ys.astype(int)  # 转换ys的数据类型为整型
df_X['label'] = ys[0].values  # 将X按照y值的结果一一打标签
ax = plt.axes()
# 在二维图中描绘X点所处位置,直观查看数据点的分布情况
df_X.query('label == 0').plot.scatter(x=0, y=1, ax=ax, color='blue')
df_X.query('label == 1').plot.scatter(x=0, y=1, ax=ax, color='red')
plt.show()
from __future__ import print_function
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LogisticRegression

df_X = pd.read_csv('./logistic_x.txt', sep='\ +',header=None, engine='python')  # 读取X值
ys = pd.read_csv('./logistic_y.txt', sep='\ +',header=None, engine='python')  # 读取y值
ys = ys.astype(int)
df_X['label'] = ys[0].values  # 将X按照y值的结果一一打标签
# 提取用于学习的数据
Xs = df_X[[0, 1]].values
Xs = np.hstack([np.ones((Xs.shape[0], 1)), Xs])
"""
【拼接数组的方法】
np.hstack——Stack arrays in sequence horizontally (column wise).   
np.vstack——Stack arrays in sequence vertically (row wise).
https://docs.scipy.org/doc/numpy/reference/generated/numpy.hstack.html
"""
ys = df_X['label'].values

lr = LogisticRegression(fit_intercept=False)  # 因为前面已经将截距项的值合并到变量中,此处参数设置不需要截距项
lr.fit(Xs, ys)  # 拟合
score = lr.score(Xs, ys)  # 结果评价
print("Coefficient: %s" % lr.coef_)
print("Score: %s" % score)

ax = plt.axes()
df_X.query('label == 0').plot.scatter(x=0, y=1, ax=ax, color='blue')
df_X.query('label == 1').plot.scatter(x=0, y=1, ax=ax, color='red')

_xs = np.array([np.min(Xs[:,]), np.max(Xs[:, 1])])
# 将数据以二维图形式描点,并用学习得出的参数结果作为阈值,划分数据区域
_ys = (lr.coef_[0][0] + lr.coef_[0][1] * _xs) / (- lr.coef_[0][2])
plt.plot(_xs, _ys, lw=1)

在这里插入图片描述

逻辑回归

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

df_X = pd.read_csv('./logistic_x.txt', sep='\ +', header=None, engine='python')  # 读取X值
ys = pd.read_csv('./logistic_y.txt', sep='\ +', header=None, engine='python')  # 读取y值
ys = ys.astype(int)  # 转换ys的数据类型为整型
df_X['label'] = ys[0].values  # 将X按照y值的结果一一打标签
# 提取用于学习的数据
Xs = df_X[[0, 1]].values
Xs = np.hstack([np.ones((Xs.shape[0], 1)), Xs])
"""
【拼接数组的方法】
np.hstack——Stack arrays in sequence horizontally (column wise).   
np.vstack——Stack arrays in sequence vertically (row wise).
https://docs.scipy.org/doc/numpy/reference/generated/numpy.hstack.html
"""
ys = df_X['label'].values

class LGR_GD():
    def __init__(self):
        self.w = None
        self.n_iters = None

    def fit(self, X, y, alpha=0.03, loss=1e-10):  # 设定步长为0.02,判断是否收敛的条件为1e-10
        y = y.reshape(-1, 1)  # 重塑y值的维度以便矩阵运算
        [m, d] = np.shape(X)  # 自变量的维度
        self.w = np.zeros((1, d))  # 将参数的初始值定为0
        tol = 1e5
        self.n_iters = 0
        # ============================= show me your code =======================
        while tol > loss:  # 设置收敛条件
            # 计算Sigmoid函数结果
            sigmoid = 1 / (1 + np.exp(-X.dot(self.w.T)))
            theta = self.w + alpha * np.mean(X * (y - sigmoid), axis=0)  # 迭代theta的值
            tol = np.sum(np.abs(theta - self.w))  # 计算损失值
            self.w = theta
            self.n_iters += 1  # 更新迭代次数
        # ============================= show me your code =======================

    def predict(self, X):
        # 用已经拟合的参数值预测新自变量
        y_pred = X.dot(self.w)
        return y_pred


if __name__ == "__main__":
    lr_gd = LGR_GD()
    lr_gd.fit(Xs, ys)

    ax = plt.axes()

    df_X.query('label == 0').plot.scatter(x=0, y=1, ax=ax, color='blue')
    df_X.query('label == 1').plot.scatter(x=0, y=1, ax=ax, color='red')

    _xs = np.array([np.min(Xs[:, 1]), np.max(Xs[:, 1])])
    _ys = (lr_gd.w[0][0] + lr_gd.w[0][1] * _xs) / (- lr_gd.w[0][2])
    plt.plot(_xs, _ys, lw=1)
    plt.show()

在这里插入图片描述

牛顿法

class LGR_GD():
    def __init__(self):
        self.w = None
        self.n_iters = None

    def fit(self, X, y, alpha=0.03, loss=1e-10):  # 设定步长为0.02,判断是否收敛的条件为1e-10
        y = y.reshape(-1, 1)  # 重塑y值的维度以便矩阵运算
        [m, d] = np.shape(X)  # 自变量的维度
        self.w = np.zeros((1, d))  # 将参数的初始值定为0
        tol = 1e5
        self.n_iters = 0
        # ============================= show me your code =======================
        while tol > loss:  # 设置收敛条件
            # 计算Sigmoid函数结果
            zs = X.dot(self.w.T)
            h_f = 1 / (1 + np.exp(-zs))

            theta = self.w + alpha * np.mean(X*(y - h_f), axis=0)  # 计算迭代的参数值
            # axis= 0 对**横轴操作**,在运算的过程中其运算的方向表现为**纵向运算**

            tol = np.sum(np.abs(theta - self.w))  # tol本身是一个差值? 平均绝对误差

            self.w = theta  # 更新参数值
            self.n_iters += 1  # 更新迭代次数
        # ============================= show me your code =======================

    def predict(self, X):
        # 用已经拟合的参数值预测新自变量
        y_pred = X.dot(self.w)
        return y_pred


if __name__ == "__main__":
    LGR_GD = LGR_GD()
    LGR_GD.fit(Xs, ys)

    ax = plt.axes()

    df_X.query('label == 0').plot.scatter(x=0, y=1, ax=ax, color='blue')
    df_X.query('label == 1').plot.scatter(x=0, y=1, ax=ax, color='red')

    _xs = np.array([np.min(Xs[:, 1]), np.max(Xs[:, 1])])
    _ys = (LGR_GD.w[0][0] + LGR_GD.w[0][1] * _xs) / (- LGR_GD.w[0][2])
    plt.plot(_xs, _ys, lw=1)
    plt.show()
    print("梯度下降法结果参数:%s;梯度下降法迭代次数:%s" % (LGR_GD.w, LGR_GD.n_iters))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值