【问题标题】:How to calculate logistic regression accuracy如何计算逻辑回归精度
【发布时间】:2017-11-22 15:04:00
【问题描述】:

我是机器学习和 Python 编码的完整初学者,我的任务是从头开始编写逻辑回归,以了解幕后发生的事情。到目前为止,我已经为假设函数、成本函数和梯度下降编码,然后为逻辑回归编码。然而,在打印精度的编码中,我得到了一个低输出(0.69),它不会随着迭代次数的增加或学习率的改变而改变。我的问题是,我下面的准确性代码有问题吗?任何指向正确方向的帮助将不胜感激

X = data[['radius_mean', 'texture_mean', 'perimeter_mean',
   'area_mean', 'smoothness_mean', 'compactness_mean', 'concavity_mean',
   'concave points_mean', 'symmetry_mean', 'fractal_dimension_mean',
   'radius_se', 'texture_se', 'perimeter_se', 'area_se', 'smoothness_se',
   'compactness_se', 'concavity_se', 'concave points_se', 'symmetry_se',
   'fractal_dimension_se', 'radius_worst', 'texture_worst',
   'perimeter_worst', 'area_worst', 'smoothness_worst',
   'compactness_worst', 'concavity_worst', 'concave points_worst',
   'symmetry_worst', 'fractal_dimension_worst']]
X = np.array(X)
X = min_max_scaler.fit_transform(X)
Y = data["diagnosis"].map({'M':1,'B':0})
Y = np.array(Y)

X_train,X_test,Y_train,Y_test = train_test_split(X,Y,test_size=0.25)

X = data["diagnosis"].map(lambda x: float(x))

def Sigmoid(z):
    if z < 0:
        return 1 - 1/(1 + math.exp(z))
    else:
        return 1/(1 + math.exp(-z))

def Hypothesis(theta, x):
    z = 0
    for i in range(len(theta)):
        z += x[i]*theta[i]
    return Sigmoid(z)

def Cost_Function(X,Y,theta,m):
    sumOfErrors = 0
    for i in range(m):
        xi = X[i]
        hi = Hypothesis(theta,xi)
        error = Y[i] * math.log(hi if  hi >0 else 1)
        if Y[i] == 1:
            error = Y[i] * math.log(hi if  hi >0 else 1)
        elif Y[i] == 0:
            error = (1-Y[i]) * math.log(1-hi  if  1-hi >0 else 1)
        sumOfErrors += error

    constant = -1/m
    J = constant * sumOfErrors
    #print ('cost is: ', J ) 
    return J

def Cost_Function_Derivative(X,Y,theta,j,m,alpha):
    sumErrors = 0
    for i in range(m):
        xi = X[i]
        xij = xi[j]
        hi = Hypothesis(theta,X[i])
        error = (hi - Y[i])*xij
        sumErrors += error
    m = len(Y)
    constant = float(alpha)/float(m)
    J = constant * sumErrors
    return J

def Gradient_Descent(X,Y,theta,m,alpha):
    new_theta = []
    constant = alpha/m
    for j in range(len(theta)):
        CFDerivative = Cost_Function_Derivative(X,Y,theta,j,m,alpha)
        new_theta_value = theta[j] - CFDerivative
        new_theta.append(new_theta_value)
    return new_theta


def Accuracy(theta):
    correct = 0
    length = len(X_test, Hypothesis(X,theta))
    for i in range(length):
        prediction = round(Hypothesis(X[i],theta))
        answer = Y[i]
    if prediction == answer.all():
            correct += 1
    my_accuracy = (correct / length)*100
    print ('LR Accuracy %: ', my_accuracy)



def Logistic_Regression(X,Y,alpha,theta,num_iters):
    theta = np.zeros(X.shape[1])
    m = len(Y)
    for x in range(num_iters):
        new_theta = Gradient_Descent(X,Y,theta,m,alpha)
        theta = new_theta
        if x % 100 == 0:
            Cost_Function(X,Y,theta,m)
            print ('theta: ', theta)    
            print ('cost: ', Cost_Function(X,Y,theta,m))
    Accuracy(theta)

initial_theta = [0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]  
alpha = 0.0001
iterations = 1000
Logistic_Regression(X,Y,alpha,initial_theta,iterations)

这是使用威斯康星州乳腺癌数据集 (https://www.kaggle.com/uciml/breast-cancer-wisconsin-data) 中的数据,我在其中权衡了 30 个特征 - 尽管将特征更改为已知相关的特征也不会改变我的准确性。

【问题讨论】:

  • 考虑使用 sklearn accuracy_score 来检查它是否产生相同的准确率,scikit-learn.org/stable/modules/generated/…
  • all 中的answer.all() 是什么?为什么不简单地将if prediction == answer for 循环内??
  • 我认为成本函数和梯度下降函数可能是错误的候选者,但您没有展示它们。你确定它们是正确的吗?另外,这段代码中有一些奇怪的东西:你为什么打电话给Cost_Function(X,Y,theta,m)而不是保存结果?您将两个参数传递给len() 等。
  • 我已经更新了几乎所有的代码,我将研究如何调用 Cost_Function 和 len() - 谢谢你的帮助

标签: python machine-learning logistic-regression


【解决方案1】:

Python 为我们提供了这个 scikit-learn 库,让我们的工作更轻松, 这对我有用:

from sklearn.metrics import accuracy_score

y_pred = log.predict(x_test)

score =accuracy_score(y_test,y_pred)

【讨论】:

    【解决方案2】:

    准确度是最直观的性能衡量指标之一,它只是正确预测的观测值与总观测值的比率。更高的精度意味着模型的性能更好。

    Accuracy = TP+TN/TP+FP+FN+TN
    
    TP = True positives
    TN = True negatives
    FN = False negatives
    TN = True negatives
    

    当您使用准确度测量时,您的误报和误报应该具有相似的成本。更好的衡量标准是 F1 分数,由

    给出
    F1-score = 2*(Recall*Precision)/Recall+Precision where,
    
    Precision = TP/TP+FP
    Recall = TP/TP+FN
    

    在这里阅读更多

    https://en.wikipedia.org/wiki/Precision_and_recall

    python 中机器学习的美妙之处在于 scikit-learn 等重要模块是开源的,因此您可以随时查看实际代码。 请使用以下链接访问 scikit learn metrics 源代码,这将使您了解 scikit-learn 如何计算准确度分数

    from sklearn.metrics import accuracy_score
    accuracy_score(y_true, y_pred)
    

    https://github.com/scikit-learn/scikit-learn/tree/master/sklearn/metrics

    【讨论】:

    • 感谢您提供这些资源,我会看看并尝试实施这些不同的指标
    【解决方案3】:

    我不确定您是如何将0.0001 的值设为alpha,但我认为它太低了。将您的代码与癌症数据一起使用表明,每次迭代的成本都在降低——只是进展缓慢。

    当我将其提高到 0.5 时,我仍然会降低成本,但处于更合理的水平。 1000 次迭代后,它报告:

    cost:  0.23668000993020666
    

    在修复 Accuracy 函数后,我在数据的测试段上得到了 92%。

    您已安装 Numpy,如 X = np.array(X) 所示。你真的应该考虑将它用于你的操作。对于这样的工作,速度会几个数量级。这是一个矢量化版本,可以立即给出结果,而不是等待:

    import math
    import numpy as np
    import matplotlib.pyplot as plt
    import pandas as pd
    from sklearn.preprocessing import MinMaxScaler
    from sklearn.model_selection import train_test_split
    
    df = pd.read_csv("cancerdata.csv")
    X = df.values[:,2:-1].astype('float64')
    X = (X - np.mean(X, axis =0)) /  np.std(X, axis = 0)
    
    ## Add a bias column to the data
    X = np.hstack([np.ones((X.shape[0], 1)),X])
    X = MinMaxScaler().fit_transform(X)
    Y = df["diagnosis"].map({'M':1,'B':0})
    Y = np.array(Y)
    X_train,X_test,Y_train,Y_test = train_test_split(X,Y,test_size=0.25)
    
    
    def Sigmoid(z):
        return 1/(1 + np.exp(-z))
    
    def Hypothesis(theta, x):   
        return Sigmoid(x @ theta) 
    
    def Cost_Function(X,Y,theta,m):
        hi = Hypothesis(theta, X)
        _y = Y.reshape(-1, 1)
        J = 1/float(m) * np.sum(-_y * np.log(hi) - (1-_y) * np.log(1-hi))
        return J
    
    def Cost_Function_Derivative(X,Y,theta,m,alpha):
        hi = Hypothesis(theta,X)
        _y = Y.reshape(-1, 1)
        J = alpha/float(m) * X.T @ (hi - _y)
        return J
    
    def Gradient_Descent(X,Y,theta,m,alpha):
        new_theta = theta - Cost_Function_Derivative(X,Y,theta,m,alpha)
        return new_theta
    
    def Accuracy(theta):
        correct = 0
        length = len(X_test)
        prediction = (Hypothesis(theta, X_test) > 0.5)
        _y = Y_test.reshape(-1, 1)
        correct = prediction == _y
        my_accuracy = (np.sum(correct) / length)*100
        print ('LR Accuracy %: ', my_accuracy)
    
    def Logistic_Regression(X,Y,alpha,theta,num_iters):
        m = len(Y)
        for x in range(num_iters):
            new_theta = Gradient_Descent(X,Y,theta,m,alpha)
            theta = new_theta
            if x % 100 == 0:
                #print ('theta: ', theta)    
                print ('cost: ', Cost_Function(X,Y,theta,m))
        Accuracy(theta)
    
    ep = .012
    
    initial_theta = np.random.rand(X_train.shape[1],1) * 2 * ep - ep
    alpha = 0.5
    iterations = 2000
    Logistic_Regression(X_train,Y_train,alpha,initial_theta,iterations)
    

    我想我可能有不同版本的 scikit,因为我更改了 MinMaxScaler 行以使其工作。结果是我可以在眨眼间完成 10K 次迭代,将模型应用于测试集的结果准确率约为 97%。

    【讨论】:

    • 感谢您的回复,现在我可以更详细地了解我需要了解的内容,以及您的代码如何提高速度。你可能知道你有什么 scikit 版本?我尝试运行您在此处提供的代码(我使用 scikit 从下载 anaconda v3.6.3)但我收到以下错误:\Anaconda3\lib\site-packages\ipykernel_launcher.py:7: RuntimeWarning: invalid value在更大的导入系统中
    • 当我上传文件时,我在代码开头也有这个问题(因为我的特征范围是数据集中的最大值):min_max_scaler = preprocessing。 MinMaxScaler(feature_range=(0,5000)) data = pd.read_csv("data.csv",header=0)
    • 更改了我代码的最初部分,现在它可以像你的一样工作了 - 所以现在我明白了,谢谢!
    • 您好,我不知道您是否有机会看到此回复,但为什么您的代码中有 ep = .012?这是我不明白的最后一部分
    • 这不重要。我喜欢将初始 theta 设置为随机的非零数字。这个数字就在我的脑海里。像这样将它与 rand() 一起使用应该会给出 +/- .012 之间的数字。对于示例来说,这是一个糟糕的选择,因为它看起来非常具体,但实际上并不是
    【解决方案4】:

    这也适用于使用 矢量化 来计算准确度 但如上述答案所述,不推荐使用准确度指标(如果数据不平衡,则不应使用准确度,而是使用 F1 分数)

    clf = sklearn.linear_model.LogisticRegressionCV();
        clf.fit(X.T, Y.T);
        LR_predictions = clf.predict(X.T)
        print ('Accuracy of logistic regression: %d ' % float((np.dot(Y,LR_predictions) + np.dot(1-Y,1-LR_predictions))/float(Y.size)*100) +
               '% ' + "(percentage of correctly labelled datapoints)")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-27
      • 2021-06-06
      • 2016-12-15
      • 1970-01-01
      • 2016-08-24
      • 2016-10-30
      • 1970-01-01
      • 2021-08-20
      相关资源
      最近更新 更多