1.sigmoid函数
当x为0时,Sigmoid函数值为0.5。随着x的增大,对应的sigmiod值将逼近于1; 而随着x的减小,Sigmoid值将逼近于0。任何sigmoid值大于0.5的数据,都被分类为1类,任何sigmoid值小于0.5的数据,都被分类为0类。以下是sigmoid函数在两种不同尺度的坐标系下的图解:
可以看出来,只要横坐标的尺度足够大,在x=0处,sigmoid函数看起来就像个阶跃函数,具有比较好的分类特性。
2.梯度法求函数最值
所谓的梯度其实就是某个方向唉,沿着梯度的方向,可以最快寻找到函数的最值。其中梯度上升方向是最快找到函数最大值的方向,而梯度下降则是最快找到函数最小值的方向。不懂梯度的建议再翻一翻高数的课本!这里直接给出梯度法更新逻辑回归中权重的迭代公式:
这里的α是每次迭代的步长,α后面那一块就是所谓的梯度。这个公式会一直被迭代,直到达到某个条件为止。
3.logisic回归梯度上升算法
以下分析一下logistic回归的梯度上升的代码:
def loadDataSet():
dataMat=[];labelMat=[]
fr=open('testSet.txt')
for line in fr.readlines():
lineArr=line.strip().split()
dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])
labelMat.append(int(lineArr[2]))
return dataMat,labelMat
##这里inX可以是矩阵运算,当inX是向量是,则exp(inX)是对inX中的每个元素取指数,然后返回一个与inX等长的向量。另外,这里的X是inX=w0*x0+w1*x1+w2*x2...wn*xn##
def sigmod(inX):
return 1/(1+np.exp(-inX))
def gradAscent(dataMatIn,classLabels):
dataMatrix=np.mat(dataMatIn)
labelMat=np.mat(classLabels).transpose()
m,n=np.shape(dataMatrix)
alpha=0.001
maxCycles=500
weights=np.ones((n,1))
h=sigmod(dataMatrix*weights)
#数据集中的每个样本都会更新权重一次,而这里还设置最大循环次数,即循环整个数据集的次数
for k in range(maxCycles):
h=sigmod(dataMatrix*weights)
error=labelMat-h
#加号后面一块我认为可以理解成每个样本对某个特征的误差的贡献之和
weights=weights+alpha*dataMatrix.transpose()*error
return weights
上面的算法更新权重的话,会有一个问题,那就是运算量太大,所以有对上述算法的一种更新,那就是随机梯度上升算法,具体的执行代码:
def stocGradAscent1(dataMatrix,classLabels,numIter=150):
m,n=np.shape(dataMatrix)
weights=np.ones(n)
for j in range(numIter):
dataIndex=range(m)
for i in range(m):
alpha=4/(1.0+j+i)+0.01
randIndex=int(np.random.uniform(0,len(dataIndex)))
h=sigmod(sum(dataMatrix[randIndex]*weights))
error=classLabels[randIndex]-h
weights=weights+alpha*error*dataMatrix[randIndex]
del(dataIndex[randIndex])
return weights
这个算法每次会随机抽取数据集中的一个样本去更新权值,同时,在更新步长也会进行更新。步长的更新可以缓解数据波动和高频波动。
总结:努力啊!