2022年 11月 4日

逻辑回归python实现

1.问题

使用线性回归怎么解决分类问题?这就是逻辑回归要做的事情,并且逻辑回归可以计算出概率

2.模型以及求解(线性)

给出一组m个样本数据,每个样本数据有n个特征,并且带有标记0或者1,代表属于哪一类,为了把输入的参数代入到预测函数后始终是一个0到1之间的数,这样我们可以把0,1看做两个类别, 引入sigmod函数 1/(1+e^-t) 这个函数的函数值始终是在0到1之间

让sigmoid函数中的t等于:xi代表某个样本,θ是一组参数

  其中θ就是我们需要训练得到的参数

  那么代价函数是什么呢?

  当实际的y=1,而给出的预测值是0时,代价函数需要付出很大 的代价

  当实际的y=0,而给出的预测值是1时,代价函数同样需要付出很大的代价

  这样,给出以下的代价函数:画出图形后很容易看出下面的函数具有我们需要的特性

      y = 1, -log(p)

      y= 0, -log(1-p)

    其中,p是预测得到的y的值,也就是 sigmod(θ*Xi)

 综合上面这两个式子,我们写成一个那么cost = y * -log(p) + (1-y)* -log(1-p)

 那么J(θ) = -1/m * E yi * log(sigmod(θ*xi)) + (1-yi) * log(1-sigmod(θ*xi))

 容易求得:

      

     其中yi就是代表第i个样本的实际y值,而xi代表第i个样本的数据(包含多个特征),i从1到m,E为求和符号

注:求解θ参数只能使用梯度下降这种方法

梯度的更新:

l

具体求解过程使用梯度下降已经在线性回归中讲过,不再赘述

3.非线性

上面做法是找到一条直线划分类别,如果线性不可分同样可以引入多项式解决这个问题,如果出现过拟合可以使用正则项

4.多分类问题

  1. one vs rest(一对多):比如有a,b,c3类,把a看做1类,其余的看做一类,把b看做一类,其余的看做一类….这样可以分别训练出三个模型出来,就可以解决多分类模型,如果有n个类别,训练出n个模型,特点:耗时少,但是效果不如one vs one
  2. one vs one(一对一): 比如有a,b,c3类,把(a,b),(a,c),(b,c)分别做逻辑回归,如果有n个类别就需要(n个中选2个/排列组合C(n,2))个模型,特点:耗时多,但效果更好

5.应用

CTR预估/推荐系统的learning to rank/各种分类场景

6.算法实现

  1. # coding: utf-8
  2. import numpy as np
  3. import math
  4. from sklearn import datasets
  5. from collections import Counter
  6. infinity = float(-2**31)
  7. '''
  8. 2018-8-5
  9. 逻辑回归的实现
  10. '''
  11. def sigmodFormatrix(Xb,thetas):
  12. params = - Xb.dot(thetas)
  13. r = np.zeros(params.shape[0])#返回一个np数组
  14. for i in range(len(r)):
  15. r[i] = 1 /(1 + math.exp(params[i]))
  16. return r
  17. def sigmodFormatrix2(Xb,thetas):
  18. params = - Xb.dot(thetas)
  19. r = np.zeros(params.shape[0])#返回一个np数组
  20. for i in range(len(r)):
  21. r[i] = 1 /(1 + math.exp(params[i]))
  22. if r[i] >=0.5:
  23. r[i] = 1
  24. else:
  25. r[i] = 0
  26. return r
  27. def sigmod(Xi,thetas):
  28. params = - np.sum(Xi * thetas)
  29. r = 1 /(1 + math.exp(params))
  30. return r
  31. class LinearLogsiticRegression(object):
  32. thetas = None
  33. m = 0
  34. #训练
  35. def fit(self,X,y,alpha = 0.01,accuracy = 0.00001):
  36. #插入第一列为1,构成xb矩阵
  37. self.thetas = np.full(X.shape[1]+1,0.5)
  38. self.m = X.shape[0]
  39. a = np.full((self.m,1),1)
  40. Xb = np.column_stack((a,X))
  41. dimension = X.shape[1]+1
  42. #梯度下降迭代
  43. count = 1
  44. while True:
  45. oldJ = self.costFunc(Xb, y)
  46. #注意预测函数中使用的参数是未更新的
  47. c = sigmodFormatrix(Xb, self.thetas)-y
  48. for j in range(dimension):
  49. self.thetas[j] = self.thetas[j] -alpha * np.sum(c * Xb[:,j])
  50. newJ = self.costFunc(Xb, y)
  51. if newJ == oldJ or math.fabs(newJ - oldJ) < accuracy:
  52. print("代价函数迭代到最小值,退出!")
  53. print("收敛到:",newJ)
  54. break
  55. print("迭代第",count,"次!")
  56. print("代价函数上一次的差:",(newJ - oldJ))
  57. count += 1
  58. #预测
  59. def costFunc(self,Xb,y):
  60. sum = 0.0
  61. for i in range(self.m):
  62. yPre = sigmod(Xb[i,], self.thetas)
  63. #print("yPre:",yPre)
  64. if yPre ==1 or yPre == 0:
  65. return infinity
  66. sum += y[i]*math.log(yPre)+(1 - y[i])*math.log(1-yPre)
  67. return -1/self.m * sum
  68. def predict(self,X):
  69. a = np.full((len(X),1),1)
  70. Xb = np.column_stack((a,X))
  71. return sigmodFormatrix2(Xb, self.thetas)
  72. def score(self,X_test,y_test):
  73. y_predict = myLogstic.predict(X_test)
  74. re = (y_test==y_predict)
  75. re1 = Counter(re)
  76. a = re1[True] / (re1[True]+re1[False])
  77. return a
  78. #if __name__=="main":
  79. from sklearn.model_selection import train_test_split
  80. iris = datasets.load_iris()
  81. X= iris['data']
  82. y = iris['target']
  83. X = X[y!=2]
  84. y=y[y!=2]
  85. X_train,X_test, y_train, y_test = train_test_split(X,y)
  86. myLogstic = LinearLogsiticRegression()
  87. myLogstic.fit(X_train, y_train)
  88. y_predict = myLogstic.predict(X_test)
  89. print("参数:",myLogstic.thetas)
  90. print("测试数据准确度:",myLogstic.score(X_test, y_test))
  91. print("训练数据准确度:",myLogstic.score(X_train, y_train))
  92. '''
  93. 2.sklean中的逻辑回归
  94. '''
  95. from sklearn.linear_model import LogisticRegression
  96. print("sklern中的逻辑回归:")
  97. logr = LogisticRegression()
  98. logr.fit(X_train,y_train)
  99. print("准确度:",logr.score(X_test,y_test))