一、广义线性模型
①、广义线性模型:将线性回归的假设函数作为自变量映射到另一个函数上即:
这样的模型为广义线性回归,其中函数g 为联系函数。
②、作用:
将分类任务的真实标记y 与线性回归模型的预测值联系起来
二、逻辑斯蒂回归
虽然逻辑回归能够用于分类,不过其本质还是线性回归。它仅在线性回归的基础上,在特征到结果的映射中加入了一层sigmoid函数(非线性)映射,即先把特征线性求和,然后使用sigmoid函数来预测。
2.1 sigmoid函数
①、首先我想到了阶跃函数:
但是阶跃函数在0处不连续,且无法求导,那就无法作为联系函数,于是我们需要找到阶跃函数的替代品,且它必须是连续可导的,还要能有分箱的功能。
②、对数几率函数
公式表示:
图像:
(手绘能力有限,读者见谅!!!ps:爱你们)
我们可以从图像看出,该函数时连续可导的,并且可以实现分箱操作,将Z值转为0~1之间的数,更惊喜的是 它竟然位于0~1之间,大致符合概率密度分布。
2.2 逻辑斯蒂回归流程
由对数几率函数得出,它可以将z值转为0~1之间的数。
我们将对数几率函数当做广义线性模型的联系函数得到:
将其化简:
其中可以将y看作样本x作为正例的可能性,1-y为反例的可能性
两者比值称为‘几率’,对其取对数称为“对数几率”。
所以逻辑斯蒂回归使用线性模型的预测结果去逼近真实标记的对数几率,因此逻辑斯蒂回归也称为“对数几率回归”
于是对于二分类问题,可以将上面函数变形得到:
其中y=0 或y=1 为y的标签取值
然后我们可以用最大似然函数来求取参数w和b。我们可以将截距项b归化到矩阵中,所有只需求w即可
似然化得:
然后利用梯度下降算法或者拟牛顿法求解参数w
2.3 sklearn实现
from skleran.liner_model import LogisticReression
参数介绍:
2.4 逻辑斯蒂回归绘制决策边界
from sklearn.linear_model import LogisticRegression
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
%matplotlib inline
# 生成样本集
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=150, n_features=2, centers=3)
# 自定义调色板
from matplotlib.colors import ListedColormap
colors = sns.color_palette('husl')
cmp = ListedColormap(colors)
# 生成预测集即生成画布上所有点,来绘制决策边界
xmin, xmax = X[:,0].min(), X[:,0].max()
ymin, ymax = X[:,1].min(), X[:,1].max()
a = np.linspace(xmin, xmax, 200)
b = np.linspace(ymin, ymax, 200)
xx, yy = np.meshgrid(a, b)
X_test = np.concatenate((xx.reshape(-1,1), yy.reshape(-1,1)), axis=1)
# 训练
lr = LogisticRegression()
lr.fit(X, y)
# 预测
y_ = lr.predict(X_test)
# 绘制决策边界图像
plt.scatter(X_test[:,0], X_test[:,1], c=y_)
plt.scatter(X[:,0], X[:,1], c=y, cmap=cmp)
由图像看出逻辑斯蒂回归只能对线性可分的数据进行更好的划分,但是由于逻辑斯蒂是一个概率估计模型,并且具备线性回归的所有优点(高效、缩减) ,所以是一个非常流行的算法
2.5 逻辑斯蒂回归的概率预测
需要导包
# 生成样本集
X = np.random.random(size=(10,5))
y = np.random.randint(0,2, size=10)
# 训练
lr = LogisticRegression()
lr.fit(X, y)
lr.predict(X)
lr.coef_
lr.score(X, y)
# 查看每个示例的概率
lr.predict_proba(X)
# 改变阈值,调整正负样本的倾向
(lr.predict_proba(X)[:,0] > 0.6)*1
隐藏的逻辑就是 逻辑斯蒂回归默认的就是看哪个分类的概率值高于0.5(阈值),如果把阈值调整,就可以影响我们对正负样本的预测结果
三、使用梯度下降优化算法实现线性回归
import numpy as np
import pandas as pd
from pandas import Series, DataFrame
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
# 假设一个代价函数f
x = np.linspace(-6,9)
f = lambda x:(x-3)**2 + 2*x - 6
# 求解代价函数的导数g
g = lambda x:2*x - 4
# 梯度下降
step = 0.1 # 不能太大也不能太小,太大可能会越过全局最小值,太小下降次数太多
precision = 0.005 # 下降的精度,表示达到下降的可接受范围,就可以停止继续下降
max_count = 3000 # 下降的最大次数
current_count = 0 # 记录当前的下降次数
last_min = np.random.randint(-8,6,1)[0] # 随机选取一个下降的起始点 西塔0
current_min = last_min + 1 # 在起始点随机取一个点,作为下一个点 西塔
points = []
print("开始梯度下降:起始值是{}".format(last_min))
while True:
current_count += 1
if current_count > max_count:
break
# last_min - current 表示的是纵向的位移,如果达到了精度以内,就可以停止继续下降了
if np.abs(last_min - current_min) < precision:
break
# 开始梯度下降
last_min = current_min
current_min = last_min - step*g(last_min)
points.append(current_min)
print("第{}次下降:min:{}".format(current_count, current_min))
# 绘制下降点图像
plt.figure(figsize=(10,4))
plt.plot(x, y, color='k')
plt.scatter(points, f(points), marker='+', color='r', s=160)