精华内容
下载资源
问答
  • 机器学习二分类模型评价指标详述

    千次阅读 2021-01-10 17:32:37
    要注意,精确率和召回率是二分类指标,不适用多分类,由此得到P-R曲线以及ROC曲线均是二分类评估指标(因为其横纵轴指标均为二分类混淆矩阵计算得到),而准确率适用于多分类评估。(可以将多分类问题转换为二分类...

    问题建模

    机器学习解决问题的通用流程:问题建模——特征工程——模型选择——模型融合

    其中问题建模主要包括:设定评估指标,选择样本,交叉验证

    解决一个机器学习问题都是从问题建模开始,首先需要收集问题的资料,深入理解问题,然后将问题抽象成机器可预测的问题。在这个过程中要明确业务指标模型预测目标,根据预测目标选择适当指标用于模型评估。接着从原始数据中选择最相关的样本子集用于模型训练,并对样本子集划分训练集和测试集,应用交叉验证的方法对模型进行选择和评估。

    评估指标

    评估指标很多,我们应该选择一个能跟业务指标波动一致的评估指标,这样通过观察评估指标就能判断模型效果,可以大大提高模型迭代效率。

    评估指标用于反应模型效果,在预测问题中,要评估模型的效果,就需要将模型预测结果 f(x) ​和真真实标注 Y​ 进行比较,评估指标定义为f(x)Y​的函数。

    score = metric(f(x),Y)

    通常线下使用的是机器学习评估指标,线上使用的是业务指标,如果线下指标和线上指标不同,则可能会出现线下指标变好而线上指标变差的现象。为此,在一个新问题的开始阶段,都会进行多轮模型迭代,来探索和线上业务指标一致的线下指标,尽可能使线下指标的变趋势和线上指标一致

    分类指标

    1. 精确率、召回率、准确率、错误率和F函数

    1.1 精确率和召回率

    精确率和召回率主要用于二分类问题(从其公式推导也可看出),结合混淆矩阵有:

     

    精确率P和召回率R的定义为:

    精确率(Precision) = \frac{True \ Positive}{True \ Positive + False \ Positive}

    召回率(Recall) = \frac{True \ Positive}{True \ Positive + False \ Negative}

     

    上述计算公式中的Positive与Negative是预测标签,True与false代表预测正误;
    要注意,精确率和召回率是二分类指标,不适用多分类,由此得到P-R曲线以及ROC曲线均是二分类评估指标(因为其横纵轴指标均为二分类混淆矩阵计算得到),而准确率适用于多分类评估。(可以将多分类问题转换为二分类问题进行求解,将关注的类化为一类,其他所有类化为一类)

    理想情况下,精确率和召回率两者都越高越好。然而事实上这两者在某些情况下是矛盾的,精确率高时,召回率低;精确率低时,召回率高;关于这个性质通过观察PR曲线不难观察出来。比如在搜索网页时,如果只返回最相关的一个网页,那精确率就是100%,而召回率就很低;如果返回全部网页,那召回率为100%,精确率就很低。因此在不同场合需要根据实际需求判断哪个指标跟重要。

    上图分析一下:

     

     

    • recall是相对真实的答案而言: true positive / golden set 。假设测试集里面有100个正例,你的模型能预测覆盖到多少,如果你的模型预测到了40个正例,那你的recall就是40%。
    • precision是相对你自己的模型预测而言:true positive /retrieved set。假设你的模型一共预测了100个正例,而其中80个是对的正例,那么你的precision就是80%。我们可以把precision也理解为,当你的模型作出一个新的预测时,它的confidence score 是多少,或者它做的这个预测是对的的可能性是多少。
    • 一般来说呢,鱼与熊掌不可兼得。如果你的模型很贪婪,想要覆盖更多的sample,那么它就更有可能犯错。在这种情况下,你会有很高的recall,但是较低的precision。如果你的模型很保守,只对它很sure的sample作出预测,那么你的precision会很高,但是recall会相对低。

    这样一来呢,我们可以选择只看我们感兴趣的class,就是minority class的precision,recall来评价模型的好坏。

    1.2 准确率和错误率

    准确率和错误率既可用于二分类也可用于多分类:

    准确率(accuracy)= \frac{TP+TN}{TP+FP+FN+TN}

    错误率(error rate) = \frac{FP+FN}{TP+FP+FN+TN}

     

    上述公式是准确率、错误率针对二分类情况时候的计算公式

    精确率和准确率是比较容易混淆的两个评估指标,两者是有区别的。精确率是一个二分类指标,而准确率能应用于多分类,其计算公式为:

     

    准确率(accuracy) = \frac{1}{n}\sum_{i=1}^{n}I(f(x_i)=y_i)

     

    1.3F函数:

    F1函数是一个常用指标,F1值是精确率和召回率的调和均值,即

     

    \frac{2}{F_1} = \frac{1}{P} + \frac{1}{R}

     

    F_1 = \frac{2PR}{P+R}

     

    F值可泛化为对精确率和召回率赋不同权值进行加权调和:

     

    F_{\alpha} = \frac{(1+\alpha^2) PR}{\alpha^2 P+R}

     

     

    利用 \alpha 给P和R赋予不同的权重,若 \alpha = 1 则为F1值。

    下面是两个场景:

    1. 地震的预测对于地震的预测,我们希望的是RECALL非常高,也就是说每次地震我们都希望预测出来。这个时候我们可以牺牲PRECISION。情愿发出1000次警报,把10次地震都预测正确了;也不要预测100次对了8次漏了两次。
    2. 嫌疑人定罪基于不错怪一个好人的原则,对于嫌疑人的定罪我们希望是非常准确的。及时有时候放过了一些罪犯(recall低),但也是值得的。对于分类器来说,本质上是给一个概率,此时,我们再选择一个CUTOFF点(阀值),高于这个点的判正,低于的判负。那么这个点的选择就需要结合你的具体场景去选择。反过来,场景会决定训练模型时的标准,比如第一个场景中,我们就只看RECALL=99.9999%(地震全中)时的PRECISION,其他指标就变得没有了意义。

    2. ROC曲线、PR曲线

    2.1 PR曲线

    我们以召回率R为横轴、以精确率P为纵轴,能够画出P-R曲线,如下图:

     

    从上图不难发现,precision与Recall的折中(trade off),曲线越靠近右上角性能越好,曲线下的面积叫AP分数,能在一定程度上反应模型的精确率和召回率都很高的比例。但这个值不方便计算,综合考虑精度与召回率一般使用F1函数或者AUC值(因为ROC曲线很容易画,ROC曲线下的面积也比较容易计算).

    先看平滑不平滑,在看谁上谁下(同一测试集上),一般来说,上面的比下面的好(红线比黑线好);

    F1(计算公式略)当P和R接近就也越大,一般会画连接(0,0)和(1,1)的线,线和PRC重合的地方的F1是这条线最大的F1(光滑的情况下),此时的F1对于P-R曲线就好象AUC对于ROC一样。一个数字比一条线更方便调模型。

    注:既然Precision与Recall都是二分类指标,则PR曲线也必然是二分类指标,虽然可以将precision、Recall及PR曲线应用到多分类,但是这种情况相当于是多分类转换为二分类情况分析(将关注的类视为一类,将其他所有类化为一类)

    2.2 ROC曲线

    在众多的机器学习模型中,很多模型输出的是预测概率,而使用精确率、召回率这类指标进行模型评估时,还需要对预测概率设分类阈值,比如预测概率大于阈值为正例,反之为负例。这使得模型多了一个超参数,并且这超参数会影响模型的泛化能力。

    接受者操作特征(Receiver Operating Characteristic, ROC)曲线不需要设定这样的阈值,ROC曲线纵坐标是真正率,横坐标是假正率,如下图,去对应的计算公式为:

     

    真正率(True \ Positive \ Rate) = \frac{TP}{TP+FN}

     

    假正率(False \ Positive \ Rate) = \frac{FP}{FP+TN}

     

    同时,TPR与FPR又有其他名称,如下:

    • sensitivity = recall = true positive rate
    • specificity = 1- false positive rate

    假设我们的minority class,也就是正例,是1。反例,为0。$\hat{Y}$是真实label Y的估计(estimate)。

     

    看出来没有,sensitivity和specificity是条件于真实label Y的概率的。我们讲这个叫条件概率嘛。那么意思就是说,无论Y的真实概率是多少,都不会影响sensitivity和specificity。也就是说,这两个metric是不会受imbalanced data 影响的,那就很客观了啊,是不是!而precision呢,就会随着你的测试集里面的正反比例而变化哦。

    另外值得注意的是, AUC的计算方法同时考虑了学习器对于正例和负例的分类能力,在样本不平衡的情况下,依然能够对分类器做出合理的评价。AUC对样本类别是否均衡并不敏感,这也是不均衡样本通常用AUC评价学习器性能的一个原因。

    例如在癌症预测的场景中,假设没有患癌症的样本为正例,患癌症样本为负例,负例占比很少(大概0.1%),如果使用准确率评估,把所有的样本预测为正例便可以获得99.9%的准确率。但是如果使用AUC,把所有样本预测为正例,TPR为1,FPR为1。这种情况下学习器的AUC值将等于0.5,成功规避了样本不均衡带来的问题。

    这个曲线就是以true positive rate 和 false positive rate为轴,取不同的threshold点画的啦。有人问了,threshold是啥子哦。这么说吧,每个分类器作出的预测呢,都是基于一个probability score的。一般默认的threshold呢都是0.5,如果probability>0.5,那么这个sample被模型分成正例了哈,反之则是反例。

     

    真正率(True Positive Rate)就是召回率Recall

    ROC曲线和P-R曲线有些类似,ROC曲线越靠近左上角性能越好。左上角坐标为(0, 1),即FPR=0,TPR=1,根据FPR和TPR公可以得知,此时FN=0, FP=0,模型对所有样本分类正确,绘制ROC曲线很简单,首先对所有样本按预测概率排序,以每条样本的预测概率为阈值,计算相应的FPR和TPR,然后线段连接。

    当数据量少时,绘制的ROC曲线不平滑;当数据量大时,绘制的ROC曲线会趋于平滑。

    ROC curve 可以很好的回答什么问题呢——“不论class的基本概率怎么样,我的模型in general能表现得多好?”

    一般来说呢,最优的threshold就是橙色曲线离蓝色虚线(基准线)最远的一点啦,或者橙色曲线上离左上角最近的一点,再或者是根据用户自己定义的cost function来的。

    一般来说,如果ROC是光滑的,那么基本可以判断没有太大的overfitting(比如图中0.2到0.4可能就有问题,但是样本太少了),这个时候调模型可以只看AUC,面积越大一般认为模型越好。

    1. 主要作用

    1. ROC曲线能很容易的查出任意阈值对学习器的泛化性能影响。
    2. 有助于选择最佳的阈值。ROC曲线越靠近左上角,模型的查全率就越高。最靠近左上角的ROC曲线上的点是分类错误最少的最好阈值,其假正例和假反例总数最少。
    3. 可以对不同的学习器比较性能。将各个学习器的ROC曲线绘制到同一坐标中,直观地鉴别优劣,靠近左上角的ROC曲所代表的学习器准确性最高。

    2. 优点

    1. 该方法简单、直观、通过图示可观察分析方法的准确性,并可用肉眼作出判断。ROC曲线将真正例率和假正例率以图示方法结合在一起,可准确反映某种学习器真正例率和假正例率的关系,是检测准确性的综合代表。
    2. 在生物信息学上的优点:ROC曲线不固定阈值,允许中间状态的存在,利于使用者结合专业知识,权衡漏诊与误诊的影响,选择一个更加的阈值作为诊断参考值。

    3. AUC

    3.1 什么是AUC

    AUC是一个模型评价指标,只能用于二分类模型的评价,对于二分类模型,还有很多其他评价指标,比如logloss,accuracy,precision。如果你经常关注数据挖掘比赛,比如kaggle,那你会发现AUC和logloss基本是最常见的模型评价指标。为什么AUC和logloss比accuracy更常用呢?因为很多机器学习的模型对分类问题的预测结果都是概率,如果要计算accuracy,需要先把概率转化成类别,这就需要手动设置一个阈值,如果对一个样本的预测概率高于这个预测,就把这个样本放进一个类别里面,低于这个阈值,放进另一个类别里面。所以这个阈值很大程度上影响了accuracy的计算。使用AUC或者logloss可以避免把预测概率转换成类别。

    AUC是Area under curve的首字母缩写。AUC就是ROC曲线下的面积,衡量学习器优劣的一种性能指标。从定义可知,AUC可通过对ROC曲线下各部分的面积求和而得。假定ROC曲线是由坐标为 {(x_1, y_1), (x_2, y_2), (x_3, y_3), \cdots, (x_m, y_m)} 的点按序连接而形成,则AUC可估算为:

     

    AUC = \frac{1}{2}\sum_{i=1}^{m-1}(x_{i+1} - x_i)(y_i + y_{i+1})

    3.2 AUC的意义

    通过AUC的定义我们知道了AUC是什么,怎么算,但是它的意义是什么呢。如果从定义来理解AUC的含义,比较困难,实际上AUC和Mann–Whitney U test有密切的联系。

    从Mann–Whitney U statistic的角度来解释,AUC就是从所有1样本中随机选取一个样本, 从所有0样本中随机选取一个样本,然后根据你的分类器对两个随机样本进行预测,把1样本预测为1的概率为p1,把0样本预测为1的概率为p0,p1>p0的概率就等于AUC。

    AUC是指随机给定一个正样本和一个负样本,分类器输出该正样本为正的那个概率值比分类器输出该负样本为正的那个概率值要大的可能性。

    所以AUC反应的是分类器对样本的排序能力。根据这个解释,如果我们完全随机的对样本分类,那么AUC应该接近0.5。(所以一般训练出的模型,AUC>0.5,如果AUC=0.5,这个分类器等于没有效果,效果与完全随机一样,如果AUC<0.5,则可能是标签标注错误等情况造成);

    另外值得注意的是,AUC的计算方法同时考虑了学习器对于正例和负例的分类能力,在样本不平衡的情况下,依然能够对分类器做出合理的评价。AUC对样本类别是否均衡并不敏感,这也是不均衡样本通常用AUC评价学习器性能的一个原因。

    这个指标尤其适用在某些场景下(如 CTR 预估),每次要返回的是最有可能点击的若干个广告(根据CTR排序, 选择排在前面的若干个),实际上便是在考验模型的排序能力。除此之外,CTR 中存在着样本不均衡的问题,正负样本比例通常会大于 1:100,如果采用 PR 曲线,则会导致 AUC 发生剧变,无法较好反映模型效果。

    然而,ROC 曲线不会随着类别分布的改变而改变的优点在一定程度上也是其缺点。因为 ROC 曲线这种不变性其实影响着的是 AUC 值,或者说是评估分类器的整体性能。但是在某些场景下,我们会更关注正样本,这时候就要用到 PR 曲线了。

    比如说信用卡欺诈检测,我们会更关注 precision 和 recall,比如说如果要求预测出为欺诈的人尽可能准确,那么就是要提高 precision;而如果要尽可能多地预测出潜在的欺诈人群,那么就是要提高 recall。一般来说,提高二分类的 threshold 就能提高 precision,降低 threshold 就能提高 recall,这时便可观察 PR 曲线,得到最优的 threshold。

    此外,AUC和Wilcoxon Test of Ranks等价;AUC还和基尼(Gini)系数有联系,满足

    Gini+1 = 2*AUC

     

    3.3 AUC的计算方法:

    AUC的计算方法有多种,从物理意义角度理解,AUC计算的是ROC曲线下的面积:

     

    AUC = \sum_{i \in (P+N)}\frac{(TPR_i + TPR_{I-1})*(FPR_i - FPR_{i-1})}{2}

     

    从概率意义角度理解,AUC考虑的是样本的排序质量,它与排序误差有密切关系,可得到计算公式:

    AUC = \frac{\sum_{i \in P}rank_i - \frac{|P|(|P|+1)}{2}}{|P||N|}

     

    其中,rank为样本排序位置从1开始, |P| 为正样本数, |N| 为负样本数。

    AUC计算主要与排序有关,所以它对排序敏感,而对预测分数没那么敏感。

    最后,我们在讨论一下:在多分类问题下能不能使用ROC曲线来衡量模型性能?

    我的理解:ROC曲线用在多分类中是没有意义的。只有在二分类中Positive和Negative同等重要时候,适合用ROC曲线评价。如果确实需要在多分类问题中用ROC曲线的话,可以转化为多个“一对多”的问题。即把其中一个当作正例,其余当作负例来看待,画出多个ROC曲线。

    “ROC 曲线具有不随样本比例而改变的良好性质,因此能够在样本比例不平衡的情况下较好地反映出分类器的优劣。”
    AUC计算主要与排序有关,所以他对排序敏感,而对预测分数没那么敏感。

    4. 对数损失

    对数损失(logistic loss,logloss)是对预测概率的似然估计,其标准形式为:

     

    logloss = -logP(Y|X)

     

    对数损失最小化本质上是利用样本中的已知分布,求解导致这种分布的最佳模型参数,是这种分布出现概率最大。

    对数损失对应的二分类的计算公式为:

     

    logloss = -\frac{1}{N}\sum_{i=1}^{N}(y \cdot logp_i + (1-y) \cdot log(1-p_i))

     

    其中, y \in \{0,1\} , p_i 为第 i 条样本预测为1的概率。

    对数损失在多分类问题中也使用广泛,其计算公式为:

     

    logloss = - \frac{1}{N}\cdot \frac{1}{C} \cdot \sum_{i=1}^{N} \sum_{j=1}^{C} y_{ij}\cdot logp_{ij}

     

    其中, N 为样本数, C 为类别数, y_{ij} = 1 表示第$i$条样本的类别为 j , p_{ij} 为第 i 条样本类别 j 的概率。

    logloss衡量的是预测概率分布和真实概率分布的差异性,取值越小越好。与AUC不同,logloss对预测概率敏感。

    总结

    1. 精确率(Precision)是指在所有系统判定的“真”的样本中,确实是真的的占比,就是TP/(TP+FP)。
    2. 召回率(Recall)是指在所有确实为真的样本中,被判为的“真”的占比,就是TP/(TP+FN)。
    3. TPR(True Positive Rate)的定义,跟Recall一样。
    4. FPR(False Positive Rate),又被称为“Probability of False Alarm”,就是所有确实为“假”的样本中,被误判真的样本,或者FP/(FP+TN)
    5. F1值是为了综合考量精确率和召回率而设计的一个指标,一般公式为取P和R的harmonic mean:2PrecisionRecall/(Precision+Recall)。
    6. ROC=Receiver Operating Characteristic,是TPR vs FPR的曲线;与之对应的是Precision-Recall Curve,展示的是Precision vs Recall的曲线。

    参考资料:

    1. 机器学习和统计里面的AUC如何理解
    2. 精确率、召回率、F1 值、ROC、AUC 各自的优缺点是什么?
    3. 美团机器学习实践
    4. ROC 曲线与 PR 曲线
    展开全文
  • 使用机器学习和深度学习对PE进行二分类和多分类

    万次阅读 多人点赞 2021-08-04 15:31:19
    1. 前言 2. 安装库 2.1 安装lief ...由于数据量规模大,所以就可以拿来训练较为有效的模型,不仅可以做对PE进行正常或者恶意的二分类,而且还可以进行更小粒度的恶意分类(如木马、蠕虫、勒索病毒等等)。

    1. 前言

      根据调研发现sophos-ai分享了两千万的PE数据集,链接为https://github.com/sophos-ai/SOREL-20M。由于数据量规模大,所以就可以拿来训练较为有效的模型,不仅可以做对PE进行正常或者恶意的二分类,而且还可以进行更小粒度的恶意分类(如木马、蠕虫、勒索病毒等等)。

      在静态条件下对PE进行分类(不把PE放到沙箱中执行),主要有两种方法:

    1. 提取特征后进行分类,例如使用LIEF进行特征提取后再进行分类。
    2. 将PE文件看作是灰度图,然后将其视作是图像进行分类。

      本文主要讲究的是方法一,即通过工具进行特征提取后进行分类

    2. 安装库

    2.1 安装lief

    pip install lief==0.11.4
    

    源码链接:https://github.com/lief-project/LIEF

    2.2 安装ember

    pip install git+https://github.com/elastic/ember.git
    

    源码链接:https://github.com/elastic/ember

    3. 数据预处理

      假设每个文件名的格式为md5_label。比如二分类,则label为0,则表示为白文件;label为1,则表示为恶意文件。如果是多分类,比如进行11分类:

    1. adware
    2. flooder
    3. ransomware
    4. dropper
    5. spyware
    6. packed
    7. crypto_miner
    8. fle infector
    9. installer
    10. worm
    11. downloader

    导包:

    import sys
    import os
    import glob
    import ember
    import json
    

    将结果保存到json文件中:

    pe_extractor = ember.features.PEFeatureExtractor()
    json_content_list = []
    
    for i in glob.iglob('/home/learn/PE/data/*'):
        label = os.path.basename(i).split('_')[1]
        if label == 'nan':
            continue
        with open(i, 'rb') as f:
            json_content = pe_extractor.raw_features(f.read())
            json_content['label'] = int(float(label))
            json_content_list.append(json_content)
    
    with open('/home/learn/PE/result/processed_data.json', 'w') as f:
        f.write('\n'.join(json.dumps(i) for i in json_content_list))
    

    读取json文件,并将特征和标签保存到dat类型文件中:

    data_dir = '/home/learn/PE/data/result/'
    extractor = ember.features.PEFeatureExtractor()
    print("Vectorizing training set")
    X_path = os.path.join(data_dir, "X_train.dat")
    y_path = os.path.join(data_dir, "y_train.dat")
    raw_feature_paths = [os.path.join(data_dir, "processed_data.json")]
    nrows = sum([1 for fp in raw_feature_paths for line in open(fp)])
    ember.vectorize_subset(X_path, y_path, raw_feature_paths, extractor, nrows)
    
    X_train, y_train = ember.read_vectorized_features(data_dir, "train", 2)
    

    4. 训练模型

      比如使用lightgbm来训练模型,代码为:

    import lightgbm as lgb
    params = {  "boosting": "gbdt",
                "objective": "binary",
                "num_iterations": 1000,
                "learning_rate": 0.05,
                "num_leaves": 100,
                "max_depth": 15,
                "min_data_in_leaf": 20,
                "feature_fraction": 0.5,
    }
    
    train_rows = (y_train != -1)
    
    # Train
    lgbm_dataset = lgb.Dataset(X_train[train_rows], y_train[train_rows].astype('int32'))
    lgbm_model = lgb.train(params, lgbm_dataset)
    
    
    lgbm_model.save_model('lightgbm.model')
    

    5. 预测新数据

    5.1 二分类预测

    import lightgbm as lgb
    import ember
    
    binary_path = 'putty.exe'
    file_data = open(binary_path, "rb").read()
    lgbm_model = lgb.Booster(model_file='lightgbm.model')
    score = ember.predict_sample(lgbm_model, file_data)
    print(score)
    

    5.2 多分类预测

    import ember
    import torch
    from torch import nn
    import torch.nn.functional as F
    
    class PENetwork(nn.Module):
        """
        This is a simple network loosely based on the one used in ALOHA: Auxiliary Loss Optimization for Hypothesis Augmentation (https://arxiv.org/abs/1903.05700)
        Note that it uses fewer (and smaller) layers, as well as a single layer for all tag predictions, performance will suffer accordingly.
        """
        def __init__(self, use_malware=True, use_counts=False, use_tags=True, n_tags=11, feature_dimension=2381, layer_sizes = None):
            self.use_malware=use_malware
            self.use_counts=use_counts
            self.use_tags=use_tags
            self.n_tags = n_tags
    
            if self.use_tags and self.n_tags == None:
                raise ValueError("n_tags was None but we're trying to predict tags. Please include n_tags")
            super(PENetwork,self).__init__()
            p = 0.05
            layers = []
            if layer_sizes is None:layer_sizes=[512,512,128]
            for i,ls in enumerate(layer_sizes):
                if i == 0:
                    layers.append(nn.Linear(feature_dimension,ls))
                else:
                    layers.append(nn.Linear(layer_sizes[i-1],ls))
                layers.append(nn.LayerNorm(ls))
                layers.append(nn.ELU())
                layers.append(nn.Dropout(p))
            self.model_base = nn.Sequential(*tuple(layers))
            self.malware_head = nn.Sequential(nn.Linear(layer_sizes[-1], 1),
                                              nn.Sigmoid())
            self.count_head = nn.Linear(layer_sizes[-1], 1)
            self.sigmoid = nn.Sigmoid()
            self.tag_head = nn.Sequential(nn.Linear(layer_sizes[-1],64),
                                            nn.ELU(), 
                                            nn.Linear(64,64),
                                            nn.ELU(),
                                            nn.Linear(64,n_tags),
                                            nn.Sigmoid())
    
        def forward(self,data):
            rv = {}
            base_result = self.model_base.forward(data)
            if self.use_malware:
                rv['malware'] = self.malware_head(base_result)
            if self.use_counts:
                rv['count'] = self.count_head(base_result)
            if self.use_tags:
                rv['tags'] = self.tag_head(base_result)
            return rv
    
    pe_extractor = ember.features.PEFeatureExtractor()
    binary_path = 'malware.exe'
    file_data = open(binary_path, "rb").read()
    X_test = pe_extractor.feature_vector(file_data)
    
    with torch.no_grad():
        model = PENetwork()
        model.load_state_dict(torch.load('nn.pt'))
        model.eval()
        y_pred = model(torch.from_numpy(X_test))
        print(y_pred['tags'].argmax())
    

    6. 代码下载

      为了方便大家进行测试,提供的代码包含的是用保存后的模型对数据进行预测的代码,下载链接为:https://download.csdn.net/download/herosunly/20721893

    展开全文
  • 这篇文章的任务是预测给定社交网络本身每个成员倾向于加入哪一社区(二分类问题)。 karate_club_graph 是 networkx 模块集成的一个数据集,这是社会网络分析领域中的经典数据集,20世纪70年代,社会学家 Zachary ...

    简介

    Zachary’s Karate Club 是一个空手道俱乐部,该俱乐部有34个成员(34个节点),根据这些成员是否关系密切建立一个基于图的社区网络(78条边),俱乐部随后分裂成两个社区,由教员(Mr.Hi 节点0)和俱乐部主席(Officer 节点33)领导。 这篇文章的任务是预测给定社交网络本身每个成员倾向于加入哪一社区(二分类问题)

    在这里插入图片描述
    文章出处:An information flow model for conflict and fission in small groups

    karate_club_graph 是 networkx 模块集成的一个数据集,这是社会网络分析领域中的经典数据集,20世纪70年代,社会学家 Zachary 用了两年的时间来观察美国一所大学中空手道俱乐部34名成员之间的社会关系。基于这些成员在俱乐部内部及外部的交往情况,他构成了成员之间的关系网,该网络包括34个节点,两个节点之间有一条边则意味着相应的两个成员之间至少是交往频繁的朋友关系
    在这里插入图片描述
    说明文档:karate_club_graph 介绍

    在这里插入图片描述

    构建网络思路

    1.构建邻接矩阵 A 和度矩阵 D ( 可以参考我这篇文章:简单模拟图卷积(numpy实现)

    '''
    求邻接矩阵A和度矩阵D,提前设置(先验知识)
    '''
    zkc = karate_club_graph()
    order = sorted(list(zkc.nodes()))
    A = to_numpy_matrix(zkc, nodelist=order)
    print("\n\nA:",A.shape,'\n',A)
    I = np.eye(zkc.number_of_nodes())
    A_hat = A + I
    D_hat = np.array(np.sum(A_hat, axis=0))[0]
    D_hat = np.matrix(np.diag(D_hat))
    print("D_hat:",D_hat.shape)
    

    2.构建两层的图卷积神经网络(根据以下公式) Z = f ( X , A ) = s o f t m a x ( A ^ R e L U ( A ^ X W 0 ) W 1 ) , 其 中 A ^ = D − 1 / 2 ( A + I ) Z=f(X,A)= softmax(\hat{A}ReLU(\hat{A}XW^0)W^1) , 其中\hat{A}= D^{-1/2}(A+I) Z=f(X,A)=softmax(A^ReLU(A^XW0)W1),A^=D1/2(A+I)

        def forward(self, g, inputs):
            h = self.gcn1(g, inputs)
            h = t.relu(h)
            h = self.gcn2(g, h)      
            return h
    

    3.使用 torch.nn.linear 全连接层来代替上式的 W 0 和 W 1 ( 可 以 利 用 优 化 器 进 行 迭 代 更 新 ) W^0 和 W^1(可以利用优化器进行迭代更新) W0W1

        def forward(self, g, inputs):
            h = t.mm(t.Tensor(D_hat**-1*A_hat),inputs)
            return self.linear(h)
    

    4.一共34个节点,利用 torch.eye(34) 作为节点的特征 X = t e n s o r . s i z e ( [ 34 , 34 ] ) , 对 应 节 点 特 征 值 都 是 1 X=tensor.size([34,34]),对应节点特征值都是1 X=tensor.size([34,34])1

    5.调用 networkx.draw 函数画节点图,参考网址 networx.draw 函数的使用

    def plot_graph(fig,outputs,epoch):
        '''
        画节点图(动图)
        '''
        outputs=t.detach(outputs).numpy()
        all_nodes = {
            node: np.array(outputs)[node] 
            for node in zkc.nodes()}
        ax = fig.add_subplot(1,1,1)
        plt.title("karate_club_graph epoch=%d"%epoch,fontsize=18)
        nx.draw(zkc,all_nodes,with_labels=True,font_color="w",node_size=350,node_shape="o",node_color=colors,alpha=0.8)
        plt.legend(["red_node is 'Mr.Hi' and blue_node is 'Officer'","edge"],loc='lower left',frameon=False,fontsize=15)
        plt.pause(0.1)
        ax.remove()
    

    完整代码(有注释)

    from networkx import karate_club_graph,to_numpy_matrix
    import matplotlib.pyplot as plt
    import networkx as nx
    import torch as t
    import torch.nn as nn
    import torch.nn.functional as F
    import numpy as np
    
    club_name=['Officer','Mr.Hi'] 
    zkc = karate_club_graph()#获取俱乐部关系图,2分类['Officer','Mr.Hi']对应[0,1]
    colors=[]#根据类别上色:红色节点是'Mr.Hi' 蓝色节点是'Officer'
    all_labels=[]
    for i in range(34):
        print("节点%d:"%i,zkc.nodes[i])
        if zkc.nodes[i]['club'] == "Officer":
            colors.append('b')
            all_labels.append("0")
        else:
            colors.append('r')
            all_labels.append("1")
    print("\n一共%d个节点的类别:"%(len(all_labels)),all_labels)
    print("\n节点的连接关系,一共%d条边:"%len(zkc.edges),zkc.edges)  
    
    '''
    求邻接矩阵A和度矩阵D,提前设置(先验知识)
    '''
    order = sorted(list(zkc.nodes()))
    A = to_numpy_matrix(zkc, nodelist=order)
    print("\n\nA:",A.shape,'\n',A)
    I = np.eye(zkc.number_of_nodes())
    A_hat = A + I
    D_hat = np.array(np.sum(A_hat, axis=0))[0]
    D_hat = np.matrix(np.diag(D_hat))
    print("D_hat:",D_hat.shape)
    
    class GCNLayer(nn.Module):
        """
        Define the GCNLayer module.
        nn.Linear相当于乘上W_1\W_2
        """
        def __init__(self, in_feats, out_feats):
            super(GCNLayer, self).__init__()
            self.linear = nn.Linear(in_feats, out_feats)#全连接层(in_feats输入二维张量大小, out_feats输出张量)
    
        def forward(self, g, inputs):
            #print("inputs:",inputs.dtype,inputs.shape)
            #print((D_hat**-1*A_hat).dtype,t.Tensor(D_hat**-1*A_hat).shape)#float64 torch.Size([34, 34])
            h = t.mm(t.Tensor(D_hat**-1*A_hat),inputs)
            #print(self.linear(h).shape)
            return self.linear(h)
    
    class GCN(nn.Module):
        """
        Define a 2-layer GCN model.
        in_feats: 34
        hidden_size: 4
        num_classes: 2
        """
        def __init__(self, in_feats, hidden_size, num_classes):
            super(GCN, self).__init__()
            self.gcn1 = GCNLayer(in_feats, hidden_size)
            self.gcn2 = GCNLayer(hidden_size, num_classes)
    
        def forward(self, g, inputs):
            h = self.gcn1(g, inputs)
            h = t.relu(h)
            h = self.gcn2(g, h)      
            return h
    
    def plot_graph(fig,outputs,epoch):
        '''
        画节点图(动图)
        '''
        outputs=t.detach(outputs).numpy()
        all_nodes = {
            node: np.array(outputs)[node] 
            for node in zkc.nodes()}
        #print("\n\nfeature_representations:",type(all_nodes),'\n',all_nodes,'\n')
        #drawing.nx_pylab.draw(zkc,feature_representations,cmap='vislid',vmin=0,vmax=32)#vmin,vmax 
        ax = fig.add_subplot(1,1,1)
        plt.title("karate_club_graph epoch=%d"%epoch,fontsize=18)
        
        nx.draw(zkc,all_nodes,with_labels=True,font_color="w",node_size=350,node_shape="o",node_color=colors,alpha=0.8)
        plt.legend(["red_node is 'Mr.Hi' and blue_node is 'Officer'","edge"],loc='lower left',frameon=False,fontsize=15)
        plt.pause(0.1)
        ax.remove()
        
        
    def main():
        inputs = t.eye(34)#对角矩阵
        '''选取4个节点做loss计算'''
        labels = t.tensor([1,1,0,0])#0表示officer类,1表示Mr.Hi类
        labeled_nodes = t.tensor([0, 8 , 9, 33])#2个类别对应的索引
        
        t.manual_seed(0)#固定初始化参数
        net=GCN(34,4,2)
        print("\nGCN结构:\n",net)
        optimizer = t.optim.Adam(net.parameters(), lr=0.005)
        all_logits = []
        
        fig = plt.figure(figsize=[10,8])    
        plt.ion()
        
        for epoch in range(50):
            outputs = net(zkc, inputs)#模型输出        
            plot_graph(fig,outputs,epoch)        
            all_logits.append(outputs.detach())
            #print("outputs.shape:",outputs.shape,outputs)
            logp = F.log_softmax(outputs, 1)#dim=1,对每一行进行softmax,当dim=0为按列
            #print("after_log_softmax:",logp)
            
            preds=t.argmax(F.softmax(outputs, 1),dim=1)
            correct_nodes=t.eq(preds,t.Tensor(all_labels)).float().sum().item()
            precision = correct_nodes/len(preds)
            #print(preds,correct_nodes)
            
            # compute loss for labeled nodes
            #print('\n',logp[labeled_nodes])
            loss = F.nll_loss(logp[labeled_nodes], labels)
            
            # compute gradient and do Adam step
            '''
            梯度归零 optimizer.zero_grad()
            反向传播计算得到每个参数的梯度值 loss.backward()
            通过梯度下降执行一步参数更新 optimizer.step()
            '''
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            
            print('\nEpoch %d | Loss: %.4f' % (epoch, loss.item()))        
            print('>>Fault: %d | Correct: %d | Precision: %f' % (len(preds)-correct_nodes,correct_nodes, precision))
        
        plt.ioff()
        #plt.close()
    
    
    if __name__ == "__main__":
        main()
    
    

    代码输出

    runfile('E:/DL/GCN/GCN_study/py/Karate_club_network.py', wdir='E:/DL/GCN/GCN_study/py')
    节点0: {'club': 'Mr. Hi'}
    节点1: {'club': 'Mr. Hi'}
    节点2: {'club': 'Mr. Hi'}
    节点3: {'club': 'Mr. Hi'}
    节点4: {'club': 'Mr. Hi'}
    节点5: {'club': 'Mr. Hi'}
    节点6: {'club': 'Mr. Hi'}
    节点7: {'club': 'Mr. Hi'}
    节点8: {'club': 'Mr. Hi'}
    节点9: {'club': 'Officer'}
    节点10: {'club': 'Mr. Hi'}
    节点11: {'club': 'Mr. Hi'}
    节点12: {'club': 'Mr. Hi'}
    节点13: {'club': 'Mr. Hi'}
    节点14: {'club': 'Officer'}
    节点15: {'club': 'Officer'}
    节点16: {'club': 'Mr. Hi'}
    节点17: {'club': 'Mr. Hi'}
    节点18: {'club': 'Officer'}
    节点19: {'club': 'Mr. Hi'}
    节点20: {'club': 'Officer'}
    节点21: {'club': 'Mr. Hi'}
    节点22: {'club': 'Officer'}
    节点23: {'club': 'Officer'}
    节点24: {'club': 'Officer'}
    节点25: {'club': 'Officer'}
    节点26: {'club': 'Officer'}
    节点27: {'club': 'Officer'}
    节点28: {'club': 'Officer'}
    节点29: {'club': 'Officer'}
    节点30: {'club': 'Officer'}
    节点31: {'club': 'Officer'}
    节点32: {'club': 'Officer'}
    节点33: {'club': 'Officer'}
    
    一共34个节点的类别: [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    
    节点的连接关系,一共78条边: [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 10), (0, 11), (0, 12), (0, 13), (0, 17), (0, 19), (0, 21), (0, 31), (1, 2), (1, 3), (1, 7), (1, 13), (1, 17), (1, 19), (1, 21), (1, 30), (2, 3), (2, 7), (2, 8), (2, 9), (2, 13), (2, 27), (2, 28), (2, 32), (3, 7), (3, 12), (3, 13), (4, 6), (4, 10), (5, 6), (5, 10), (5, 16), (6, 16), (8, 30), (8, 32), (8, 33), (9, 33), (13, 33), (14, 32), (14, 33), (15, 32), (15, 33), (18, 32), (18, 33), (19, 33), (20, 32), (20, 33), (22, 32), (22, 33), (23, 25), (23, 27), (23, 29), (23, 32), (23, 33), (24, 25), (24, 27), (24, 31), (25, 31), (26, 29), (26, 33), (27, 33), (28, 31), (28, 33), (29, 32), (29, 33), (30, 32), (30, 33), (31, 32), (31, 33), (32, 33)]
    
    A: (34, 34) 
     [[0. 1. 1. ... 1. 0. 0.]
     [1. 0. 1. ... 0. 0. 0.]
     [1. 1. 0. ... 0. 1. 0.]
     ...
     [1. 0. 0. ... 0. 1. 1.]
     [0. 0. 1. ... 1. 0. 1.]
     [0. 0. 0. ... 1. 1. 0.]]
    D_hat: (34, 34)
    
    GCN结构:
     GCN(
      (gcn1): GCNLayer(
        (linear): Linear(in_features=34, out_features=4, bias=True)
      )
      (gcn2): GCNLayer(
        (linear): Linear(in_features=4, out_features=2, bias=True)
      )
    )
    
    Epoch 0 | Loss: 0.6971
    >>Fault: 17 | Correct: 17 | Precision: 0.500000
    
    Epoch 1 | Loss: 0.6959
    >>Fault: 17 | Correct: 17 | Precision: 0.500000
    
    ..................中间省略......................
    
    Epoch 49 | Loss: 0.5492
    >>Fault: 1 | Correct: 33 | Precision: 0.970588
    

    训练过程可视化

    在这里插入图片描述

    参考链接
    【1】PyTorch实现简单的图神经网络
    【2】NetworkX系列教程(2)-graph生成器
    【3】How to do Deep Learning on Graphs with Graph Convolutional Networks
    【4】GRAPH CONVOLUTIONAL NETWORKS

    展开全文
  • logistic回归是一个二分类模型

    万次阅读 2021-03-09 16:54:52
    首先给大家强调一点,这是一个分类模型而不是一个回归模型!下文开始将从不同方面讲解logistic回归的原理,随后分别使用梯度上升算法和随机梯度上升算法将logistic回归算法应用到实例中。 一、logistic回归和线性...

    logistic回归,又叫对数几率回归(从后文中便可此名由来)。首先给大家强调一点,这是一个分类模型而不是一个回归模型!下文开始将从不同方面讲解logistic回归的原理,随后分别使用梯度上升算法和随机梯度上升算法将logistic回归算法应用到实例中。


    一、logistic回归和线性回归的关系

    想必大家也早有疑惑,既然logistic回归名字中都带有“回归”二者,难道和回归模型一点关系都没有!没错,二者是有联系的,下面我们便来谈一谈!

    首先给出线性回归模型: 

    这里写图片描述


    写成向量形式为: 

    这里写图片描述


    同时“广义线性回归”模型为: 

    这里写图片描述


    注意,其中g(~)是单调可微函数。

     

    下面我们便从线性回归的回归模型引出logistic回归的分类模型!!!

    我们知道上诉线性回归模型只能够进行回归学习,但是若要是做分类任务如何做!答案便是在“广义线性回归”模型中:只需找一个单调可微函数将分类任务的真实标记y与线性回归模型的预测值联系起来便可以了!

    logistic回归是处理二分类问题的,所以输出的标记y={0,1},并且线性回归模型产生的预测值z=wx+b是一个实值,所以我们将实值z转化成0/1值便可,这样有一个可选函数便是“单位阶跃函数”: 

    这里写图片描述


    这种如果预测值大于0便判断为正例,小于0则判断为反例,等于0则可任意判断!

     

    但是单位阶跃函数是非连续的函数,我们需要一个连续的函数,“Sigmoid函数”便可以很好的取代单位阶跃函数: 

    这里写图片描述


    sigmoid函数在一定程度上近似单位阶跃函数,同时单调可微,图像如下所示: 

    这里写图片描述

     

    这样我们在原来的线性回归模型外套上sigmoid函数便形成了logistic回归模型的预测函数,可以用于二分类问题: 

    这里写图片描述


    对上式的预测函数做一个变换为: 

    这里写图片描述


    观察上式可得: 若将y视为样本x作为正例的可能性,则1-y便是其反例的可能性。二者的比值便被称为“几率”,反映了x作为正例的相对可能性,这也是logistic回归又被称为对数几率回归的原因!

     

    这里我们也便可以总结一下线性回归模型和logistic回归的关系: 
    logistic回归分类模型的预测函数是在用线性回归模型的预测值的结果去逼近真实标记的对数几率!这样也便实现了上面说的将线性回归的预测值和分类任务的真实标记联系在了一起!


    二、梯度上升算法求解logistic回归模型参数w

    在上一个话题中我们已经得到了logistic回归的预测函数: 

    这里写图片描述

     

    这里写图片描述

     

    这里我们将式子中的y视为类后验概率估计p(y=1|x),则上式可以重写为: 

    这里写图片描述


    求解上式有: 

    这里写图片描述

     

    这里写图片描述

     

    先给出求解参数w的思路,下面我们便按照这个思路进行求解参数w: 
    1、为求解参数w,我们需要定义一个准则函数 J(w),利用准则函数求解参数w 
    2、我们通过最大似然估计法定义准则函数J(w) 
    3、接下来通过最大化准则函数J(w)便可求出参数w的迭代表达式 
    4、为了更好地使用数据求出参数w,我们将第三步得到的w的迭代时向量化。自此便完成了对于参数w的推导过程,接下来便可以进行实例应用了!

    步骤一、求解准则函数J(w)

    合并(3)(4)两个式子可得: 

    这里写图片描述


    在(5)式中y={0,1},是个二分类问题,所以y只是取两个值0或是1。 
    根据(5)式可得似然函数为: 

    这里写图片描述


    对(6)式取对数有: 

    这里写图片描述


    因此定义准则函数为: 

    这里写图片描述


    最终我们的目标便是最大化似然函数,也就是最大化准则函数: 

    这里写图片描述

     


    步骤二、梯度上升算法求解参数w

    这里我们使用梯度上升算法求解参数w,因此参数w的迭代式为: 

    这里写图片描述


    其中α是正的比例因子,用于设定步长的“学习率” 
    其中对准则函数J(w)进行微分可得: 

    这里写图片描述


    所以得到最终参数w的迭代式为: 

    这里写图片描述


    上式将(1/m)去掉不影响结果,等价于下式: 

    这里写图片描述

     

    至此我们已经得出了w的迭代公式,按说是可以在引入数据的情况下进行w的计算,进而进行分类!但是数据基本都是以矩阵和向量的形式引入的,所以我们需要对上面w的迭代时进行向量化,以方便实例应用中的使用。


    步骤三、w迭代公式向量化

    首先对于引入的数据集x来说,均是以矩阵的形式引入的,如下: 

    这里写图片描述


    其中m数据的个数,n是数据的维度,也就是数据特征的数量!

     

    再者便是标签y也是以向量的形式引入的: 

    这里写图片描述


    参数w向量化为: 

    这里写图片描述


    在这里定义M=x*w,所以: 

    这里写图片描述

     

    定义上面说的sigmoid函数为: 

    这里写图片描述


    所以定义估计的误差损失为: 

    这里写图片描述


    在此基础上,可以得到步骤二中得到的参数迭代时向量化的式子为: 

    这里写图片描述

     

    至此我们便完成了参数w迭代公式的推导,下面便可以在实例中应用此迭代公式进行实际的分析了!下面我们便以简单的二分类问题为例来分析logistic回归算法的使用!!


    三、logistic回归算法的实例应用(pyhton)

    此实例便是在二维空间中给出了两类数据点,现在需要找出两类数据的分类函数,并且对于训练出的新的模型,如果输入新的数据可以判断出该数据属于二维空间中两类数据中的哪一类!

    在给出Python实现的示例代码展示之前,先介绍一下两种优化准则函数的方法: 
    1、梯度上升算法 
    2、随机梯度上升算法

    梯度上升算法: 
    梯度上升算法和我们平时用的梯度下降算法思想类似,梯度上升算法基于的思想是:要找到某个函数的最大值,最好的方法是沿着这个函数的梯度方向探寻!直到达到停止条件为止! 
    梯度上升算法的伪代码: 

    这里写图片描述

     

    随机梯度上升算法: 
    梯度上升算法在每次更新回归系数时都需要遍历整个数据集,该方法在处理小数据时还尚可,但如果有数十亿样本和成千上万的特征,那么该方法的计算复杂度太高了,改进方法便是一次仅用一个数据点来更新回归系数,此方法便称为随机梯度上升算法!由于可以在更新样本到来时对分类器进行增量式更新,因而随机梯度上升算法是一个“在线学习算法”。而梯度上升算法便是“批处理算法”!

    改进的随机梯度上升算法: 
    随机梯度上升算法虽然大大减少了计算复杂度,但是同时正确率也下降了!所以可以对随机梯度上升算法进行改进!改进分为两个方面: 
    改进一、对于学习率alpha采用非线性下降的方式使得每次都不一样 
    改进二:每次使用一个数据,但是每次随机的选取数据,选过的不在进行选择

    在知道这些信息之后下面给出示例代码,其中有详细的注释:

    #!/usr/bin/env python3
    
    # -*- coding: utf-8 -*-
    
    
    from numpy import *
    
    import matplotlib.pyplot as plt
    
    
    #从文件中加载数据:特征X,标签label
    
    def loadDataSet():
    
    dataMatrix=[]
    
    dataLabel=[]
    
    #这里给出了python 中读取文件的简便方式
    
    f=open('testSet.txt')
    
    for line in f.readlines():
    
    #print(line)
    
    lineList=line.strip().split()
    
    dataMatrix.append([1,float(lineList[0]),float(lineList[1])])
    
    dataLabel.append(int(lineList[2]))
    
    #for i in range(len(dataMatrix)):
    
    # print(dataMatrix[i])
    
    #print(dataLabel)
    
    #print(mat(dataLabel).transpose())
    
    matLabel=mat(dataLabel).transpose()
    
    return dataMatrix,matLabel
    
    
    #logistic回归使用了sigmoid函数
    
    def sigmoid(inX):
    
    return 1/(1+exp(-inX))
    
    
    #函数中涉及如何将list转化成矩阵的操作:mat()
    
    #同时还含有矩阵的转置操作:transpose()
    
    #还有list和array的shape函数
    
    #在处理矩阵乘法时,要注意的便是维数是否对应
    
    
    #graAscent函数实现了梯度上升法,隐含了复杂的数学推理
    
    #梯度上升算法,每次参数迭代时都需要遍历整个数据集
    
    def graAscent(dataMatrix,matLabel):
    
    m,n=shape(dataMatrix)
    
    matMatrix=mat(dataMatrix)
    
    
    w=ones((n,1))
    
    alpha=0.001
    
    num=500
    
    for i in range(num):
    
    error=sigmoid(matMatrix*w)-matLabel
    
    w=w-alpha*matMatrix.transpose()*error
    
    return w
    
    
    
    #随机梯度上升算法的实现,对于数据量较多的情况下计算量小,但分类效果差
    
    #每次参数迭代时通过一个数据进行运算
    
    def stocGraAscent(dataMatrix,matLabel):
    
    m,n=shape(dataMatrix)
    
    matMatrix=mat(dataMatrix)
    
    
    w=ones((n,1))
    
    alpha=0.001
    
    num=20 #这里的这个迭代次数对于分类效果影响很大,很小时分类效果很差
    
    for i in range(num):
    
    for j in range(m):
    
    error=sigmoid(matMatrix[j]*w)-matLabel[j]
    
    w=w-alpha*matMatrix[j].transpose()*error
    
    return w
    
    
    #改进后的随机梯度上升算法
    
    #从两个方面对随机梯度上升算法进行了改进,正确率确实提高了很多
    
    #改进一:对于学习率alpha采用非线性下降的方式使得每次都不一样
    
    #改进二:每次使用一个数据,但是每次随机的选取数据,选过的不在进行选择
    
    def stocGraAscent1(dataMatrix,matLabel):
    
    m,n=shape(dataMatrix)
    
    matMatrix=mat(dataMatrix)
    
    
    w=ones((n,1))
    
    num=200 #这里的这个迭代次数对于分类效果影响很大,很小时分类效果很差
    
    setIndex=set([])
    
    for i in range(num):
    
    for j in range(m):
    
    alpha=4/(1+i+j)+0.01
    
    
    dataIndex=random.randint(0,100)
    
    while dataIndex in setIndex:
    
    setIndex.add(dataIndex)
    
    dataIndex=random.randint(0,100)
    
    error=sigmoid(matMatrix[dataIndex]*w)-matLabel[dataIndex]
    
    w=w-alpha*matMatrix[dataIndex].transpose()*error
    
    return w
    
    
    #绘制图像
    
    def draw(weight):
    
    x0List=[];y0List=[];
    
    x1List=[];y1List=[];
    
    f=open('testSet.txt','r')
    
    for line in f.readlines():
    
    lineList=line.strip().split()
    
    if lineList[2]=='0':
    
    x0List.append(float(lineList[0]))
    
    y0List.append(float(lineList[1]))
    
    else:
    
    x1List.append(float(lineList[0]))
    
    y1List.append(float(lineList[1]))
    
    
    fig=plt.figure()
    
    ax=fig.add_subplot(111)
    
    ax.scatter(x0List,y0List,s=10,c='red')
    
    ax.scatter(x1List,y1List,s=10,c='green')
    
    
    xList=[];yList=[]
    
    x=arange(-3,3,0.1)
    
    for i in arange(len(x)):
    
    xList.append(x[i])
    
    
    y=(-weight[0]-weight[1]*x)/weight[2]
    
    for j in arange(y.shape[1]):
    
    yList.append(y[0,j])
    
    
    ax.plot(xList,yList)
    
    plt.xlabel('x1');plt.ylabel('x2')
    
    plt.show()
    
    
    
    if __name__ == '__main__':
    
    dataMatrix,matLabel=loadDataSet()
    
    #weight=graAscent(dataMatrix,matLabel)
    
    weight=stocGraAscent1(dataMatrix,matLabel)
    
    print(weight)
    
    draw(weight)

    上面程序运行结果为: 
    这里写图片描述

    其中: 
    图(1)是使用梯度上升算法的结果,运算复杂度高; 
    图(2)是使用随机梯度上升算法,分类效果略差吗,运算复杂度低; 
    图(3)是使用改进后的随机梯度上升算法,分类效果好,运算复杂度低。

    上述程序数据连接,提取密码为:1l1s

    文中如有何问题,欢迎指正,谢谢!!!

    参考文献:

    https://blog.csdn.net/feilong_csdn/article/details/64128443

    展开全文
  • 、平均准确率 针对不平衡数据,对n个类,分别计算每个类别的准确率,然后求平均值。 metrics.average_precision_score(y_true=y_true, y_score=y_pred) 三、基于相似度的评价指标 3.1 log-loss...
  • 二分类和多分类交叉熵函数区别详解 写在前面 查了下百度,交叉熵,是度量两个分布间差异的概念。而在我们神经网络中,两个分布也就是y的真实值分布和预测值分布。当两个分布越接近时,其交叉熵值也就越小。 根据上面...
  • 目录:手动实现前馈神经网络、Dropout、正则化、K折交叉验证,解决多分类、二分类、回归任务一、实验内容手动实现前馈神经网络完成回归、二分类、多分类任务利用torch.nn实现前馈神经网络完成回归、二分类、多分类...
  • 转自个人微信公众号【Memo_Cleon】的统计学习笔记两个概念:RR和OR二分类资料的logistic回归SPSS操作示例几个需要注意的问题:样本量、哑变量、模型拟合效果和拟合优度检验、多重共线【1】两个概念RR(Relative Risk)...
  • 常用的二分类损失函数

    千次阅读 2021-12-16 10:11:38
  • [n,1]范围为[0,1] # 将概率转化为预测的类别 def binary(self, y): y = y > 0.5 return y.astype(int) # 二分类sigmoid函数 def sigmoid(self, x): return 1/(1 + np.exp(-x)) # 二分类交叉熵损失 def cross_entropy...
  • python绘制散点图:二分类样本

    千次阅读 2021-01-28 20:09:08
    在做机器学习数据集的探索时,需要绘制变量的散点图,散点图要能够区分正负样本。 如何用python绘制散点图呢?思路其实不复杂: 1.绘制正样本,使用“+”图标 2.在同一张图上绘制负样本,使用“o”图标 3.展示正负...
  • 原理SVM被提出于1964年,在十世纪90年代后得到快速发展并衍生出一系列改进和扩展算法,在人像识别、文本分类等模式识别(pattern recognition)问题中有得到应用。支持向量机(Support Vector Machine, SVM)是一类按...
  • ML之CatboostC:基于titanic泰坦尼克数据集利用catboost算法实现二分类 目录 基于titanic泰坦尼克数据集利用catboost算法实现二分类 设计思路 输出结果 核心代码 相关内容:ML之CatBoost:Cat...
  • 多分类损失函数 sparse_categorical_crossentropy 与 categorical_crossentropy区别 二分类 binary_crossentropy交叉熵损失函数
  • 本次我们选择鸢花数据(iris)进行方法的尝试训练,该数据集一共包含5个变量,其中4个特征变量,1个目标分类变量。共有150个样本,目标变量为 花的类别 其都属于鸢尾属下的三个亚属,分别是山鸢尾 (Iris-setosa),...
  • 二分类的激活函数通常选择sigmoid或者softmax函数,对于二分类的问题,sigmoid函数和softmax函数可以等价 首先记隐层的输出为h。 如果使用sigmoid的话,输出层有一个结点,值为θh\theta hθh。然后类别1,2的预测...
  • 要在高维数据集(即包含许多预测变量的数据集)上训练用于二分类的线性支持向量机模型,可以改用fitclinear。 fitclinear训练线性分类模型,用于高维、全或稀疏预测数据的二类(binary)学习。现有的线性分类模型...
  • 这里针对类图像语义分割任务,常用损失函数有:[1] - softmax 交叉熵损失函数(softmax loss,softmax with cross entroy loss)[2] - dice loss(dice coefficient loss)[3] - 值交叉熵损失函数(bce loss,binary ...
  • plt.show() 补充: 如上sigmoid代表二分类,如果需要多分类需要其他参数 如上代表356行5列训练集 需要适当调整好自己的参数 运行截图: 代表1000代时正确率已经很高了 接近于1 如下为预测集最后的概率预测结果
  • 功能就是对该数据进行二分类。 为了学习的更深入,笔者将svm常用的四种核,linear,inter,sigmoid,rbf作了对比。 详细步骤见代码 二、代码 import numpy as np from cv2 import cv2 from sklearn import datasets ...
  • · 代码目的:利用手写、sklearn两种感知机模型,对鸢尾花数据集进行二分类 作者:CSDN 征途黯然.    一、鸢尾花(iris)数据集   Iris 鸢尾花数据集是一个经典数据集,在统计学习和机器学习领域都经常被用作示例...
  • tf.math.multiply((1-y), tf.math.log(1-p)) # 第一种在实际训练中存在边界的问题,实际tensorflow中交叉熵的源码是进行了公式推导后实现的,避免了边界问题,所以第种方法可以直接基于原有api进行改写 ones = tf....
  • BCELoss(二分类交叉熵损失)

    千次阅读 2021-03-10 09:28:21
    BCELoss(二分类交叉熵损失)BCELoss(二分类交叉熵损失)BCELoss(二分类交叉熵损失) def clip_by_tensor(t,t_min,t_max): t=t.float() result = (t >= t_min).float() * t + (t ).float() * t_min result = ...
  • 首先,你的数据不管是库自带的如: from sklearn.datasets import load_breast_cancer X = data.data Y = data.target 还是自备的如: # 读取csv数据 data = pd.read_csv("MyData.csv") ...对于二分类 直接用 Y
  • 最近在尝试用CrossEntropyLoss(),实现猫狗图像分类的功能。遇到了一个奇怪的问题:loss一直停留在0.69附近,我查了查loss函数的公式,公式如下:
  • 基于DEAP情感数据集的卷积神经网络实现对期待值的二分类** DEAP情感数据集介绍: 被试:32名字(16名男性和16名女性); EGG电极:10-20国际标准的32导联电极帽; 采样率:512Hz; 在观看完1分钟的刺激视频后,被试...
  • MATLAB实现SVM二分类 SVM是名噪一时的机器学习方法,自20世纪末 以来在模式识别领域风生水起,至今仍然活跃在各大论文期刊中。无论是和其他特征提取方法的结合,还是和其他模式识别方法的对比,SVM的表现都可圈可点...
  • 文章目录基于鸢尾花(iris)数据集在二分类上进行训练和预测1、了解数据集概况2、数据可视化和特征分析3、划分数据集4、模型训练5、分录指标评价计算6、利用混淆矩阵对于结果进行可视化7、总结 关于比赛最新进展&...
  • 解决方法 修改nn.CrossEntropyLoss()为nn.BCELoss() ...pytorch 中二分类任务交叉熵要用二分类交叉熵(Binary Cross Entropy),BCELoss()或是BCEWithLogitsLoss(),而CrossEntropyLoss是用来解决多分类问题的
  • AdaBoost二分类

    千次阅读 2021-10-24 17:48:30
    AdaBoost二分类 AdaBoost算法是一个加性模型 F(x)=∑m=1Mαmfm(x)(1) F(x)=\sum_{m=1}^{M}\alpha_mf_m(x)\tag{1} F(x)=m=1∑M​αm​fm​(x)(1) 其中fm(x)f_m(x)fm​(x)称为弱分类器或基分类器,αm\alpha_mαm​为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,131,914
精华内容 452,765
关键字:

二分类