机器学习之逻辑回归
线性回归 和逻辑回归
逻辑回归 也是求解分类问题。
线性回归
前面我们讲了 线性回归 其实就是 求出一条直线 尽量的让所有的数据 离这条直线 距离最小 。 来了新的数据 根据 这条直线去预测。一般是求解 连续的数值。
逻辑回归
比如根据人的饮食,作息,工作和生存环境等条件预测一个人"有"或者"没有"得恶性肿瘤,可以先通过回归任务来预测人体内肿瘤的大小,取一个平均值作为阈值,假如平均值为y,肿瘤大小超过y为恶心肿瘤,无肿瘤或大小小于y的,为非恶性.这样通过线性回归加设定阈值的办法,就可以完成一个简单的二分类任务.如下图:
上图中,红色的x轴为肿瘤大小,粉色的线为回归出的函数的图像,绿色的线为阈值.
预测肿瘤大小还是一个回归问题,得到的结果(肿瘤的大小)也是一个连续型变量.通过设定阈值,就成功将回归问题转化为了分类问题.但是,这样做还存在一个问题.
我们上面的假设,依赖于所有的肿瘤大小都不会特别离谱,如果有一个超大的肿瘤在我们的例子中,阈值就很难设定.加入还是取平均大小为阈值,则会出现下图的情况:
从上边的例子可以看出,使用线性的函数来拟合规律后取阈值的办法是行不通的,行不通的原因在于拟合的函数太直,离群值(也叫异常值)对结果的影响过大,但是我们的整体思路是没有错的,错的是用了太"直"的拟合函数,如果我们用来拟合的函数是非线性的,不这么直,是不是就好一些呢?
上述这个实例中 求这个 因为有个别超大 数据的影响导致 求解的 这个阀值 不太精确 。
怎么求解这个阀值呢 ?
sigmod函数
sigmod 公式:
sigmod函数的图像如下
因为这个 sigmod 函数的特性 所以 很容易找到阀值。中间 x=0 的时候 y=0.5 作为 一个二分类 。那么肿瘤实例的线性方程 带入 这个式子中 就可以很明确的区分 求得阀值。
将 sigmod函数 中的 z = WX 带入 。
g(x) =
那么 只要 g(x) 大于 0.5 就是 癌症 小于 0.5 就是 正常 。 很容易定义这个阀值。 不管 y = wx 取值多大 也不影响取阀值。
将一个连续的 线性回归 转换成 一个二分类问题。
损失函数:
均方差
如果按照线性回归的逻辑 损失函数是这个:
那么带入去求解 将非常的困难 。
最大似然估计
转换成概率问题
那么我们不妨来换一个思路解决这个问题。 将上述问题转换成 以下描述:
p(y=1|x;w)= ϕ(wTx+b)=ϕ(z)
p(y=0|x;w)=1−ϕ(z)
y=1 表示 其中的一个分类 比如 换了癌症。
最大似然估计
最大似然估计的意思就是最大可能性估计,其内容为:如果两件事A,B相互独立,那么A和B同时发生的概率满足公式
P(A , B) = P(A) * P(B)
P(x)表示事件x发生的概率.
如何来理解独立呢?两件事独立是说这两件事不想关,比如我们随机抽取两个人A和B,这两个人有一个共同特性就是在同一个公司,那么抽取这两个人A和B的件事就不独立,如果A和B没有任何关系,那么这两件事就是独立的.
也可以根据 伯努利分布得到 。
其中 y = 1 , 0
用极大似然估计 求参数 W
接下来我们就要用极大似然估计来根据给定的训练集估计出参数w。
为了简化运算,我们对上面这个等式的两边都取一个对数
我们现在要求的是使得l(w)最大的w。没错,我们的代价函数出现了,我们在l(w)前面加个负号不就变成就最小了吗?不就变成我们代价函数了吗?
为了更好地理解这个代价函数,我们不妨拿一个例子的来看看
我们来看看这是一个怎么样的函数
从图中不难看出,如果样本的值是1的话,估计值ϕ(z)越接近1付出的代价就越小,反之越大;同理,如果样本的值是0的话,估计值ϕ(z)越接近0付出的代价就越小,反之越大。
梯度函数
我们最终的目的是求 g(x) = 那么就是要求 最佳的 W 参数值 。 W 这个值 均一化后 取值 在 (0,1) 之间 y = w0 * x0 + w1x1 …Wnxn 那么我们可以使 W0 —Wn 初始值都设置成1 。 那么慢慢的减少w里面的值 看看是否是符合整个数据模型 。 这个过程 就是 梯度下降 求解法 。 反之 让 W初始值设置为 0 慢慢 增加到 符合的值 就称为 梯度上升 。
怎么样 上升 或者下降呢?
如上图 比如一个盲人在山顶 怎么能最快的下山呢 , 盲人 会脚或者 拐杖 探路那边 陡峭 就忘哪里走 。那么我们换成 刚刚的问题 。 W 怎么样减少呢?
我们都知道 一阶 求导 得到 速度 二阶求导 得到加速度。
那么 我们想让 W 里面的值 从 1 下降到 合适的值 。就求 这个 W 所在的 函数 g(x) 的 一阶导数得出的速度方向下降就可以了。
所以
w:=w+Δw, Δw=−η∇J(w)
wj:=wj+Δwj, Δwj=−η∂J(w) / ∂wj
η 是人为设置的参数 表示 给下降加一个速度 控制下降步长 。Δw 就是我们要下降多少和下降方向。
那么现在 就可以将 求W 转换成 求 J(w) 的导数问题。
求解W过程
已知:
1, 对数求导知识 :
2,sigmoid 求导
ϕ′(z)=ϕ(z)(1−ϕ(z))
z(i)=W *x(i)+b
∂z(i) / ∂wj = X(i)
3, 求解 ∂J(w) / wj
有了上述预备知识 可以得出下面的 推导过程。
所以,在使用梯度下降法更新权重时,只要根据下式即可
python 实现
sigmoid函数和初始化数据
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def init_data():
data = np.loadtxt('data.csv')
dataMatIn = data[:, 0:-1]
classLabels = data[:, -1]
dataMatIn = np.insert(dataMatIn, 0, 1, axis=1) #特征数据集,添加1是构造常数项x0
return dataMatIn, classLabels
// 梯度上升
def grad_descent(dataMatIn, classLabels):
dataMatrix = np.mat(dataMatIn) #(m,n)
labelMat = np.mat(classLabels).transpose()
m, n = np.shape(dataMatrix)
weights = np.ones((n, 1)) #初始化回归系数(n, 1)
alpha = 0.001 #步长
maxCycle = 500 #最大循环次数
for i in range(maxCycle):
h = sigmoid(dataMatrix * weights) #sigmoid 函数
weights = weights + alpha * dataMatrix.transpose() * (labelMat - h) #梯度
return weights
// 计算结果
if __name__ == '__main__':
dataMatIn, classLabels = init_data()
r = grad_descent(dataMatIn, classLabels)
print(r)
随机梯度
上述公式 可以得出 没一次 求参 W 就需要 所有的数据 都计算一次 当数据量 非常庞大的时候 效率就很低。
每次循环矩阵都会进行m * n次乘法计算,时间复杂度是maxCycles* m * n。当数据量很大时, 时间复杂度是很大。
这里尝试使用随机梯度上升法来进行改进。
随机梯度上升法的思想是,每次只使用一个数据样本点来更新回归系数。这样就大大减小计算开销。
改进算法:
def stoc_grad_ascent(dataMatIn, classLabels):
m, n = np.shape(dataMatIn)
alpha = 0.01
weights = np.ones(n)
maxCycle = 3 #最大循环次数
for j in range(maxCycle):
for i in range(m):
h = sigmoid(sum(dataMatIn[i] * weights)) #数值计算
error = classLabels[i] - h
weights = weights + alpha * error * dataMatIn[i]
return weights
// 计算结果
if __name__ == '__main__':
dataMatIn, classLabels = init_data()
r = stoc_grad_ascent(dataMatIn, classLabels)
print(r)
参考文献
https://blog.csdn.net/zjuPeco/article/details/77165974
https://blog.csdn.net/weixin_39445556/article/details/83930186
https://www.jianshu.com/p/4cfb4f734358