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])

    最总的结果显示如下:

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

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

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

    上善若水,为而不争。
  • 相关阅读:
    函数、对象
    webpack配置
    创智培训内容
    oracle方法
    Weblogic
    药店
    ip
    jdk账号
    ansible
    目录编码
  • 原文地址:https://www.cnblogs.com/Bearoom/p/11721778.html
Copyright © 2011-2022 走看看