TowardsDataScience 博客中文翻译 2020(二百零七)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

等级不平衡,SMOTE,临界 SMOTE,ADASYN

原文:https://towardsdatascience.com/class-imbalance-smote-borderline-smote-adasyn-6e36c78d804?source=collection_archive---------15-----------------------

类别不平衡会使我们的算法失去平衡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图像来源

那是在 20 世纪 90 年代末,当时南佛罗里达大学的一名研究生 Niesh V . Chawla(SMOTE 背后的主脑)正在研究一个二元分类问题。他正在处理乳房 x 光摄影图像,他的任务是建立一个分类器,该分类器将像素作为输入,并将它分类为正常像素或癌变像素。当他达到 97%的分类准确率时,他相当高兴。当他看到 97.6%的像素正常时,他的快乐是短暂的。

你可能在想,这有什么问题?有两个问题

  • 假设在一个 100 个像素的样本中,98 个是正常的,2 个是癌性的,如果我们写一个程序,它可以预测任何正常的东西。分类准确率会是多少?高达 98%。程序学会了吗?一点也不。
  • 还有另一个问题。分类器努力在训练数据中获得良好的性能,并且随着正常观察值越来越多,它们将更加专注于学习“正常”类的模式。这就像任何学生知道 98%的问题来自代数,2%来自三角学时会做的一样。他们会安全地忽略三角测量

那么,为什么这个问题会表现出来呢?这是因为上课的频率和次数之间有很大的差异。我们称这样的数据集为展示类不平衡。正常阶层被称为多数阶层,罕见阶层被称为少数阶层。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作为少数派的海鸥(https://unsplash.com/photos/SQBtDa6cKDA)

现实应用中存在这种情况吗?以垃圾邮件检测、假新闻检测、欺诈检测、可疑活动检测、入侵检测等为例,其中表现出了类别不平衡问题。

实现某种平衡的解决方案:

基本的方法被称为重采样技术。有两种基本方法。

欠采样:-

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

欠采样或欠采样多数类(图像源作者)

我们从多数类中随机选取样本,并使其等于少数类计数。这被称为欠采样或多数类的下采样。

问题:忽略或放弃这么多原始数据并不是一个好主意。

过采样:-

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对少数类进行过采样或上采样(图片来源作者)

这里,替换抽样应用于少数类,以创建与多数类一样多的观察值,并且这两个类是平衡的。这被称为过采样或少数类上采样。

问题:相同少数类数据的重复导致过度拟合。

重击:

SMOTE 的完整形式,综合技术。这里的综合观察是从少数类中产生的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

SMOTE,合成少数观察生成过程(来源:作者)

假设有来自少数类的两个观察值(x1,y1)和(x2,y2)。作为第一步,创建一个介于 0 和 1 之间的随机数,我们称之为 r。合成点将是(x1 + r*(x2 -x1),y1 + r*(y2 -y1))。下面的例子进一步说明了这一点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从少数类生成的合成点(图片来源:作者)

【SMOTE 的一个问题:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

左侧:原始数据右侧:应用 SMOTE 后的数据(图片来源:作者)

如果少数类中的观察值是外围的并且出现在多数类中,则通过创建与多数类的线桥,会给 SMOTE 带来问题。

临界击打:-

这解决了上述问题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

边界线 SMOTE:(图片来源作者)

该算法首先对少数类观测值进行分类。如果所有邻居都是多数类,则它会将任何少数观察分类为噪声点,并且在创建合成数据时会忽略此类观察(类似于 DBSCAN)。此外,它将几个点分类为具有多数和少数类作为邻域的边界点,并完全从这些点重新采样(支持向量通常会关注的极端观察)。

问题:结束对这些极端观察的更多关注。

阿达辛:

ADASYN 是一个更通用的框架,对于每个少数观察值,它首先通过取邻域中多数观察值与 k 的比值来找到邻域的杂质。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

阿达辛杂质比率

现在,首先,通过使总和为 1,将该杂质比转换成概率分布。那么该比率越高,为该特定点生成的合成点就越多。因此,为 Obs 3 创建的合成观测数据的数量将是 Obs 2 的两倍。因此,它不像边界平滑那样极端,噪声点、边界点和常规少数点之间的边界要柔和得多。(不是硬性边界)。因此得名自适应。

这个在下面的视频教程里也有讲解,请给它一个

尾注:

阶层失衡是一个非常现实的问题。基于重采样的方法没有前途,这促使研究人员开发 SMOTE,并通过 borderline SMOTE、ADASYN 等逐渐改进。要了解更多的变体,参考文献 2 是一个很好的读物。

参考

[1]舒拉 NV,鲍耶 KW,霍尔 LO,凯格尔迈耶 WP。SMOTE:合成少数过采样技术。人工智能研究杂志。2002 年 6 月 1 日;16:321–57.

[2]费尔南德斯 A、加西亚 S、埃雷拉 F、舒拉 NV。SMOTE 从不平衡数据中学习:进步与挑战,15 周年纪念。人工智能研究杂志。2018 年 4 月 20 日;61:863–905.

Python 中的类实例

原文:https://towardsdatascience.com/class-instances-in-python-d89ebf545ba4?source=collection_archive---------38-----------------------

类实例的字符串表示

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源

自定义类实例的表示方式是简化调试和实例输出的好方法。在这篇文章中,我们将讨论如何通过定义“repr”和“str”方法来改变实例的字符串表示。

我们开始吧!

首先,让我们定义一个描述 YouTube 频道的类。该类将包含特定于 Youtube 频道的属性(数据),如频道名称、订户和验证状态:

class YouTube:
    def __init__(self, channel_name, subscribers, verification):
        self.channel_name = channel_name
        self.subscribers = subscribers
        self.verification = verification

让我们创建一个 YouTube 类的实例。提醒一下,实例是一个类对象的具体实例。对于我们的实例,让我们设置对应于我最喜欢的 YouTube 频道之一的属性,:

*sentdex = YouTube('Sentdex', 847000, True)*

现在我们已经创建了实例,让我们打印出实例:

*print(sentdex)*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们看到在指定的内存地址中有一个类型为“YouTube”的对象。虽然这符合我们的预期,但它并不是我们的实例可读性最好的表示。如果我们想改变这个对象的表示方式,我们可以定义’ repr ‘和’ str ‘方法。首先,让我们定义’ repr '方法:

*class YouTube:
    def __init__(self, channel_name, subscribers, verification):
        self.channel_name = channel_name
        self.subscribers = subscribers
        self.verification = verification

    def __repr__(self):
        return 'YouTube({0.channel_name!r}, {0.subscribers!r}, {0.verification!r})'.format(self)*

让我们重新定义我们的对象’ sentdex ',并打印结果:

*sentdex = YouTube('Sentdex', 847000, True)
print(sentdex)*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们看到’ repr '方法返回了我们实例的代码表示。它只是对应于我们为创建实例而键入的代码。

现在,让我们定义’ str '方法:

*class YouTube:
    def __init__(self, channel_name, subscribers, verification):
        self.channel_name = channel_name
        self.subscribers = subscribers
        self.verification = verification

    def __repr__(self):
        return 'YouTube({0.channel_name!r}, {0.subscribers!r}, {0.verification!r})'.format(self) def __str__(self):
        return '({0.channel_name!s}, {0.subscribers!s}, {0.verification!s})'.format(self)*

让我们再次定义我们的实例并打印结果:

*sentdex = YouTube('Sentdex', 847000, True)
print(sentdex)*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们看到我们现在有了实例的字符串表示。如果我们想要打印出代码表示,使用我们当前的类实现,我们可以使用内置的“repr()”方法:

*sentdex = YouTube('Sentdex', 847000, True)
print(repr(sentdex))*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我还想指出’ repr()‘和’ str()'在文本格式上的区别。特别的!“r”格式代码指示应使用“repr()”的输出,而不是默认的“str()”。例如,如果我们包括!我们字符串中的“r ”:

*sentdex = YouTube('Sentdex', 847000, True)
print('sentdex is {0!r}'.format(sentdex))*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们得到了代码表示。如果我们省略掉!r '代码,字符串表示用作默认值:

*sentdex = YouTube('Sentdex', 847000, True)
print('sentdex is {0}'.format(sentdex))*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

定义“repr()”和“str()”方法通常是很好的做法,因为它可以使类实例更容易解释和调试。例如,记录实例的自定义字符串表示可以为程序员提供更多关于实例内容的有用信息。我就讲到这里,但是我鼓励你自己去研究代码。如果你有兴趣学习更多与 python 中的类定义相关的编程模式,我鼓励你去看看 Python 食谱

结论

总之,在这篇文章中,我们讨论了类实例的字符串表示。我们展示了如何定义“repr()”和“str()”方法,这允许我们显示实例的代码表示和字符串表示。这种做法可以使类实例的内容透明,如果做得好,可以大大简化调试。我希望你觉得这篇文章有用/有趣。这篇文章中的代码可以在 GitHub 上找到。感谢您的阅读!

Python 中的类

原文:https://towardsdatascience.com/classes-in-python-e31c21120c3d?source=collection_archive---------17-----------------------

理解面向对象编程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源

类允许我们以某种方式组织数据和函数,使它们在将来易于重用和扩展。在这篇文章中,我们将讨论用 python 构建类的基础。

我们开始吧!

首先,让我们创建一个表示 Spotify 用户的简单类,没有数据(也称为属性)或函数(也称为方法):

class Spotify_User:
    pass

现在,让我们花些时间来区分类和类的实例。类基本上是创建实例的蓝图。我们创建的每个唯一用户都将是 Spotify_User 类的一个实例。例如,我可以定义两个 Spotify 用户实例,user_1 和 user_2:

user_1 = Spotify_User()
user_2 = Spotify_User()

这些用户中的每一个都将是他们自己的 Spotify_User 类的唯一实例。我们可以打印这两个对象:

print(user_1)
print(user_2)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们看到这两个都是内存地址不同的 Spotify_User 对象。我们可以做的另一件事是创建实例变量,这些变量对于每个实例都是唯一的。让我们定义保存每个用户姓名的实例变量:

user_1.name = 'Sarah Phillips'
user_2.name = 'Todd Grant'

让我们给每个实例发一封电子邮件:

user_1.email = 'sphillips@gmail.com'
user_2.email = 'tgrant@gmail.com'

最后,让我们定义实例变量,告诉我们每个用户是否是 Spotify 的高级会员:

user_1.premium = True
user_2.premium = False

现在,这些实例中的每一个都具有每个实例独有的属性。让我们打印每个用户的姓名:

print(user_1.name)
print(user_2.name)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

理想情况下,我们希望为每个用户自动设置所有这些信息,而不是手动设置这些值。为了获得类的全部好处,我们应该定义一个方法,允许我们用手动定义的值初始化每个用户实例。初始化方法基本上是一个构造函数,将被称为“init ”:

class Spotify_User:
    def __init__(self, name, email, premium):
        self.name = name
        self.email = email
        self.premium = premium

这里,“self”参数是实例,它允许我们在实例中共享属性信息。例如,当我们写下:

user_1 = Spotify_User('Sarah Phillips', 'sphillips@gmail.com', True)
user_2 = Spotify_User('Todd Grant', 'tgrant@gmail.com', False)

每种情况下的“self”参数分别是 user_1 和 user_2 对象。如果我们打印电子邮件,我们会看到:

print(user_1.email)
print(user_2.email)

这允许我们用比手工定义属性少得多的代码来定义属性。现在假设我们想要对每个用户的属性执行一些操作。例如,我们可以定义一个方法来告诉我们用户是否拥有高级会员资格。在我们的方法中,如果“self.premium”为真,我们打印“用户是 Spotify 高级用户”,否则,我们打印“用户不是 Spotify 高级用户”:

def isPremium(self):
        if self.premium:
            print("{} is a Premium User".format(self.name))
        else:
            print("{} is not a Premium User".format(self.name))

让我们使用 user_1 实例调用该方法:

user_1.isPremium()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

并且在用户 2 上:

user_2.isPremium()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如您所见,由于“self”参数被传递给“init”和“isPremium”,因此在初始化时,“isPremium”方法可以完全访问相应实例的属性。

我将在这里停下来,但是您可以随意摆弄代码。例如,您可以尝试定义 Spotify_User 类的几个额外的用户实例。在那里,您可以练习提取实例属性并使用类方法“isPremium”。一旦你觉得舒服了,我鼓励你定义额外的类方法。一个有趣的方法是为每个用户显示定制的播放列表。

结论

总之,在这篇文章中,我们讨论了用 python 定义类的基础。我们展示了如何定义类的实例、初始化实例、访问实例属性以及用方法操作属性。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

Python 中的类:数据科学家的基础

原文:https://towardsdatascience.com/classes-in-python-fundamentals-for-data-scientists-fb7deb4fcda1?source=collection_archive---------26-----------------------

用一个具体的例子来理解基础!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Unsplash 上的 Alexandru Acea 拍摄

类通过将数据和函数封装在一个实体中来帮助我们整理代码。此外,它们增加了代码的可重用性和可伸缩性,简化了调试过程。

一旦我们定义了一个类,我们就可以使用这个类的实例来处理特定的任务。在这方面,它们是我们在代码中使用的对象的蓝图。

让我们用一个具体的例子来了解一下基础知识。

定义类别

在我们的例子中,我将使用 Pandas ,这是一个流行的 Python 数据操作库,以及几个包含表格数据的 CSV 文件

在 Python 中,基本类定义具有以下格式:

classClassName():
 # Comments / Notes
 ...
 # Initializer / Instance Attributes
 ...
 # Methods
 ...

首先,让我们创建一个简单的类,帮助我们显示 CSV 文件中包含的表格数据的摘要信息。

*class* CSVGetInfo:
**""" This class displays the summary of the tabular data contained in a CSV file """***def* **__init__**(*self*, *path*, *file_name*):
 self.path = path
 self.file_name = file_name*def* **display_summary**(*self*):
 data = pd.read_csv(self.path + self.file_name)
 print(self.file_name)
 print(data.info())

在 Python 中,一个简单的类定义以下面的符号开始:

*class* ClassName:

在我们的例子中,我们的类名是**“CSV getinfo”**。请注意 Python 中的类名遵循 UpperCaseCamelCase 命名约定。虽然这不是强制性的,但是通常将类存储在一个单独的文件中,并在以后需要时导入它们。

增加一个评论区让其他人知道我们的类是做什么的,这是一个很好的做法。我们可以通过在三重双引号内提供注释来做到这一点。

*class* CSVGetInfo:
**""" This class displays the summary of the tabular data contained in a CSV file """**

初始化实例变量(属性)

在这些最初的步骤之后,现在是时候定义我们的类所涉及的数据了。在我们的例子中,我们需要知道想要读取的 CSV 文件的路径和文件名信息。

所以,我们的类有**‘path’‘file _ name’**变量。它们将为我们的 CSVGetInfo 类的每个实例初始化,它们被称为我们类的实例变量或属性。

**# Initializer / Instance Attributes** 
 *def* __init__(*self*, *path*, *file_name*):
  self.path = path
  self.file_name = file_name

init 方法指出当我们创建类的新实例时必须提供什么数据。

本地变量提供的数据存储在 self.pathself.file_name 中。 在这里, self 代表实例本身。

在创建实例时,变量初始化是一个强制性的过程,这个特殊的 init 方法保证了它总是发生。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Tra TranUnsplash 上拍摄

添加实例函数(方法)

现在,我们可以定义使用这些数据来处理特定任务的函数。类结构中的函数称为方法或实例函数,因为它们与类的每个实例都有联系。我们将在我们的 CSVGetInfo 类结构中定义 “display_summary” 方法,它显示包含在 CSV 文件中的表格数据的摘要信息。

**# M****ethods***def* **display_summary**(*self*):
 data = pd.read_csv(self.path + self.file_name)
 print(self.file_name)
 print(data.info())

注意,我们在方法中再次使用了 self 作为参数。这是访问我们正在处理的实例中包含的数据所需要的。

为了访问 “display_summary” 方法中的实例变量,我们使用 self.path 和 self.file_name 符号。

创建类(对象)的实例

由于类本身是对象的蓝图,我们需要创建类(对象)的实例,以使用类定义中可用的方法来处理任务。

在我们的类中,我们有**“display _ summary”**方法。

因此,让我们创建两个 CSVGetInfo 的实例,并使用**“display _ summary”**方法来查看 CSV 文件中的内容。

为了创建一个类的实例/对象,我们使用类名并将值传递给该类所需的参数。

data_by_artists = CSVGetInfo("/Users/erdemisbilen/Lessons/", "data_by_artists.csv")data_by_genres = CSVGetInfo("/Users/erdemisbilen/Lessons/", "data_by_genres.csv")

现在,变量 data_by_artist 保存了对我们的 CSVGetInfo 类的第一个实例的引用。它是 CSVGetInfo 类的对象/实例,将**“data _ by _ artists . CSV”的值存储在 file_name (实例变量)中。其他变量data _ by _ 流派保存了对我们类的第二个实例的引用,该实例的“data _ by _ 流派. CSV”值存储在文件名**中。尽管它们是用相同的类定义创建的,但是它们在实例变量(属性)中存储了不同的值。

print(data_by_artists)
print(data_by_genres)**#Output**
<__main__.CSVGetInfo instance at 0x10b84f248>
<__main__.CSVGetInfo instance at 0x114eb58c0>

当我们打印实例时,我们可以看到它们存储在内存的不同位置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

彼得·德·卢奇亚在 Unsplash 上的照片

让我们用**【展示 _ 总结】**的方法。

data_by_artists.display_summary()
data_by_genres.display_summary()**#Output
data_by_artists.csv**
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 27606 entries, 0 to 27605
Data columns (total 15 columns):
artists             27606 non-null object
acousticness        27606 non-null float64
danceability        27606 non-null float64
duration_ms         27606 non-null float64
energy              27606 non-null float64
instrumentalness    27606 non-null float64
liveness            27606 non-null float64
loudness            27606 non-null float64
speechiness         27606 non-null float64
tempo               27606 non-null float64
valence             27606 non-null float64
popularity          27606 non-null float64
key                 27606 non-null int64
mode                27606 non-null int64
count               27606 non-null int64
dtypes: float64(11), int64(3), object(1)
memory usage: 3.2+ MB
None**data_by_genres.csv**
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2617 entries, 0 to 2616
Data columns (total 14 columns):
genres              2617 non-null object
acousticness        2617 non-null float64
danceability        2617 non-null float64
duration_ms         2617 non-null float64
energy              2617 non-null float64
instrumentalness    2617 non-null float64
liveness            2617 non-null float64
loudness            2617 non-null float64
speechiness         2617 non-null float64
tempo               2617 non-null float64
valence             2617 non-null float64
popularity          2617 non-null float64
key                 2617 non-null int64
mode                2617 non-null int64
dtypes: float64(11), int64(2), object(1)
memory usage: 286.3+ KB
None

结论

在这篇文章中,我解释了 Python 中类的基础知识。

这篇文章中的代码和使用的 CSV 文件可以在 my GitHub repository 中找到。

我希望这篇文章对你有用。

感谢您的阅读!

经典概率问题#1:折断的棍子、三角形和概率

原文:https://towardsdatascience.com/classic-interview-question-1-broken-sticks-triangles-and-probability-98b0b1974fd8?source=collection_archive---------27-----------------------

数据科学和机器学习面试

以下是概率论中的经典玩具问题,作为数据科学和机器学习角色的精彩技术面试问题。问题如下:

**问题:**你有一根任意长度的棍子。你沿着棍子的长度在两个地方均匀地随机折断它,给你留下三个不同的碎片。你能用产生的三块组成一个三角形的概率是多少?

我们将首先解析地解决这个问题,然后通过计算模拟这个问题来验证我们的发现。

**解决方案:**注意我们的棍子是任意长度的。为了从数学上界定这个问题,让我们选择一个易于管理的长度。假设这根棍子的单位长度为 1。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,我们沿着棍子的长度在两个地方随机均匀地折断它,这样我们就有三段了。注意,因为我们已经将总长度定义为“单位长度 1”,所以只需要两个变量 ab 来完全指定产生的三个片段的长度。第一段长度为 a ,第二段长度为 b ,第三段长度为 1-a-b :

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

请注意,每个片段的长度范围可以从 0 到 1,条件是三个片段的总和为 1。让我们以图形方式将总概率空间映射为 ab 的函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在问题来了,我们的三块拼成三角形了吗?让我们回忆一下所有三角形所要求的几何条件:三角形的每条边都严格小于其他两条边之和。因此,我们可以指定从三个部分形成三角形所需的三个不同的边界条件:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们将上述三个边界条件叠加在我们的概率空间上,以确定 ab 的值,我们可以形成一个三角形:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从上图我们可以看到,边界条件指定了总概率空间的 1/4。因此,我们可以得出结论,这三个碎片有 1/4 的概率形成一个三角形。

现在让我们用 python 通过计算模拟这个问题,以确认我们的解析解:

######################
## import libraries ##
######################
import numpy as np
import pandas as pd
import math
import matplotlib.pyplot as plt## number of iterations 
iterations = 10000
results = pd.DataFrame()
results['iteration'] = list(range(1,iterations+1))
percentage = iterations*[None]np.random.seed(10815657)
count = 0
for i in range(0, iterations):
    random_draws = np.random.uniform(low=0, high=1, size=2)
    a = min(random_draws)
    b = abs(random_draws[0] - random_draws[1])
    if((a<0.5) and (b<0.5) and (0.5 < a+b)):
        count=count+1
    percentage[i] = count / (i+1)results['percentage'] = percentageplt.plot(results['iteration'], results['percentage'], color='blue')
plt.xlabel('Number of trials') 
plt.ylabel('Percentage of simulations where pieces can form a triangle')percentage[iterations-1]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如上所示,经过 10,000 次模拟,结果收敛到三个碎片可以形成三角形的概率为 1/4(即 25%)。

希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在【LinkedIn】上与我联系,并在 Medium 上关注我的更新!

经典概率问题#2:优惠券问题

原文:https://towardsdatascience.com/classic-probability-problem-2-the-coupon-problem-7acd7febaabd?source=collection_archive---------28-----------------------

数据科学和机器学习面试

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

freeimages.com

这是我第二次进入概率论中的经典玩具问题。“息票问题”是一个需要注意的大问题;它出现在许多应用场合。从技术面试的角度来看,通过在最后添加一个小的计算组件,它可以作为对一般概率和编码知识的可靠测试。问题如下:

问题:

有一种品牌的麦片,每买一盒都有一张优惠券。有 5 种不同类型的优惠券。每购买一盒麦片,获得 5 张优惠券中任何一张的概率是一致的。目标是收集所有 5 种独特的优惠券类型。

现在问题来了,你需要购买多少盒麦片才能收集到所有 5 张独特的优惠券?

我们将首先解析地解决这个问题,然后通过计算模拟这个问题来验证我们的发现。

分析解决方案:

让我们从一些观察开始:

  1. 购买的每一盒麦片都独立于最后购买的一盒(或多盒)。
  2. 在给定的盒子中获得 5 种优惠券类型中的任何一种的概率是相同的。

我们需要某种数学方法来界定这个问题。也许我们可以使用一些参数工具?让我们快速绕道,讨论几何随机变量。

几何随机变量:

几何随机变量是具有单参数分布的离散随机变量,具体如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

请注意,我们可以将我们的优惠券收集问题视为五个几何随机变量的期望值之和,每个变量具有不同的成功参数 p :

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意,几何随机变量的期望值是 1/p:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

几何 RV 期望值的证明(可选部分):

对于那些对几何随机变量的期望值的推导感兴趣的人,下面我包括了两个推导(一个直接使用 PMF,另一个使用 MGF)。如果您对这些证明不感兴趣,可以跳过这一部分:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

解决问题:

现在我们简单地将五个指定的随机变量的期望值相加:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因此,四舍五入到最接近的整数,我们需要购买的收集所有 5 个独特优惠券的预期盒数是 12 盒。

计算模拟:

现在让我们用 python 模拟这个场景,计算 10,000 次以上的迭代,以证实我们上面的分析结果:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt## specify number of coupons, and the probability of getting a coupon
num_coupons=5
expected_number_of_trials = 0
for i in range(num_coupons, 0, -1):
    expected_number_of_trials = expected_number_of_trials + (1/(i/num_coupons))iterations = 10000
df = pd.DataFrame()
df['iteration'] = range(1,iterations+1)
df['average_num_trials_required'] = Nonefor i in range(0, iterations):
    full_set = set(range(0,num_coupons))
    current_set = set([])
    total_number_of_coupons_collected = 0
    while(current_set != full_set):
        total_number_of_coupons_collected = total_number_of_coupons_collected+1
        random_coupon = np.asscalar(np.random.randint(low=0, high=num_coupons, size=1))
        update_set = list(current_set)
        update_set.append(random_coupon)
        current_set = set(update_set)
        del random_coupon, update_set

    if(i+1 == 1):
        df.loc[df['iteration']==i+1, 'average_num_trials_required'] = total_number_of_coupons_collected
    else:
        df.loc[df['iteration']==i+1, 'average_num_trials_required'] = float(((df.loc[df['iteration']==i, 'average_num_trials_required']*i) + total_number_of_coupons_collected)/(i+1))print(df['average_num_trials_required'][i])

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如上所示,在该场景的 10,000 次迭代中,收集所有 5 个唯一优惠券所需购买的盒子数量的样本平均值约为 11.431。这个结果与我们上面的解析解一致。

最后的想法——我们为什么要关心这个问题,或者任何其他玩具问题??

正如技术领域中大多数众所周知的玩具问题一样,这个“优惠券问题”和关于谷物和优惠券收集的傻孩子般的场景有一个重要的目的。这个问题(以及它的微小变化)在应用实践中不断出现;关于离散等待时间的期望值的问题,或者在某事发生之前可能需要发生的事件的数量的问题。这些问题通常可以归结为优惠券问题的某种变体。因此,拥有良好的基础知识和关于玩具问题的理论基础知识,比如这里讨论的,对你的应用实践有很大的帮助。

此外,值得一提的是,我们为 5 独特优惠券解决了这个问题。但是我们可以选择任何大于零的任意常数 n 唯一优惠券**。这里使用的方法仍然适用。**

最后,我想留给你一个挥之不去的问题。在我们上面的问题中,假设你已经收集了 4 个独特的优惠券,现在正在收集第 5 个也是最后一个独特的优惠券。张贴您收集的第四张独特优惠券,您已经购买了 50 多盒麦片,但所有都包含更多您已经拥有的 4 张独特优惠券。从那时起,您需要购买多少盒才能获得第五张优惠券?我给你一个提示,几何分布是指数分布的离散对应物,它有一个关于等待时间的独特性质。欢迎在评论中加入你的想法,以及我上面的谜语的可能答案。

希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在 LinkedIn 上与我联系,并在 Medium 上 关注我的更新!

经典分类器组合技术:投票方法、Borda 计数和行为知识空间

原文:https://towardsdatascience.com/classical-classifier-combination-techniques-voting-approaches-borda-counts-and-5b047faaffbc?source=collection_archive---------40-----------------------

在本文中,我们回顾了经典的分类器组合技术,这些技术通常被用作新提出的方法的基准。

在本文的其余部分,我们用ôᵏ( x 表示 kᵗʰ分类器关于测试样本的决策 x ,用 K 表示决策将被组合的小组中分类器的数量。类别标签的总数为 m.

投票方式

一个显而易见的方法是通过投票系统来协调一系列的决定。投票方案的几种变体可以用于分类器融合,并且其中一些可以集成上下文信息,例如单个分类器的准确度。投票原则背后的想法是基于直觉,即小组中分类器(专家)的数量越多,就越有可能做出正确的最终决定。

常见的投票方案如下:

  • 一致投票是这样一种系统,其中如果所有个体分类器决策都是 cᵢ,则组合决策是标签 cᵢ,否则组合分类器拒绝输入 x :

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 修改一致投票是这样一种系统,其中如果所有个体分类器决策是 cᵢ或 cᵣₑ,则组合决策是标签 cᵢ,否则组合分类器拒绝输入**x。**换句话说,没有分类器应该预测不同于 cᵢ的分类标签

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 多数表决是一种系统,其中如果预测 cᵢ的分类器的数量最大,则组合决策是标签 cᵢ

博尔达和 w 博尔达计数

Borda counts 是一种基于等级的组合方案,其中每个分类器根据成为正确(真实)类别的机会对类别(候选)进行分级。每个等级与一个分数相关联,从第一个等级的 m-1 到最后一个等级的 0,其中 m 是等级的总数。第二次,计算每个班级获得的分数的总和,获得最高累积分数的班级标签是小组的最终决定。可能存在平局,即几个类别标签使累积分数最大化,在这种情况下,需要额外的算法步骤来解决平局。基线策略包括随机挑选一个具有最大累积分数的标签。博尔达法是一位名叫让-克洛德·博尔达的法国政治家在寻求真正民主的选举制度时发明的。瑙鲁共和国和斯洛文尼亚共和国目前使用这种方式选举议员。

  • 示例 1:假设有四个候选类别标签ω= {c₁,c₂,c₃,c₄}.对于决策函数为{ 0,0 和 0 }的三个分类器,Borda 计数工作如下:每个分类器ôᵏ对标签进行排序(表 1):
+---------------+------------------+
| Classifiers   | Labels ranking   |
+---------------+------------------+
|       ô¹      |c₂ - c₃ - c₁ - c₄ |
|       ô²      |c₃ - c₁ - c₂ - c₄ |
|       ô³      |c₃ - c₂ - c₁ - c₄ |
+---------------+------------------+
Table 1: Ranks of the four candidates (labels)

然后计算每个标签的累积分数(表 2):

+---------------+------------------+
| Candidate     |      Score       | 
+---------------+------------------+
|      c₁       | 1 + 2 + 1 = 4    |
|      c₂       | 3 + 1 + 2 = 6    |
|      c₃       | 3 + 3 + 2 = 8    |
|      c₄       | 0 + 0 + 0 = 0    |
+---------------+------------------+
Table 2: Candidates and their accumulated points

Borda 计数被认为是最简单的非线性组合算法之一。在某些情况下(主要是当分类器的数量很大时),可以观察到多数人的意见和由 Borda 计数推导出的决定之间的冲突。这个问题是帕克[0]提出来的。在博尔达计数中,

由同一分类器排序的每两个连续候选之间的分数差为 1,使得所有候选等距并且以均匀的方式分布在同一轴上

这种假设并不总是有道理的。

例如,概率分类器可以为两个标签分配非常高的概率,而为第三个标签分配低概率值(例如,对于三类分类问题,后验概率为 49%、48%、3%;显然,当应用 Borda 计数组合方法时,每个候选之间有一个单位差异并不能反映现实情况和分类器的置信度水平)。

帕克主张,对排名进行加权可能会有助于减少偏见。Fishburn [1]认为,来自混淆矩阵的上下文知识可以用来估计这些权重。将这样的权重分配给候选标签被认为是统一 Borda 计数的推广,通常称为 w Borda

  • 示例 2:考虑到 m 类标签,当应用统一性时,等级为 r 的项目将被分配等于 (m-r) 的分数,但是在 w Borda 中,它可以被分配等于 *(m-r)w ᵖ的分数,其中 p =( r-1)w 是权重。下图说明了 Borda 和 wBorda 之间的区别

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

行为知识空间

黄和孙[2,3]提出的行为-知识空间(BKS)方法的优点是不依赖于前提假设,如分类器输出之间的统计独立性。

根据定义,BKS 是一个 K 维空间,其中 k ᵗʰ维与 k ᵗʰ分类器相关。在每个维度 km 上,可以做出对应于ω中所有可能标签的决定。对于每个测试样本 **x,**我们获得一个决策向量[ôᵏ(x]//k:{ 1,…,K} 对应于 BKS 中的一个点。

对于 mᵏ 个可能点中的每个点,我们跟踪映射到该点的训练样本的数量以及它们的类别标签。

BKS 是在训练时建立的,它有个 mᵏ 个节点需要学习。因此,该方法在面板中分类器的数量或类别的数量方面都不能很好地扩展,因为可能有一些配置从未被访问过。为了决定测试样本的类别,输出[ôᵏ(x]//k:{ 1,…,K} 并映射到相应的 BKS 节点。预测标签是在该节点中出现次数最多的标签。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

结论

在本文中,我们看到了三种经典的分类器组合方法:投票系统、Borda 计数和 BKS。这些技术在许多应用中表现出良好的性能。

这篇文章是我第一篇题为“关于量词组合的见解”的文章的延续。这是从我的博士论文中摘录的,你可以在这个链接中找到。

参考

[0]j . r .帕克(2001 年)。来自混淆矩阵数据的等级和响应组合。信息融合2 (2),113–120。

[1]菲什伯恩,P. (1999 年)。偏好结构及其数字表示。理论计算机科学217 (2),359–383。

[2]黄友生、孙春英(1993 年 6 月)。多分类器组合的行为-知识空间方法。IEEE 计算机学会关于计算机视觉和模式识别的会议(第 347-347 页)。电气工程师协会。

[3]黄友生、孙春英(1995)。一种多专家联合识别无约束手写数字的方法。 IEEE 模式分析与机器智能汇刊17 (1),90–94。

用 Python 实现定量光谱分析的经典最小二乘法

原文:https://towardsdatascience.com/classical-least-squares-method-for-quantitative-spectral-analysis-with-python-1926473a802c?source=collection_archive---------19-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用经典最小二乘法寻找光谱成分

摘要。在这个简短的教程中,将解释计算光谱之间相似性的经典最小二乘法。这种方法也称为比尔法,可用于估算未知光谱中不同组分的浓度。首先,将介绍物理背景和朗伯-比尔定律,然后是经典的最小二乘理论方法和正规方程的推导。最后,将使用 Python 实现来展示一个应用程序示例,说明如何计算样品光谱中不同组分的浓度。

介绍

光谱学是研究固体、液体或气体发射、反射或散射光与波长的函数关系[1]。大多数光谱学方法因此被分类为吸收、发射或散射光谱学。一些例子是吸收、X 射线、红外和拉曼光谱等。

有时,光谱研究中的物质是未知的。如果需要知道这种物质的成分,可以将其测量光谱(查询光谱)与已知物质(成分)的光谱库进行比较,以便进行识别。为此,使用搜索算法来搜索未知光谱,该算法基于相似性度量来计算分数,从而提供最接近匹配或浓度的列表。相似性度量是量化两个对象之间的相似性的函数。在某种意义上,这种度量与距离度量相反:对于相似的对象,它们返回一个大值,而对于不相似的对象,则返回零或负值。规范化后,相似度的范围在 1(完全相似,表示对象相等)和 0(完全不相似)之间。相似性度量也是推荐系统、聚类、分类或异常检测等其他活动的非常基本的构件。
关于光谱学,有几种基于不同相似性度量的标准光谱搜索算法【2】。在下文中,经典的最小二乘法将用于识别未知物质的光谱,并获得混合物中已知物质的浓度。这种方法也称为直接最小二乘法、K 矩阵校准算法或比尔法,因为它是基于比尔-朗伯定律。

物理背景与经典最小二乘法——比尔法

比尔-朗伯定律将光的衰减与光穿过的材料的性质联系起来。它通常应用于物理和化学分析测量,并用于理解物理光学中的光衰减。比尔-朗伯定律表明,在任何给定的波长 I 下,吸光度( A )与所选波长 I 下纯物质(k)的吸光度系数和纯物质©的浓度成正比:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中吸收系数(kᵢ = aᵢL)是光通过材料的路径长度(l)与纯物质在选定波长 I 下的摩尔衰减系数或吸收率(a)的乘积,这是构成这种分子“光谱”的分子特性。

Aᵢ = kᵢc 公式适用于样品中的单一纯物质或成分。当有多种吸收成分时,任何波长下的总吸光度是混合物中所有成分在该波长下的吸光度之和:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们记录的不是给定波长 I 的单个值 A,而是具有 w 个点的整个吸收光谱,则最好用矩阵符号表示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

或者以更紧凑的方式

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在哪里

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因此,A 是我们记录的吸收光谱(也称为查询光谱,或未知光谱,因为我们还不知道它包含什么),K 是纯组分光谱的矩阵(其中这些组分的光谱值排列在列中),c 是 n 种纯物质浓度的向量。

因此,有了我们测得的未知光谱 Aᵢ的值,并知道组成混合物的纯组分光谱 Kᵢⱼ的值,我们可以找到最佳确定混合物吸光度的浓度 cⱼ*a。然而,*因为测得的光谱和纯物质光谱包含噪声,所以一般来说,方程 A = Kc 没有精确解。但是我们仍然可以找到 c,使得乘积 Kc 尽可能接近 A,如欧几里德范数所测量的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

换句话说,我们希望找到 c,使得误差 A-Kc 的平方和最小。误差定义为测得的光谱 A 与通过乘以 K 和 c 计算的光谱之间的差值,c 将是等式 A = Kc 的最佳最小二乘解。

利用这个事实

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们误差的欧几里德范数是

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了找到此类函数的最小值,我们只需对其进行推导,将结果表达式设置为零,并求解 c。为此,我们将利用属性

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 x 是向量,M 是对称矩阵[4]。

所以,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将该表达式设置为 0,我们得到正规方程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其可以被求解以最终获得测量光谱和库中已知光谱之间的相似性分数,或者同样地,未知混合物中纯物质的浓度:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

请注意,A-Kc 的平方和的二阶导数是一个半正定矩阵,这意味着解 c 是全局最小值(而不是最大值或鞍点)。

关于这种方法的更详细的信息可以在《用于定量分析的化学计量技术》一书中找到[5]或者在 spectroscopyonline 网页上关于 CLS 的专栏[6]。

用 Python 实现的代码和示例

首先,加载所需的 Python 包:

import numpy as np
import matplotlib.pyplot as plt
from numpy.linalg import inv

获得未知混合物中纯物质浓度的最小二乘公式定义为:

def least_sq(sample_spectrum, components): # sample_spectrum (unknown spectrum): array of w values.
   # components (known spectra): array of n (number of components) columns with w values.
   # This def returns an array of n values. Each value is the similarity score for the sample_spectrum and a component spectrum. similarity = np.dot(inv(np.dot(components, components.T)) , np.dot(components, sample_spectrum)) return similarity

接下来,我们制作了一些光谱。这些光谱将由高斯峰组成。因此高斯函数被定义为:

def Gauss(x, mu, sigma, intensity = 1):# x is an array
# mu is the expected value
# sigma is the square root of the variance
# intensity is a multiplication factor
# This def returns the Gaussian function of x return intensity/(sigma * np.sqrt(2*np.pi)) * np.exp(-0.5*((x-mu)/sigma)**2

并用它来创建三个不同的组件:

# X-axis (Wavelengths)
x_range =  np.linspace(100, 200, 1000)# Let's create three different components# Component A
mu_a1 = 120
sigma_a1 = 2
intensity_a1 = 1mu_a2 = 185
sigma_a2 = 2
intensity_a2 = 0.2gauss_a =  Gauss(x_range, mu_a1, sigma_a1, intensity_a1) + Gauss(x_range, mu_a2, sigma_a2, intensity_a2)# Component B
mu_b = 150
sigma_b = 15
intensity_b = 1
gauss_b = Gauss(x_range, mu_b, sigma_b, intensity_b)# Component C
mu_c1 = 110
sigma_c1 = 2
intensity_c1 = 0.05mu_c2 = 160
sigma_c2 = 10
intensity_c2 = 1gauss_c = Gauss(x_range, mu_c1, sigma_c1, intensity_c1) + Gauss(x_range, mu_c2, sigma_c2, intensity_c2)# Spectra normalization:
component_a = gauss_a/np.max(gauss_a)
component_b = gauss_b/np.max(gauss_b)
component_c = gauss_c/np.max(gauss_c)# How do they look?
plt.plot(x_range, component_a, label = 'Component 1')
plt.plot(x_range, component_b, label = 'Component 2')
plt.plot(x_range, component_c, label = 'Component 3')
plt.title('Known components in our mixture', fontsize = 15)
plt.xlabel('Wavelength', fontsize = 15)
plt.ylabel('Normalized intensity', fontsize = 15)
plt.legend()
plt.show()

这导致接下来的三个不同的组件:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这三个光谱将构成我们的分量矩阵或 K 矩阵,其中光谱按行排列。

为了生成查询谱,这三个分量将被乘以一个浓度并加在一起。为了让它更真实一点,将会添加一些噪声。

# What concentrations we want them to have in our mixture:
c_a = 0.5
c_b = 0.3
c_c = 0.2# Let's build the spectrum to be studied: The mixture spectrum
query_spectra = c_a * component_a + c_b * component_b + c_c *component_c
# Let's add it some noise for a bit of realism:
query_spectra = query_spectra +  np.random.normal(0, 0.02, len(x_range))plt.plot(x_range, query_spectra, color = 'black', label = 'Mixture spectrum with noise')
plt.title('Mixture spectrum', fontsize = 15)
plt.xlabel('Wavelength', fontsize = 15)
plt.ylabel('Intensity',  fontsize = 15)
plt.show()

得到的混合光谱看起来像:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们的查询谱由三个已知成分(n=3)组成。因此,对于这个例子,矩阵形式的方程组看起来像:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 w = 1000(波长轴有 1000 个值)。因此,A 是由 1000 个值组成的向量,c 是由 3 个值(三种成分浓度)组成的向量,K 是 3×1000 矩阵。

已知 A 和 K,现在可以重新计算“未知”混合物中 3 种成分的浓度:

# Generate the components matrix or K matrix
components = np.array([component_a, component_b, component_c])# Apply Least squares
cs = least_sq(query_spectra, components)# And plot the result:plt.plot(x_range, query_spectra, color = 'black', label = 'Mix spectrum' ) # Plot the unknown spectrumplt.plot(x_range, np.dot(cs,components), color = 'red', linewidth = 2, label = 'Calculation') # Plot the calculated spectrumfor i in np.arange(len(cs)):
    plt.plot(x_range, cs[i]*components[i], label = 'c' + str(i)+ ' =               ' + str(np.round(cs[i], 3)))plt.title('Mixture spectrum and calculated components', fontsize = 15)
plt.xlabel('Wavelength', fontsize = 15)
plt.ylabel('Intensity', fontsize = 15)
plt.legend()
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图:混合光谱(黑色)、计算光谱(红色)和计算成分光谱(蓝色、橙色和绿色)

图中图例所示的计算浓度与设定值完全一致。
注意混合物光谱没有归一化。在混合物光谱被归一化的情况下,这种归一化常数的倒数应该应用于所获得的浓度,以便具有正确的值。

下图显示了另外三个例子,其中计算的浓度与之前设定的值一致(参见图的标题)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

再举三个例子。查询光谱是使用第一光谱的浓度= (0,0.5,0.5)、第二光谱的浓度 c = (0.1,0.5,0.4)和第三光谱的浓度 c = (0.2,0.2,0.6)生成的。用最小二乘法计算的曲线以蓝色、橙色和绿色显示,其计算的浓度写在图例框中。

使用 Python 库的最小二乘法:SciPy 和 Skit-learn

或者,最小二乘问题也可以使用一些 Python 的库来解决。

以 SciPy 为例:

import scipy.optimize as optimizationx0 = np.array([1,1,1])def func(params, xdata, ydata):
    return (ydata - np.dot(xdata.T, params))**2optimization.leastsq(func, x0, args=(components, query_spectra))[0]

或使用 Scikit-learn:

import sklearn.linear_model as linear_modellinear_model.LinearRegression().fit(components.T, query_spectra).coef_

导致组分 A、B 和 C 的浓度分别为 0.48、0.30、0.20。

总结和进一步的考虑

在这个简短的教程中,使用了一种经典的最小二乘法来计算光谱之间的相似性,并展示了这种方法如何用于估算吸收光谱中不同组分的浓度(比尔法)。给出了用 Python 实现这一点的三种不同方法(基于正规方程并使用 SciPy 和 Scikit-learn 包)。重要的是,这种方法不仅可以应用于吸收光谱,还可以应用于任何种类的光谱数据,例如拉曼光谱、红外光谱等。然而,由于某些伪像和副作用的存在,在应用任何相似性度量之前,需要几个光谱预处理步骤来清理光谱[2,7]。这些步骤包括光谱的裁剪和插值、尖峰去除(见我以前的帖子)、基线扣除、平滑和光谱归一化,这些在处理弱信号(例如拉曼光谱)时特别重要。但这将是另一篇文章的主题。

Jupyter 的原版笔记本可以在 GitHub 上找到。

**致谢。**我要感谢豪尔赫·路易斯·希塔博士阿维纳什·米什拉安娜·索拉古伦-比斯科博士花时间校对这些笔记。

参考资料:

[1]光谱学。维基百科。https://en.wikipedia.org/wiki/Spectroscopy

[2] Khan,S. S .,& Madden,M. G. (2012 年)。拉曼光谱的新相似性度量。化学计量学和智能实验室系统114 ,99–108。

[3]在 Python 中实现五个最流行的相似性度量。https://data aspirant . com/2015/04/11/five-most-popular-similarity-measures-implementation-in-python/

[4]济科·科尔特,Chuong Do(2015 年 9 月 30 日)。线性代数复习和参考笔记。http://cs229.stanford.edu/section/cs229-linalg.pdf

[5] Kramer,R. (1998 年)。定量分析的化学计量学技术。CRC 出版社。

[6]沃克曼和马克(2010 年)。光谱学中的化学计量学:经典最小二乘法,第一部分:数学理论
http://www . spectroscopyonline . com/classic-Least-Squares-Part-I-Mathematical-Theory?id =&pageID = 1&sk =&date =

[7] Bocklitz,T. W .,Guo,s .,Ryabchykov,o .,n .,& Popp,J. (2016)。基于拉曼的分子成像和分析:生物医学应用的灵丹妙药!?。分析化学88 (1),133–151。

经典神经网络:为什么/哪些激活功能?

原文:https://towardsdatascience.com/classical-neural-net-why-which-activations-functions-401159ba01c4?source=collection_archive---------32-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

权利:自有形象

今天我将教你不同的可能的激活函数以及它们在经典神经网络中的用途。

激活函数是一族函数,其目的是在层计算之后引入非线性。

事实上,如果没有激活函数,无论进行多少增强或训练,都不会出现良好的拟合(该模型不够复杂):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不合适(权利:自有图像)

这可能是该决策的界限(该模型足够复杂):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

良好的拟合(权利:自有图像)

上面解释的原因只是给出了一个经验上的见解,在我写的关于神经网络层的文章中给出了更深入的解释,其中我谈到了具有一个隐藏层的连续函数的近似。

希望你相信,让我们继续前进!

Sigmoid 函数:

  • Sigmoid 是逼近阶跃函数的第一个直观的连续函数
  • 通过高梯度值,增加系数允许更清晰的近似

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Sigmoid 情节(权利:自有形象)

双曲正切函数:

  • Tanh 与 Sigmoid 非常相似,但当用作输出图层的激活函数时,它允许负值
  • 它还在 0 附近具有更尖锐的过渡(即更高的梯度),而不必增加权重值

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Tanh 情节(权利:自有形象)

校正线性单位函数:

  • 与 Tanh 和 Sigmoid 不同,ReLU 在权重的正值方面没有消失梯度问题
  • 它的简单性也受到高度赞扬

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

热卢情节(权利:自有形象)

泄漏整流线性单位函数:

  • 类似于 ReLU,但是在权重值被转移到负值的情况下,我们允许一些空间来避免渐变消失
  • 我们定义负值的方式可能存在差异(例如:指数线性单位,swish →非常有趣)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

漏雷鲁情节(权利:自有形象)

显然,这些函数是常见的,列表并不详尽,但是您很少会看到其他函数,也很少会发现其他函数有用。

总结一下隐藏层中的激活函数:

  • 由于消失梯度问题,Sigmoids 和 tanh 函数有时会被避免,但它们有助于避免权重值激增。
  • 再次为了避免一些更棘手的消失梯度,漏 ReLU 有时可以用来代替 ReLU
  • 通常的做法是对所有隐藏层使用 ReLU

对于输出层中的激活功能:

  • 对于分类,例如,逻辑回归,您应该使用 sigmoid,这样您就有了增强逻辑回归的效果。
  • 如果你知道你想要接近的函数(有一个粗略的想法), ReLU 可以用作输出层激活函数,例如当你可以保证积极性并且可以只留下你的最后一个线性组合作为你的输出时。

感谢您的阅读,敬请关注,因为更多内容即将到来:经典神经网络的解释和非常好的每日文章!此外,点击这个链接(指向联盟计划)真的会帮我解决问题!您只需完成一些快速任务(只需等待和激活通知),所有这些将真正帮助我了解更多未来的硬件相关内容!

经典神经网络:什么是真正的节点和层?

原文:https://towardsdatascience.com/classical-neural-network-what-really-are-nodes-and-layers-ec51c6122e09?source=collection_archive---------10-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

权利:来源

一个节点和一个层在数学上代表什么?简单易懂的幕后概念介绍。

我们之前已经讨论过激活函数,正如承诺的那样,我们将解释它与神经网络架构中的层和节点的联系。

注意,这是对经典神经网络的解释,而不是对专门神经网络的解释。尽管如此,这些知识在研究特定的神经网络时还是有用的。

好吧,说了这么多,我们开始吧。

首先,我们将以下面非常简单的神经网络(NN)结构为例。(图 1)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图一(右图:来源

  • 输入层:节点 1 → X |激活:sigmoid
  • 隐藏层:节点 1 →N1 和节点 2 → N2(从上到下)|激活:sigmoid
  • 输出层:节点 1 → M |激活
#This code is the keras implementation of the above described NNdef simple_nn():
    model = Sequential()
    model.add(Dense(2, input_dim=1, activation='sigmoid'))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='mean_squared_error', optimizer='sgd')
    return model

这个神经网络代表哪种功能?

给定上面的符号,我们得到下面的函数(图 2):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2(权利:自己的形象)

这里需要注意多种情况:

  • 神经网络的输出将总是属于[0,1]。正如我们在激活功能文章中提到的,输出层激活功能非常重要,它定义了你想要实现的模型类型(例如分类/回归等)
  • 由于只有一个由两个节点组成的隐藏层,我们最终得到一个维数为 7 的权重向量。这使得当节点数量增加时,训练变得困难。
  • 除了激活函数,操作都是线性组合。再次,激活函数引入了非线性。

为什么我们要使用线性组合和这些类型的激活函数?

首先,尽管深度学习(多层神经网络的研究)本身是一种研究,但它与经典的机器学习有着相同的目标:“从数据点(大部分时间)接近特定的底层模型/分布”。因此,神经网络的目标也是逼近一个分布,即一个函数,但如何实现呢?这里介入一些关于分析的基础知识,振作起来!

为了简单起见(如果你有兴趣知道更一般的解释,可以联系我),我们将改为下面的架构。下面是它的功能(图 3):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3(权利:自己的形象)

我们先从一个从实数到实数的连续函数开始。让我们为自己设定一个接近这样一个函数的目标。开始的标准方法是首先画出我们的神经网络所代表的函数(图 3)。由于我们不需要任何具体的数据来解释这个想法,我们将不训练神经网络,而只是简单地任意分配权重(图 4)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4(权利:自己的形象)

下面是曲线图(图 5):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5(权利:自己的形象)

惊喜!这是什么形状?一个长方形!!!

所以我们的神经网络实际上是在模仿一个矩形的分布(或多或少)。对于一些人来说,这似乎并不特别,但对于其他一些听说过黎曼积分和阶梯函数的人来说,他们或多或少会明白我的意思。确切地说,是像神经网络这样的阶跃函数对连续函数的近似(不完全是阶跃函数,但是求和完成了这项工作)。

还有几件事需要注意:

  • 矩形边缘的锐度由 X 前面的标量定义,高值导数的位置由加到乘积上的标量定义。
  • 两个节点足以构成一个矩形,因此要实现连续函数,我们只需添加节点!(在奇数个节点的情况下,我们将简单地使用矩形和阶梯函数)

尽管这很难描述,但在更高维度中,连续函数的近似值几乎是一样的(除了我们重新调整值的那一步)。

既然我们已经看到了这样的近似,我们可以对神经网络逼近分布(即使是非连续的)的能力充满信心。但这种解释仍然缺乏一些东西,我们任意地给我们的神经网络一些准确的权重,但不幸的是,我们无法在一般的数据集这样做,因为我们忽略了分布。这里介入了优化技术,如著名的 SGD(随机梯度下降)或批处理 GD(等等)。假设这些优化确实让我们得到了一个足够接近的解决方案,这将意味着我们超出了我们给出的原始权重(对于矩形)。显示上面的例子(矩形)在某种程度上给出了精确度的下限,即使提到的技术看起来是最佳的,权重的优化可能不一定收敛于该技术的最佳值,但会再次超过它。

感谢您的阅读,敬请关注后续文章。此外,点击这个链接(指向联盟计划)真的会帮我解决问题!您只需完成一些快速任务(只需等待和激活通知),所有这些将真正帮助我了解更多未来的硬件相关内容!

经典神经网络:损失函数景观看起来像什么?

原文:https://towardsdatascience.com/classical-neural-networks-what-does-a-loss-function-landscape-look-like-f69518270223?source=collection_archive---------29-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(权利:来源)

有没有想过我们在什么样的拓扑结构上优化我们的神经网络?现在你知道了!

每个神经网络的目标/损失函数都要最小化!但是这个损失函数到底是什么样子的呢?今天,我们将展示两个不同神经网络的损失函数(N1,N2:图 1)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1(权利:自己的形象)

我们在训练时将损失函数的族是 MSE(均方误差)。尽管其他损失函数族可能会很有趣,但为了便于说明,我们将坚持使用这一个。

对于特别好奇的人来说,我们将训练 N2 神经网络(训练部分不是很有趣,因为我们想要的是一个风景图)这个分布(图 2:是的,我懒得添加噪声)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2(权利:自己的形象)

和 N1 神经网络(图 3):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3(权利:自己的形象)

作为输入函数的损失函数值(N2)

让我们先简单地画出损失函数本身(图 4)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4(权利:自己的形象)

要做的说明:

  • 我们看到,在[-1,1]中,x=-2 和 y 附近的误差值特别高。
  • 除了看到损失函数是什么样子,拥有这样的插图对于想要有目的地攻击这样的神经网络的人来说是有用的!对于对手来说,这可能是试探性的第一步。

作为权重函数的损失函数值(N1)

能够将损失函数视为输入的函数固然很好,但这并不是人们感兴趣的。看到风景进行优化肯定更适合制作建筑!正如我在之前的文章中提到的,N1 有 7 个权重标量需要优化。绘制一个 7 维空间对于我们的理解来说只有很小的意义,所以我们将任意地投射到 2 维空间。请注意,我们固定了输入,因此变量只有两个权重。(图 5)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5(权利:自己的形象)

这是一个数据点的情况。需要注意以下几点:

  • 如果我们在该图上优化(最小),任意选取两个权重,那么一个数据点的损失将明显减少。
  • 现在,为了最小化这样一个函数,任何简单的梯度搜索就足够了,甚至不需要 SGD,因为它是一个严格的凸分布,但因为它有一个平台,我们需要一些动量下降而不是一般下降来获得足够大的梯度方向。

当使用 MSE 作为损失度量时,可以对多个数据点进行这样的绘图。由于权重的数量,能够描绘一般神经网络中的损失更加困难,但这可以是一种在训练时不随机尝试优化算法的方法,而是理解您想要接近的底层数据模型。我再次希望这有助于人们理解机器学习不是黑魔法,而是真正需要分析!超参数发现不一定是随机试验。

感谢阅读!敬请关注更多文章!此外,点击这个链接(指向联盟计划)真的会帮我解决问题!您只需完成一些快速任务(只需等待和激活通知),所有这些将真正帮助我了解更多未来的硬件相关内容!

分类、异常检测和预测

原文:https://towardsdatascience.com/classification-anomaly-detection-and-prediction-68b046d9c436?source=collection_archive---------40-----------------------

为了准确识别各种网络攻击,必须仔细分析底层系统的行为和生成的数据。

因此,有必要分析和研究现有的和新开发的网络安全系统,以确定其弱点,并通过整合机器学习算法提出可能的改进措施。现有的基于特征的检测和行为分析系统为攻击者和入侵者的工作提供了便利。他们可以通过隐藏的门进入系统。

基于网络入侵和检测的异常在受保护网络中起着至关重要的作用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

机器学习和数据挖掘算法可以通过代表性的学习算法对数据进行进一步分类。这使得系统能够自动识别从原始数据中识别和分类特征所需的表示。它们用于处理和分析生成的大数据、检测异常、检测威胁、对特征进行分类等等。例如,可以使用代表性的学习算法对熟悉和未知的单元进行分类。这种方法需要一个包含正常和异常样本的已标记数据集来构建用于分类未来数据点的预测模型。当涉及到检测异常时,SVM(支持向量机)算法可以在学习区域捆绑正常的数据行为。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

支持向量机(维基百科)

这些方法对于实时系统是有用的,但是具有非常高的错误警报百分比,并且会破坏底层系统的性能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

还有其他使用空间和时间特征的方法,这些空间和时间特征是通过非侵入式传感器模态的正常活动来学习的,然后被输入特征。DeepFall 框架是一种使用自动编码器学习深度函数的方法。有一个基于 RNN(递归神经网络)的时间序列异常检测器,它由一系列时间序列和每个异常的一组时间和空间特征组成。这类似于使用非侵入式传感器模态从正常活动中学习空间或时间特征,然后将特征输入神经网络的另一种方法。

对于我个人的研究,我试图建立一个 LSTM(长短期记忆——一种特殊的 RNN,能够学习长期依赖关系)自动编码器,在许多信号中找到异常并进行分类。我认为分析博客异常将是这个实验的良好开端,所以我在网络服务器的帮助下做了这件事。如果信号与其过去和未来之间的偏差很大,则事件会影响其发生的概率。为此,最常用的算法是支持多种数据类型的受监控神经网络(受监控神经网络)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

视觉发现异常检测也可以通过视觉发现来实现。检测视频异常的方法基于模型的类型和检测的标准进行检查,并分为两类:基于深度学习的方法和不基于深度学习的方法。异常检测系统通过考虑各种数据类型(如视频、音频、文本、图像等)来检测计算机和工作中的问题。

另一个例子是变分自动编码器(UAE)来检测时间序列中的异常。一旦安装,模型的编码器部分可用于编码和压缩数据序列,这又可用作预测新类别预测模型(例如,时间序列的预测模型)的基础。

根据我的个人经验,在预测异常检测模型和支持人为干预以获得真实和准确结果所需的解释之间架起一座桥梁。

引用来源

分类基础:Iris 数据集演练

原文:https://towardsdatascience.com/classification-basics-walk-through-with-the-iris-data-set-d46b0331bf82?source=collection_archive---------11-----------------------

从 iris 数据集中学习使用引导代码进行分类的基础知识

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

桑迪·米勒在 Unsplash 上拍摄的照片

当我第一次学习如何编码时,我会在不同的数据集上练习我的数据技能,以创建迷你 Jupyter 笔记本参考指南。由于我发现这是一个非常有用的工具,我想我应该开始分享代码走查。希望这对那些学习使用 Python 进行数据科学的人来说是一个积极的资源,并且可以在未来的项目中参考。完整代码可在 Github 上获得。

正在设置

第一步是从 scikit-learn python 库中导入预加载的数据集。更多关于“玩具”数据集的信息可以在这里找到。数据描述还将提供关于特性、统计数据和来源的更多信息。

from sklearn.datasets import load_iris#save data information as variable
iris = load_iris()#view data description and information
print(iris.DESCR)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据将预先保存为带有“数据”和“目标”的字典,每个键都与一个列表数组配对,作为。最初,信息将像这样输出:

{'data': array([[5.1, 3.5, 1.4, 0.2],
        [4.9, 3\. , 1.4, 0.2],
        [4.7, 3.2, 1.3, 0.2],
        [4.6, 3.1, 1.5, 0.2],
        [5\. , 3.6, 1.4, 0.2],
        [5.4, 3.9, 1.7, 0.4],
        [4.6, 3.4, 1.4, 0.3] ...
'target': array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ...}

将数据放入数据框

特征数据

为了更容易地查看数据,我们可以使用 Pandas 库将这些信息放入数据框中。让我们首先创建一个数据框来存储关于花的特征的数据信息。

import pandas as pd#make sure to save the data frame to a variabledata = pd.DataFrame(iris.data)
data.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 data.head()将自动输出前 5 行数据,但是如果我们还可以在括号中指定我们想要的行数,data.head(10)。

现在,我们有了一个包含虹膜数据的数据框,但是没有清楚地标记列。查看我们上面打印的数据描述,或者参考源代码可以告诉我们更多关于特性的信息。在文档中,数据特征如下:

  • 以厘米为单位的萼片长度
  • 以厘米为单位的萼片宽度
  • 以厘米为单位的花瓣长度
  • 花瓣宽度厘米

让我们重命名这些列,这样功能就清晰了。

data.columns = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']#note: it is common practice to use underscores between words, and avoid spacesdata.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

目标数据

既然与要素相关的数据已经整齐地放在数据框中,我们就可以对目标数据做同样的事情了。

#put target data into data frame
target = pd.DataFrame(iris.target)#Lets rename the column so that we know that these values refer to the target values
target = target.rename(columns = {0: 'target'})
target.head()

目标数据框只有一列,它给出了值 0、1 和 2 的列表。我们将使用来自特征数据的信息来预测一朵花属于组 0、1 还是 2。但是这些数字指的是什么呢?

  • 0 是鸢尾
  • 1 是虹膜杂色
  • 2 是北美鸢尾

探索性数据分析

为了帮助我们更好地理解我们的数据,让我们首先合并我们刚刚创建的两个数据框。这样我们可以一起看到花的特征和分类。

df = pd.concat([data, target], axis = 1)#note: it is common practice to name your data frame as "df", but you can name it anything as long as you are clear and consistent#in the code above, axis = 1 tells the data frame to add the target data frame as another column of the data data frame, axis = 0 would add the values as another row on the bottomdf.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在我们可以清楚地看到单朵花的特征和它的类别之间的关系。

数据清理

检查你的数据,确保它是干净的,并开始探索特征和目标变量之间的关系,这是非常重要的。因为这是一个相对简单的数据集,所以不需要做太多的清理工作,但是让我们来完成这些步骤。

  1. 看数据类型
df.dtypes

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

=带小数的数字(1.678)
int =不带小数的整数或整数(1,2,3)
obj =对象、字符串或单词(’ hello’)
这些数据类型后的 64 是指该值占用多少位的存储空间。你会经常看到 32 或 64。

在这个数据集中,数据类型都已准备好进行建模。在某些情况下,数值将被编码为对象,因此我们必须在执行统计建模之前更改数据类型。

2.检查缺失值

df.isnull().sum()

该数据集没有丢失任何值。虽然这使得建模容易得多,但通常情况并非如此——现实生活中的数据总是杂乱无章的。如果有缺失值,您可以删除有缺失值的数据行,或者有几个选项可以用来填充缺失的数字(使用列的平均值、前一个值……)。

3.统计概述

df.describe()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这使我们能够快速浏览数据。我们可以通过查看每列相对于平均值的最小值和最大值来检查异常值。花点时间浏览这个图表,开始理解数据的分布。

肉眼观察

EDA 过程的下一步是开始可视化一些关系。

相关

Seaborn 库有一个很好的热图可视化工具,可以用来映射特性之间的相关性。数字越大,两个元素之间的相关性越大。高的正相关表示两个元素具有正的线性关系(一个增加,另一个也增加),低的负相关表示负的线性关系(一个增加,另一个减少)。

import seaborn as sns
sns.heatmap(df.corr(), annot = True);#annot = True adds the numbers onto the squares

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

花瓣长度和宽度与目标最相关,这意味着随着这些数字的增加,目标值也会增加。在这种情况下,这意味着类别 2 中的花通常比类别 0 中的花具有更长的花瓣长度和宽度。萼片宽度最不相关,表明类别 0 中的花比类别 2 中的花具有最大的萼片宽度。我们还可以看到一些特征之间的相互关系,例如花瓣的宽度和长度也高度相关。这些信息不一定是分析数据的最佳方式,但它让我们开始看到这些关系。

散点图

为了开始查看特征之间的关系,我们可以创建散点图来进一步可视化不同种类的花与萼片和花瓣数据的关系。

# The indices of the features that we are plotting (class 0 & 1)
x_index = 0
y_index = 1# this formatter will label the colorbar with the correct target names
formatter = plt.FuncFormatter(lambda i, *args: iris.target_names[int(i)])plt.figure(figsize=(5, 4))
plt.scatter(iris.data[:, x_index], iris.data[:, y_index], c=iris.target)
plt.colorbar(ticks=[0, 1, 2], format=formatter)
plt.xlabel(iris.feature_names[x_index])
plt.ylabel(iris.feature_names[y_index])plt.tight_layout()
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

三类花的萼片宽度与长度的关系。Virginica 和 versica 在萼片大小上看起来相对相似,但 setosa 在左侧创建了自己的簇。

现在让我们创建相同的散点图来比较花瓣数据点。

x_index = 2
y_index = 3# this formatter will label the colorbar with the correct target names
formatter = plt.FuncFormatter(lambda i, *args: iris.target_names[int(i)])plt.figure(figsize=(5, 4))
plt.scatter(iris.data[:, x_index], iris.data[:, y_index], c=iris.target)
plt.colorbar(ticks=[0, 1, 2], format=formatter)
plt.xlabel(iris.feature_names[x_index])
plt.ylabel(iris.feature_names[y_index])plt.tight_layout()
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可视化花瓣长度和宽度之间的关系。我们可以看到,花开始单独成簇,与花瓣大小相关的元素可能是类的一个强有力的决定因素。

建模

既然我们已经清理和探索了数据,我们就可以开始开发模型了。我们的目标是创建一个逻辑回归分类模型,根据花瓣和萼片的大小来预测花属于哪一类。

#divide our data into predictors (X) and target values (y)
X = df.copy()
y = X.pop('target')

列车测试分离

一旦我们从目标中分离出特性,我们就可以创建一个训练和测试类。顾名思义,我们将在训练集上训练我们的模型,并在测试集上测试模型。我们将随机选择 80%的数据用于我们的培训,20%作为测试。

from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=1, stratify = y)'''
by stratifying on y we assure that the different classes are represented proportionally to the amount in the total data (this makes sure that all of class 1 is not in the test group only)
'''

使标准化

随着 X 值在训练和测试之间分离,现在我们可以标准化这些值。这将数字放在一个一致的范围内,同时保持它们之间的比例关系。

from sklearn.preprocessing import StandardScalerscaler = StandardScaler()
X_train = pd.DataFrame(scaler.fit_transform(X_train), columns=X_train.columns)
X_test = pd.DataFrame(scaler.transform(X_test), columns=X_test.columns)

基线预测

基线是模型实现前预测类的概率。如果数据被平均分成两类,就有 50%的机会将一个元素随机分配给正确的类。我们模型的目标是改进这个基线,或随机预测。此外,如果存在严重的类别不平衡(如果 90%的数据在类别 1 中),那么我们可以改变每个类别的比例,以帮助模型更准确地预测。

df.target.value_counts(normalize= True)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个模型的基线预测是 1/3

逻辑回归模型

from sklearn.linear_model import LogisticRegression#create the model instance
model = LogisticRegression()#fit the model on the training data
model.fit(X_train, y_train)#the score, or accuracy of the model
model.score(X_test, y_test)
# Output = 0.9666666666666667#the test score is already very high, but we can use the cross validated score to ensure the model's strength 
from sklearn.model_selection import cross_val_scorescores = cross_val_score(model, X_train, y_train, cv=10)
print(np.mean(scores))
# Output = 0.9499999999999998

在没有任何调整或优化的情况下,该模型已经表现得非常好,测试得分为 0.9667,交叉验证得分为 0.9499。这意味着该模型在大约 95%的时间里预测了花的正确类别。远高于 33%的基准线!

理解预测

通常会对参数进行大量的微调和实验,以找到得分最高的模型。然而,由于这个数据集是简单明了的,我们现在可以继续,开始看看模型是如何做出预测的。

系数

df_coef = pd.DataFrame(model.coef_, columns=X_train.columns)
df_coef

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

逻辑回归中的系数通常有点难以解释,但我们可以了解每个特征在决定一朵花是否属于该类时的影响程度。例如,花瓣长度几乎不是一朵花是否属于第一类的决定性因素,但花瓣宽度是第二类的一个强有力的预测因素。

预测值

我们还可以将模型预测的值与实际值进行比较。

predictions = model.predict(X_test)#compare predicted values with the actual scores
compare_df = pd.DataFrame({'actual': y_test, 'predicted': predictions})
compare_df = compare_df.reset_index(drop = True)
compare_df

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测几乎完美地排列在一起,只有一次模型错误地预测一朵花属于第 1 类,而它实际上属于第 2 类。

混淆矩阵

为了更仔细地观察模型做出的预测,我们可以使用混淆矩阵。在混淆矩阵中,预测值是列,实际值是行。它可以让我们看到模型在哪里做出了正确和错误的预测,如果它预测错误,我们可以看到它错误地预测了哪个类。

from sklearn.metrics import confusion_matrix
pd.DataFrame(confusion_matrix(y_test, predictions, labels=[2, 1, 0]),index=[2, 1, 0], columns=[2, 1, 0])

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到,0 类和 1 类都被正确预测了 10 次,但在一个实例中,模型错误地将 2 类标记为 1 类。

分类报告

检查模型性能的另一个好方法是查看分类报告。它显示了精确度、召回率、f1 分数和准确度分数,下面是对这些特性的简要说明。

  • 精度:在预测的海滨鸢尾花总数(10)中,正确预测的海滨鸢尾花数(10)。预测海滨鸢尾的精度=10/10 = 1.0**
  • 回忆:在实际的黑鸢尾数量中,正确预测的黑鸢尾数量。回忆= 9/10 = .9**
  • F1 得分:这是精确度和召回率的调和平均值。公式为 F1 得分= 2(精度*召回)/(精度+召回)*
  • 准确性:将所有类别的所有正确预测相加,然后除以预测总数。29 个正确预测/30 个总值= 0.9667 的准确度。
from sklearn.metrics import classification_report
print(classification_report(y_test, predictions))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测概率

使用下面的代码,我们可以查看每行数据被分配到三个类之一的概率。默认情况下,模型会将该项分配给概率最高的类。如果我们想要调整准确度或精度,我们可以通过更改阈值来实现,在将预测概率分配给该类之前,该阈值必须有多高。

在这种情况下,错误地将一朵花分配给另一个类别不会产生后果,但用于检测癌细胞的模型会调整其模型以“假设最坏的情况”,并更经常地将其分配为真正的癌细胞。这在许多情况下使用,当过度谨慎比错误地将细胞标记为安全和健康更好时。

probs = model.predict_proba(X_test)#put the probabilities into a dataframe for easier viewing
Y_pp = pd.DataFrame(model.predict_proba(X_test), 
             columns=['class_0_pp', 'class_1_pp', 'class_2_pp'])
Y_pp.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

希望这个演练有助于展示数据科学项目过程中的一些主要步骤。当然,这并不是对该数据集可以采取的步骤的详尽列表,但它旨在仔细展示分类的一些重要步骤。

这是一个经典的数据集,因为它相对简单,但这里强调的步骤可以应用于任何类型的分类项目。请关注未来更简单(和高级)的数据集演练!

寻找下一步?阅读关于回归的基础知识,一个预测汽车销售价格的数据科学项目。

不平衡数据集中的分类。

原文:https://towardsdatascience.com/classification-framework-for-imbalanced-data-9a7961354033?source=collection_archive---------10-----------------------

理解和利用不平衡数据。

介绍

C 分类是机器学习中的一种监督学习,处理将数据分类成类。监督学习意味着模型将输入与其匹配的输出相结合来训练模型,该模型稍后可以在没有输出的情况下对一组新数据做出有用的预测。分类问题的一些例子包括:邮件中的垃圾邮件检测、订阅分析、手写数字识别、生存预测等。它们都涉及利用训练数据来理解输入变量如何与输出(目标)变量相关的分类器的使用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

米切尔·施瓦茨在 Unsplash 上的照片

类别不平衡指的是分类中的一个问题,类别的分布是偏斜的。这种不平衡从轻微到极端都有。

这是一个问题,因为大多数分类算法对少数类的预测精度较低,因为它们是在假设类之间存在平衡的情况下运行的。

类别不平衡的一个例子是信用卡欺诈检测。在这种情况下,类别是欺诈非欺诈。大多数交易都是不欺诈,因此欺诈阶层是少数阶层。少数类预测的准确性低是有问题的,因为它是最重要的类。

这篇博客涵盖了处理不平衡数据集中的分类问题的步骤。包含所有代码的 Github 库可以在这里找到。

资料组

使用的数据来自 UCI 机器学习知识库。该数据与葡萄牙银行机构的营销活动相关。分类的目标是预测客户是否会订阅定期存款(变量 y )。

有效的模式有助于提高营销活动的效率,因为可以将更多的精力放在订阅机会高的客户身上。

数据示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可视化目标变量(y ),以观察类别不平衡:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片作者。

圆圈的大小代表每个类的值计数。显然存在极端的阶级不平衡。这将在预处理部分处理。

预处理

预处理包括以下步骤:

输入空值

需要处理缺失值,因为它们可能会导致错误的预测,还可能导致任何给定模型的高偏差。

分类特征将用列模式估算,离散数字特征用列中位数估算,连续数字特征用列平均数估算。

处理异常值

离群值是许多机器学习算法的问题,因为它们会导致重要见解的丢失或扭曲真实结果,最终导致模型不太准确。

将使用第 10 个和第 90 个百分位数对异常值进行剪裁。

特征生成

从现有要素生成新要素增加了在模型训练期间可访问的新信息,因此提高了模型精度。

缩放数值变量

标准定标器对数字特征进行标准化,以消除不同测量单位带来的差异。

编码分类变量

大多数机器学习和神经网络算法需要数字输入,因此为了利用分类特征,我们必须重新映射它们。

应用一种热编码技术。它获取一个包含分类数据的列,然后将该列拆分成多个列。条目被 0 和 1 替换,这取决于哪一列有什么值。

对不平衡数据集进行重采样。

重采样包括创建不平衡数据集的新版本。

重采样有两种主要方法:

  • 过采样:随机复制少数类中的条目。适用于小型数据集。
  • 欠采样:从多数类中随机删除条目。适用于大型数据集。

我们的数据集有 41188 行和 21 列,因此使用过采样是安全的。

预处理类:

预处理类代码。

# calling the class and its methodsd = DataPrep()
path = '/content/bank-additional-full.csv'
data = d.read_data(path)
data = d.treat_null(data)
data = d.outlier_correcter(data)
data = d.generate_features(data)
data = d.scaler(data)
print('After scaling:', data.shape)
data = d.encoder(data)
data = d.over_sample(data)
data.head()

输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

请注意分类和数字列中的变化。

建模

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由亨特·哈里特Unsplash 上拍摄

从预处理到进行预测,我们首先使用训练和验证数据来训练和评估我们的模型。但首先,我们必须分离目标和预测变量,然后将它们分成训练集、验证集和测试集。测试集不是单独提供的,因此我们从数据集中检索它。

# split the data to have the predictor and predicted variables
x = data.drop(['y'], axis = 1)
y = data[['y']]# Encode labels in target df.
encoder = LabelEncoder()
y = encoder.fit_transform(y)# get the sets
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.10, random_state = 42)x_train, x_val, y_train, y_val = train_test_split(x_train ,y_train, test_size = 0.20, random_state = 42)

有待探索的算法:

  • XGBoost :

XGBoost 分类器是一种基于树的集成学习算法,是梯度推进机器的一种实现。

它针对速度和性能进行了优化。

  • 多层感知器:

多层感知器(MLP)是一类前馈人工神经网络。它至少由三层节点组成:输入层、隐藏层和输出层。

它区分不可线性分离的数据的能力是我们探索它的原因。

  • 逻辑回归:

逻辑回归是一种简单但非常有效的分类算法,它使用对数比值比来预测组成员。

它的简单性和使用对数比值比代替概率是我们探索它的原因。

交叉验证

交叉验证是一种重采样程序,用于在有限的数据样本上评估机器学习模型。

使用的技术:

  • K-fold : K-Fold CV 是将给定的数据集分成 n 个折叠,其中每个折叠在某个点用作测试集,其余的用作训练集。
  • 分层 K 折叠:分层 K 折叠将数据打乱,然后将其分成 n 个折叠,每个折叠都用作一个测试集。分层保持数据集目标之间的平衡(每个分层折叠保持目标类的相同比率)。这种策略在不平衡数据的情况下是最好的。

在这两种技术中,默认的评分标准是 准确度分数 (做出的正确预测数除以做出的预测总数)。

实施:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,我们使用这些技术在训练数据上观察我们的模型性能。

# using grid search to find optimal parametersregressor = LogisticRegression()
grid_values = {'penalty': ['l1','l2'], 'C': [0.001,0.01,0.1,1,10,100,1000]}model = GridSearchCV(regressor, param_grid=grid_values)
model.fit(x_train,y_train)
print(model.best_score_)
print(model.best_params_)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

# using the optimal parametes printed out
regressor = LogisticRegression(C = 1000, penalty= 'l2')
regressor.fit(x_train, y_train)# using kfolds
print('Logistic Regression mean accuracy score using kfold:', overall_score(regressor, x_train))# stratified KFold
print('Logistic Regression mean accuracy score using Stratifiedkfold :', overall__stratified_score(regressor, x_train))

输出:

Logistic Regression mean accuracy score using kfold: 0.742437522099093
Logistic Regression mean accuracy score using Stratifiedkfold : 0.7420879248958712

对 XGBoost 和 MLP 重复相同的过程。

xgb = XGBClassifier(silent = True,max_depth = 6, n_estimators = 200)
xgb.fit(x_train, y_train)# using kfolds
print('xgb mean score on the original dataset (kfold):', overall_score(xgb, x_train))# stratified KFold
print('xgb mean score on the original dataset (stratified kfold):', overall__stratified_score(xgb, x_train))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

mlp = MLPClassifier() # working with default parameters
mlp.fit(x_train, y_train)# using kfolds
print('mlp mean score on the original dataset (kfold):', overall_score(mlp, x_train))# stratified KFold
print('mlp mean score on the original dataset (stratified kfold):', overall__stratified_score(mlp, x_train))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在所有的 3 个模型中,K-fold 产生了最高的准确性,尽管它随分层的变化是如此之小。如前所述,分层最适合不平衡的数据,但我们已经在预处理过程中对数据进行了重新采样,使其不再有用。

进一步评估

我们可以通过验证集探索其他准确性指标。

  • ROC — ROC 曲线是针对 0.0 和 1.0 之间的多个不同候选阈值的真阳性率(y 轴)与假阳性率(x 轴)的关系图。
  • 精度和召回 精度是正确鉴定的阳性结果的数量除以所有阳性结果的数量,包括那些没有正确鉴定的阳性结果,召回是正确鉴定的阳性结果的数量除以所有本应被鉴定为阳性的样本的数量。
  • F1 分数 — F1 分数是对测试准确性的衡量。它是根据测试的精确度和召回率计算出来的。

当每类的观察值大致相等时,应使用 ROC 曲线。当存在中等到大的类别不平衡时,应该使用精确召回曲线。

由于我们对数据进行了重新采样以保持平衡,ROC 是我们的最佳选择。

ROC 图:实施:

这些图在其他模型上实现:RandomForest、CatBoost 和 LGBM,它们可以被编辑以适合任何模型。(代码可在github链接中共享)。

from sklearn.datasets import make_classification
from sklearn.metrics import roc_curve
from sklearn.metrics import roc_auc_score#predict probabilities
ns_probs = [0 for _ in range(len(x_val))]  # no skill classifier
f_prob = forest.predict_proba(x_val)
c_prob = cat.predict_proba(x_val)
l_prob = lgbm.predict_proba(x_val)# keep probabilities for the positive outcome only
f_prob = f_prob[:, 1]
c_prob = c_prob[:, 1]
l_prob = l_prob[:, 1]# calculate scores then print them
f_auc = roc_auc_score(y_val, f_prob)
c_auc = roc_auc_score(y_val, c_prob)
l_auc = roc_auc_score(y_val, l_prob)
ns_auc = roc_auc_score(y_val, ns_probs)print('RandomForest:', f_auc)
print('CatBoost: ', c_auc)
print('LGBM:', l_auc)# calculate roc curves
f_fpr, f_tpr, _ = roc_curve(y_val, f_prob)
c_fpr, c_tpr, _ = roc_curve(y_val, c_prob)
l_fpr, l_tpr, _ = roc_curve(y_val, l_prob)
ns_fpr, ns_tpr, _ = roc_curve(y_val, ns_probs)# plot the roc curve for the model
plt.figure(figsize = (12,7))
plt.plot(f_fpr, f_tpr, marker='.', label='random forest')
plt.plot(l_fpr, l_tpr, marker='.', label='lgbm')
plt.plot(c_fpr, c_tpr, marker='.', label='catboost')
plt.plot(ns_fpr, ns_tpr, linestyle='--', label='No Skill')plt.legend()
plt.title('ROC curves for different models')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')

输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片作者。

曲线下的面积越大,精确度越高。

无技能分类器是一种不能区分类别的分类器,它在所有情况下都会预测随机类别或恒定类别。(我们的基准)。

预言

使用 MLP,我们最初 3 个模型中表现最好的。

# mlp
pred = mlp.predict(x_test)
pred_df = pd.DataFrame(pred)
pred_df.columns = ['y']
pred_df.to_csv('pred_df.csv') # export to a csv file

结论

我们可以继续研究我们的分类问题,探索不同的技术,比如降维,仅仅是为了获得一个性能更好的模型。但是现在,我们知道拥有不平衡的数据并不妨碍我们进行预测,它只是召唤我们使用适当的技术来避免对少数类的糟糕预测。

附言:向我在 10academy.org 的所有同学和导师表示敬意,感谢他们无尽的支持。

参考

  1. 如何在 Python 中使用 ROC 曲线和精确召回曲线进行分类

2.了解 AUC — ROC 曲线。

3.XGBoost 算法:愿她统治长久!

4.处理不平衡数据。

  1. XGBoost 文档。

6.不平衡数据:如何处理不平衡分类问题。

7.为什么不平衡分类很难?

人们应该知道的分类度量数据

原文:https://towardsdatascience.com/classification-metrics-everyone-should-know-b67fd0044c0c?source=collection_archive---------46-----------------------

了解数据科学成功的基础!

学习分类标准可能是一个模糊的混乱。☁️:有很多衡量标准。很多听起来很像。有时同一个东西有两个名字。有时有五个。🤦‍♀️🤦‍♂️

这一系列文章旨在拨开迷雾。🌤这是一个帮助您理解、使用和记住七个最常见的分类标准的指南。

今天我们将探索每个人都需要的基础。数据科学家和统计学家必须先打好基础,然后才能进入更高级的指标。😀

我们开始吧!🚀

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

雾蒙蒙的。资料来源:pixabay.com

在二元分类问题中有两种可能的结果:真或假,1 或 0,买或不买,感染或不感染,等等。在本文中,我们将重点关注二进制分类,因为它很常见,而且这种东西与两个结果类就足够混淆了。😉

我们要查看的指标在 scikit-learn Python 包中。每个函数都是从 sklearn 中导入的。指标模块模块。

我们将使用一些假设的分类任务来说明这些指标是如何工作的。让我们从预测网站访问者是否会在 Jeff 的牛逼夏威夷衬衫店购买衬衫开始吧!🏝+🌺+👕+💵

混淆矩阵

混淆矩阵是构建指标的基础。它显示了你的模型的预测有多少是正确的,有多少是不正确的,由实际的积极和消极的结果组织。

矩阵的一个轴是现实生活中的结果——正面和负面的情况。在我们的例子中,如果访问者购买了一件衬衫,这是一个实际的积极因素。😀如果游客不买衬衫,这是一个实际的负面影响。☹️

 **Predicted Label**        
                Predicted Positive    Predicted Negative
  **True Label       ** Actual Positive     
Actual Negative 

另一个轴是你的模型的预测。如果你的模型预测到访问者会买一件衬衫,那就是一个积极的预测。如果你的模型预测访客不会买衬衫,那就是负面预测。

结合预测和实际结果,你会得到四个象限:

真阳性
真阴性
假阳性
假阴性

或简称 *TP、TN、FP、*和 FN 。😁

 Predicted Positive    Predicted Negative
Actual Positive            **TP**               **FN**
Actual Negative            **FP**               **TN**

让我们将这四组分解开来:

指模型预测正确的情况。指模型预测错误的情况。你希望你的模型预测准确,所以你希望更多的和更少的。👍

如果这个群体在名字*、中有阳性*,那么这些人就是模型预测会购买的人。如果该组的名称中有负数,则这些是模型预测不会购买的人。

理解这四个群体是关键。在继续之前,确保你能用自己的话解释这四个象限。☝️

请注意,其他混淆矩阵图可能会以不同的顺序显示行和列。可惜没有标准顺序。☹️

下面是从混淆矩阵创建四个结果变量的 Python 代码(导入了 numpy 库,从 sklearn.metrics 导入了混淆矩阵*)😗

tn, fp, fn, tp = confusion_matrix(y_test, predictions).ravel()

这段代码将基础事实( y_test )和预测传递给混淆 _ 矩阵函数,用拉平结果。ravel() ,*,*然后把结果解包成四个变量。

您可以使用 scikit-learn 的新plot _ confusion _ matrix函数绘制更漂亮的混淆矩阵图。向凯文·马卡姆致敬。🧢

这里有一个混淆矩阵的例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面是我用来制作这个混淆矩阵的代码(带有作为 plt 导入的 matplotlib.pyplot 和从 sklearn.metrics 导入的 plot_confusion_matrix ):

plot_confusion_matrix(
    clf, 
    X_test, 
    y_test, 
    values_format=’d’, 
    display_labels=[‘Bought’,’Didn\’t buy’], 
    cmap=plt.cm.coolwarm
);

请注意,您必须首先通过评估程序。我添加了一些额外的参数来显示标签,使情节更漂亮。如果您想更改输出值,使它们不是科学记数法格式,那么values_format参数可以解决您的问题。🎉

现在让我们看看如何使用混淆矩阵中的这四个数字来制作我们最常用的分类度量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

少雾。资料来源:pixabay.com

准确(性)

术语准确性在一般对话中通常用来表示“良好的性能”,但是在分类度量领域中它有一个特定的定义。准确度分数回答了以下问题:

你猜对了几次?

精确度的公式为:

准确度= (真阳性+真阴性)/所有观测值

或者,简称:

精度 = (TP + TN) /全部

以下是我们的模型预测游客是否会在杰夫的夏威夷衬衫店购物的假设结果。🌺👕

困惑矩阵#1:

 Predicted Positive    Predicted Negative
Actual Positive          80  (TP)            20 (FN)
Actual Negative          50  (FP)            50 (TN)

该模型预测了 130 次购买和 70 次不购买。实际上有 100 次购买和 100 次不购买。

我们来计算一下准确率得分。将真阳性真阴性相加,并除以观察总数。

(80 + 50 ) / 200

看起来模型正确预测了 200 个案例中的 130 个,准确率为 65%。听起来不可怕。😀

但是我们并不真正知道我们的模型做得有多好,直到我们把它与另一个模型的预测进行比较。最基本的替代模型是一个简单的决策规则,它预测购买的概率为 50%。我们的模型比 50%的基线做得更好,这很了不起。😉

请注意,当模型正确预测所有事情时,可能的最佳准确度分数是 1 (100%)。当模型没有正确预测时,最差的分数可能是 0。

现在让我们看看当结果类不平衡时会发生什么。

不平衡数据

假设你在一家银行工作🏦并且想要检测信用卡交易中的欺诈。你要预测 1000 笔交易。你建立了一个机器学习模型来预测哪些是欺诈性的,这是产生的混淆矩阵:

困惑矩阵#2:

 Predicted Fraud   Predicted Not-fraud
Actual Fraud               1                      8
Actual Not-fraud           2                    989

我们的四个混淆矩阵值如下所示:

TP=1
TN=989
FP=2
FN=8

该模型预测有 3 个案例是欺诈性的,而实际上有 9 个案例是欺诈性的。

准确率为(1+989)/1000 = 99%。听起来很神奇,对吧?🏆

但是等等。沉住气。少了什么?🤔

该模型将 9 个实际欺诈案例中的 8 个分类错误!我们想找的 9 样东西,我们漏掉了 8 样!那可不行。☹️

99%的准确率分数并没有反映出模型在工作中做得有多好。事实上,如果很多人只看到正确的分数,就会误导他们。许多人不知道去问这些课程是否平衡。这是人们有意或无意误导统计数据的方式之一。☝️

一些好消息是,在 scikit-learn 中不需要手工计算精度。准确性是默认的分类评分标准。此外,您可以使用函数accuracy _ score来查找任何一组预测值和实际值的精确度。🎉

结果

准确度同等地加权混淆矩阵的所有象限。当两种结果类别的数量相对相等时,这是一个很好的汇总统计。当您更关心避免误报或漏报时,您会希望使用我们将在下一篇文章中探讨的其他度量之一。

你肯定想知道术语的准确性及其被不平衡数据误导的风险。😀

概述

您已经了解了混淆矩阵和准确性,这是数据科学家需要了解的最基本的分类术语。在下一篇文章中,我们将探索你肯定想知道的三个基本指标,但这可能很难保持直线。

我希望这篇关于分类标准基础部分的介绍对您有所帮助!如果你有,请在你最喜欢的社交媒体上分享,这样其他人也可以找到它。😀

我写了关于 Python、T2、SQL、T4、Docker 和其他技术主题的文章。如果你对此感兴趣,请关注我,在这里阅读更多。👍

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传**外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不再有雾。资料来源:pixabay.com

分类快乐!📊

解释了分类指标和阈值

原文:https://towardsdatascience.com/classification-metrics-thresholds-explained-caff18ad2747?source=collection_archive---------8-----------------------

揭开常用分类指标的神秘面纱

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

马库斯·温克勒在 Unsplash 上的照片

分类评估

我们用来评估分类器的度量取决于我们想要解决的问题的性质和预测误差的潜在后果。让我们检查一个非常常见的癌症诊断例子(即分类为患癌或未患癌)。我们希望我们的模型能够预测尽可能多的实际/真实癌症诊断,但我们也知道,从统计学角度来看,正确识别所有真实的癌症诊断是不可能的。我们的模型最终会在某人实际上没有患癌症时将其分类/预测为患有癌症(假阳性),并在某人实际上患有癌症时预测其没有患癌症(假阴性)。我们必须问自己的问题是“什么更糟?预测某人会得癌症,而实际上他们不会,还是预测某人不会得癌症?”。这个例子中的答案是显而易见的,因为告诉某人他们没有癌症的后果远远超过前者。让我们记住这个例子,但是让我们回顾一下常用的分类性能指标。

分类性能指标

混淆矩阵

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

混淆矩阵总结了模型的预测。它给出了正确预测的数量(真阳性和真阴性)和不正确预测的数量(假阳性和假阴性)。在我们的癌症例子中,如果我们的模型预测某人患有癌症,并且这个人患有癌症,这是一个真正的肯定。当我们的模型预测某人没有患癌症,而那个人没有患癌症,这是一个真正的否定。当我们的模型预测某人患有癌症,但那个人没有患癌症时,这是假阳性(即该模型错误地预测了阳性癌症诊断)。最后,当我们的模型预测某人没有患癌症,但他们确实患了,那就是假阴性(即该模型错误地预测了阴性癌症诊断)。

其余的许多性能指标都是从混淆矩阵中得出的,因此,您必须很好地理解。

准确(性)

简而言之,准确性详细说明了我们的模型正确的频率。换句话说,就是正确预测数(TP,TF)除以预测总数。准确性通常是第一个衡量标准,但如果不仔细考虑,它可能会非常误导人。例如,让我们考虑一个用于训练我们的模型的不平衡数据集。我们有 1000 个非癌症诊断和 10 个癌症诊断。模型能够正确预测 900 个非癌症诊断,1 个癌症诊断的准确率为 0.89% ((900+1)/1010=0.89)。

(TP+TN)/(TP+FP+FN+TN)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

精确度(也称为特异性)

精度告诉我们预测的正类中有多少是正确的。换句话说,预测的癌症诊断中有百分之多少实际患有癌症。Precision 只关心我们的模型准确地预测了正类。我喜欢把精确度看作是衡量一个模型正确预测阳性癌症诊断的“挑剔”程度或“确定”程度的标准。一个不同的例子可能与僵尸启示录有关。即使允许一个被感染的僵尸进入你的营地,也会导致每个人都被感染。一个具有高精度的模型将确保你让进入你的营地的那些人是健康的。然而,该模型也会有很高的假阴性计数(即被认为感染的健康人)。高精度与低 FP 速率相关。当假阳性的后果很严重时首选。

TP/(TP+FP)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

回忆(也称为敏感度)

召回率是我们的模型预测的实际阳性的百分比。我们的模型预测(由医生)诊断患有癌症的人有多少百分比患有癌症。回忆不太关心准确预测阳性病例,而是确保我们已经捕获了所有的阳性病例,因为当某人患有癌症时,将其归类为非癌症的后果要严重得多。我们希望我们的模型具有高召回率,以将尽可能多的实际癌症诊断分类为患有癌症。不幸的是,这意味着该模型还会将大量没有患癌症的个体归类为患有癌症(即假阳性)。高召回率与低 FN 率相关。当假阴性的后果很严重时首选。

TP/(TP+FN)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

F1 分数

从数学上讲,同时拥有高精确度和高召回率是不可能的,这就是 F1 分数派上用场的地方。F1 分数是精确度和召回率的调和平均值。如果你想建立一个平衡精确度和召回率的模型,F1-score 是一个很好的选择。当数据集不平衡时,F1-score 也是一个不错的选择。一个好的 F1 分数意味着你有低 FP 和低 FN。

2(召回精度)/(召回+精度)**

ROC 曲线/AUC 得分

接收器工作特性曲线(ROC)绘制了在任何概率阈值下的真阳性率与假阳性率。阈值是将观察结果分类为 0(无癌症)或 1(有癌症)的指定临界值。

那是一口………

这将帮助我们更好地理解什么是阈值,我们如何通过改变阈值来调整模型的预测,以及如何创建 ROC 曲线。这个例子还将引入你在上面学到的 TP、TN、FN 和 FP 的概念。

我保证,这一切都是有意义的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

逻辑回归是一个二元分类器,在上面的例子中,我们试图只根据一个特征/预测因子体重来正确预测肥胖。我们有一个包含 9 个观察值的数据集,其中 4 个(绿色)观察值不肥胖,5 个(红色)观察值肥胖。基于对数回归产生的 sigmoid 函数(曲线),前 3 个绿色非肥胖观察值基于其体重被预测为肥胖的几率为 0%。最后 3 个红色肥胖观察值也有 100%的概率被预测为肥胖。第二个红色肥胖观察有大约 70%的机会被预测为肥胖。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然而,第四个绿色的非肥胖观察有大约 85%的机会根据其体重(必须非常肌肉)被预测为肥胖,但我们知道这是错误的预测。此外,第一次肥胖观察有大约 15%的机会肥胖,这再次是错误的预测。记住阈值是 0.5,因此,任何处于 51%肥胖概率的数据点将被分类为肥胖,任何低于 50%的数据点将被分类为非肥胖。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们假设,当某人实际上肥胖时,错误地预测他不肥胖的后果是很严重的。换句话说,我们希望调整模型,以捕捉或预测尽可能多的实际肥胖个体(即高召回)。为了完成这项任务,我们需要改变我们的门槛。随着阈值降低到 0.2,我们的模型将正确地将所有 5 个肥胖观察预测为肥胖。任何高于 0.2 阈值的数据点将被归类为肥胖,反之亦然。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然而,通过将阈值降低到 0.2,第四次非肥胖观察现在被预测为肥胖。这是我们在调整模型的阈值时所做的权衡。

让我们再一次考虑我们的癌症例子。我们可以接受阈值为 0.2 的模型,因为它可以正确预测所有实际的癌症诊断(即真阳性)并且具有非常高的召回率。然而,该模型将做出权衡,因为它最终将更多实际上没有患癌症的个体预测为患有癌症(即假阳性)。假阳性的后果没有错误地预测某人没有患癌症那么严重。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,阈值为 0.9 的模型会做与阈值为 0.2 相反的事情。它将确保预测所有 4 个非肥胖个体为非肥胖,然而,前两个肥胖个体最终将被预测为非肥胖。既然我们理解了阈值及其目的,让我们回到 ROC 曲线。

那么 ROC 曲线在哪里起作用呢?

这是一个简单的例子,只有 9 个数据点,阈值很容易看到和解释。如果你有一百万个观察值和一个比我们的肥胖或癌症例子更复杂的情况呢?在这种情况下,最佳阈值是多少?我们是不是要做一堆这样的图,才能找到最符合我们需求的阈值?".答案是否定的。ROC 曲线是快速总结这些数据的好方法,这样你就可以选择你的阈值。

这是一个 ROC 曲线的例子(绿线),注意 y 轴上的真实阳性率(实际肥胖和预测为肥胖)和 x 轴上的假阳性率(非肥胖但预测为肥胖)。最后,请记住 ROC 用于总结不同阈值下的 TP 比率和 FP 比率。曲线不会显示阈值,但会显示不同真阳性率下的假阳性率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

真实阳性率

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

真阳性率=TP/(TP+FN)

假阳性率

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

假阳性率=FP/(FP+TN)

让我们快速比较 ROC 曲线上的 3 个独立阈值。0.9 的阈值具有下面的混淆矩阵,从中我们可以计算出 0.6 的 TP 速率和 0 的 FP 速率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们在 ROC 曲线上绘制 TP 比率和 FP 比率点。为了演示,我们还绘制了阈值为 0.6 和 0.2 时的 TP 和 FP 速率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

绿色虚线代表 ROC 曲线。单独的蓝点是 4 个单独的混淆矩阵的结果,其中阈值被调整。现在问问你自己,“如果这是一个癌症的例子,你想确保你捕捉/预测所有实际的癌症诊断,你会选择哪个阈值?”

如果你说 0.2 你就对了!在这个阈值,你的 TP 率是 100%,这意味着你捕捉/预测了所有实际的癌症诊断。你的 FP 率约为 0.33,这意味着你的模型将一些非癌症诊断错误分类为癌症,但这没关系。恐吓某人,让他们花钱去做检查,比告诉他们没有癌症的人后果要轻。

现在,ROC 简单地连接每个点,以帮助可视化阈值从非常保守到更加宽松。最后,ROC 曲线有助于显示 AUC。

那么曲线下面积(AUC)是多少呢?

你经常会看到一个 ROC 图,有许多 ROC 曲线,每条曲线是一个不同的分类器(即。对数回归、SVC、决策树等。).AUC 是一个非常简单的指标,它提供了一个从 0 到 1 的十进制数,数字越大,分类器越好。AUC 衡量所有可能阈值的模型预测质量。一般来说,AUC 代表正确分类真阳性和真阴性数据点的概率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

怎么才能调整门槛?

# Adjusting the threshold down from 0.5 to 0.25
# Any data point with a probability  of 0.25 or higher will be 
#  classified as 1\. clf = LogisticRegression()
clf.fit(X_train, y_train)
THRESHOLD = 0.25
y_pred = np.where(clf.predict_proba(X_test)[:,1] >= THRESHOLD, 1, 0)
y_pred_proba_new_threshold = (clf.predict_proba(X_test)[:,1] >= THRESHOLD).astype(int)

逻辑回归没有调整阈值的内置方法。也就是说,因为我们知道默认情况下阈值设置为 0.50,所以我们可以使用上面的代码来说明任何高于 0.25 的值都将被归类为 1。

结论

我希望我能够帮助澄清一些关于分类标准的困惑。我发现保持所有的条款(即。召回、精准、TP、TN 等。)当你用一个特定的例子来记忆它们时,你的头脑会更清楚。癌症诊断)。

请随时提供您的反馈,并感谢您的阅读。

从零开始的分类模型

原文:https://towardsdatascience.com/classification-model-from-scratch-49f24bdd0636?source=collection_archive---------37-----------------------

使用 Python 从头构建朴素贝叶斯分类模型(简单分类模型)的初学者指南。

Github 库

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

卡梅隆·福克斯里《旧电脑的基本编程》

在机器学习中,我们可以使用概率来进行预测。也许最广泛使用的例子是所谓的朴素贝叶斯算法。它不仅简单易懂,而且在一系列问题上取得了令人惊讶的好结果。

朴素贝叶斯算法是一种基于贝叶斯定理的分类技术。它假设一个类中的一个特性与任何其他特性的存在无关。如以下公式所示,该算法依赖于给定预测值的类的后验概率:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中:

  • P(c|x) 是给定一个预测值的类的概率
  • P(x|c) 是给定 la 类的预测值的概率。也称为可能性
  • P© 是类的先验概率
  • P(x) 是预测值的先验概率。

或者用简单的英语来说,朴素贝叶斯分类器等式可以写成:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好消息是朴素贝叶斯分类器易于实现并且表现良好,即使训练数据集很小。在预测数据类别时,这是最好的快速解决方案之一。 Scikit-learn 为各种类型的问题提供不同的算法。其中之一就是高斯朴素贝叶斯。当要素为连续变量时使用,并假设要素遵循高斯分布。让我们深入挖掘,使用 Python 从头开始构建我们自己的朴素贝叶斯分类器。

1.加载所需的库

构建自己的朴素贝叶斯分类器唯一需要的库是 NumPy 。NumPy 是一个开源项目,旨在用 Python 实现数值计算,我们将使用它进行算术运算。

2.实例化该类

下一步是实例化我们的朴素贝叶斯分类器类。一个类就像一个对象构造器,或者一个创建对象的“蓝图”。在面向对象的编程语言中,几乎所有东西都是对象,包括它的属性和方法。

init”是 python 类中的保留方法。在面向对象的概念中,它被称为构造函数。当从类创建对象时调用此方法,它允许类初始化类的属性。

3.分开上课

根据贝叶斯定理,在试图预测某一特定类别之前,我们需要知道该类别的先验概率。为了计算这一点,我们必须将特征值分配给特定的类。我们可以通过分离类并将它们保存到字典中来做到这一点。

字典是 Python 对一种数据结构的实现,这种数据结构通常被称为关联数组。字典由一组键值对组成。每个键-值对都将键映射到其关联的值。

4.功能摘要(统计信息)

给定类别的可能性或预测值的概率假定为正态分布(高斯),并基于平均值和标准差*(见公式)*进行计算。我们将为数据集中的每个特征创建一个摘要,这样做可以使我们在将来更容易地访问特征的均值和标准差。

  • 这里的zip()函数是元组的迭代器,其中每个特性的值被配对在一起。在 Python 中,元组是不可变的复合数据类型。
  • 我们选择yield,因为我们想要生成一个值序列,稍后我们将对其进行迭代,而不需要显式地将该序列保存在内存中。

5.高斯分布函数

使用高斯分布函数计算遵循正态分布的要素的可能性:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了使用该公式进行进一步的计算,我们定义了一个分配方法,并完全按照上面的公式嵌入了该公式。

6.训练模型

训练模型意味着将模型应用于数据集,以便它可以遍历数据集并学习数据集的模式。在朴素贝叶斯分类器中,训练包括计算每个类的每个特征的平均值和标准差。这将允许我们计算用于预测的可能性。

如果我们仔细看看上面的代码片段,我们可以看到我们已经在训练数据集中分离了类。然后,计算每类的均值和标准差,然后使用len(feature_values)/len(X)计算该类的先验概率。

7.预测

为了预测一个类,我们必须首先计算每个类的后验概率。具有最高后验概率的类别将是预测的类别。

后验概率是联合概率除以边际概率。边际概率或分母是所有类的总联合概率,并且在所有类中都是相同的。我们需要具有最高后验概率的类,这意味着它将是最大的联合概率。

联合概率

联合概率是用于计算后验概率的分数的分子。对于多个特征,联合概率公式为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 Python 应用相同的公式会产生以下代码片段:

仔细看看上面的片段,我们对每个类都遵循了以下步骤:

  • 获得摘要(平均值、标准偏差和先验概率)
  • 计算每个特征的正态概率
  • 获得总可能性(所有正态概率的乘积)
  • 将先验概率乘以总似然得到联合概率。

预测班级

有了每个类的联合概率后,我们可以选择联合概率值最大的类:

max(joint_proba, key=joint_proba.get)

将所有这些放在一起

如果我们将联合概率步骤和预测类步骤放在一起,我们可以用下面的代码片段预测测试数据集中每一行的类。

8.准确度分数

计算准确度分数是测试任何机器学习模型的基本部分。为了测试我们的朴素贝叶斯分类器的性能,我们将正确预测的数量除以预测的总数,得到一个从 0 到 1 的数。

我们的 naive Bayes classifier vs . sk learn gaussianb

现在我们已经建立了分类模型,让我们使用 UCI 葡萄酒数据集来比较我们的模型与 scikit-learn 的 GaussianNB 模型的性能。

朴素贝叶斯分类器

naive Bayes 分类器精度: 0.972

Sklearn 高斯 NB(朴素贝叶斯)

sci kit-学习高斯精度: 0.972

如您所见,模型的准确性是相同的,这意味着我们从头开始实现了一个成功的高斯朴素贝叶斯模型。

请随意使用这里的 github 资源库来查找整个 python 文件和用于创建本文的笔记本。

参考

朴素贝叶斯分类器如何在机器学习中工作

UCI 葡萄酒数据集

Scikit-学习朴素贝叶斯

脑 MRI 的肿瘤/非肿瘤分类

原文:https://towardsdatascience.com/classification-of-brain-mri-as-tumor-non-tumor-d48838ccc162?source=collection_archive---------24-----------------------

学习训练和应用一个简单的 CNN 来区分有肿瘤的 MRI 和没有肿瘤的 MRI。

大家好!作为一名生物医学本科生,如果我没有向大家展示一个 AI 在医学 中的应用,这难道不是我的错吗?在这个故事中,我将介绍 d eep learning 在医学领域的实际应用,以及它如何在很大程度上帮助医生和放射科医生。

概观

我将在这个实验中使用的数据集来自 Kaggle 链接https://www . ka ggle . com/navoneel/brain-MRI-images-for-brain-tumor-detection

首先,让我描述一下我们将在这里解决的问题。在这种情况下,我们希望将在轴面上获得的患者大脑的 MRI 扫描分类为是否存在肿瘤。我正在分享一个有肿瘤和没有肿瘤的核磁共振扫描的样本图像。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有肿瘤的核磁共振

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

没有肿瘤的磁共振成像

我们看到在第一张图片中,在大脑的左侧,有一个肿瘤形成,而在第二张图片中,没有这样的形成。因此,我们可以看到这两幅图像之间有明显的区别。现在,我们将如何使用人工智能或深度学习来将图像分类为肿瘤或不是肿瘤?

答案是卷积神经网络 ( CNN )。CNN 或 ConvNet 是深度学习的一类,多应用于分析视觉图像。python 中有很多框架可以应用 CNN 如 TensorFlowPyTorch 来训练模型。我将使用带有 TensorFlow 后端的 Keras 库来训练这个模型。好吧!技术术语说够了,让我们回到解决问题上来。

步骤 1:数据可视化

第一步,我们将分析 MRI 数据。在这个问题中,我们一共有 253 张核磁共振图像。其中, 155 标注为“ 是” ,表示有肿瘤,其余 98 标注为“ ”,表示没有肿瘤。

print("The number of MRI Images labelled 'yes':",len(os.listdir('yes')))print("The number of MRI Images labelled 'no':",len(os.listdir('no')))The number of MRI Images labelled 'yes': 155The number of MRI Images labelled 'no': 98

现在,在一个 CNN 中,我们要训练一个 神经网络 ,它可以被可视化为一系列的算法,可以识别一组数据中图像之间的关系,并可以对它们进行分类。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

CNN 架构的一个例子。(图片来自 engmrk.com)

简单来说,神经网络的功能类似于 人脑 。我们用一组带有标签(是或否)的图像来训练神经网络,它有能力理解这两个类别之间的差异。因此,当我们给神经网络一个新的未标记图像时,它可以用训练过程中获得的知识对该图像进行分类。很简单,不是吗?

在我们的例子中,我们有 253 个图像,其中 155 个属于“是”类,98 个属于“否”类。我们遇到了一个新问题,称为数据不平衡。 数据不平衡 是每类的观测值数量分布不均匀的地方(这里我们有 155 个属于“是”类,只有 98 个属于“否”类)。难道我们的神经网络不会在“不”类中得不到足够的训练吗?😦

步骤 2:数据扩充

为了解决这个问题,我们使用了一种叫做 的技术,数据扩充 。这是医学中一个非常重要的方面,在医学中会有很多数据不平衡的例子。不明白吗?加油!通常,在大多数情况下,不健康患者的数量会比健康患者的数量少得多。不是吗?

在数据增强中,我们获取特定的 MRI 图像,并执行各种类型的 图像增强 ,例如旋转、镜像和翻转,以获得更多数量的图像。我们将对图像数量较少的类应用更多的增强,以使两个类的图像数量大致相等。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据扩充

从上面的图像中,我们可以看到应用于“是”类 MRI 图像的各种增强。通过这种方式,我们增加了数据集的所有图像。

因此,在对我们的数据集应用数据扩充之后,我们有“是”类的图像 1085 和“否”类的 图像 979 。几乎相等,对吗?

*print(f"Number of examples: {m}")print(f"Percentage of positive examples: {pos_prec}%, number of pos examples: {m_pos}")print(f"Percentage of negative examples: {neg_prec}%, number of neg examples: {m_neg}")Number of examples: 2064 Percentage of positive examples: 52.56782945736434%, number of pos examples: 1085 Percentage of negative examples: 47.43217054263566%, number of neg examples: 979*

步骤 3:拆分数据

下一步,我们将数据分为训练集和测试集。图像的 80% ( 1651 个图像)将进入训练集,我们的神经网络将使用该训练集进行训练。剩余的 20% ( 413 张图像)将进入测试集,我们将使用该测试集应用我们训练好的神经网络并对其进行分类,以检查我们的神经网络的准确性。

*The number of MRI Images in the training set labelled 'yes':868The number of MRI Images in the test set labelled 'yes':217The number of MRI Images in the training set labelled 'no':783The number of MRI Images in the test set labelled 'no':196*

步骤 4:构建 CNN 模型

好吧!很好,你已经明白了。现在,我一直告诉你的神经网络在哪里?只是在这个下一步,我们设计了一个神经网络使用 Keras 库与各种卷积和池层。

*model = tf.keras.models.Sequential([tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(150, 150, 3)),tf.keras.layers.MaxPooling2D(2,2),tf.keras.layers.Conv2D(32, (3,3), activation='relu'),tf.keras.layers.MaxPooling2D(2,2),tf.keras.layers.Conv2D(64, (3,3), activation='relu'),tf.keras.layers.MaxPooling2D(2,2),tf.keras.layers.Flatten(),tf.keras.layers.Dense(512, activation='relu'),tf.keras.layers.Dense(1, activation='sigmoid')])model.compile(optimizer='adam'), loss='binary_crossentropy', metrics=['acc'])*

*对于本文来说,对这些层的解释有点复杂。我将在后面的文章中解释神经网络的设计。到目前为止,你可以把它看作是帮助’*记忆’图像数据的一系列语句。

步骤 5:预先训练 CNN 模型

在这之后,我们将创建一个“ train_generator 和“validation _ generator”来将我们的训练集和测试集的分割图像存储到两个类中(是和否)。

*Found 1651 images belonging to 2 classes. 
Found 413 images belonging to 2 classes.*

如我们所见,2084 幅图像被分为 1651 幅(80%)用于“训练 _ 生成器”的图像和 413 幅(20%)用于“验证 _ 生成器”的图像。

步骤 6:训练 CNN 模型

最后,我们进入将图像数据拟合到训练好的神经网络的阶段。

*history=model.fit_generator(train_generator,epochs=2,verbose=1,validation_data=validation_generator)*

我们将训练大约 100 个“ 时期 ”的图像数据。一个时期可以被认为是一个迭代*,其中我们一次又一次地馈送训练图像,以便神经网络用训练图像得到更好的训练。*

*Epoch 1/100 50/50 [==============================] - 22s 441ms/step - loss: 0.7400 - acc: 0.5703 - val_loss: 0.6035 - val_acc: 0.6901 Epoch 2/100 50/50 [==============================] - 20s 405ms/step - loss: 0.6231 - acc: 0.6740 - val_loss: 0.5508 - val_acc: 0.7409 Epoch 3/100 50/50 [==============================] - 20s 402ms/step - loss: 0.6253 - acc: 0.6460 - val_loss: 0.5842 - val_acc: 0.6852 Epoch 4/100 50/50 [==============================] - 20s 399ms/step - loss: 0.6421 - acc: 0.6517 - val_loss: 0.5992 - val_acc: 0.6562 Epoch 5/100 50/50 [==============================] - 20s 407ms/step - loss: 0.6518 - acc: 0.6599 - val_loss: 0.5719 - val_acc: 0.7433 Epoch 6/100 50/50 [==============================] - 21s 416ms/step - loss: 0.5928 - acc: 0.6920 - val_loss: 0.4642 - val_acc: 0.8015 Epoch 7/100 50/50 [==============================] - 21s 412ms/step - loss: 0.6008 - acc: 0.6840 - val_loss: 0.5209 - val_acc: 0.7579 Epoch 8/100 50/50 [==============================] - 21s 411ms/step - loss: 0.6435 - acc: 0.6180 - val_loss: 0.6026 - val_acc: 0.6973 Epoch 9/100 50/50 [==============================] - 20s 408ms/step - loss: 0.6365 - acc: 0.6480 - val_loss: 0.5415 - val_acc: 0.7627 Epoch 10/100 50/50 [==============================] - 20s 404ms/step - loss: 0.6383 - acc: 0.6354 - val_loss: 0.5698 - val_acc: 0.7966*

从上图可以看出,训练集的“ acc 【精度】随着每次迭代不断提高。这意味着神经网络模型能够在将图像分类为肿瘤或非肿瘤方面有所改进。记下“”val _ ACC*”[验证精度],它表示测试集上模型的精度。很高,不是吗?*

在第 100 个历元结束时,我们看到训练好的 CNN 模型的验证准确率为 73.85%

这表明我们的神经网络可以正确地将大约 74%的测试集图像分类为肿瘤或非肿瘤。很准,不是吗?

*Epoch 100/100 50/50 [==============================] - 20s 402ms/step - loss: 0.3604 - acc: 0.8720 - val_loss: 0.5600 - val_acc: 0.7942*

第七步:CNN 模型的分析

在训练之后,我们最终为所有 100 个时期(迭代)绘制“训练 _ 生成器”和“验证 _ 生成器”的“准确性”和“损失”。

*外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传**外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

准确度和损耗图*

在这个故事的最后,使用这个模型,你可以输入一个单独的核磁共振图像,检查它是否有肿瘤。很酷,不是吗?

我已经分享了我的 GitHub 资源库的链接,在那里你可以找到代码和数据供你试用。所以,继续吧,转到我的存储库并开始实验。

* [## MK-gurucharan/脑肿瘤检测

这是一个储存库,有各种核磁共振成像的肿瘤检测代码。总共有 253 张图片,标签为…

github.com](https://github.com/mk-gurucharan/Brain-Tumor-Detection)

希望我已经对这个问题做了很好的解释,让你了解 CNN 及其在医学上的应用。请务必查看我的 Github 以获得详细的代码版本。到那时,快乐的机器学习!*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值