zoukankan      html  css  js  c++  java
  • tensorflow之逻辑回归模型实现

    前面一篇介绍了用tensorflow实现线性回归模型预测sklearn内置的波士顿房价,现在这一篇就记一下用逻辑回归分类sklearn提供的乳腺癌数据集,该数据集有569个样本,每个样本有30维,为二分类数据集,212个正样本,357个负样本。

    首先,加载数据,并划分训练集和测试集:

    # 加载乳腺癌数据集,该数据及596个样本,每个样本有30维,共有两类
    cancer = skd.load_breast_cancer()
    
    # 将数据集的数据和标签分离
    X_data = cancer.data
    Y_data = cancer.target
    x_train,x_test,y_train,y_test = train_test_split(X_data,Y_data,test_size=0.3,random_state=0)

    这里还要注意一下,因为后面要用到的损失函数为交叉熵,而数据集的标签是一维的,所以我们需要将其转换为位数来表示类别,也就是[0,1]=>[[0,1],[1,0]]这种形式的标签:

    y_train_new = np.zeros([y_train.shape[0], 2], dtype='int32')    
    y_test_new = np.zeros([y_test.shape[0], 2], dtype='int32')
    for i in range(y_train.shape[0]):
        if y_train[i] == 0:
            y_train_new[i,0] = 0
            y_train_new[i,1] = 1
        else:
            y_train_new[i,0] = 1
            y_train_new[i,1] = 0
    for i in range(y_test.shape[0]):
        if y_test[i] == 0:
            y_test_new[i,0] = 0
            y_test_new[i,1] = 1
        else:
            y_test_new[i,0] = 1
            y_test_new[i,1] = 0

    接着就是老套路,初始化训练参数,设置模型输入输出,然后是构建模型,二分类逻辑回归模型的数学表达式为:

    用tensorflow实现代码如下:

    pred = tf.nn.sigmoid(tf.matmul(X, W) + b) # sigmoid

    然后是构建交叉熵表达式,其数学公式为:

    用tensorflow实现代码如下:

    cost = tf.reduce_mean(-tf.reduce_sum(Y*tf.log(pred), reduction_indices=1))

    对于训练好的模型的测试性能的评价,这里我采用计算ROC曲线的方式来展现。首先是模型对于输入数据的预测会得到一个对应的1*2的输出,这个输出不一定是很好的[0 1]或者[1 0],而是一个类似于概率的量,也就是类似于这样[0.9527, 0.0473],所以我们需要判断,如果第一位小于第二位,依照前面的设定应该是0,反之为1,当然可能会有第一位等于第二位的情况,那就只能是存在误差了:

    y_test_pred = sess.run(pred, feed_dict={X: x_test})
    y_scores = np.empty((y_test_pred.shape[0]))
    for i in range(y_scores.shape[0]):
        if y_test_pred[i,0]<y_test_pred[i,1]:
            y_scores[i]=0
        else:
            y_scores[i]=1

    然后roc曲线和其AUC值这里调用的是sklearn提供的函数:

    fpr, tpr, thresholds = roc_curve((y_test), y_scores)
    AUC_ROC = roc_auc_score(y_test, y_scores)

    然后是画出precision recall curve(精确率-召回率曲线),同样也是调用sklearn的函数:

    precision, recall, thresholds = precision_recall_curve(y_test, y_scores)
    precision = np.fliplr([precision])[0] #so the array is increasing (you won't get negative AUC)
    recall = np.fliplr([recall])[0]  #so the array is increasing (you won't get negative AUC) AUC_prec_rec = np.trapz(precision,recall)

    接着是计算置信度矩阵,得到矩阵后顺带的就可以计算准确率、灵敏性、特异性等几个参数了,同样的,还是调用sklearn的函数即可:

    confusion = confusion_matrix(y_test, y_pred)
    
    accuracy = float(confusion[0,0]+confusion[1,1])/float(np.sum(confusion))
    specificity = float(confusion[0,0])/float(confusion[0,0]+confusion[0,1])
    sensitivity = float(confusion[1,1])/float(confusion[1,1]+confusion[1,0])
    precision = float(confusion[1,1])/float(confusion[1,1]+confusion[0,1])

    同样的衡量指标还有Jaccard系数和F1分数:

    jaccard_index = jaccard_similarity_score(y_test, y_pred, normalize=True)
    F1_score = f1_score(y_test, y_pred, labels=None, average='binary', sample_weight=None)

    这里涉及到了很多模型性能的评价指标,具体的含义就不细究了,下一次专门写一篇来总结吧。完整的代码如下:

    from __future__ import print_function
    
    import tensorflow as tf
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import datasets as skd
    from sklearn.model_selection import train_test_split
    from sklearn.preprocessing import scale
    from sklearn.metrics import roc_curve
    from sklearn.metrics import roc_auc_score
    from sklearn.metrics import confusion_matrix
    from sklearn.metrics import precision_recall_curve
    from sklearn.metrics import jaccard_similarity_score
    from sklearn.metrics import f1_score
    
    # 加载乳腺癌数据集,该数据及596个样本,每个样本有30维,共有两类
    cancer = skd.load_breast_cancer()
    
    # 将数据集的数据和标签分离
    X_data = cancer.data
    Y_data = cancer.target
    print("X_data.shape = ", X_data.shape)
    print("Y_data.shape = ", Y_data.shape)
    
    # 将数据和标签分成训练集和测试集
    x_train,x_test,y_train,y_test = train_test_split(X_data,Y_data,test_size=0.3,random_state=0)
    x_train = scale(x_train)
    x_test = scale(x_test)
    y_train_new = np.zeros([y_train.shape[0], 2], dtype='int32')
    y_test_new = np.zeros([y_test.shape[0], 2], dtype='int32')
    for i in range(y_train.shape[0]):
        if y_train[i] == 0:
            y_train_new[i,0] = 0
            y_train_new[i,1] = 1
        else:
            y_train_new[i,0] = 1
            y_train_new[i,1] = 0
    for i in range(y_test.shape[0]):
        if y_test[i] == 0:
            y_test_new[i,0] = 0
            y_test_new[i,1] = 1
        else:
            y_test_new[i,0] = 1
            y_test_new[i,1] = 0
    print("x_train.shape = ", x_train.shape)
    print("x_test.shape = ", x_test.shape)
    print("y_train.shape = ", y_train_new.shape)
    print("y_test.shape = ", y_test_new.shape)
    
    
    
    # 初始化参数
    learning_rate = 0.01
    training_epochs = 50000
    display_step = 50
    
    # 定义图模型输入
    X = tf.placeholder(tf.float32, [None, 30]) # mnist data image of shape 28*28=784
    Y = tf.placeholder(tf.float32, [None, 2]) # 0-9 digits recognition => 10 classes#
    
    # 设置模型权重和偏置
    W = tf.Variable(tf.random_normal([30, 2]),dtype=tf.float32, name="weight")
    b = tf.Variable(tf.random_normal([2]),dtype=tf.float32, name="bias")
    
    # 构建模型
    #pred = tf.nn.softmax(tf.matmul(x, W) + b) # Softmax
    pred = tf.nn.sigmoid(tf.matmul(X, W) + b) # sigmoid
    
    # 使用交叉熵来最小化训练误差
    cost = tf.reduce_mean(-tf.reduce_sum(Y*tf.log(pred), reduction_indices=1))
    # 梯度下降法
    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)#
    
    # 初始化器
    init = tf.global_variables_initializer()
    
    # 开始训练
    with tf.Session() as sess:#
    
        #  初始化
        sess.run(init)#
    
        # 迭代训练
        for epoch in range(training_epochs):
            avg_cost = 0.
    
            sess.run(optimizer, feed_dict={X: x_train, Y: y_train_new})
    
            # 显示训练信息
            if (epoch+1) % display_step == 0:
                c = sess.run(cost, feed_dict={X: x_train, Y:y_train_new})
                print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(c))
        print("完成训练!")
    
        # 测试模型
        correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(Y, 1))
        # 计算准确度
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        print("Accuracy:", accuracy.eval({X: x_test, Y: y_test_new}))
        # 计算模型预测
        y_test_pred = sess.run(pred, feed_dict={X: x_test})
        y_pred = np.empty((y_test_pred.shape[0]), dtype='int32')
        # 二值化
        for i in range(y_pred.shape[0]):
            if y_test_pred[i,0]<y_test_pred[i,1]:
                y_pred[i]=0
            else:
                y_pred[i]=1
        # 得到ROC曲线
        fpr, tpr, thresholds = roc_curve((y_test), y_pred)
        AUC_ROC = roc_auc_score(y_test, y_pred)
        roc_curve =plt.figure()
        plt.plot(fpr,tpr,'-',label='Area Under the Curve (AUC = %0.4f)' % AUC_ROC)
        plt.title('ROC curve')
        plt.xlabel("FPR (False Positive Rate)")
        plt.ylabel("TPR (True Positive Rate)")
        plt.legend(loc="lower right")
        plt.show()
    
        # 得到precision_recall曲线
        precision, recall, thresholds = precision_recall_curve(y_test, y_pred)
        precision = np.fliplr([precision])[0]  #so the array is increasing (you won't get negative AUC)
        recall = np.fliplr([recall])[0]  #so the array is increasing (you won't get negative AUC)
        AUC_prec_rec = np.trapz(precision,recall)
        print("
    Area under Precision-Recall curve: " +str(AUC_prec_rec))
        prec_rec_curve = plt.figure()
        plt.plot(recall,precision,'-',label='Area Under the Curve (AUC = %0.4f)' % AUC_prec_rec)
        plt.title('Precision - Recall curve')
        plt.xlabel("Recall")
        plt.ylabel("Precision")
        plt.legend(loc="lower right")
        plt.show()
        
        # 计算置信度矩阵
        threshold_confusion = 0.5
        print("
    Confusion matrix:  Costum threshold (for positive) of " +str(threshold_confusion))
        confusion = confusion_matrix(y_test, y_pred)
        print(confusion)
        accuracy = 0
        if float(np.sum(confusion))!=0:
            accuracy = float(confusion[0,0]+confusion[1,1])/float(np.sum(confusion))
        print("Global Accuracy: " +str(accuracy))
        specificity = 0
        if float(confusion[0,0]+confusion[0,1])!=0:
            specificity = float(confusion[0,0])/float(confusion[0,0]+confusion[0,1])
        print("Specificity: " +str(specificity))
        sensitivity = 0
        if float(confusion[1,1]+confusion[1,0])!=0:
            sensitivity = float(confusion[1,1])/float(confusion[1,1]+confusion[1,0])
        print("Sensitivity: " +str(sensitivity))
        precision = 0
        if float(confusion[1,1]+confusion[0,1])!=0:
            precision = float(confusion[1,1])/float(confusion[1,1]+confusion[0,1])
        print("Precision: " +str(precision))
    
        #Jaccard similarity index
        jaccard_index = jaccard_similarity_score(y_test, y_pred, normalize=True)
        print("
    Jaccard similarity score: " +str(jaccard_index))
    
        #F1 score
        F1_score = f1_score(y_test, y_pred, labels=None, average='binary', sample_weight=None)
        print("
    F1 score (F-measure): " +str(F1_score))
    
        print("y_test[0:20]=", y_test[0:20])
        print("y_pred[0:20]=", y_pred[0:20])

    最总的结果显示如下:

    古人学问无遗力,少壮工夫老始成。

    纸上得来终觉浅,绝知此事要躬行。

      -- 陆游 《冬夜读书示子聿》

    上善若水,为而不争。
  • 相关阅读:
    Python 集合
    Python sorted()
    CodeForces 508C Anya and Ghosts
    CodeForces 496B Secret Combination
    CodeForces 483B Friends and Presents
    CodeForces 490C Hacking Cypher
    CodeForces 483C Diverse Permutation
    CodeForces 478C Table Decorations
    CodeForces 454C Little Pony and Expected Maximum
    CodeForces 313C Ilya and Matrix
  • 原文地址:https://www.cnblogs.com/Bearoom/p/11721778.html
Copyright © 2011-2022 走看看