机器学习-理解Logistic Regression

背景介绍

本文讨论了Logistic回归的基础知识及其在Python中的实现。逻辑回归基本上是一种监督分类算法。在分类问题中,目标变量(或输出)y对于给定的一组特征(或输入)X,只能采用离散值。

与普遍看法相反,逻辑回归是一种回归模型。 该模型建立回归模型以预测给定数据条目属于编号为“1”的类别的概率。 就像线性回归假设数据遵循线性函数一样,Logistic回归使用sigmoid函数对数据进行建模。

只有当决策阈值进入图片时,逻辑回归才成为分类技术。 阈值的设置是Logistic回归的一个非常重要的方面,并且取决于分类问题本身。

阈值的决定主要受精度和召回值的影响。 理想情况下,我们希望精度和召回都是1,但很少这种情况。 在Precision-Recall权衡的情况下,我们使用以下参数来决定thresold:

1.低精度/高回调:在我们想要减少假阴性数量而不必减少误报数量的应用中,我们选择具有低精度值或高回调值的决策值。 例如,在癌症诊断应用中,如果患者被错误地诊断为患有癌症,我们不希望任何受影响的患者被归类为不受影响而没有给予足够的注意。 这是因为,可以通过其他医学疾病来检测不存在癌症,但是在已经被拒绝的候选者中不能检测到疾病的存在。

2.高精度/低回调:在我们希望减少误报数量而不必减少假阴性数量的应用中,我们选择具有高精度值或低回调值的决策值。例如,如果我们对客户进行分类,他们是否会对个性化广告做出积极或消极的反应,我们希望绝对确定客户会对广告做出积极反应,否则,负面反应会导致客户的潜在销售损失。

根据类别数量,Logistic回归可分为:

二项式:目标变量只能有两种可能的类型:“0”或“1”代表“赢”与“损失”,“通过”与“失败”,“死”与“活着”等。

多项式:目标变量可以具有3种或更多种未被排序的可能类型(即类型没有定量意义),例如“疾病A”与“疾病B”对比“疾病C”。

顺序:它处理具有有序类别的目标变量。 例如,测试分数可以分类为:“非常差”,“差”,“好”,“非常好”。 在这里,每个类别可以给出分数,如0,1,2,3。

首先,我们探索最简单的Logistic回归形式,即二项Logistic回归。

二项Logistic回归

考虑一个示例数据集,该数据集将学习小时数与考试结果进行映射。结果只能采用两个值,即通过(1)或失败(0):

HOURS(X)0.500.751.001.251.501.752.002.252.502.753.003.253.503.754.004.254.504.755.005.50PASS(Y)00000010101010111111

所以我们有:

即y是分类目标变量,它只能采用两种可能的类型:“0”或“1”。

为了概括我们的模型,我们假设:

  • 数据集具有'p'特征变量和'n'观察值。
  • 特征矩阵表示为:

被称为学习率,需要明确设置。

让我们在样本数据集上看到上面技术的python实现:

import csvimport numpy as npimport matplotlib.pyplot as plt def loadCSV(filename): ''' function to load dataset ''' with open(filename,"r") as csvfile: lines = csv.reader(csvfile) dataset = list(lines) for i in range(len(dataset)): dataset[i] = [float(x) for x in dataset[i]] return np.array(dataset) def normalize(X): ''' function to normalize feature matrix, X ''' mins = np.min(X, axis = 0) maxs = np.max(X, axis = 0) rng = maxs - mins norm_X = 1 - ((maxs - X)/rng) return norm_X def logistic_func(beta, X): ''' logistic(sigmoid) function ''' return 1.0/(1 + np.exp(-np.dot(X, beta.T))) def log_gradient(beta, X, y): ''' logistic gradient function ''' first_calc = logistic_func(beta, X) - y.reshape(X.shape[0], -1) final_calc = np.dot(first_calc.T, X) return final_calc def cost_func(beta, X, y): ''' cost function, J ''' log_func_v = logistic_func(beta, X) y = np.squeeze(y) step1 = y * np.log(log_func_v) step2 = (1 - y) * np.log(1 - log_func_v) final = -step1 - step2 return np.mean(final) def grad_desc(X, y, beta, lr=.01, converge_change=.001): ''' gradient descent function ''' cost = cost_func(beta, X, y) change_cost = 1 num_iter = 1 while(change_cost > converge_change): old_cost = cost beta = beta - (lr * log_gradient(beta, X, y)) cost = cost_func(beta, X, y) change_cost = old_cost - cost num_iter += 1 return beta, num_iter def pred_values(beta, X): ''' function to predict labels ''' pred_prob = logistic_func(beta, X) pred_value = np.where(pred_prob >= .5, 1, 0) return np.squeeze(pred_value) def plot_reg(X, y, beta): ''' function to plot decision boundary ''' # labelled observations x_0 = X[np.where(y == 0.0)] x_1 = X[np.where(y == 1.0)] # plotting points with diff color for diff label plt.scatter([x_0[:, 1]], [x_0[:, 2]], c='b', label='y = 0') plt.scatter([x_1[:, 1]], [x_1[:, 2]], c='r', label='y = 1') # plotting decision boundary x1 = np.arange(0, 1, 0.1) x2 = -(beta[0,0] + beta[0,1]*x1)/beta[0,2] plt.plot(x1, x2, c='k', label='reg line') plt.xlabel('x1') plt.ylabel('x2') plt.legend() plt.show() if __name__ == "__main__": # load the dataset dataset = loadCSV('dataset1.csv') # normalizing feature matrix X = normalize(dataset[:, :-1]) # stacking columns wth all ones in feature matrix X = np.hstack((np.matrix(np.ones(X.shape[0])).T, X)) # response vector y = dataset[:, -1] # initial beta values beta = np.matrix(np.zeros(X.shape[1])) # beta values after running gradient descent beta, num_iter = grad_desc(X, y, beta) # estimated beta values and number of iterations print("Estimated regression coefficients:", beta) print("No. of iterations:", num_iter) # predicted labels y_pred = pred_values(beta, X) # number of correctly predicted labels print("Correctly predicted labels:", np.sum(y == y_pred)) # plotting regression line plot_reg(X, y, beta)

Estimated regression coefficients: [[  1.70474504  15.04062212 -20.47216021]]
No. of iterations: 2612
Correctly predicted labels: 100

意:梯度下降是估算

的众多方法之一。

基本上,这些是更高级的算法,一旦您定义了成本函数和渐变,就可以在Python中轻松运行。这些算法是:

  • BFGS(Broyden-Fletcher-Goldfarb-Shanno算法)
  • L-BFGS(与BFGS一样,但使用有限的内存)
  • 共轭梯度

使用这些算法中的任何一种优于梯度下降的优点/缺点:

好处

  • 不需要选择学习率
  • 经常跑得更快(并非总是如此)
  • 可以在数值上近似梯度(并不总是很好)

缺点

  • 更复杂
  • 除非你了解具体细节,否则更多的是黑匣子

多项Logistic回归

在Multiomial Logistic回归中,输出变量可以具有两个以上可能的离散输出。考虑一下数字数据集。这里,输出变量是数字值,它可以取出(0,12,3,4,5,6,7,8,9)中的值。

下面给出了使用scikit实现Multinomial Logisitc回归 - 学习对数字数据集进行预测。

from sklearn import datasets, linear_model, metrics # load the digit datasetdigits = datasets.load_digits() # defining feature matrix(X) and response vector(y)X = digits.datay = digits.target # splitting X and y into training and testing setsfrom sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=1) # create logistic regression objectreg = linear_model.LogisticRegression() # train the model using the training setsreg.fit(X_train, y_train) # making predictions on the testing sety_pred = reg.predict(X_test) # comparing actual response values (y_test) with predicted response values (y_pred)print("Logistic Regression model accuracy(in %):", metrics.accuracy_score(y_test, y_pred)*100)

Logistic Regression model accuracy(in %): 95.6884561892

最后,这里有一些关于Logistic回归思考的观点:

  • 不假设因变量和自变量之间存在线性关系,但它假设解释变量的logit与响应之间存在线性关系。
  • 独立变量甚至可以是原始自变量的幂项或一些其他非线性变换。
  • 因变量不需要是正态分布的,但它通常假设来自指数族的分布(例如二项式,泊松,多项式,正态,......); 二元逻辑回归假设响应的二项分布。
  • 方差的同质性不需要满足。
  • 错误需要是独立的,但不是正常分布的。
  • 它使用最大似然估计(MLE)而不是普通最小二乘(OLS)来估计参数,因此依赖于大样本近似。
  • 参考文献:
  • http://cs229.stanford.edu/notes/cs229-notes1.pdf
  • http://machinelearningmastery.com/logistic-regression-for-machine-learning/
  • https://onlinecourses.science.psu.edu/stat504/node/164

本文由Nikhil Kumar撰写。

原文发布于微信公众号 - yale记(python_yale_learning)

原文发表时间:2019-09-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券