10 篇文章 2 订阅

# 1. 引言

Logistic 回归数学公式推导

# 2. 通过 python 实现 logistic 算法

# -*- coding:UTF-8 -*-
# {{{
import matplotlib.pyplot as plt
import numpy as np

"""
生成数据矩阵与标签矩阵

:return: 数据矩阵与标签矩阵
"""
dataMat = []
labelMat = []
fr = open('test_dataset.txt')
lineArr = line.strip().split()
""" 每行数据钱添加特征 x0 """
dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
labelMat.append(int(lineArr[2]))
fr.close()
return dataMat, labelMat

def sigmoid(inX):
return 1.0 / (1 + np.exp(-inX))

"""
梯度上升算法

:param dataMatIn: 数据矩阵
:param classLabels: 标签矩阵
:return: 最有参数数组
"""
dataMatrix = np.mat(dataMatIn)
""" 转置 """
labelMat = np.mat(classLabels).transpose()

""" 获取矩阵行数 m 和列数 n """
m, n = np.shape(dataMatrix)
""" 迭代步长 """
alpha = 0.001
""" 迭代次数 """
maxCycles = 500
weights = np.ones((n, 1))
for k in range(maxCycles):
""" 带入数学公式求解 """
h = sigmoid(dataMatrix * weights)
weights = weights + alpha * dataMatrix.transpose() * (labelMat - h)
""" 转换为 array """
return weights.getA()

def plotBestFit(weights):
"""
绘制数据集与结果分类线

:param weights: 权重参数数组
:return:
"""
dataArr = np.array(dataMat)

""" 数据个数 """
n = np.shape(dataMat)[0]

""" 测试数据两组分类结果集 """
xcord1 = []
ycord1 = []
xcord2 = []
ycord2 = []

""" 对数据进行分类 """
for i in range(n):
if int(labelMat[i]) == 1:
xcord1.append(dataArr[i, 1])
ycord1.append(dataArr[i, 2])
else:
xcord2.append(dataArr[i, 1])
ycord2.append(dataArr[i, 2])

""" 绘图 """
fig = plt.figure()
""" 分割画布为一整份，占据其中一整份 """
""" 离散绘制分类结果为 1 的样本 """
ax.scatter(xcord1, ycord1, s=20, c='red', marker='s', alpha=.5)
""" 离散绘制分类结果为 0 的样本 """
ax.scatter(xcord2, ycord2, s=20, c='green', alpha=.5)
x1 = np.arange(-3.0, 3.0, 0.1)
x2 = (-weights[0] - weights[1] * x1) / weights[2]
ax.plot(x1, x2)
plt.title('BestFit')
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()

if __name__ == '__main__':
plotBestFit(weights)
# }}}


# 3. 随机梯度上升算法

## 3.1. 算法代码

def randGradientAscent(dataMatrix, classLabels, numIter=20):
"""
随机梯度上升算法

:param dataMatrix: 数据矩阵
:param classLabels: 标签矩阵
:param numIter: 外循环次数
:return: 权重数组与回归系数矩阵
"""
time0 = time.time()
m,n = np.shape(dataMatrix)
weights = np.ones(n)
weights_array = np.array([])
innerIterNum = int(m/100)
for j in range(numIter):
dataIndex = list(range(m))
for i in range(innerIterNum):
alpha = 4/(1.0 + j + i) + 0.01  # 降低alpha的大小，每次减小1/(j+i)
""" 随机选取样本 """
randIndex = int(random.uniform(0,len(dataIndex)))
chose = dataIndex[randIndex]
h = sigmoid(sum(dataMatrix[chose]*weights))
error = classLabels[chose] - h
weights = weights + alpha * error * dataMatrix[chose]
weights_array = np.append(weights_array,weights,axis=0)
del(dataIndex[randIndex])
weights_array = weights_array.reshape(numIter*innerIterNum, n)
print("随机梯度算法耗时：", time.time() - time0)
return weights, weights_array


1. 将原有的迭代 + 矩阵操作替换成内外层双层循环实现，内循环只随机选取原数据集的 1/100 规模，从而实现计算量的缩减
2. alpha 动态调整，随着内循环的进行，逐步缩小，从而对获取更准确的最优值与运行时间二者的优化

# 4. 随机梯度上升算法与梯度上升算法效果对比

# -*- coding:UTF-8 -*-
# {{{
import time

from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
import numpy as np
import random

"""
加载数据

:return: 数据集，标签集
"""
dataMat = []
labelMat = []
fr = open('test_dataset.txt')
for i in range(100):
lineArr = line.strip().split()
dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
labelMat.append(int(lineArr[2]))
fr.close()
return dataMat, labelMat

def sigmoid(inX):
return 1.0 / (1 + np.exp(-inX))

def gradAscent(dataMatIn, classLabels, maxCycles = 300):
"""
梯度上升算法

:param dataMatIn: 数据矩阵
:param classLabels: 数据集
:param maxCycles: 迭代次数
:return: 权重数组与回归系数矩阵
"""
time0 = time.time()
dataMatrix = np.mat(dataMatIn)
labelMat = np.mat(classLabels).transpose()
m, n = np.shape(dataMatrix)
alpha = 0.0001
weights = np.ones((n,1))
weights_array = np.array([])
for k in range(maxCycles):
h = sigmoid(dataMatrix * weights)
error = labelMat - h
weights = weights + alpha * dataMatrix.transpose() * error
weights_array = np.append(weights_array,weights)
weights_array = weights_array.reshape(maxCycles,n)
print("梯度上升算法耗时：", time.time() - time0)
return weights.getA(), weights_array

"""
随机梯度上升算法

:param dataMatrix: 数据矩阵
:param classLabels: 标签矩阵
:param numIter: 外循环次数
:return: 权重数组与回归系数矩阵
"""
time0 = time.time()
m,n = np.shape(dataMatrix)
weights = np.ones(n)
weights_array = np.array([])
innerIterNum = int(m/100)
for j in range(numIter):
dataIndex = list(range(m))
for i in range(innerIterNum):
alpha = 4/(1.0 + j + i) + 0.01  #降低alpha的大小，每次减小1/(j+i)
""" 随机选取样本 """
randIndex = int(random.uniform(0,len(dataIndex)))
chose = dataIndex[randIndex]
h = sigmoid(sum(dataMatrix[chose]*weights))
error = classLabels[chose] - h
weights = weights + alpha * error * dataMatrix[chose]
weights_array = np.append(weights_array,weights,axis=0)
del(dataIndex[randIndex])
weights_array = weights_array.reshape(numIter*innerIterNum, n)
print("随机梯度算法耗时：", time.time() - time0)
return weights, weights_array

"""
绘制回归系数与迭代次数的关系

:return:
"""

font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)
"""
将fig画布分隔成1行1列,不共享x轴和y轴,fig画布的大小为 (13,8)，分为六个区域
"""
fig, axs = plt.subplots(nrows=3, ncols=2, sharex='none', sharey='none', figsize=(20,10))

axs0_title_text = axs[0][0].set_title(u'改进的随机梯度上升算法：回归系数与迭代次数关系',FontProperties=font)
axs0_ylabel_text = axs[0][0].set_ylabel(u'W0',FontProperties=font)
plt.setp(axs0_title_text, size=20, weight='bold', color='black')
plt.setp(axs0_ylabel_text, size=20, weight='bold', color='black')

axs1_ylabel_text = axs[1][0].set_ylabel(u'W1',FontProperties=font)
plt.setp(axs1_ylabel_text, size=20, weight='bold', color='black')

axs2_xlabel_text = axs[2][0].set_xlabel(u'迭代次数',FontProperties=font)
axs2_ylabel_text = axs[2][0].set_ylabel(u'W1',FontProperties=font)
plt.setp(axs2_xlabel_text, size=20, weight='bold', color='black')
plt.setp(axs2_ylabel_text, size=20, weight='bold', color='black')

axs0_title_text = axs[0][1].set_title(u'梯度上升算法：回归系数与迭代次数关系',FontProperties=font)
axs0_ylabel_text = axs[0][1].set_ylabel(u'W0',FontProperties=font)
plt.setp(axs0_title_text, size=20, weight='bold', color='black')
plt.setp(axs0_ylabel_text, size=20, weight='bold', color='black')

axs1_ylabel_text = axs[1][1].set_ylabel(u'W1',FontProperties=font)
plt.setp(axs1_ylabel_text, size=20, weight='bold', color='black')

axs2_xlabel_text = axs[2][1].set_xlabel(u'迭代次数',FontProperties=font)
axs2_ylabel_text = axs[2][1].set_ylabel(u'W1',FontProperties=font)
plt.setp(axs2_xlabel_text, size=20, weight='bold', color='black')
plt.setp(axs2_ylabel_text, size=20, weight='bold', color='black')

plt.show()

if __name__ == '__main__':
plotWeights(weights_array1, weights_array2)
# }}}


## 4.1. 输出结果

随机梯度算法耗时： 0.03397965431213379



# 5. 《机器学习实战》随机梯度上升算法讲解中的错误

def stocGradAscent1(dataMatrix, classLabels, numIter=150):
m,n = shape(dataMatrix)
weights = ones(n)   #initialize to all ones
for j in range(numIter):
dataIndex = range(m)
for i in range(m):
alpha = 4/(1.0+j+i)+0.0001    #apha decreases with iteration, does not
randIndex = int(random.uniform(0, len(dataIndex)))#go to 0 because of the constant
h = sigmoid(sum(dataMatrix[randIndex]*weights))
error = classLabels[randIndex] - h
weights = weights + alpha * error * dataMatrix[randIndex]
del(dataIndex[randIndex])
return weights


## 5.1. 随机样本选择时下标问题

。。。

randIndex = dataIndex[int(random.uniform(0, len(dataIndex)))]


# 6. 附录

## 6.1. 训练样本数据

-0.017612       14.053064       0
-1.395634       4.662541        1
-0.752157       6.538620        0
-1.322371       7.152853        0
0.423363        11.054677       0
0.406704        7.067335        1
0.667394        12.741452       0
-2.460150       6.866805        1
0.569411        9.548755        0
-0.026632       10.427743       0
0.850433        6.920334        1
1.347183        13.175500       0
1.176813        3.167020        1
-1.781871       9.097953        0
-0.566606       5.749003        1
0.931635        1.589505        1
-0.024205       6.151823        1
-0.036453       2.690988        1
-0.196949       0.444165        1
1.014459        5.754399        1
1.985298        3.230619        1
-1.693453       -0.557540       1
-0.576525       11.778922       0
-0.346811       -1.678730       1
-2.124484       2.672471        1
1.217916        9.597015        0
-0.733928       9.098687        0
-3.642001       -1.618087       1
0.315985        3.523953        1
1.416614        9.619232        0
-0.386323       3.989286        1
0.556921        8.294984        1
1.224863        11.587360       0
-1.347803       -2.406051       1
1.196604        4.951851        1
0.275221        9.543647        0
0.470575        9.332488        0
-1.889567       9.542662        0
-1.527893       12.150579       0
-1.185247       11.309318       0
-0.445678       3.297303        1
1.042222        6.105155        1
-0.618787       10.320986       0
1.152083        0.548467        1
0.828534        2.676045        1
-1.237728       10.549033       0
-0.683565       -2.166125       1
0.229456        5.921938        1
-0.959885       11.555336       0
0.492911        10.993324       0
0.184992        8.721488        0
-0.355715       10.325976       0
-0.397822       8.058397        0
0.824839        13.730343       0
1.507278        5.027866        1
0.099671        6.835839        1
-0.344008       10.717485       0
1.785928        7.718645        1
-0.918801       11.560217       0
-0.364009       4.747300        1
-0.841722       4.119083        1
0.490426        1.960539        1
-0.007194       9.075792        0
0.356107        12.447863       0
0.342578        12.281162       0
-0.810823       -1.466018       1
2.530777        6.476801        1
1.296683        11.607559       0
0.475487        12.040035       0
-0.783277       11.009725       0
0.074798        11.023650       0
-1.337472       0.468339        1
-0.102781       13.763651       0
-0.147324       2.874846        1
0.518389        9.887035        0
1.015399        7.571882        0
-1.658086       -0.027255       1
1.319944        2.171228        1
2.056216        5.019981        1
-0.851633       4.375691        1
-1.510047       6.061992        0
-1.076637       -3.181888       1
1.821096        10.283990       0
3.010150        8.401766        1
-1.099458       1.688274        1
-0.834872       -1.733869       1
-0.846637       3.849075        1
1.400102        12.628781       0
1.752842        5.468166        1
0.078557        0.059736        1
0.089392        -0.715300       1
1.825662        12.693808       0
0.197445        9.744638        0
0.126117        0.922311        1
-0.679797       1.220530        1
0.677983        2.556666        1
0.761349        10.693862       0
-2.168791       0.143632        1
1.388610        9.341997        0
0.317029        14.739025       0


# 参考资料

• 3
点赞
• 6
评论
• 14
收藏
• 打赏
• 扫一扫，分享海报

08-30 4万+

04-15 9054
06-30 4699
07-08 7564
09-12 472
03-12 3659
04-09 1241
11-20 1335
08-02 1182
11-26 764
06-25 4448
02-26 129
11-22 1339
11-01 166
01-23 5584
11-28 2358
05-18 149

DILIGENT203

¥2 ¥4 ¥6 ¥10 ¥20

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