精华内容
下载资源
问答
  • 机器之心报道机器之心...近日,有开发者在 GitHub 上开源了一个包含数据挖掘类比赛常用模型的项目,主要涵盖二分类、多分类以及回归任务。项目代码全部使用 Python 实现。项目地址:https://github.com/QLMX/data_m...

    机器之心报道

    机器之心编辑部

    数据挖掘类比赛必备模型,四种实现方法,你值得拥有。

    数据科学竞赛是学习各类算法、深入理解数据科学、提升和挑战自己的绝佳机会,而这些竞赛中有一些常用的模型。

    近日,有开发者在 GitHub 上开源了一个包含数据挖掘类比赛常用模型的项目,主要涵盖二分类、多分类以及回归任务。项目代码全部使用 Python 实现。

    项目地址:https://github.com/QLMX/data_mining_models

    该项目包含二分类模型、多分类模型以及回归模型,它们分别基于 lightgbm 实现、xgboost 实现、keras 实现和 pytorch 实现:

    lightgbm

    binary_class.py :lightgbm 实现的二分类

    multi_class.py :lightgbm 实现的多分类

    regression.py :lightgbm 实现的回归

    multi_class_custom_feval.py :lightgbm 自定义评价函数实现多分类

    multi_class_weight_loss.py :lightgbm 多类别不平衡问题,实现类别加权优化

    xgboost

    binary_class.py :xgboost 实现的二分类

    multi_class.py :xgboost 实现的多分类

    regression.py :xgboost 实现的回归

    keras 实现的 mlp

    binary_class.py :keras 实现的 mlp,做二分类任务

    multi_class.py :keras 实现的 mlp,做多分类任务

    regression.py :keras 实现的 mlp,做回归任务

    pytorch 实现的 mlp

    binary_class.py :pytorch 实现的 mlp,做二分类任务

    multi_class.py :pytorch 实现的 mlp,做多分类任务

    regression.py :实现的 mlp,做回归任务

    环境设置

    可以直接通过 pip install -r requirements.txt 安装指定的函数包,具体的函数包如下:

    pandasnumpymatplotlibsklearntensorflow==1.12.0keras==2.2.4pytorchseabornlightgbm==2.2.1xgboost==0.90

    项目解读

    第一部分 lightgbm 的数据是基于拍拍贷比赛截取的一部分特征,随机选择了 5000 个训练数据,3000 个测试数据。针对其中 gender、cell_province 等类别特征,直接进行重新编码处理。

    第二部分又基于 xgboost 实现了二分类、多分类和回归任务。

    第三、四部分是深度网络部分,是基于 keras 实现的多层感知机网络 (mlp)。pytorch 主要用于图像处理任务,在数据挖掘类比赛中很少用到,但该项目整理了基于 pytorch 实现的 mlp 做分类与回归任务代码。

    项目作者对项目的各部分进行了详细的解读,具体参考以下内容:

    参考链接:

    https://mp.weixin.qq.com/s/t6EpWmLWP81DcJ7AUro3Ng

    https://mp.weixin.qq.com/s/Td0Vrx9YO5rEn66L4C42Zw

    https://mp.weixin.qq.com/s/XaB1BsLL_Va7dGL0S0rUOQ

    https://zhuanlan.zhihu.com/p/80381974

    2020 NeurIPS MeetUp

    12月6日北京,机器之心将举办2020 NeurIPS MeetUp。活动设置4个Keynote、 12篇论文报告与30个Poster,邀请顶级专家、论文作者与现场参会观众共同交流。

    原标题:《二分类、多分类、回归任务,一个项目get竞赛必备模型》

    展开全文
  • python分类模型评估.doc

    2020-06-06 00:24:17
    Python 数据科学实战 作者常国珍 赵仁乾 张秋剑 模型评估与模型监控 1. 模型评估 模型评估指标是对模型的...1.1 混淆矩阵 在二分类模型预测中混淆矩阵是评估模型好坏的一种基本方法其通过模型预测 值与实际值的一致性来
  • 本Fisher二分类判别模型的代码是利用Python独立完成编写的,基本基于上课所讲内容,没有参考网上代码。 2. 实现算法思路 - 数据集选择与载入初始化 电力行业中,比较适合Fisher分类判别模型的数据集为用户画像的分类...

    1. 完成形式

    本Fisher二分类判别模型的代码是利用Python独立完成编写的,基本基于上课所讲内容,没有参考网上代码。

    2. 实现算法思路

    - 数据集选择与载入初始化
    电力行业中,比较适合Fisher分类判别模型的数据集为用户画像的分类。然而电力行业由于国家管控的特殊性,导致网络上能够找到的开源的数据集过少,在Dataju平台原先有的十多个能源客户画像数据集在今年下半年也全部由于版权、客户信息保密原则等原因而下架。在搜索了一段时间之后无奈放弃选择现成的开源分类数据集。本代码的数据集采用的是Scikit-Learn包中的乳腺癌数据集。

    #数据
    #二分类问题
    #直接从sklearn.datasets导入乳腺癌数据集
    from sklearn.datasets import load_breast_cancer
    

    以下为乳腺癌数据集中较为重要的信息
    Breast cancer wisconsin (diagnostic) dataset

    Data Set Characteristics:

    :Number of Instances: 569
    
    :Number of Attributes: 30 numeric, predictive attributes and the class
    
    :Attribute Information:
        - radius (mean of distances from center to points on the perimeter)
        - texture (standard deviation of gray-scale values)
        - perimeter
        - area
        - smoothness (local variation in radius lengths)
        - compactness (perimeter^2 / area - 1.0)
        - concavity (severity of concave portions of the contour)
        - concave points (number of concave portions of the contour)
        - symmetry
        - fractal dimension ("coastline approximation" - 1)
    
        The mean, standard error, and "worst" or largest (mean of the three
        worst/largest values) of these features were computed for each image,
        resulting in 30 features.  For instance, field 0 is Mean Radius, field
        10 is Radius SE, field 20 is Worst Radius.
    
        - class:
                - WDBC-Malignant
                - WDBC-Benign
    
    :Summary Statistics:
    
    ===================================== ====== ======
                                           Min    Max
    ===================================== ====== ======
    radius (mean):                        6.981  28.11
    texture (mean):                       9.71   39.28
    perimeter (mean):                     43.79  188.5
    area (mean):                          143.5  2501.0
    smoothness (mean):                    0.053  0.163
    compactness (mean):                   0.019  0.345
    concavity (mean):                     0.0    0.427
    concave points (mean):                0.0    0.201
    symmetry (mean):                      0.106  0.304
    fractal dimension (mean):             0.05   0.097
    radius (standard error):              0.112  2.873
    texture (standard error):             0.36   4.885
    perimeter (standard error):           0.757  21.98
    area (standard error):                6.802  542.2
    smoothness (standard error):          0.002  0.031
    compactness (standard error):         0.002  0.135
    concavity (standard error):           0.0    0.396
    concave points (standard error):      0.0    0.053
    symmetry (standard error):            0.008  0.079
    fractal dimension (standard error):   0.001  0.03
    radius (worst):                       7.93   36.04
    texture (worst):                      12.02  49.54
    perimeter (worst):                    50.41  251.2
    area (worst):                         185.2  4254.0
    smoothness (worst):                   0.071  0.223
    compactness (worst):                  0.027  1.058
    concavity (worst):                    0.0    1.252
    concave points (worst):               0.0    0.291
    symmetry (worst):                     0.156  0.664
    fractal dimension (worst):            0.055  0.208
    
    ===================================== ====== ======
    

    研究数据集可以发现,该数据集由30个指标与一个二分类的target组成表明是否患病。由min&max表可以发现存在方差特别大的指标area,在不确定其对患病影响的情况下,需要考虑是否需要对数据集做标准化处理。
    载入数据集之后,将20%的数据作为测试样本。

    from sklearn.model_selection import train_test_split
    x = breast_cancer['data']
    y = breast_cancer['target']
    #随机采样,将20%的数据作为测试样本
    x_train,x_test,y_train,y_test=train_test_split(x,y,random_state=0,test_size=0.2)
    

    标准化代码如下,在实际运行模型的时候根据最后生成结果选择是否做数据与处理。

    # 标准化处理
    from sklearn.preprocessing import StandardScaler
    ss_x=StandardScaler()
    ss_y=StandardScaler()
    #分别对训练和测试数据的特征以及目标值进行标准化处理
    x_train = ss_x.fit_transform(x_train)
    x_test = ss_x.transform(x_test)
    

    - 函数设计
    根据课堂学到的内容,设计如下函数
    | get_mean_vector(target) | 求均值向量|
    | get_dispersion_matrix(target, mean_vector) |求样本内离散度矩阵|
    | get_sample_divergence(mean_vector1, mean_vector2) | 求样本间离散度 |
    | get_w_star(dispersion_matrix, mean_vector1, mean_vector2) | 求Fisher准则函数的w_star解|
    | get_sample_projection(w_star, x) | 求一特征向量在w_star上的投影|
    | get_segmentation_threshold(w_star, way_flag) |求分割阈值 |
    | test_single_smaple(w_star, y0, test_sample, test_target) | 单例测试 |
    | test_single_smaple_check(w_star, y0, test_sample, test_target)|单例测试(用于统计) |
    | test_check(w_star, y0) | 统计测试样本 |
    具体实现如下:

    def get_mean_vector(target):
        '''
        求均值向量
        :param target:
        :return:
        '''
        m_target_list = [0 for i in range(x_train.shape[1])]
        count = 0
        for i in range(x_train.shape[0]):
            if y_train[i] == target:
                count = count + 1
                temp = x_train[i].tolist()
                m_target_list = [m_target_list[j] + temp[j] for j in range(x_train.shape[1])]
        m_target_list = [x / count for x in m_target_list]
        # 其实可以用类似torch的压缩维度的函数直接求和
        return m_target_list
    

    通过target的值选择计算标签为target的均值向量。

    def get_dispersion_matrix(target, mean_vector):
        '''
        求样本内离散度矩阵
        :param target:
        :param mean_vector:
        :return:
        '''
        s_target_matrix = np.zeros((x_train.shape[1], x_train.shape[1]))
        for i in range(x_train.shape[0]):
            if y_train[i] == target:
                temp = np.multiply(x_train[i] - mean_vector, (x_train[i] - mean_vector).transpose())
                s_target_matrix = s_target_matrix + temp
        return s_target_matrix
    

    通过target和与其匹配的mean_vector计算求得样本内离散度矩阵。

    def get_sample_divergence(mean_vector1, mean_vector2):
        '''
        求样本间离散度
        :param mean_vector1:
        :param mean_vector2:
        :return:
        '''
        return np.multiply((mean_vector1 - mean_vector2), (mean_vector1 - mean_vector2).transpose())
    

    计算两个均值向量的样本间离散度。

    def get_w_star(dispersion_matrix, mean_vector1, mean_vector2):
        '''
        求Fisher准则函数的w_star解
        :param dispersion_matrix:
        :param mean_vector1:
        :param mean_vector2:
        :return:
        '''
        return np.matmul(np.linalg.inv(dispersion_matrix), (mean_vector1 - mean_vector2))
    

    由样本内离散度矩阵和两个均值向量,根据Fisher准则逆向求解被投影向量的最优解w_star。

    def get_sample_projection(w_star, x):
        '''
        求一特征向量在w_star上的投影
        :param w_star:
        :param x:
        :return:
        '''
        return np.matmul(w_star.transpose(), x)
    

    利用求得的w_star求一特征向量在w_star上的投影值。

    def get_segmentation_threshold(w_star, way_flag):
        '''
        求分割阈值
        :param w_star:
        :param way_flag:
        :return:
        '''
        if way_flag == 0:
            y0_list = []
            y1_list = []
            for i in range(x_train.shape[0]):
                if y_train[i] == 0:
                    y0_list.append(get_sample_projection(w_star, x_train[i]))
                else:
                    y1_list.append(get_sample_projection(w_star, x_train[i]))
            ny0 = len(y0_list)
            ny1 = len(y1_list)
            my0 = sum(y0_list) / ny0
            my1 = sum(y1_list) / ny1
            segmentation_threshold = (ny0 * my0 + ny1 * my1) / (ny0 + ny1)
            return  segmentation_threshold
        elif way_flag == 1:
            y0_list = []
            y1_list = []
            for i in range(x_train.shape[0]):
                if y_train[i] == 0:
                    y0_list.append(get_sample_projection(w_star, x_train[i]))
                else:
                    y1_list.append(get_sample_projection(w_star, x_train[i]))
            ny0 = len(y0_list)
            ny1 = len(y1_list)
            my0 = sum(y0_list) / ny0
            my1 = sum(y1_list) / ny1
            py0 = ny0 / (ny0 + ny1)
            py1 = ny1 / (ny0 + ny1)
            segmentation_threshold = (my0 + my1) / 2 + math.log(py0 / py1) / (ny0 - ny1 - 2)
            return segmentation_threshold
        else:
            return 0
    

    利用w_star投影标签内的原特征向量用来求分割阈值,该函数提供了两种分割阈值的实现方法。

    def test_single_smaple(w_star, y0, test_sample, test_target):
        '''
        单例测试
        :param y0:
        :param x:
        :return:
        '''
        y_test = get_sample_projection(w_star, test_sample)
        predection = 1
        if y_test > y0:
            predection = 0
        print("This x_vector's target is {}, and the predection is {}".format(test_target, predection))
    

    测试函数,该单例测试函数可以由用户输入一个新的特征向量,之后会给出模型的预测结果。

    def test_single_smaple_check(w_star, y0, test_sample, test_target):
        '''
        单例测试(用于统计)
        :param y0:
        :param x:
        :return:
        '''
        y_test = get_sample_projection(w_star, test_sample)
        predection = 1
        if y_test > y0:
            predection = 0
        if test_target == predection:
            return True
        else:
            return False
    

    该单例测试函数用于统计数据使用。

    def test_check(w_star, y0):
        '''
        统计测试样本
        :param w_star:
        :param y0:
        :return:
        '''
        right_count = 0
        for i in range(x_test.shape[0]):
            boolean = test_single_smaple_check(w_star, y0, x_test[i], y_test[i])
            if boolean == True:
                right_count = right_count + 1
        return x_test.shape[0], right_count, right_count / x_test.shape[0]
    

    测试数据集的测试统计,通过比对预测结果与实际标签求得统计样本数,正确预测样本数和准确率。

    - 算法实现

    if __name__ == "__main__":
        m0 = np.array(get_mean_vector(0)).reshape(-1, 1)
        m1 = np.array(get_mean_vector(1)).reshape(-1, 1)
        s0 = get_dispersion_matrix(0, m0)
        s1 = get_dispersion_matrix(1, m1)
        sw = s0 + s1
        sb = get_sample_divergence(m0, m1)
        w_star = np.array(get_w_star(sw, m0, m1)).reshape(-1, 1)
        y0 = get_segmentation_threshold(w_star, 0)
        print("The segmentation_threshold is ", y0)
        test_sum, right_sum, accuracy = test_check(w_star, y0)
        print("Total specimen number:{}\nNumber of correctly predicted samples:{}\nAccuracy:{}\n".format(test_sum, right_sum, accuracy))
    

    根据划分的数据集,利用正反标签的训练数据集分别计算均值向量,样本内离散度矩阵,样本间离散度矩阵。利用正反标签的样本内离散度矩阵求得总样本内离散度矩阵。之后利用总样本内离散度矩阵求得被投影向量。根据被投影向量将原特征向量均投影到一维线上,采用阈值割裂的方法加权修正得到分割阈值。之后利用测试样本数据集检验得到的分割阈值的质量。

    - 实验结果
    采用数据标准化和修正加权阈值算法结果:
    在这里插入图片描述
    采用数据标准化和普通加权阈值算法结果:
    在这里插入图片描述
    不采用数据标准化,采用修正加权阈值算法结果:
    在这里插入图片描述
    不采用数据标准化,不采用修正加权阈值算法结果:
    在这里插入图片描述

    - 实验结论分析

    • area这一指标对患病与否并没有什么影响,而其他指标会由于标准化而被削弱特征差异导致预测质量的下降。
    • 不采用数据标准化,不采用修正加权阈值算法结果的情况下,模型预测准确率可达到93.8596%,超过笔者对此模型的期望。
    • 修正加权阈值函数在样本分布均匀的情况下可能会有更好的效果,但是该样本数据集可能分布不太均匀。
      添加函数:
    def analysis_train_set():
        train_positive_count = 0
        train_negative_count = 0
        sum_count = 0
        for i in range(x_train.shape[0]):
            if y_train[i] == 0:
                train_negative_count = train_negative_count + 1
            else:
                train_positive_count = train_positive_count + 1
            sum_count = sum_count + 1
        print("Train Set Analysis:\nTotal number:{}\nNumber of positive samples:{}\tProportion of positive samples:{"
              "}\nNumber of negative samples:{}\tProportion of negative samples:{}\nPositive and negative sample ratio:{"
              "}\n".format(sum_count, train_positive_count, train_positive_count / sum_count, train_negative_count,
                           train_negative_count / sum_count, train_positive_count / train_negative_count))
    

    观察输出结果:
    在这里插入图片描述可以发现,该数据集中,正样本数据占比达到了63.7%, 正负样本比率达到了1.76,远超过1.2的比率阈值。导致了修正加权阈值函数的更偏向性加权从而使得预测质量大幅下降。想要解决这个问题可能需要修改数据集或者做数据增强。此处暂且不提。

    - 后续试验改进

    • 训练测试样本集划分比例参数调整
      在代码中,笔者采用了train_test_split(x,y,random_state=0,test_size=0.2)来划分训练集和测试集,为获取最好的预测准确率,调整test_size参数最终为0.326。训练结果如下:

    The segmentation_threshold is 4.033086595385092e-06
    Total specimen number:186
    Number of correctly predicted samples:179
    Accuracy:0.9623655913978495
    Train Set Analysis:
    Total number:383
    Number of positive samples:238 Proportion of positive samples:0.6214099216710183
    Number of negative samples:145 Proportion of negative samples:0.3785900783289817
    Positive and negative sample ratio:1.6413793103448275

    展开全文
  • 多类分类问题本质上可以分解为多个二分类问题,而解决二分类问题的方法有很多。这里我们利用Keras机器学习框架中的ANN(artificial neural network)来解决多分类问题。这里我们采用的例子是著名的UCI Machine ...

    多类分类问题本质上可以分解为多个二分类问题,而解决二分类问题的方法有很多。这里我们利用Keras机器学习框架中的ANN(artificial neural network)来解决多分类问题。这里我们采用的例子是著名的UCI Machine Learning Repository中的鸢尾花数据集(iris flower dataset)。

    1. 编码输出便签

    多类分类问题与二类分类问题类似,需要将类别变量(categorical function)的输出标签转化为数值变量。这个问题在二分类的时候直接转换为(0,1)(输出层采用sigmoid函数)或(-1,1)(输出层采用tanh函数)。类似的,在多分类问题中我们将转化为虚拟变量(dummy variable):即用one hot encoding方法将输出标签的向量(vector)转化为只在出现对应标签的那一列为1,其余为0的布尔矩阵。以我们所用的鸢尾花数据为例:

    sample, label

    1, Iris-setosa

    2, Iris-versicolor

    3, Iris-virginica

    用one hot encoding转化后如下:

    sample, Iris-setosa, Iris-versicolor, Iris-virginica

    1, 1, 0, 0

    2, 0, 1, 0

    3, 0, 0, 1

    注意这里不要将label直接转化成数值变量,如1,2,3,这样的话与其说是预测问题更像是回归预测的问题,后者的难度比前者大。(当类别比较多的时候输出值的跨度就会比较大,此时输出层的激活函数就只能用linear)

    这一步转化工作我们可以利用keras中的np_utils.to_categorical函数来进行。

    2. 构建神经网络模型

    Keras是基于Theano或Tensorflow底层开发的简单模块化的神经网络框架,因此用Keras搭建网络结构会比Tensorflow更加简单。这里我们将使用Keras提供的KerasClassifier类,这个类可以在scikit-learn包中作为Estimator使用,故利用这个类我们就可以方便的调用sklearn包中的一些函数进行数据预处理和结果评估(此为sklearn包中模型(model)的基本类型)。

    对于网络结构,我们采用3层全向连接的,输入层有4个节点,隐含层有10个节点,输出层有3个节点的网络。其中,隐含层的激活函数为relu(rectifier),输出层的激活函数为softmax。损失函数则相应的选择categorical_crossentropy(此函数来着theano或tensorflow,具体可以参见这里)(二分类的话一般选择activation=‘sigmoid’, loss=‘binary_crossentropy’)。

    PS:对于多类分类网络结构而言,增加中间隐含层能够提升训练精度,但是所需的计算时间和空间会增大,因此需要测试选择一个合适的数目,这里我们设为10;此外,每一层的舍弃率(dropout)也需要相应调整(太高容易欠拟合,太低容易过拟合),这里我们设为0.2。

    3. 评估模型

    这里我们利用评估机器学习模型的经典方法: k折交叉检验(k-fold cross validation)。这里我们采用10折(k=10)。

    4. 代码实现

    import numpy as np

    import pandas as pd

    from keras.models import Sequential

    from keras.layers import Dense, Dropout

    from keras.wrappers.scikit_learn import KerasClassifier

    from keras.utils import np_utils

    from sklearn.model_selection import train_test_split, KFold, cross_val_score

    from sklearn.preprocessing import LabelEncoder

    # load dataset

    dataframe = pd.read_csv("iris.csv", header=None)

    dataset = dataframe.values

    X = dataset[:, 0:4].astype(float)

    Y = dataset[:, 4]

    # encode class values as integers

    encoder = LabelEncoder()

    encoded_Y = encoder.fit_transform(Y)

    # convert integers to dummy variables (one hot encoding)

    dummy_y = np_utils.to_categorical(encoded_Y)

    # define model structure

    def baseline_model():

    model = Sequential()

    model.add(Dense(output_dim=10, input_dim=4, activation='relu'))

    model.add(Dropout(0.2))

    model.add(Dense(output_dim=3, input_dim=10, activation='softmax'))

    # Compile model

    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

    return model

    estimator = KerasClassifier(build_fn=baseline_model, nb_epoch=40, batch_size=256)

    # splitting data into training set and test set. If random_state is set to an integer, the split datasets are fixed.

    X_train, X_test, Y_train, Y_test = train_test_split(X, dummy_y, test_size=0.3, random_state=0)

    estimator.fit(X_train, Y_train)

    # make predictions

    pred = estimator.predict(X_test)

    # inverse numeric variables to initial categorical labels

    init_lables = encoder.inverse_transform(pred)

    # k-fold cross-validate

    seed = 42

    np.random.seed(seed)

    kfold = KFold(n_splits=10, shuffle=True, random_state=seed)

    results = cross_val_score(estimator, X, dummy_y, cv=kfold)

    5. 参考

    展开全文
  • model_selection.py​github.com1. 分类...上述问题就是典型的分类问题,确切的说是二分类问题,而能够解决这些二分类问题的数学模型就被称为二分类模型。用数学的方式表达就是,给定自变量X,代入到我们的分类模型...

    model_selection.py​github.com

    1. 分类模型

    分类问题其实在生活中处处可见,比如我们在大街上看妹纸,会把妹纸的外貌分为好看和非常好看(求生欲。。。);再比如我们刷微博,会把微博推送给我们的内容分为喜欢的和不喜欢的。上述问题就是典型的分类问题,确切的说是二分类问题,而能够解决这些二分类问题的数学模型就被称为二分类模型。用数学的方式表达就是,给定自变量X,代入到我们的分类模型F,会输出因变量y,y的取值为0或1,其中0代表负样本(好看的妹纸、不喜欢的微博),1代表正样本(非常好看的妹纸、喜欢的微博)。

    2. 准确率

    如何评估一个分类模型计算出来的结果是否准确呢?最简单的方式就是用准确率(Accuracy)来评价。比如我们手机上有5条微博,我们对这5条微博的态度分别是喜欢、喜欢、不喜欢、不喜欢、喜欢,用数组表示就是y = [1, 1, 0, 0, 1]。我们将微博的文字内容,图片内容等特征X代入到分类模型F中,得到分类结果是y_hat = [1, 1, 0, 0, 0]。显然5个样本中我们正确分类了4个,准确率 = 4 / 5 * 100% = 80%。用Python实现计算准确率的函数如下:

    def get_acc(y, y_hat):

    return sum(yi == yi_hat for yi, yi_hat in zip(y, y_hat)) / len(y)

    3. 准确率的陷阱

    如果用准确率就足以评估分类模型的优劣,那么我也就不会专门写一篇文章了[微笑]。假设大街上我们遇到好看的妹纸的概率是99%,遇到非常好看的妹纸的概率是1%。那么我们用模型F(X) = 0,即不分青红皂白,一律简单粗暴地预测所有妹纸都是好看的(负样本),模型就可以达到99%的准确率,这显然是非常荒谬的。

    4. 混淆矩阵

    如何解决准确率的陷阱呢,接下来轮到混淆矩阵矩阵出场了。混淆矩阵,顾名思义,就是可以让你混淆各种模型评价指标的矩阵。矩阵的形状是2 x 2,其中, - 矩阵的左上角表示,预测值为1,实际值为1(True Positive,简称TP); - 右上角表示预测值为1,实际值为0(False Positive,简称FP); - 左下角表示预测值为0,实际值为1(False Negative,简称FN); - 右下角表示预测值为0,实际值为0(True Negative,简称TN);

    5. TPR

    equation?tex=TPR+%3D+TP+%2F+NumberOfPositive

    TPR也被称作召回率,即正例被我们准确预测的比例。我们再回头看看准确率的陷阱,简单粗暴地预测所有妹纸都是好看的(负样本),模型就可以达到99%的准确率。但是其TPR是0,即非常好看的妹纸都没有被模型识别出来。用全宇宙最简单的编程语言Python实现TPR的计算函数如下:

    def get_tpr(y, y_hat):

    true_positive = sum(yi and yi_hat for yi, yi_hat in zip(y, y_hat))

    actual_positive = sum(y)

    return true_positive / actual_positive

    6. Precision

    equation?tex=Precision+%3D+TP+%2F+NumberOfPredictedPositive

    Precision也被称作精确率,即我们预测的正例中有多少个是准确的,可以从另一个角度来评估模型的预测能力。用全宇宙最简单的编程语言Python实现Precision的计算函数如下:

    def get_precision(y, y_hat):

    true_positive = sum(yi and yi_hat for yi, yi_hat in zip(y, y_hat))

    predicted_positive = sum(y_hat)

    return true_positive / predicted_positive

    7. TNR

    equation?tex=TNR+%3D+TN+%2F+NumberOfNegative

    TNR也称特异度,即我们预测的负例中有多少个是准确的。除此之外,特异度更多地被用于ROC曲线的绘制。用全宇宙最简单的编程语言Python实现TNR的计算函数如下:

    def get_tnr(y, y_hat):

    true_negative = sum(1 - (yi or yi_hat) for yi, yi_hat in zip(y, y_hat))

    actual_negative = len(y) - sum(y)

    return true_negative / actual_negative

    8. 分类模型的阈值

    为了简化问题,前面我们讨论分类模型的输出都是0和1的离散变量。事实上分类模型一般会输出一个介于0和1之间的数字x,比如0.75。我们需要设定一个阈值k,默认是0.5也可以根据实际情况调整。如果x>= k,那么预测结果就是1,否则预测结果就是0。由于0.75 >= 0.5,所以预测结果是1。

    9. ROC

    由于TPR = TP / Number of Positive,所以当阈值为0时,所有的样本都会被预测为Positive,所以TPR等于1,同理这时的1 - TNR为1,当阈值为1时TPR等于0,1- TNR等于0。如果我们让阈值从1逐渐降低到0,会得到很多对TPR和1 - TNR,将这些值当做数据点,以TPR为y轴,1 - TNR为x轴绘制出一条曲线,这条曲线就是ROC曲线。用全宇宙最简单的编程语言Python实现ROC数据点的计算函数如下:

    def get_roc(y, y_hat_prob):

    thresholds = sorted(set(y_hat_prob), reverse=True)

    ret = [[0, 0]]

    for threshold in thresholds:

    y_hat = [int(yi_hat_prob >= threshold) for yi_hat_prob in y_hat_prob]

    ret.append([get_tpr(y, y_hat), 1 - get_tnr(y, y_hat)])

    return ret

    10. AUC

    ROC曲线下的面积被称为AUC,可以评估模型的性能。用全宇宙最简单的编程语言Python实现AUC的计算函数如下:

    def get_auc(y, y_hat_prob):

    roc = iter(get_roc(y, y_hat_prob))

    tpr_pre, fpr_pre = next(roc)

    auc = 0

    for tpr, fpr in roc:

    auc += (tpr + tpr_pre) * (fpr - fpr_pre) / 2

    tpr_pre = tpr

    fpr_pre = fpr

    return auc

    10.1 AUC为0.5,模型没有预测能力

    我们生成1000个实际值,其中500个值为1,500个值为0,顺序被随机打乱。

    import pandas as pd

    import numpy as np

    from numpy.random import rand, seed, shuffle, normal

    seed(100)

    y = np.array([0, 1] * 500)

    shuffle(y)

    然后我们随机生成1000个实际值

    seed(20)

    y_pred = rand(1000)

    计算出ROC曲线的数据点,并绘制ROC曲线。不难看出这条ROC曲线的AUC值约等于0.5,而预测值都是我们随机生成的,也就印证了AUC为0.5时模型没有预测能力的说法。

    points = get_roc(y, y_pred)

    df = pd.DataFrame(points, columns=["tpr", "fpr"])

    print("AUC is%.3f." % get_auc(y, y_pred))

    df.plot(x="fpr", y="tpr", label="roc")

    7e5bd1bef010b2f2cf57289f946fd821.png

    10.2 AUC值为1,模型的预测能力最强

    我们让预测值直接等于实际值

    y_pred = np.array(y)

    计算出ROC曲线的数据点,并绘制ROC曲线。不难看出这条ROC曲线的AUC值1,也就印证了AUC值为1,模型的预测能力最强的说法。当然,在实际应用时这种情况是几乎不可能出现的。

    points = get_roc(y, y_pred)

    df = pd.DataFrame(points, columns=["tpr", "fpr"])

    print("AUC is%.3f." % get_auc(y, y_pred))

    df.plot(x="fpr", y="tpr", label="roc")

    70b4417da277227c0e913381d4d17b17.png

    10.3 对于正例和负例有着对等预测能力的ROC曲线

    阈值为0.5时,我们让预测值有70%的可能性是正确预测。比如yi = 1,那么预测值有70%的可能性是[0.5, 1]之间的随机数。如果yi = 0,那么预测值有70%的可能性是[0, 0.5]之间的随机数

    seed(15)

    f = lambda x: rand() / 2 + 0.5 if x else rand() / 2

    y_pred = np.array([f(yi) if rand() > 0.3 else f(1 - yi) for yi in y])

    计算出ROC曲线的数据点,并绘制ROC曲线。可以看出ROC曲线的形状是对称的。

    points = get_roc(y, y_pred)

    df = pd.DataFrame(points, columns=["tpr", "fpr"])

    print("AUC is%.3f." % get_auc(y, y_pred))

    df.plot(x="fpr", y="tpr", label="roc")

    39103d7d827c3805c63e37a54fd1f56b.png

    10.4 对于正例有着较强预测能力的ROC曲线

    阈值为0.5时,我们让正例的预测值有95%的可能性是正确预测,负例的预测值有70%的可能性是正确预测

    seed(200)

    def f(x):

    if x == 1:

    if rand() > 0.05:

    return rand() / 2 + 0.5

    else:

    return rand() / 2

    else:

    if rand() > 0.3:

    return rand() / 2

    else:

    return rand() / 2 + 0.5

    y_pred = np.array([f(yi) for yi in y])

    计算出ROC曲线的数据点,并绘制ROC曲线。可以看出ROC曲线的形状是偏上的。

    points = get_roc(y, y_pred)

    df = pd.DataFrame(points, columns=["tpr", "fpr"])

    print("AUC is%.3f." % get_auc(y, y_pred))

    df.plot(x="fpr", y="tpr", label="roc")

    39103d7d827c3805c63e37a54fd1f56b.png

    10.5 对于负例有着较强预测能力的ROC曲线

    阈值为0.5时,我们让正例的预测值有70%的可能性是正确预测,负例的预测值有95%的可能性是正确预测

    seed(120)

    def f(x):

    if x == 1:

    if rand() > 0.3:

    return rand() / 2 + 0.5

    else:

    return rand() / 2

    else:

    if rand() > 0.05:

    return rand() / 2

    else:

    return rand() / 2 + 0.5

    y_pred = np.array([f(yi) for yi in y])

    计算出ROC曲线的数据点,并绘制ROC曲线。可以看出ROC曲线的形状是偏左的。

    points = get_roc(y, y_pred)

    df = pd.DataFrame(points, columns=["tpr", "fpr"])

    print("AUC is%.3f." % get_auc(y, y_pred))

    df.plot(x="fpr", y="tpr", label="roc")

    e8e42e49f292832fca2a840f195d4c68.png

    10.6 预测值集中在0.5左右的ROC曲线

    阈值为0.5时,我们让预测值有80%的可能性是正确预测,但值集中在0.5左右

    seed(220)

    def f(x):

    if x == 1:

    if rand() > 0.2:

    return rand() / 10 + 0.5

    else:

    return 0.5 - rand() / 10

    else:

    if rand() > 0.2:

    return 0.5 - rand() / 10

    else:

    return rand() / 10 + 0.5

    y_pred = np.array([f(yi) for yi in y])

    计算出ROC曲线的数据点,并绘制ROC曲线。

    points = get_roc(y, y_pred)

    df = pd.DataFrame(points, columns=["tpr", "fpr"])

    print("AUC is%.3f." % get_auc(y, y_pred))

    df.plot(x="fpr", y="tpr", label="roc")

    c39d43ba4071ab43883c82a7dfde618e.png

    10.7 预测值靠近1或0的ROC曲线

    阈值为0.5时,我们让预测值有80%的可能性是正确预测,但值靠近1或0。

    seed(50)

    def f(x):

    if x == 1:

    if rand() > 0.2:

    return 1 - rand() / 10

    else:

    return rand() / 10

    else:

    if rand() > 0.2:

    return rand() / 10

    else:

    return 1 - rand() / 10

    y_pred = np.array([f(yi) for yi in y])

    计算出ROC曲线的数据点,并绘制ROC曲线。可以看出曲线跟10.6几乎没有差异,根据ROC曲线的定义不难思考出原因。

    points = get_roc(y, y_pred)

    df = pd.DataFrame(points, columns=["tpr", "fpr"])

    print("AUC is%.3f." % get_auc(y, y_pred))

    df.plot(x="fpr", y="tpr", label="roc")

    8e3a2d6168413c6d489d616e369d5916.png

    10.8 预测值恒等于0.9的ROC曲线

    y_pred = np.array([0.9] * len(y))

    计算出ROC曲线的数据点,并绘制ROC曲线。发现预测值为定值的模型,ROC曲线是一条直线,AUC恒等于0.5。

    points = get_roc(y, y_pred)

    df = pd.DataFrame(points, columns=["tpr", "fpr"])

    print("AUC is%.3f." % get_auc(y, y_pred))

    df.plot(x="fpr", y="tpr", label="roc")协同过滤(ALS)的原理及Python实现梯度下降的原理及Python实现

    展开全文
  • 举一个简单易懂的例子:将电子邮件分类为“ 垃圾邮件 ”或“ 非垃圾邮件”(二分类的典型特征“非此即彼”,关于二分类,后文会涉及)。你可能会在机器学习中遇到许多不同类型的分类任务,但是其实每种模型都会使用与...
  • python里的分类模型

    2020-05-07 10:11:09
    python里有两个包可以做分类模型,一个是sm.logit,另外一个是sklearn里的logisticRegression。 sm.logit能给出p value,但只针对于二分类。 logisticRegression可以做多分类,但是不能给出p value 要想做多分类...
  • Python深度学习笔记(三)二分类模型 继续来写我的学习笔记 -----二分类问题 我从数据的处理,模型的构架,训练过程,验证模型及损失和精度的比较这几个方面来介绍。 一,数据的处理 一个典型的二分类问题的例子:...
  • 二分类模型评价指标-Python实现

    千次阅读 2018-07-16 12:43:52
      Sklearn的metrics模块下有多个计算模型评价指标的函数,本文只介绍二分类的指标函数。 1.准确率 1.1参数说明 sklearn.metrics.accuracy_score(y_true, y_pred, normalize=True, sample_weight=None) ...
  • 我在一开始学习数据科学中机器学习(Machine Learning)的时候重点都放在理解每个模型上,但是真的到用机器学习去解决问题的时候发现自己完全没有思路。所以今天的主要目的是用一个简单的例子和大家分享下使用Python的...
  • 虽然模型本身运行良好(它对新数据进行了正确的预测),但我在为模型绘制混淆矩阵和分类报告时遇到了问题。我用ImageDataGenerator训练模型train_path = '../dataset/TRAIN'test_path = '../DATASET/TEST'IMG_BREDTH =...
  • 本文,我将简单介绍分类模型的基础知识以及如何在...最简单的分类形式是分两个类别,即“二分类”。一般讲其中一类标记为正类(记为1),另外一类标记为负类(记为-1或者0)。 分类是监督学习的一种形式,我们用带有类标
  • 通常面临的二分类问题可能是:一封邮件是否为垃圾邮件;那么可以抽象成数字标签: y=0 表示负类->垃圾邮件 y=1 表示正类->正常邮件 模型的提出 这要求数学模型的结果取值要在[0,1]范围内,通常线性回归h(θ)...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,245
精华内容 498
关键字:

python二分类模型

python 订阅