逻辑回归:二分类问题
核心:激活函数sigmoid ,其中,
梯度上升/下降法 沿梯度最大的方向/反方向去更新权重值,求取函数最大、最小值
梯度优化算法:
利用梯度算法来更新参数,普通梯度下降法和随机梯度下降算法。
sigmoid函数:
def sigmoid(inX):
return 1.0 / (1 + exp(-inX))
普通梯度下降法:
def gradAscent(dataMatIn, classLabels):
dataMatrix = mat(dataMatIn)
labelMat = mat(classLabels).transpose()
m, n = shape(dataMatrix)
alpha = 0.001 # Learning rate
maxCycles = 500 # Max iterations number
weights = ones((n,1)) # Initial weights value
for k in range(maxCycles):
h = sigmoid(dataMatrix * weights)
error = (labelMat - h)
weights = weights + alpha * dataMatrix.transpose() * error # Reference: Zhou--MachineLearning--P55
return weights
可以看到,在这里整个过程设置的最大迭代次数为500次,事实上,这个迭代次数可以自己去设置,通过不断的测试以求获得最佳的测试效果。
在这里,需要注意到的是在求倒数时,采用的是矩阵的形式,矩阵求导数的原理如下:
我们已经知道,在计算误差时可以用均方误差表示,即
将其转换为矩阵形式表示就是
对W求导可以打的如下结果
由于我们在这里采用了激活函数sigmoid,因此有
随机梯度下降法:
def stocGradAscent0(dataMatrix, classLabels, numIter):
m, n = shape(dataMatrix)
weights = ones((n,1))
weights_record = []
for j in range(numIter):
dataIndex = list(range(m))
for i in range(m):
alpha = 4 / (1.0 + j + i) + 0.01
randIndex = int(random.uniform(0, len(dataIndex)))
h = sigmoid(sum(dataMatrix[randIndex] * weights))
error = classLabels[randIndex] - h
weights = weights + alpha * mat(dataMatrix[randIndex]).transpose() * error # X.T * (y - Xw)
weights_record.append(weights)
del(dataIndex[randIndex])
return weights, weights_record
在这里,我们改进了学习速率alpha的值,使其随着迭代次数的变换而变换,两种算法下的权重参数变化如下(在这里我们使用的数据有三个特征,故有三个特征值):
应用:
errorRateSum = 0.0
iterationNum = 10
for iterNum in range(iterationNum):
frTrainSet = open('horseColicTraining.txt')
frTestSet = open('horseColicTest.txt')
trainingSet = []
trainingLabel = []
for line in frTrainSet.readlines():
currLine = line.strip().split('\t')
lineArr = []
for i in range(len(currLine) - 1):
lineArr.append(float(currLine[i]))
trainingSet.append(lineArr)
trainingLabel.append(float(currLine[-1]))
weights, weightsRecord = stocGradAscent0(trainingSet, trainingLabel, 500)
errorCount = 0
testSetNum = 0
for line in frTestSet.readlines():
currLine = line.strip().split('\t')
testSetNum += 1
lineArr = []
for i in range(len(currLine) - 1):
lineArr.append(float(currLine[i]))
label = classifyVect(lineArr, weights)
if label != int(currLine[-1]):
errorCount += 1
errorRate = float(errorCount / testSetNum)
print('\n%drd test error rate is: %f' % (iterNum, errorRate))
errorRateSum += errorRate
finalErrorRate = float(errorRateSum / iterationNum)
print('\nFinal error rate is: %f' % finalErrorRate)
主要流程:
- 处理数据,得到训练集的特征集和标签集
- 采用随机梯度法得到最优权重值,其中,迭代次数取500
- 处理数据得到测试集的特征集和标签集
- 采用训练集得到的权重值对测试集进行预测并与标签集比对,得到错误率
在这里,我们采用了总共训练十次,取其平均值来做为最后结果的方式来提高准确度。