前言:现在网络上有很多文章,数据和代码都不全,胖哥对此重新梳理后,把用到的数据和代码全部奉上,如果想直接要数据和代码,请查看文章最后!!!
逻辑回归概念:逻辑回归是以线性回归为基础,通过计算出概率,来达到最终分类的目的。
模型算法实现: 给出一组M个样本数据,每个样本数据有n个特征,并且带有标记0或者1,代表属于哪一类,为了把输入的参数代入到预测函数后始终是一个0到1之间的数,这样我们可以把0,1看做两个类别, 引入sigmod函数() 这个函数的函数值始终是在0到1之间。
让sigmoid函数中的t等于:代表某个样本,θ是一组参数:
其中θ就是我们需要训练得到的参数。
那么代价函数是什么呢?
当实际的y=1,而给出的预测值是0时,代价函数需要付出很大 的代价
当实际的y=0,而给出的预测值是1时,代价函数同样需要付出很大的代价
这样,给出以下的代价函数:画出图形后很容易看出下面的函数具有我们需要的特性
y = 1, -log(p)
y= 0, -log(1-p)
其中,p是预测得到的y的值,也就是 sigmod(θ*)综合上面这两个式子,我们写成一个:
cost = y * -log(p) + (1-y)* -log(1-p)
那么J(θ) = -1/m * * log(sigmod(θ*)) + (1-) * log(1-sigmod(θ*))
其中就是代表第i个样本的实际y值,而代表第i个样本的数据(包含多个特征),i从1到m,为求和符号。
实战:鸢尾花分类
#!/usr/bin/python # -*- coding: UTF-8 -*- import numpy as np import math from collections import Counter import pandas as pd infinity = float(-2 ** 31) ''' 自定义逻辑回归的实现 ''' def sigmodFormatrix(Xb, thetas): params = - Xb.dot(thetas) r = np.zeros(params.shape[0]) # 返回一个np数组 for i in range(len(r)): r[i] = 1 / (1 + math.exp(params[i])) return r def sigmodFormatrix2(Xb, thetas): params = - Xb.dot(thetas) r = np.zeros(params.shape[0]) # 返回一个np数组 for i in range(len(r)): r[i] = 1 / (1 + np.exp(params[i])) if r[i] >= 0.5: r[i] = 1 else: r[i] = 0 return r def sigmod(Xi, thetas): params = - np.sum(Xi * thetas) r = 1 / (1 + np.exp(params)) return r class LinearLogsiticRegression(object): thetas = None m = 0 # 训练 def fit(self, X, y, alpha=0.01, accuracy=0.00001): # 插入第一列为1,构成xb矩阵 self.thetas = np.full(X.shape[1] + 1, 0.5) self.m = X.shape[0] a = np.full((self.m, 1), 1) Xb = np.column_stack((a, X)) dimension = X.shape[1] + 1 # 梯度下降迭代 count = 1 while True: oldJ = self.costFunc(Xb, y) # 注意预测函数中使用的参数是未更新的 c = sigmodFormatrix(Xb, self.thetas) - y for j in range(dimension): self.thetas[j] = self.thetas[j] - alpha * np.sum(c * Xb[:, j]) newJ = self.costFunc(Xb, y) if newJ == oldJ or math.fabs(newJ - oldJ) < accuracy: print("代价函数迭代到最小值,退出!") print("收敛到:", newJ) break print("迭代第", count, "次!") print("代价函数上一次的差:", (newJ - oldJ)) count += 1 # 预测 def costFunc(self, Xb, y): sum = 0.0 for i in range(self.m): yPre = sigmod(Xb[i,], self.thetas) # print("yPre:",yPre) if yPre == 1 or yPre == 0: return infinity sum += y[i] * math.log(yPre) + (1 - y[i]) * math.log(1 - yPre) return -1 / self.m * sum def predict(self, X): a = np.full((len(X), 1), 1) Xb = np.column_stack((a, X)) return sigmodFormatrix2(Xb, self.thetas) def score(self, X_test, y_test): y_predict = myLogstic.predict(X_test) re = (y_test == y_predict) re1 = Counter(re) a = re1[True] / (re1[True] + re1[False]) return a from sklearn.model_selection import train_test_split data=pd.read_excel('shuju_test_lianxi.xlsx') X=data.drop('y',axis=1) y=data['y'] X_train, X_test, y_train, y_test = train_test_split(X, y,test_size=0.2) myLogstic = LinearLogsiticRegression() myLogstic.fit(X_train, y_train) y_predict = myLogstic.predict(X_test) print("参数:", myLogstic.thetas) print("测试数据准确度:", myLogstic.score(X_test, y_test)) print("训练数据准确度:", myLogstic.score(X_train, y_train))
调用sklearn中LogisticRegression代码实现:
#!/usr/bin/python # -*- coding: UTF-8 -*- import pandas as pd from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression data=pd.read_excel('shuju_test_lianxi.xlsx') X=data.drop('y',axis=1) y=data['y'] X_train, X_test, y_train, y_test = train_test_split(X, y,test_size=0.2) print("sklern中的逻辑回归:") logr = LogisticRegression() logr.fit(X_train,y_train) print("准确度:",logr.score(X_test,y_test))
关于两者的准确度可以进行比较,然后不断地去优化自己手写的算法。
需要完整Python代码和数据集的朋友们,请关注如下微信公众号,回复"逻辑回归分类01",即可获取完整内容;
添加胖哥微信:zy10178083,胖哥拉你进去python学习交流群,胖哥会不定期分享干货!
微信公众号:胖哥真不错。