#!/usr/bin/env python
# _*_coding:utf-8 _*_
#@Time :2018/4/9 7:56
#@Author :niutianzhuang
#@FileName: test_Logistic Regression_stochastic gradient ascent.py
#@Software: PyCharm
#所采用的官方的数据集(共100个样本),包含了两个特征X1和X2,以及第0维特征X0,故dataMatIn存放的是100*3的矩阵
'''梯度上升算法每次更新回归系数时都需要遍历整个数据集,样本规模大时,计算复杂大;故,改进:
随机梯度上升算法:一次仅用一个样本点来更新回归系数,可以在新样本到来时对分类器进行增量式更新,是在线学习算法,一次处理所有的数据称“批处理”
伪代码:
所有回归系数初始化为1
对数据集中每个样本
计算该样本的梯度
使用alpha * gradient更新回归系数值
返回回归系数值'''
import matplotlib.pyplot as plt
from numpy import *
#加载数据集
def loadDataSet():
'''数据集的前两个值分别为X1和X2,第三个值是数据对应的类别标签,为了方便计算,把X0的值设置成了1.0'''
dataMat = []
labelMat = []
fr = open('C:/Users/cjz/Desktop/testSet(logistics regression 数据集).txt') #打开logistics regression 数据集).txt文件
# 一定要输入正确的数据集文件所在的地址目录
for line in fr.readlines(): #逐行读取
lineArr = line.strip().split()
dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) #因为线性回归化式为 H(x) = W0 + W1*X1 + W2*X2即为 (W0, W1, W2)*(1, X1, X2),
# 其中 (W0, W1, W2) 即为所求回归系数 W。 为了方便计算, 读出 X1, X2 后要在前面补上一个 1.0
labelMat.append(int(lineArr[2]))
return dataMat, labelMat
#分类器的分类(转换)函数
def sigmoid(inX):
return 1.0 / (1 + exp(-inX)) ##计算 sigmoid 函数
#随机梯度上升算法,用来计算出最佳回归系数
def stocGradAscent(dataMatrix, classLabels):
'''第一个参数是2维数组,每列代表每个不同特征,每行代表每个训练样本
第二个参数是类别标签
'''
#dataMatrix = mat(dataMatIn) # convert to NumPy matrix 获得输入数据并将其转换为Numpy矩阵数据类型
#labelMat = mat(classLabels).transpose() # convert to NumPy matrix 获得输入数据并将其转换为Numpy矩阵数据类型
m, n = shape(dataMatrix) #shape函数是numpy.core.fromnumeric中的函数,它的功能是查看矩阵或者数组的维数
alpha = 0.01 #步长,向函数增长最快的方向的移动量,即学习率
# m = 500 #迭代次数
weights = ones(n) #回归系数初始化为1
#循环 maxCycles次, 每次都沿梯度向真实值 labelMat 靠拢
for i in range(m): # heavy on matrix operations
h = sigmoid(sum(dataMatrix[i] * weights)) # matrix multiplication 矩阵相乘 包含了300次的乘积
error = classLabels[i] - h # vector subtraction 向量减法,计算真实类别与预测类别的差值,h是一个列向量,列向量的元素个数等于样本数,即为100
weights = weights + alpha * dataMatrix[i] * error # matrix multiplication 矩阵相乘,dataMatrix.transpose()* error 就是梯度f(w),按照该差值的方向调整回归系数
return weights
#输出运用梯度上升优化算法后得到的最理想的回归系数的值
def GetResult():
dataMat, labelMat = loadDataSet()
weights = stocGradAscent(array(dataMat), labelMat)
print(weights)
plotBestFit(weights)
#画出数据集和Logistic回归最佳拟合直线
def plotBestFit(weights):
#画点
dataMat, labelMat = loadDataSet()
dataArr = array(dataMat)
n = shape(dataArr)[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()
ax = fig.add_subplot(111)
ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
ax.scatter(xcord2, ycord2, s=30, c='green')
# 画线
x = arange(-3.0, 3.0, 0.1) # x取值区间为 [-3.0, 3.0),步长 为 0.1
y = (-weights[0]-weights[1]*x)/weights[2]
ax.plot(x, y)
plt.title('testSet Dataset')
plt.xlabel('X1')
plt.ylabel('X2')
plt.show() #显示
if __name__ == '__main__':
GetResult()