@Macux
2018-04-10T13:44:45.000000Z
字数 3836
阅读 1409
Algorithm
本质理解:LR的loss function选择的是对数损失(对数似然损失),所以其cost function的形式和MLE的形式如此神似。
loss function 和 cost function的区别:
- Cost函数(损失函数),表示预测的输出(h(x))与训练数据类别(y)之间的偏差,可以是二者之间的差(h(x)-y)或者是其他的形式。综合考虑所有训练数据的“损失”,将Cost求和或者求平均,表示所有训练数据预测值与实际类别的偏差。
- 个人对 LR 的 cost func 的理解:
- LR 是基于 MLE 求解各个 feature 的权重;
- 等价于会有个似然函数,优化的方向是最大化;
- 对极大似然函数取对数,再乘以 1/(-m) 后,便将 cost func 的优化方向变为 min;(这样做的目的是符合人的思考习惯,想一想 SVM 的原问题也是做了类似的转化);
- So 最小化 cost func <=> MLE
- h(x)函数的值,表示结果取1的概率。
- 自己没事了,可以推导一遍 损失函数的偏导为什么是下面这个样子?
(1)![]()
(2)推导的时候注意一个点:f(x)对θ求导,等于x的累加。- 计算机比较笨,无法一步找到全局最优解或者局部最优解。So,只能用梯度的方法(梯度下降or梯度上升)或者其它的方法来找到或近似找到最优解。比如使用梯度上升的方法,就会是:
![]()
α是学习率,目的是为了让学习的步伐较慢。如果学习率太快,会导致求解过程不稳定。学习率的倒数决定了function达到当前局部最优最小值的迭代次数。- 关于梯度下降的优化方法
- 机器学习的三大元素:一个model,一个loss fuction,一个优化算法
- 由上图可知,学习步长控制着每次迭代时朝着负梯度方向前进的长度,不同的学习步长会呈现如下情况:
#!/usr/bin/env python#coding:utf8import randomimport pandas as pdimport scipy.stats as statsfrom sklearn import preprocessingfrom sklearn import datasetsimport numpyfrom sklearn.linear_model import LogisticRegressiondef sigmodFunc(inx):return 1.0/(1+numpy.exp(-inx))def graAscent(dataMatIn, classLabels):dataMatrix = numpy.mat(dataMatIn) # 转为矩阵labelMat = numpy.mat(classLabels).transpose() # 转置m,n = numpy.shape(dataMatrix) # 获取结构alpha = 0.001 # 设置学习率maxCycles = 500 # 设置最大迭代次数weights = numpy.ones((n,1)) # 初始化weights向量# 迭代的目标的是更新weights向量,即更新特征对于label的权重。# 这也就回归到了LR的本质:估计特征对label的重要程度。for k in range(maxCycles):h = sigmodFunc(dataMatrix*weights)error = (labelMat-h)weights = weights+alpha*dataMatrix.transpose()*errorreturn weights# 构建数据集X, y = datasets.make_classification(n_samples=100000, n_features=20, n_informative=2, n_redundant=2)train_samples = 100X_train = X[:train_samples]X_test = X[train_samples:]y_train = y[:train_samples]y_test = y[train_samples:]"""使用自定义的func训练LR"""weights_self = graAscent(X_train, y_train)# print weights_self"""使用大牛的轮子训练LR"""clf = LogisticRegression()skModel = clf.fit(X_train, y_train)# print skModel.coef_selfList = str(numpy.matrix.tolist(weights_self))selfList = selfList.replace('[','')selfList = selfList.replace(']','')selfList = list(eval(selfList))confList = skModel.coef_confList = confList.tolist()[0]"""计算自己实现的LR和大牛造LR,训练结果的差异:用weights的分布来判断差异的大小。"""statList = []for index in xrange(len(weights_self)):statList.append(selfList[index] - confList[index])calList = statList"""计算自己造的轮子和别人造的轮子之间差异"""maxValue = max(abs(max(calList)), abs(min(calList)))# 均值meanValue = sum(map(abs,calList)) / float(len(calList))# 计算分位数时,需要先排序calList.sort()# 计算分位数value_Q05 = calList[int(round(0.05 * len(calList) + 0.5))-1]value_Q25 = calList[int(round(0.25 * len(calList) + 0.5))-1]value_Q50 = calList[int(round(0.5 * len(calList) + 0.5))-1]value_Q75 = calList[int(round(0.75 * len(calList) + 0.5))-1]value_Q95 = calList[int(round(0.95 * len(calList) + 0.5))-1]# 统计两个描述分布倾斜程度的变量:meanValue与各分位数之间的差值"""1、meanValue - value_Q05 < 0:95%的记录 大于 均值2、meanValue - value_Q95 > 0:95%的记录 小于 均值"""deviation_1 = meanValue-value_Q05deviation_2 = meanValue-value_Q25deviation_3 = meanValue-value_Q50deviation_4 = meanValue-value_Q75deviation_5 = meanValue-value_Q95# 标准差if len(calList) > 1:sdsq = sum([(i - meanValue) ** 2 for i in calList])stdValue = (sdsq / (len(calList) - 1)) ** .5else:stdValue = 0print 'maxValue:' , maxValueprint 'meanValue:', meanValueprint 'stdValue:' , stdValueprint 'value_Q05:', value_Q05print 'value_Q25:', value_Q25print 'value_Q50:', value_Q50print 'value_Q75:', value_Q75print 'value_Q95:', value_Q95print 'deviation_1:', deviation_1print 'deviation_2:', deviation_2print 'deviation_3:', deviation_3print 'deviation_4:', deviation_4print 'deviation_5:', deviation_5
- 优点:由于 LR 模型简单,训练时便于并行化,在预测时只需要对特征进行线性加权,所以性能比较好,往往适合处理海量 id 类特征,用 id 类特征有一个很重要的好处,就是防止信息损失(相对于范化的 CTR 特征),对于头部资源会有更细致的描述。
- 缺点:LR 的缺点也很明显,首先对连续特征的处理需要先进行离散化,如上文所说,人工分桶的方式会引入多种问题。另外 LR 需要进行人工特征组合,这就需要开发者有非常丰富的领域经验,才能不走弯路。这样的模型迁移起来比较困难,换一个领域又需要重新进行大量的特征工程。