Apache Spark:哈希还是字典?
作为构建推荐系统的一部分,我最近不得不计算大量数据中的文本相似度。如果你对 Spark 的一个字符串相似性算法感兴趣,可以看看。
本文的结构。
- 实验背后的动机。
- TF-IDF 的 Spark 实现及其重要性。
- 比较和结论。
动机
这不是我的问题陈述,但为了简单起见,让我们假设你有两列这样的单词,我们必须匹配它们。
List A | List B
---------------------
GOOGLE INC. | Google
MEDIUM.COM | Medium Inc
Amazon labs | Amazon
Google, inc | Yahoo
在这个例子中,我们的目标是将 GOOGLE INC .和 GOOGLE,INC .匹配到 GOOGLE;并使 MEDIUM.COM 与媒体公司相匹配;以及亚马逊实验室到亚马逊等。
最简单的方法之一是计算这个单词列表的 TF-IDF 分数,并创建一个这样的矩阵。
该矩阵基本上具有 TF-IDF 得分,行和列元素为“GOOGLE”、“MEDIUM”。com ‘,‘亚马逊实验室’,‘谷歌’,‘雅虎’,’ COM '按顺序。我只是加了‘com’来展示 IDF 有多牛逼。如果一个术语在语料库中出现多次,那么它对于该特定文档就变得不太重要。添加了虚构的公司“com ”,因此“Medium.com”中的“Medium”变得更加重要。
如果 sklearn 行就能搞定这个,为什么还要用 spark?嗯,我的输入文件有 660 万行,正如你所猜测的,我的 Mac 真的不能处理这些。
我们找到动机了。让我们点燃激情。
Spark 和 TF-IDF
Spark 附带的一个示例脚本是针对文档集的 TF-IDF 的实现。这当然使事情变得更容易,因为只需要一点点的预处理,我就可以开始了。
由于我不能在这里展示机密数据的解决方案,我将只处理这个例子这里给出的微小数据。
如果您查看第一个表,它是应用标准 TF-TDF 脚本的结果,通过简单的分析,您可以将单词列中的单词映射到特征列中的值。比如‘我’大概 29。
这个方法在我的情况下完全没有用。我有大约 200 万个不同的单词,却没有办法将这些值映射回单词。😦
为什么?Spark 在这里,使用的是一个哈希函数。哈希函数利用了哈希技巧。通过应用散列函数将原始特征映射到索引(术语)中。这里使用的哈希函数是 MurmurHash 3。然后基于映射的索引计算术语频率。
虽然这种方法避免了计算全局术语-索引映射的需要,这对于大型语料库来说可能是昂贵的,但是它遭受潜在的哈希冲突,其中不同的原始特征在哈希之后可能变成相同的术语。😕
必须找到一种方法来检索单词到值的映射。解决方案?计数矢量器。
在上图中,第二个表是使用 countvectorizer 对数据进行令牌化并获得 TF 而不是散列函数的结果。“词汇表”存储所有不同的单词,它们的索引是值。是的。😃
比较和结论
但是等等。
这是哈希函数和字典之间的一个古老的权衡。在什么情况下哈希函数会更好?为什么 Spark 有 2 个版本计算 TF-IDF?
再来看存储:
HashingTF 需要固定大小的存储,与词汇表的大小无关。CountVectorizer 需要与词汇表大小成比例的存储空间。实际上,计数通常需要额外的特征选择。
转型呢?
HashingTF 只需要对数据进行一次扫描,不需要额外的存储和转换。CountVectorizer 必须扫描数据两次(一次用于构建模型,一次用于转换),需要与唯一标记数量成比例的额外空间和昂贵的排序。
显然,这两种实现各有优缺点。这就是我的结论。如果 TF-IDF 只是另一个需要数字特征的算法的预处理步骤,那么与 CountVectorizer 相比,HashingTF 的工作速度更快,内存效率更高。由于我当前的模块仅仅停留在计算单词的相似性,我需要知道反向映射和 CountVectorizer 似乎更合适。😃
感谢阅读!
PS:这篇论文让我对特性散列有了很好的了解,可能值得一读。
苹果也想让你的手机看到
在谷歌的 I/O 事件之后,我写道谷歌希望你的手机看到。当然,在 WWDC,苹果也为 iOS 应用程序推出了令人兴奋的新机器学习驱动功能。
苹果为开发者提供了一些不同可定制级别的框架,实现难度越来越大。
Vision and NLP purpose-built frameworks and CoreML for all kinds of other use cases, and you can build anything you want with the ‘ML Performance Primitives’
无论视觉材料是照片还是视频,Vision framework 都非常擅长查看,这包括人脸识别和对象跟踪,NLP(自然语言处理)有助于从话语或文本中提取意思。
CoreML 可以帮助应用程序做所有你期望的事情,包括识别声音剪辑和图片中发生的事情。
这一切都很酷,但这并不新鲜——其他系统已经有了。这里很酷的一点是,这些技术都是关于在设备上运行的,而且启动并运行起来非常容易*。*
在设备上更好,因为你不通过网络发送数据进行处理,这意味着你保留了你正在处理的内容的隐私,没有相关的数据成本,即使你没有网络覆盖,也可以使用。如果你关注这些东西,你应该听说过为 HBO 的硅谷开发的而非热狗应用。该过程中的一个重要经验是决定在设备上运行分类器,以获得准确性、性能和经济性。
Not Hotdog 博客文章还解释了在设备上运行 TensorFlow 模型的一些困难。这需要一些时间,而且没有很好的例子,他们直接与 TensorFlow 团队一起工作以获得使其工作的技巧。CoreML 更多的是关于在设备上运行,它主要是关于易用性。易用性是…另一回事。
在 WWDC 的 CoreML 演示中,苹果澄清了任务声明:
“CoreML 旨在尽可能轻松地将机器学习模型集成到您的应用程序中。”
有一种新的描述模型的公共格式,并且有新的工具可以将现有的经过训练的模型转换成这种格式。
The model gets compiled into your app, so it’s bundled right onto the device
花
一旦到了那里,演示表明你可以教一个应用程序通过拖动模型并编写 3 行代码来识别图片中的花的类型。真的就这么简单。
苹果公司强调,他们设计这种模式的目的是为了让 Xcode 开发中的其他一切工作起来完全一样,这样工程师就不需要新的技能来利用这些模式。
Literally drag and drop
访问分类器遵循现有的模式,提前输入建议有助于实现。
Converted to an MLmodel type, Xcode can compile the classifier to Swift generated source
应用该模型就像直接将图像作为输入传递给它一样简单。
The Classifier has a prediction output
您可以从模型的预测中访问“flowerType”字符串。对于演示来说,最简单的事情就是将它作为一个标签。
See the available attributes of the prediction
你就完了。
With just that, choosing a picture results in the model predicting the type of flower and changing the caption
不是花呢?
显然,弄清楚你正在看的是哪种花是一个利基用例——尽管这确实是在大约一个月前的一次家庭公园散步中出现的——但应用程序开发人员可以轻松地在应用程序中使用机器学习模型才是重点。
Some functions Apple suggests for this capability
有很多方法可以使用这些模型。应用程序可以为社交分享提供预测标记,以确保你的朋友——以及未来的你——可以找到你发布的他们最感兴趣的内容。使用带铅笔的 iPad Pro,应用程序可以像对待打字文本一样对待手写输入。表情符号建议是一个巨大的机会,我对此特别兴奋。
虽然所有这些事情听起来很有趣,但这也是一件严肃的事情。金融科技的应用可能是无穷无尽的,但一些基本的用例包括:
- 上传前,在捕获时识别文档类型;确认客户提供了正确的文件,没有来回
- 客户服务情绪响应度;对心烦意乱的客户和好奇的人做出不同的回应
- 优化建议;基于最佳实践或以前的客户端行为,预测设置和输入
今后
苹果向前迈出了一大步,让开发者能够轻松地将这些功能融入他们的应用。与所有事情一样,我们应该期待看到一些简单的用例几乎立即出现。这些大多不会去任何地方,这很好!公司会进行试验,但并不是所有的试验都会成功。
在此之后,我们应该期待下一代体验——无论是第一次体验的迭代,还是需要更长时间才能推向市场的新体验——开始发挥作用。
一如既往,问题是:现在有什么是可能的,而以前没有?
应用假设检验和 Spearman 等级相关系数揭示世界范围内的自杀现象
介绍
背景: 据世界卫生组织(世卫组织)统计,全球每年约有一百万人自杀,每年死亡率为 11.6/10 万人。每年有如此多的人自杀,这是一个令人震惊的事实。你可以想象每 40 秒就有一个人自杀,据估计,到 2020 年,每 20 秒就有一个人死于自杀。
我们可以使用数据分析来研究全球自杀数据,并使用统计技术量化我们的结果。这将有助于我们了解世界各地发生的自杀事件。
本研究的目的 :
展示统计方法在现实世界问题中的应用,以发现我们在对数据集进行初步分析后所做的假设是否具有统计学意义。
在这里,我们将解释和应用两个众所周知的统计技术。假设检验
2。斯皮尔曼等级相关系数
这些统计实验的结果将为我们分析一组数据后所做的假设提供具体的证明。
什么是假设检验?
《牛津词典》将假设的含义定义为“在有限证据的基础上做出的假设或提出的解释,作为进一步研究的起点”
假设检验,也称为验证性数据分析是一种通过统计证据来确定我们假设的假设是真还是假的技术。
例如,我们可以获取两家不同公司生产的相同/相似产品的价格数据集,并想知道一家公司的产品是否比另一家贵。
我们的目的可以通过假设检验来实现。
Flowchart for Hypothesis Testing
零假设 是我们在测试开始时做出的默认假设。就像,两组数据之间没有显著差异。 交替假设 是这种假设的对立面。
检验统计量 是两组数据之间的均值、中值、标准差等的差异,这是我们从两组数据中抽取样本并计算检验统计量后实际观察到的。
决定 样本大小 是一个非常重要的因素,因为测试统计值会根据样本大小而不同。样本量越大,结果就越准确。
显著性水平或阿尔法 是概率的阈值,我们根据它来决定是接受还是拒绝我们的零假设。默认情况下,取 5%或 0.05。如果需要非常高的精确度,您可以降低它。
P 值 是通过重采样和排列测试
计算出来的,下面的插图会让事情更清楚****
Re-Sampling illustration 1
Re-Sampling illustration 2
Re-Sampling illustration 3
下一步是对我们从 K 次重采样中得到的均值差的数据列表进行升序排序。k 可以是 100,1000 或任何我们认为合适的数字。
Calculation of P-Value
所以,p 值是我们测试统计的百分位数(delta),小于 100%。如果 delta 位于第 90 百分位,则 p 值为 10%或 0.10。
做出最终决定
我们说,p 值是假设我们的零假设为真,观察到δ的概率。
因此,如果我们的假设实际上是真的,观察到我们在进行实验时实际观察到的结果的概率(delta)将会很高。“高”的意思不仅仅是显著性水平。
如果 p 值低于显著性水平,这意味着在零假设为真的情况下,我们实际观察的发生概率较低。
由此,我们可以说:
——当 p 值≥显著性水平时接受零假设。
-如果 p 值<显著性水平,拒绝零假设并接受替代假设。
自杀率数据集
数据集来源:https://www . ka ggle . com/russellyates 88/自杀率-概览-1985 年至 2016 年
按年份和国家将社会经济信息与自杀率进行比较
www.kaggle.com](https://www.kaggle.com/russellyates88/suicide-rates-overview-1985-to-2016)
在这项研究中,我使用了 python 库:Numpy、Pandas、Matplotlib、Seaborn 和 scikit-learn。让我向您展示我是如何对这个数据集进行探索性数据分析和假设检验的。
正在加载。csv 文件转换成熊猫数据帧
#Importing python libraries
import numpy as np
import pandas as pd
import seaborn as sb
import matplotlib.pyplot as mp
#Loading csv file into pandas dataframe
SuicideData= pd.read_csv('master.csv')
SuicideData.head()
数据集的初步分析
print(SuicideData.shape)
print(SuicideData.columns)
There are 27820 Data points(Rows) and 12 Columns. Also showing column names for future reference
print(SuicideData.age.value_counts())
The data set has 6 age groups
SuicideData['suicides/100k pop'].mean()
Mean Suicide rate/100k persons on the whole population
上述结果并不准确,但非常接近世卫组织公布的数字 11.6。这可能是因为我们的数据样本较少。
我们进一步挖掘数据,根据性别和年龄组进行分析。下面是代码片段和结果:
#DIVIDING BY GENDER
M=SuicideData[SuicideData.sex=='male']
F=SuicideData[SuicideData.sex=='female']print('TOTAL MALE POPULATION = ',M.population.sum())
print('TOTAL MALE SUICIDES = ',M.suicides_no.sum())
print('AVERAGE MALE SUICIDES per 100k Population = ',M['suicides/100k pop'].mean())
print('TOTAL FEMALE POPULATION = ',F.population.sum())
print('TOTAL FEMALE SUICIDES = ',F.suicides_no.sum())
print('AVERAGE FEMALE SUICIDES per 100k Population = ',F['suicides/100k pop'].mean())print('\nAVERAGE SUICIDE RATES BY AGE GROUP')
print(SuicideData.groupby(['age'])['suicides/100k pop'].mean())print('\nAVERAGE SUICIDE RATES OF MALES BY AGE GROUP')
print(M.groupby(['age'])['suicides/100k pop'].mean())print('\nAVERAGE SUICIDE RATES OF FEMALES BY AGE GROUP')
print(F.groupby(['age'])['suicides/100k pop'].mean())print("\nSUICIDE RATE RATIO of FEMALE:MALE = 1 :",(M['suicides/100k pop'].mean()) / (F['suicides/100k pop'].mean()))
箱线图——男性与女性的自杀率
sb.boxplot(x='sex',y='suicides/100k pop', data=SuicideData)
mp.show()
小提琴情节——男性与女性自杀率对比
sb.violinplot(x='sex',y='suicides/100k pop', data=SuicideData)
mp.show()
根据年龄组显示自杀率——箱线图
sb.boxplot(x='age',y='suicides/100k pop', data=SuicideData)
mp.show()
75+ years age group is most Suicidal
初步分析的观察结果
- 男性自杀人数和自杀率都远高于女性。女性:男性= 1 : 3.75
- 即使我们按照年龄组来研究他们,结果也是一样的。
- 一个惊人的事实是,75 岁以上年龄组的人自杀倾向最强,无论性别如何。
- 5-14 岁年龄组自杀倾向最小,这很正常。
问题:哪个国家的自杀倾向最强?
我们将找到答案,并使用假设检验对其进行量化。按国家分组后,计算自杀率的平均值和中位数,并对结果进行排序。这将使我们成为自杀率最高的国家。
suicide_mean_by_country=pd.DataFrame(SuicideData.groupby(['country'])['suicides/100k pop'].mean())
suicide_mean_by_country = suicide_mean_by_country.sort_values(by='suicides/100k pop', ascending=False)
suicide_mean_by_country
Ranking by Mean Suicide Rates
suicide_median_by_country=pd.DataFrame(SuicideData.groupby(['country'])['suicides/100k pop'].quantile(0.5))
suicide_median_by_country = suicide_median_by_country.sort_values(by='suicides/100k pop', ascending=False)
suicide_median_by_country
Ranking by Median Suicide Rates
我们观察到,除了斯里兰卡和日本之外,十大自杀国家中几乎 90%来自欧洲和俄罗斯。我们可以宣布立陶宛是自杀率最高的国家,但在做出决定之前,最好用一些统计数据来量化结果。
应用假设检验找出世界上自杀率最高的国家
我们进行假设检验,因为当按平均值排名时,立陶宛以高得多的值排名第一,但当按中位数排名时,斯里兰卡以非常小的差距在立陶宛之上。
如果假设检验证明立陶宛和斯里兰卡的自杀率没有显著差异,我们肯定可以认为立陶宛是世界上自杀率最高的国家(基于 1985-2016 年的数据)。
无效假设 —立陶宛和斯里兰卡的自杀率没有显著差异。
交替假设— 立陶宛和斯里兰卡的自杀率存在显著差异。
检验统计 —立陶宛和斯里兰卡自杀率中位数的差异 。
我们从每个国家的 100 个中选取 样本量 ,并设定 显著性水平为 5% (0.05)。
现在我们进行实验。首先我们按国家划分数据。
lithuania=SuicideData[SuicideData.country=='Lithuania']
srilanka=SuicideData[SuicideData.country=='Sri Lanka']
然后我们从立陶宛和斯里兰卡各随机抽取 100 个数据点。
sample_lithuania=lithuania.sample(100)
sample_srilanka=srilanka.sample(100)
现在,我们只从样本数据的 pandas 数据帧中取出自杀率列,并将其转换为 numpy 数组,以便于计算。
S1=np.array(sample_lithuania['suicides/100k pop'])
print(S1)
median1=np.median(S1)
print('MEDIAN1=',median1)
Numpy array of Lithuania sample suicide rates
S2=np.array(sample_srilanka['suicides/100k pop'])
print(S2)
median2=np.median(S2)
print('MEDIAN2=',median2)
Numpy array of Sri-Lanka sample suicide rates
我们可以看到,即使是两国样本的自杀率中位数也非常接近。因此,我们现在计算我们的测试统计值如下
TS= median1-median2
print("Test Statistic is (Median of Lithuania - Median of Sri Lanka)=", TS)
如前所述,下一步是将两组样本数据连接成一组,并对它们进行混排,这样两组数据的观察值就能正确地混合成一组数据。
S= np.concatenate((S1,S2), axis=None)
np.random.shuffle(S)
print(S)
200 mixed observations from both countries
我们通过取 100 个点的两个样本集来执行 1000 次重采样,并且每次计算它们的中位数的差。中值差列表存储在另一个 numpy 数组中。
#Randomly sample 100-100 data points and calculate the difference of medians
medianlist=np.zeros(1000)
for i in range(1000):
_s1= np.random.choice(S,100)
_s2= np.setdiff1d(S, _s1)
_median1= np.median(_s1)
_median2= np.median(_s2)
medianlist[i]= np.array(_median1 - _median2)
最后一步,对 medianlist 进行升序排序,计算 p 值,得出最终结论。代码片段和结果如下:
medianlist=np.sort(medianlist)#calculation of p-value
ct=0
for i in medianlist:
if i < TS:
ct+=1
pvalue= (1000-ct) / 1000medianlist=pd.DataFrame(medianlist, columns=['mediandiff'])
pv95=medianlist.mediandiff[949]
print('VALUE in 95th Percentile position=', pv95)
print('TEST STATISTIC =',TS)
print('P-VALUE OF TS =', pvalue)if pvalue>0.05:
print('OBSERVATION VALUE IS LOWER THAN THE 95th Percentile.\nTHUS probability of OCCURENCE OF OUR OBSERVATION GIVEN NULL HYPOTHESIS IS High, AS P-VALUE OF {} IS HIGHER THAN THE SIGNIFICANCE LEVEL OF 0.05'.format(pvalue))
print('SO WE ACCEPT THE NULL HYPOTHESIS AS TRUE : LITHUANIA AND SRI LANKA HAVE NO SIGNIFICANT DIFFERENCE IN SUICIDE RATES')
else:
print('OBSERVATION VALUE IS HIGHER THAN THE 95th Percentile.\nTHUS probability of OCCURENCE OF OUR OBSERVATION GIVEN NULL HYPOTHESIS IS Extremely Low, AS P-VALUE OF {} IS LOWER THAN THE SIGNIFICANCE LEVEL OF 0.05'.format(pvalue))
print('SO WE REJECT THE NULL HYPOTHESIS AND ACCEPT THE ALTERNATE HYPOTHESIS : LITHUANIA AND SRI LANKA HAVE A SIGNIFICANT DIFFERENCE IN SUICIDE RATES')
if TS > 0:
print('FROM THE SIGN OF TS WE KNOW LITHUANIA HAS A HIGHER SUICIDE RATE')
else:
print('FROM THE SIGN OF TS WE KNOW SRI LANKA HAS A HIGHER SUICIDE RATE')
p 值为 0.511 意味着,鉴于立陶宛和斯里兰卡的自杀率之间没有显著差异,我们的样本观察结果出现的概率接近 50%,远高于 5%的显著性水平。因此,我们接受我们的零假设为真。
所以我们可以说立陶宛是世界上自杀率最高的国家 因为立陶宛和第二高的国家——斯里兰卡的平均自杀率差异很大,但中位数差异并不显著。因此,我们通过我们的判断基于平均差异。
现在你可能会怀疑假设检验的结果,所以我将展示如果我们对立陶宛和日本进行同样的检验会发生什么。
假设检验:立陶宛和日本哪个国家更有自杀倾向?
我们知道日本的自杀率比立陶宛低得多,根据中位数排名,日本排在第八位。因此,如果我们的假设检验给出了相同的结果,那么我们可以相信这种检验方法。
零假设 —立陶宛和日本的自杀率没有显著差异。
替代假设— 立陶宛和日本的自杀率存在显著差异。
检验统计 —立陶宛和日本自杀率中位数的差异 。
我们从每个国家的 100 个中取 样本量 ,并设定 显著性水平为 5% (0.05)。
为日本执行采样:
sample_japan=japan.sample(100)S3=np.array(sample_japan['suicides/100k pop'])
print(S3)
median3=np.median(S3)
计算测试统计值
TS2=median1-median3
print("Test Statistic is (Median of Lithuania - Median of Japan)=", TS2)
连接和洗牌:
SS= np.concatenate((S1,S3), axis=None)
np.random.shuffle(SS)
print(SS)
随机抽取 100–100 个数据点,计算中位数的差值
medianlist2=np.zeros(1000)
for i in range(1000):
_s1= np.random.choice(SS,100)
_s3= np.setdiff1d(SS, _s1)
#print(_s1)
#print(_s3)
_median1= np.median(_s1)
_median3= np.median(_s3)
medianlist2[i]= np.array(_median1 - _median3)
对中值列表排序后的最终计算和结果
medianlist2=np.sort(medianlist2)#calculation of p-value
ct2=0
for i in medianlist2:
if i < TS2:
ct2+=1
pvalue2= (1000-ct2) / 1000medianlist2=pd.DataFrame(medianlist2, columns=['mediandiff'])
pv95_2=medianlist2.mediandiff[949]
print('VALUE in 95th Percentile position=', pv95_2)
print('TEST STATISTIC =',TS2)
print('P-VALUE OF TS =', pvalue2)
if pvalue2>0.05:
print('OBSERVATION VALUE IS LOWER THAN THE 95th Percentile.\nTHUS probability of OCCURENCE OF OUR OBSERVATION GIVEN NULL HYPOTHESIS IS High, AS P-VALUE OF {} IS HIGHER THAN THE SIGNIFICANCE LEVEL OF 0.05'.format(pvalue2))
print('SO WE ACCEPT THE NULL HYPOTHESIS AS TRUE : LITHUANIA AND JAPAN HAVE NO SIGNIFICANT DIFFERENCE IN SUICIDE RATES')
else:
print('OBSERVATION VALUE IS HIGHER THAN THE 95th Percentile.\nTHUS probability of OCCURENCE OF OUR OBSERVATION GIVEN NULL HYPOTHESIS IS Extremely Low, AS P-VALUE OF {} IS LOWER THAN THE SIGNIFICANCE LEVEL OF 0.05'.format(pvalue2))
print('SO WE REJECT THE NULL HYPOTHESIS AND ACCEPT THE ALTERNATE HYPOTHESIS : LITHUANIA AND JAPAN HAVE A SIGNIFICANT DIFFERENCE IN SUICIDE RATES')
if TS2 > 0:
print('FROM THE SIGN OF TS WE KNOW LITHUANIA HAS A HIGHER SUICIDE RATE')
else:
print('FROM THE SIGN OF TS WE KNOW JAPAN HAS A HIGHER SUICIDE RATE')
我们的假设检验证明,立陶宛的自杀率高于日本,因为 p 值极低,约为 1%。
总结一下
Summary Report
因此,我们可以得出结论,假设检验是一种很好的方法,可以通过统计证明来检验一个假设的可能性。
问题:自杀率是否依赖于人均 GDP?
人们可能会想,当一个地方的经济条件恶化时,自杀的人会更多,而当经济条件或收入较好时,自杀的人会更少。我们可以从我们的自杀数据集中找出这种情况是否真的发生,并用另一个测试参数(称为 Spearman 等级相关系数)对其进行量化。
什么是斯皮尔曼秩相关系数?
这是一种测试,用来确定一个随机变量的值是否稳定地增加或减少,而另一个随机变量的值是否有相同的变化。称之为单调地递增或递减。如果一个增加而另一个增加,则结果为正(+),如果一个减少而另一个增加,则结果为负(-)。结果介于-1 和+1 之间。
假设有两组随机变量 X 和 Y,首先对它们进行排序。这种相关性是基于他们的排名,而不是他们的价值观。这就是为什么这项技术受异常值的影响最小。
应用 Spearman 等级相关系数回答我们的问题
在我们的案例中,我们可以测试人均 GDP 的变化是否会带来自杀率的变化。
让我们绘制一个图表并可视化数据,其中 X 轴是人均 GDP的增长,Y 轴是每 10 万人口的自杀人数。它也根据 年龄组 进行颜色编码**
**sb.set_style("whitegrid");
sb.FacetGrid(SuicideData, hue="age", height=7) \
.map(mp.scatter, "gdp_per_capita ($)", "suicides/100k pop") \
.add_legend();
mp.show();**
我们可以看到,人均国内生产总值较高的点较少,但数据点分散,似乎没有很好的相关性。因此,最好将数据分成不同的年龄组,对它们进行绘图,并找到它们各自的 Spearman 等级相关系数值。我已经使用了scipy . statspython 库来计算我们的结果。
**#DIVIDING BY AGE GROUPA5_14=SuicideData[SuicideData.age=='5-14 years']
A15_24=SuicideData[SuicideData.age=='15-24 years']
A25_34=SuicideData[SuicideData.age=='25-34 years']
A35_54=SuicideData[SuicideData.age=='35-54 years']
A55_74=SuicideData[SuicideData.age=='55-74 years']
A75P=SuicideData[SuicideData.age=='75+ years']**
图形的代码片段
**sb.set_style("whitegrid");
sb.FacetGrid(A5_14, hue='sex', height=5) \
.map(mp.scatter, "gdp_per_capita ($)", "suicides/100k pop") \
.add_legend();
mp.title('AGE GROUP 5-14')
mp.show();**
类似的代码可以用于每个年龄组
即使对于单个年龄组来说,这些特性也是相似的。现在我们计算系数值。
**#Spearman's rank correlation coefficient
#IF THERE IS A CORRELATION BETWEEN GDP PER CAPITA & SUICIDE RATES
#FOR ALL THE AGE GROUPSsp.spearmanr(A5_14['gdp_per_capita ($)'],A5_14['suicides/100k pop'] )
sp.spearmanr(A15_24['gdp_per_capita ($)'],A15_24['suicides/100k pop'] )
sp.spearmanr(A25_34['gdp_per_capita ($)'],A25_34['suicides/100k pop'] )
sp.spearmanr(A35_54['gdp_per_capita ($)'],A35_54['suicides/100k pop'] )
sp.spearmanr(A55_74['gdp_per_capita ($)'],A55_74['suicides/100k pop'] )
sp.spearmanr(A75P['gdp_per_capita ($)'],A75P['suicides/100k pop'] )**
****
我们观察到相关值非常接近于零。这表明人均 GDP 和自杀率之间没有相关性。
结论
你已经看到统计方法对于证实我们根据观察到的数据所做的任何假设是多么重要。有时我们观察到的一些东西可能实际上并不真实,这就是这些方法帮助我们证明我们的理论具有统计学意义的地方。
Github 代码链接
在 GitHub 上创建一个帐户,为 souravkajuri/suiciderate 开发做贡献。
github.com](https://github.com/souravkajuri/suiciderate)****
RNN 在顾客评论情感分析中的应用
在我之前的博客文章中,我写了关于使用 BeautifulSoup 收集两千多条 Flixbus 客户评论,并通过执行 NLP 分析来识别公司的优势和劣势。
基于之前的故事,我决定使用收集的文本数据来训练一个递归神经网络模型来预测客户的情绪,这被证明是非常高效的,在测试集上达到 95.93%的准确率。
什么是情感分析?维基百科提供了一个很好的解释:
“……情感分析旨在确定发言人、作者或其他主体对某个主题的态度,或对某个文档、互动或事件的整体上下文极性或情感反应。”——来源
事不宜迟,让我们开始实施吧。
加载和准备数据
首先,我加载了一个 csv 文件,其中包含 1,780 条英文客户评论,相应的评分从 1 到 5,其中 1 是最低(负面)评分,5 是最高(正面)评分。以下是对数据框的快速浏览:
Data frame with customer reviews and rating
太好了!现在我们有了可以处理的数据。然而,由于我们的目标是预测情绪——无论评论是正面的还是负面的,我们必须为这项任务选择适当的数据。
使用计数器功能,我注意到每个评分的评论分布相当不平衡:
# Count of reviews per rating
Counter({5: 728, 4: 416, 1: 507, 3: 86, 2: 43})
为了平衡它,并确保情绪类的良好表现,我决定保留“积极”的 5 星评论,而“消极”的 1 星和 2 星评论。结果,我得到了总共 1278 条评论的样本量。不多,但让我们看看能从中得到什么。
在处理评论之前,应该使用列表理解对情感进行二进制编码,1 表示积极情感,0 表示消极情感。
data['Sentiment'] = [1 if x > 4 else 0 for x in data.Rating]
现在我们有了一个基本的设置,是时候继续进行数据预处理了。
数据预处理
RNN 输入需要数组数据类型,因此,我们将“评论”转换为 X 数组,并将“情绪”转换为 y 数组。
X, y = (data['Review'].values, data['Sentiment'].values)
文本数据在输入 RNN 模型之前必须进行整数编码。这可以通过使用 Keras 库中的基本工具轻松实现,只需几行代码:
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequencestk = Tokenizer(lower = True)
tk.fit_on_texts(X)
X_seq = tk.texts_to_sequences(X)
X_pad = pad_sequences(X_seq, maxlen=100, padding='post')
首先,应该通过在数据集上安装标记器类来标记文本。如你所见,我使用“lower = True”参数将文本转换成小写,以确保数据的一致性。然后,我们应该使用 texts_to_sequences 类将单词(标记)列表映射到每个唯一单词的唯一整数列表。
Dictionary
作为一个例子,下面您可以看到在应用预处理后,原始评论是如何变成一个整数序列的。
Original reviews vs after tokenization and sequencing
接下来,我们使用整数列表上的 pad_sequences 类来确保所有评论的长度相同,这是为 RNN 模型准备数据的非常重要的一步。应用这个类要么将评论缩短到 100 个整数,要么在它们更短的情况下用 0 填充它们。
Reviews after padding
现在,我们使用 sklearn 的 train_test_split 将数据集分为训练集和测试集,并保留 25%的原始数据作为保留集:
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X_pad, y, test_size = 0.25, random_state = 1)
此外,训练集可以分为训练集和验证集:
batch_size = 64
X_train1 = X_train[batch_size:]
y_train1 = y_train[batch_size:]X_valid = X_train[:batch_size]
y_valid = y_train[:batch_size]
是时候使用 Keras 构建模型并使其符合训练数据了:
from keras.models import Sequential
from keras.layers import Embedding, LSTM, Dense, Dropoutvocabulary_size = len(tk.word_counts.keys())+1
max_words = 100embedding_size = 32
model = Sequential()
model.add(Embedding(vocabulary_size, embedding_size, input_length=max_words))
model.add(LSTM(200))
model.add(Dense(1, activation='sigmoid'))model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
由于嵌入需要词汇的大小和输入序列的长度,我们将词汇大小设置为 Tokenizer 字典中的单词数+ 1,将输入长度设置为 100 (max_words),其中后一个参数的值必须与填充(!idspnonenote)的值相同。).嵌入大小参数指定将使用多少维度来表示每个单词。通常使用值 50、100 和 300 作为该参数的输入,但在这种情况下,调整模型值 32 可获得最佳结果。
接下来,我们添加一个隐藏的 200 个内存单元的 LSTM 层。潜在地,添加更多的层和单元可以导致更好的结果。
最后,我们添加带有 sigmoid 激活函数的输出层来预测评论为正面的概率。
在对模型进行 10 个时期的训练后,我们在验证集和测试集上分别获得了 98.44%和 95.93%的准确率。
Training and testing accuracy results
Confusion matrix of hold out set prediction
是不是很牛逼?为了安全起见,我们再检查一下吧!
最终验证
为了进一步验证模型的准确性,我另外从 Trustpilot 搜集了 100 条 Flixbus 的最新客户评论,当然这些评论不包括在原始数据集中。新抓取的评论包括 1、4 和 5 星级评论,计数如下:
# Count of reviews per rating
Counter({1: 83, 4: 13, 5: 4})
为了准备用于预测的评论,在将它们传递到训练模型之前,必须对文本应用相同的预处理步骤。
# Prepare reviews for check
Check_set = df.Review.values
Check_seq = tk.texts_to_sequences(Check_set)
Check_pad = pad_sequences(Check_seq, maxlen = 100, padding = 'post')# Predict sentiment
check_predict = model.predict_classes(Check_pad, verbose = 0)# Prepare data frame
check_df = pd.DataFrame(list(zip(df.Review.values, df.Rating.values, check_predict)), columns = ['Review','Rating','Sentiment'])
check_df.Sentiment = ['Pos' if x == [1] else 'Neg' for x in check_df.Sentiment]
check_df
最后,我们得到以下结果:
Final check results
Confusion matrix of validation prediction
从上面的截图中,您可以立即发现一些错误分类的情况。在 100 个预测案例中,只有 16 个实际评级为 1 星的评论被错误地归类为“Pos”(具有正面情绪)。然而,如果我们深入挖掘,我们会发现问题实际上并没有看起来那么大:
Misclassifications
16 个案例中,只有 3 个独特的评论!一个评论重复 14 次(不公平💩).与此同时,所有评级为 4 和 5 的其他人都被正确分类为阳性。
就是这样!
呜哇!我们已经成功地训练和验证了 RNN 的情感预测性能。总的来说,这是一个相对简单和容易的任务,交付出色的结果。希望你喜欢这篇文章,并努力实现你自己!
机器学习在现代商业中的应用
Photo by Scott Graham on Unsplash
根据 Constellation Research 最近的一项研究,2017 年企业部门对人工智能的投资预计将增加两倍,预计到 2025 年将达到 1000 亿美元。仅此一点就足以凸显机器学习在当今商业中发挥的日益重要的作用。这也许就是为什么在最近的一项调查中,30%的参与者得出结论,人工智能和机器学习将在未来五年内大规模颠覆数字产业!
机器学习使公司能够促进增长、优化流程、改善客户体验并提高员工参与度。这里有几个坚实的例子,将展示人工智能和机器学习如何为当今的公司提供支持:
检测欺诈和可疑活动
如果数字可信的话,一个组织每年因欺诈损失 5%的收入。这就是人工智能和机器学习可以帮助你降低这些数字的地方。机器学习可以帮助您基于社交网络信息、历史交易、机器和其他数据建立模型,以开发一种有助于及时检测异常、异常值和异常的模式。
例如,银行可以利用历史数据建立基于以前欺诈活动的算法。因此,每当此类欺诈活动重复出现时,这将有助于您识别欺诈行为。
这是 PayPal 10 年来一直在做的事情。PayPal 每秒处理10,900 美元,2015 年在 202 个国家产生了 49 亿笔支付。这很好地解释了 PayPal 每秒钟都可能面临的风险。但是,PayPal 及其数据科学家和数学家使用自主开发的人工智能引擎来打击任何欺诈活动。
识别业务运营中可能存在问题的领域
商业运作中的问题几乎在任何地方都会突然出现。某台机器可能开始工作缓慢,或者可能有过量的产品订单。在这种情况下,机器学习会自动引起你的注意。
这可以通过在 HANA 的帮助下在您的系统上安装应用程序来轻松实现。因此,每次生产放缓时,HANA 都会处理数据并提供结果,以便您决定某台机器或设备是否需要关注或检查。
沃尔玛一直在使用 HANA 来监控其交易记录。事实上,沃尔玛在全球经营着超过 11,000 家店铺。他们一直在使用 HANA 来获得更好更快的控制;通过自动化操作来管理后台办公室。
通过识别客户行为模式简化销售运营
机器学习可以被证明是识别你的客户/线索行为的一个转折点,从而促进你的销售业务。事实上,客户服务软件公司 Zendesk 一直在使用领先的预测分析和机器学习软件 MarianalQ 来促进其销售。Zendesk 见证了销售线索质量的四倍增长。此外,通过社交定位,沃尔玛仅在三天内就接触到了 50%以上的顾客。
然而,这并不是结束。机器学习可以用于一系列其他领域,包括:
职业生涯规划
机器智能可以帮助进行适当的指导,从而建议员工选择职业道路,从而提高满意度、保留率和绩效。
无人机管理
在无人机的帮助下,机器学习可以进一步帮助及时检查商业结构。无人机可以点击图像,然后可以分析任何裂缝或退化。
简而言之,机器学习使一家公司能够用数字智能进行超乎想象的思考。可能性是无穷的。但是,有各种各样的障碍需要克服。最重要的是,应该有足够的数据来训练算法,以获得更好的输出。
人工智能在经济、贸易和预测中的应用
随着第一台计算机的出现,许多经济学家对计算机的应用感兴趣。随着互联网的发明,大量的数据可供分析。此外,这种趋势如今仍在继续,在许多现实世界的任务中,如交易,人工智能积极超越并取代金融工作者。
人工智能相对于人类的主要优势是处理大量输入数据的能力。例如,要评估未来的股票价格,你可以使用来自公司活动、评论、新闻、推特和许多其他来源的信息。相反,对于人类交易员来说,实时处理所有这些数据几乎是不可能的。看看这个:
研究人员开发了许多不同的技术,将人工智能应用于金融科技的各个分支。例如,递归神经网络在价格预测中显示出令人信服的结果。相应地,其他深度学习方法在破产和欺诈预测、信誉测量和风险管理方面表现出色。
Left — traders, Center — common machine trading systems, Right — HFT
高频交易的人工智能(HFT)
直到去年,HFT 交易员还在使用非常简单的算法。首先,他们的时间框架非常有限,所以十年前大数据分析不是一个选项。如今,机器学习在交易中的影响越来越大,而 GPU 和其他人工智能硬件为大型神经网络提供了高性能。快速下降的计算成本和延迟也在外汇交易的人工智能进化中发挥了重要作用。
学习如何制作人工智能驱动的交易软件
30 多年来,人工智能开发人员对其技能在金融领域的应用越来越感兴趣。由于这个原因,他们开发了第一批神经网络,甚至在 NN 在其他领域受到任何关注之前。这是可以理解的——金融科技公司的薪水相对较高。
今天你可以在网上学习如何创建这种程序。在这种情况下,您可能会对那些免费的审计课程感兴趣:
总而言之,我建议按照这个顺序去参观。然而,你可能会在 Coursera、edX 甚至 YouTube 等平台上找到更多的在线讲座。
最初发表于 认知混乱 。
强化学习在现实世界中的应用
没有推理,没有推论或比较的过程;没有对事物的思考,没有把两两放在一起;没有想法——动物不会想到盒子、食物或它要做的动作。———爱德华·桑戴克(1874-1949),提出效果定律的心理学家。
虽然卷积神经网络(CNN)和递归神经网络(RNN)因其在计算机视觉(CV)和自然语言处理(NLP)中的应用而对企业变得越来越重要,但强化学习(RL)作为计算神经科学的框架来模拟决策过程似乎被低估了。此外,似乎很少有资源详细介绍 RL 在不同行业中的应用。尽管对 RL 的弱点提出了批评,但鉴于其在辅助决策方面的巨大潜力,RL 在企业研究领域不应被忽视。正如 Deepmind 的研究主管 Koray Kavukcuoglu 在一次会议上所说,
“如果我们在这里工作的目标之一是人工智能,那么它就是它的核心。强化学习是学习顺序决策任务的一个非常通用的框架。另一方面,深度学习当然是我们用来学习表示的最佳算法集。这两种不同模型的结合是迄今为止我们在学习非常具有挑战性的任务的非常好的状态表示方面的最佳答案,这些任务不仅是为了解决玩具领域,而且实际上是为了解决具有挑战性的现实世界问题。”
因此,本文旨在 1)调查现实世界中强化学习应用的广度和深度;2)从不同角度看待 RL;3)说服决策者和研究人员加大研发力度。
文章的其余部分组织如下。第一节是总论。第二节介绍了 RL 在不同领域的应用,并简要说明了如何应用 RL。第三节总结了应用 RL 需要的东西。第四部分是来自其他学科的直觉,第五部分是关于 RL 在未来如何有用。第六部分是结论。
一、强化学习简介
RL 在机器学习中被称为半监督学习模型,是一种允许代理采取行动并与环境交互以最大化总回报的技术。RL 通常被建模为马尔可夫决策过程 (MDP)。
Source: Reinforcement Learning:An Introduction
想象一下,在你家(环境)给一个婴儿一个电视遥控器。简单来说,婴儿(代理人)将首先观察和构建他/她自己对环境(状态)的表征。然后,好奇的宝宝会采取某些行动,如按遥控器(行动),并观察电视会如何反应(下一个状态)。由于没有反应的电视是乏味的,婴儿不喜欢它(接受负面奖励),并会采取较少的行动导致这样的结果(更新政策),反之亦然。宝宝会重复这个过程,直到他/她找到一个自己满意的政策(不同情况下该怎么做)(最大化总(贴现)奖励)。
强化学习的研究就是要建立一个数学框架来解决问题。例如,要找到一个好的策略,我们可以使用基于值的方法,如 Q-learning,来衡量一个动作在特定状态下有多好,或者使用基于策略的方法来直接找出在不同状态下要采取什么动作,而不知道这些动作有多好。
然而,我们在现实世界中面临的问题可能在许多不同的方面极其复杂,因此典型的 RL 算法没有解决的线索。例如,在围棋游戏中,状态空间非常大;在扑克游戏中,环境无法完全观察到;在现实世界中,有许多智能体相互作用。研究人员发明了一些方法来解决一些问题,通过使用深度神经网络来建模期望的策略、价值函数甚至转换模型,因此这被称为深度强化学习。这篇文章没有区分 RL 和 Deep RL。
网上有很多关于 RL 的好东西,感兴趣的读者可以访问 awesome-rl 、 argmin 和 dennybritz 。
二。应用程序
这部分是写给一般读者的。同时,对于对 RL 有一定了解的读者来说,也将有更大的价值。
计算机集群中的资源管理
设计算法来将有限的资源分配给不同的任务是具有挑战性的,并且需要人类产生的启发。论文“具有深度强化学习的资源管理”【2】展示了如何使用 RL 来自动学习分配和调度计算机资源给等待的作业,目的是最小化平均作业减速。
状态空间被表述为当前的资源分配和作业的资源轮廓。对于动作空间,他们使用了一个技巧,允许代理在每个时间步选择多个动作。奖励是系统中所有工作的总和(-1/工作持续时间)。然后,他们结合强化算法和基线值来计算策略梯度,并找到最佳策略参数,以给出最小化目标的动作概率分布。点击这里查看 Github 上的代码。
交通灯控制
在论文“基于强化学习的网络交通信号控制多智能体系统”【3】中,研究人员试图设计一种交通灯控制器来解决拥堵问题。虽然只在模拟环境中测试,但他们的方法显示出优于传统方法的结果,并揭示了多智能体 RL 在设计交通系统中的潜在用途。
Five-intersection traffic network. Source.
五个智能体被放置在五个交叉路口的交通网络中,其中一个 RL 智能体位于中央交叉路口以控制交通信号。状态被定义为八维向量,每个元素代表每条车道的相对交通流量。代理人有八个选择,每个选择代表一个相位组合,奖励函数定义为与前一时间步相比延迟的减少。作者使用 DQN 来学习{状态,动作}对的 Q 值。
机器人技术
在机器人学中应用 RL 的工作非常多。读者可以参考【10】了解机器人领域的 RL 概况。特别是,【11】训练一个机器人学习策略,将原始视频图像映射到机器人的动作。RGB 图像被馈送到 CNN,输出是电机转矩。RL 组件是引导式策略搜索,用于生成来自其自身状态分布的训练数据。
Demo of the paper.
Web 系统配置
web 系统中有 100 多个可配置的参数,调整参数的过程需要熟练的操作员和大量的反复试验。论文“在线 web 系统自动配置的强化学习方法”【5】展示了在基于 VM 的动态环境中如何在多层 Web 系统中进行参数的自主重新配置的首次尝试。
重新配置过程可以被公式化为有限 MDP。状态空间是系统配置,动作空间是每个参数的{增加、减少、保持},奖励定义为给定的目标响应时间和测量的响应时间之差。作者使用无模型 Q 学习算法来完成这项任务。
虽然作者使用了一些其他技术(如策略初始化)来弥补该问题的大状态空间和计算复杂性,而不是 RL 和神经网络的潜在组合,但相信该开创性工作为该领域的未来研究铺平了道路。
化学
RL 还可以应用于优化化学反应。【4】在论文《用深度强化学习优化化学反应》中表明,他们的模型优于最先进的算法,并推广到不同的底层机制。
结合 LSTM 来对策略函数建模,RL 代理使用由{S,A,P,R}表征的马尔可夫决策过程(MDP)来优化化学反应,其中 S 是实验条件(如温度、pH 等)的集合,A 是可以改变实验条件的所有可能动作的集合,P 是从当前实验条件到下一个条件的转移概率,R 是作为状态的函数的回报。
应用很好地展示了 RL 如何在相对稳定的环境中减少耗时和反复试验的工作。
个性化推荐
以往的新闻推荐工作面临着新闻动态变化快、用户容易厌倦、点击率不能反映用户留存率等挑战。关捷等人在题为“DRN:新闻推荐的深度强化学习框架”的论文中已经将强化学习应用于新闻推荐系统,以解决这些问题【1】。
在实践中,他们构建了四类特征,即 A)用户特征和 B)上下文特征作为环境的状态特征,以及 C)用户新闻特征和 D)新闻特征作为动作特征。这四个特征被输入到深度 Q 网络(DQN)以计算 Q 值。基于 Q 值选择推荐一系列新闻,用户对新闻的点击是 RL 代理收到的奖励的一部分。
作者还采用了其他技术来解决其他具有挑战性的问题,包括记忆回放,生存模型,决斗土匪梯度下降等。详情请参考论文。
招标和广告
来自阿里巴巴集团的研究人员发表了一篇论文“展示广告中多代理强化学习的实时竞价”【6】,并声称他们的分布式基于集群的多代理竞价解决方案(DCMAB)取得了令人鼓舞的结果,因此他们计划在淘宝平台进行现场测试。
实现的细节留给用户去研究。一般来说,淘宝广告平台是商家为了向顾客展示广告而进行竞价的地方。这可能是一个多代理人的问题,因为商家正在相互竞价,他们的行为是相互关联的。在论文中,商家和顾客被分成不同的组以减少计算的复杂性。代理的状态空间表示代理的成本-收益状态,行动空间表示出价(连续),回报表示客户群带来的收益。
The DCMAB algorithm. Source: https://arxiv.org/pdf/1802.09756.pdf
本文还研究了其他问题,包括不同的报酬设置(自利与协调)对代理人收益的影响。
游戏
RL 如今如此知名,是因为它是用于解决不同游戏的主流算法,有时还能达到超人的性能。
RL vs linear model vs Human. Click here for the source.
最著名的一定是 alpha go【12】和 alpha go Zero【13】。通过在策略网络中使用价值网络和蒙特卡罗树搜索(MCTS ),用无数人类游戏训练的 AlphaGo 已经实现了超人的性能。然而,研究人员后来回想并尝试了一种更纯粹的 RL 方法——从头开始训练。研究人员让新代理 AlphaGo Zero 与自己对弈,最终以 100 比 0 击败 AlphaGo。
深度学习
最近可以看到越来越多的将 RL 和其他深度学习架构相结合的尝试,它们显示出令人印象深刻的结果。
RL 中最有影响力的作品之一就是 Deepmind 将 CNN 与 RL【7】结合的开创性工作。这样做,智能体就有能力通过高维度的感官“看见”环境,然后学会与之互动。
RL 和 RNN 是人们用来尝试新想法的另一种组合。RNN 是一种具有“记忆”的神经网络。当与 RL 结合时,RNN 赋予代理人记忆事物的能力。例如:[8]LSTM 与 RL 相结合,创建了深度递归 Q-Network(DRQN),用于玩 Atari 2600 游戏。[4]还利用 RNN 和 RL 解决了化学反应优化问题。
Deepmind 向 [9] 展示了如何使用生成模型和 RL 来生成程序。在该模型中,经过敌对训练的代理人使用信号作为奖励来改进动作,而不是像在 GAN 训练中那样将梯度传播到输入空间。
Input vs Generated result. See source.
三世。在将 RL 应用于您的问题之前,您需要了解什么
在应用 RL 之前,需要做几件事:
- 了解您的问题:您不一定需要在您的问题中使用 RL,有时您只是不能使用 RL。在决定使用 RL 之前,您可能需要检查您的问题是否具有以下某些特征:a)试错法(通过接收来自环境的反馈可以学着做得更好);b)延迟奖励;c)可以模拟为 MDP;d)您的问题是控制问题。
- 模拟环境:在 RL 算法工作之前,需要多次迭代。我敢肯定,你不希望看到一个 RL 代理尝试不同的东西在自动驾驶汽车在高速公路上,对不对?因此,需要一个能够正确反映现实世界的模拟环境。
- MDP:你的世界需要把你的问题变成一个 MDP。你需要设计状态空间、动作空间、奖励功能等等。您的代理人将在约束条件下执行其应执行的操作。如果你用不同的方式设计,你可能不会得到你想要的结果。
- 算法:有不同的 RL 算法可供您选择,您也可以自己提问。您想直接了解保单还是想了解价值函数?您想要无模型还是基于模型?您是否需要结合其他类型的深层神经网络或方法来解决您的问题?
为了保持客观和公正,您还会被警告 RL 的缺点,这里有一篇关于它的很棒的帖子。
静脉。其他学科的直觉
RL 与心理学、生物学、神经科学的关系非常密切。如果你想一想,RL 代理所做的只是试错:它根据从环境中获得的奖励来学习其行为的好坏。这正是人类学习做决定的方式。此外,探索和开发问题,信用分配问题,试图模拟环境也是我们在日常生活中面临的问题。
经济学理论也能对 RL 有所启发。特别地,多主体强化学习(MARL)的分析可以从博弈论的角度来理解,博弈论是由约翰·纳西开发的一个研究领域,用于理解系统中主体的交互作用。除了博弈论,MARL,部分可观察马尔可夫决策过程(POMDP)也可以用于理解其他经济主题,如市场结构(如垄断、寡头垄断等)外部性和信息不对称。
五、RL 未来可能实现的目标
RL 仍然有很多问题,不容易使用。然而,只要在解决这些问题上付出更多的努力,研究性学习将在以下几个方面产生影响:
- 协助人类:也许说人工智能有一天会进化成人工智能(AGI)有点过了,但人工智能肯定有潜力协助人类并与之合作。想象一下,一个机器人或一个虚拟助手与你一起工作,将你的行动纳入其考虑范围,以采取行动,从而实现一个共同的目标。那岂不是很棒?
- 理解不同策略的后果:生活如此神奇是因为时间不会倒流,事情只会发生一次。然而,有时我们想知道如果我采取不同的行动,事情会有什么不同(至少在短期内)?或者,如果教练采用另一种策略,克罗地亚会有更大的机会赢得 2018 年世界杯吗?当然,要做到这一点,我们需要对环境、转移函数等进行完美的建模,还要分析代理之间的相互作用,这在目前看来是不可能的。
六。结论
本文只是展示了 RL 在各种行业中应用的一些例子。他们不应该限制你的 RL 用例,一如既往,你应该使用第一原则来理解 RL 的本质和你的问题。
如果你是一家公司的决策者,我希望这篇文章足以说服你重新思考你的业务,看看 RL 是否有潜在的用途。如果你是一名研究人员,我希望你会同意我的观点,虽然 RL 仍然有不同的缺点,但这也意味着它有很多改进的潜力和很多研究机会。
你有什么想法?你能想到 RL 能解决的任何问题吗?
参考文献
[1]郑,张,郑,向,倪.袁,谢,李。DRN:新闻推荐的深度强化学习框架。2018.
[2] H.Mao,Alizadeh,M. Alizadeh,Menache,I.Menache 和 S.Kandula .具有深度强化学习的资源管理.2016 年 ACM 网络热点专题研讨会。
[3] I. Arel,C. Liu,T. Urbanik,A. Kohls,“基于强化学习的多智能体网络交通信号控制系统”,智能交通系统,2010 .
[4]周志忠、李晓霞和。用深度强化学习优化化学反应。ACSCentral Science3,2017。
[5]卜晓霞,饶军,徐春忠。在线 web 系统自动配置的强化学习方法。分布式计算系统,2009。第 29 届 IEEE 国际会议。IEEE,2019。
[6]靳,宋春春,李,盖,王,张。展示广告中基于多智能体强化学习的实时竞价。arXiv 预印本 arXiv:1802.09756,2018。
[7] V. Mnih、K. Kavukcuoglu、D. Silver、A. Graves、I. Antonoglou、D. Wierstra 和 M. Riedmiller。用深度强化学习玩雅达利。arXiv 预印本 arXiv:1312.5602,2013。
M. J. Hausknecht 和 P. Stone。部分可观测 MDP 的深度递归 Q 学习。继续。Conf .的。人工智能,AAAI,2015。
[9] Y. Ganin、T. Kulkarni、I. Babuschkin、S. Eslami 和 O. Vinyals 使用强化对抗学习的图像合成程序。arXiv 预印本 arXiv:1804.01118。
10j .科贝尔、J. A. D .巴格内尔、j .彼得斯。机器人学中的强化学习:综述。 Int。j .机器人。2013 年 7 月的决议。
[11] S. Levine、C. Finn、T. Darrell 和 P. Abbeel。深度视觉运动策略的端到端培训。arXiv 预印本 arXiv:1504.00702,2015。
[12]西尔弗、a .黄、a .、C.J .、A. Guez、L. Sifre、G. van den Driessche、J. Schrittwieser、I. Antonoglou、V. Panneershelvam、M. Lanctot、S. Dieleman、D. Grewe、J. Nham、N. Kalchbrenner、I. Sutskever、T. Lillicrap、M. Leach、K. Kavukcuoglu、T. Graepel 和 D. Has-sabis。用深度神经网络和树搜索掌握围棋。自然,529(7587)。2016.
[13]西尔弗、施里特维泽、西蒙扬、安托诺格鲁、黄、古埃斯、休伯特、贝克、赖、博尔顿、陈、利利卡普、许、西弗尔、范登德里斯切、格雷佩尔和哈萨比斯。在没有人类知识的情况下掌握围棋。《自然》,2017。
情感分析在商业中的应用
商业中的情感分析,也称为意见挖掘,是根据一段文本所传达的语气对其进行识别和分类的过程。这些文字可以是推文、评论、反馈,甚至是带有积极、消极和中性情绪的随机咆哮。每个企业都需要实施自动化情感分析。如果你怀疑,这里有一个小小的视角。准确率永远不可能是 100%。当然,机器不理解讽刺。然而,根据一项研究,人们不同意 80%的时间。这意味着,即使机器精度没有得到完美的 10 分,它仍将比人类分析更准确。此外,当语料库庞大时,手动分析不是一个选项。因此,商业情感分析不仅仅是一种趋势。
情感分析在商业中的作用:
情感分析在商业中的应用不容忽视。商业中的情感分析可以证明是全面品牌振兴的一个重大突破。利用情感数据成功经营企业的关键是能够利用非结构化数据获得可操作的见解。机器学习模型在分类前很大程度上依赖于人工创建的特征,在过去几年中很好地服务于这一目的。然而,深度学习是更好的选择,因为它:
- 自动提取相关特征。
- 有助于去除多余的功能。
- 排除了手工制作特征的努力。
在 ParallelDots,我们有强大的情感分析 API,它使用深度学习对给定文本的整体情感进行准确分析。
接下来是企业如何利用情绪分析数据:
商业智能构建中的情感分析;
拥有见解丰富的信息消除了猜测和及时决策的执行。有了关于你已有产品和新产品的情感数据,估计你的客户保持率就更容易了。基于商业中通过情感分析产生的评论,你可以随时调整以适应当前的市场形势,并以更好的方式满足你的客户。总的来说,您可以通过自动化洞察立即做出决策。商业智能就是始终保持动态。拥有情感数据给了你这种自由。如果你有了一个伟大的想法,你可以在实现它之前测试它。这就是所谓的概念测试。无论是新产品、活动还是新 logo,只要把它放到概念测试中,分析它所附带的情绪就可以了。
商业竞争优势中的情感分析:
如果你真的赶上了情感分析在商业中的应用,你应该有策略地尝试它。就像我之前提到的,情感分析可以在任何文本上进行。那么,为什么仅仅满足于将它应用于你的品牌呢?如果你没有一个 y%的指标与之比较,那么在某个产品上获得 x%的负面或正面评价是没有多大意义的。了解竞争对手的情绪数据会给你机会和动力来提升你的表现。商业情感分析对预测客户趋势非常有帮助。一旦你熟悉了当前的客户趋势,就可以很容易地开发出利用这些趋势的策略。并最终在竞争中获得领先优势。
通过商业情感分析提升客户体验:
一家企业依靠顾客的满意来生存。顾客的体验可以是正面的、负面的或中性的。由于互联网时代的到来,这种体验变成了他们社交帖子和在线反馈的文本。可以检测这些数据的语气和气质,然后根据附加的情感进行分类。这有助于了解在产品、服务和客户支持方面正确实施了什么,以及需要改进什么。
对你的产品获得积极的回应并不总是足够的。无论你的服务有多出色,你公司的客户支持系统都应该是无可挑剔的。
48 小时锁定退出@ Snapchat和@ Snapchat support仍未响应。这非常令人失望。#客户支持#不支持
**—蔡斯·莱帕德(@蔡斯·莱帕德)2016 年 12 月 10 日
商业情感分析促进品牌活力:
品牌不是由它制造的产品或提供的服务来定义的。建立一个品牌的名字和名气主要取决于他们的在线营销、社会活动、内容营销和客户支持服务。商业情感分析有助于量化当前和潜在客户对所有这些因素的看法。将负面情绪保留在知识中,你可以开发更吸引人的品牌技术和营销策略,从迟钝转变为了不起的品牌地位。商业中的情感分析可以帮助你快速转变。
情感分析在商业中的应用非常广泛。通过情绪分析获得更大的商业价值取决于你使用什么工具,以及你如何利用它。
对使用人工智能感兴趣?你现在可以免费注册账号,使用触手可及的人工智能。
应用深度学习-第 1 部分:人工神经网络
概观
欢迎来到应用深度学习教程系列。我们将从人工神经网络(ANN)开始,特别是前馈神经网络,对几种深度学习技术进行详细分析。本教程与您可以在网上找到的其他教程的不同之处在于,我们将采用一种带有大量代码示例和可视化的实践方法。为了将重点放在应用上,我不会深入这些模型背后的太多数学和理论。
我们将使用 Keras 深度学习框架,它是 Tensorflow 之上的高级 API。Keras 最近变得超级流行,因为它很简单。建立复杂的模型并快速迭代是非常容易的。我也用了准系统 Tensorflow,实际上很费劲。试用过 Keras 之后,我就不回去了。
这是目录。首先对 ANN 和这些深度模型背后的直觉进行概述。那么我们就从简单的 Logistic 回归开始,主要是为了熟悉 Keras。然后我们将训练深度神经网络,并演示它们如何优于线性模型。我们将比较二元和多类分类数据集上的模型。
- 安概述
1.1)简介
1.2)直觉
1.3)推理 - 逻辑回归
2.1)线性可分数据
2.2)复杂数据-月亮
2.3)复杂数据-圆 - 人工神经网络(ANN) 3.1)复数数据-月亮
3.2)复数数据-圆
3.3)复数数据-正弦波 - 多类分类 4.1) Softmax 回归
4.2)深安 - 结论
这篇文章的代码可以在这里获得作为一个 Jupyter 笔记本,请随意下载并亲自试用。
我想你会从这篇文章中学到很多。你不需要有深度学习的先验知识,只需要对一般的机器学习有一些基本的熟悉。所以让我们开始吧…
1.人工神经网络概述
1.1)简介
人工神经网络(ANN)是多层全连接神经网络,如下图所示。它们由一个输入层、多个隐藏层和一个输出层组成。一层中的每个节点都与下一层中的所有其他节点相连。我们通过增加隐藏层的数量使网络更深。
Figure 1
如果我们放大到一个隐藏或输出节点,我们将看到下图。
Figure 2
给定节点获取其输入的加权和,并将其传递给非线性激活函数。这是节点的输出,然后成为下一层中另一个节点的输入。信号从左向右流动,通过对所有节点执行该过程来计算最终输出。训练这个深度神经网络意味着学习与所有边相关联的权重。
给定节点的等式如下。通过非线性激活函数的输入的加权和。它可以表示为矢量点积,其中 n 是节点的输入数。
为了简单起见,我省略了偏差项。Bias 是所有节点的输入,其值始终为 1。它允许向左或向右移动激活功能的结果。它还有助于模型在所有输入特征都为 0 时进行训练。如果这听起来很复杂,你可以放心地忽略偏见条款。为了完整起见,上面的等式包括了偏差,如下所示。
到目前为止,我们已经描述了正向传递,这意味着给定一个输入和权重,如何计算输出。训练完成后,我们只运行正向传递来进行预测。但是我们首先需要训练我们的模型来实际学习权重,训练过程如下:
- 随机初始化所有节点的权重。我们将在另一篇文章中探讨一些智能初始化方法。
- 对于每个训练示例,使用当前权重执行向前传递,并从左到右计算每个节点的输出。最终输出是最后一个节点的值。
- 将最终输出与训练数据中的实际目标进行比较,并使用损失函数测量误差。
- 从右到左执行反向传递,并使用反向传播将错误传播到每个节点。计算每个权重对误差的影响,并使用梯度下降相应调整权重。从最后一层开始往回传播误差梯度。
梯度下降的反向传播实际上是深度学习模型背后的“魔法”。这是一个相当长的话题,涉及到一些微积分,所以我们不会在这个应用深度学习系列中深入讨论细节。关于梯度下降的详细说明,请参考此处的。反向传播的基本概述可以在这里找到。有关详细的数学处理,请参考此处的和此处的和。更多高级优化算法请参考这里的。
在标准的 ML 世界中,这种前馈架构被称为多层感知器。人工神经网络和感知器的区别在于,人工神经网络使用非线性激活函数,如 sigmoid ,而感知器使用阶跃函数。这种非线性赋予了人工神经网络更大的能力。
1.2)直觉
已经发生了很多事情,即使是基本的向前传球。现在我们来简化一下,理解一下背后的直觉。
本质上,人工神经网络的每一层所做的是输入从一个向量空间到另一个向量空间的非线性变换。
让我们以上面图 1 中的人工神经网络为例。我们有一个对应于 3D 空间中一个矢量的三维输入。然后,我们通过两个隐藏层传递它,每个隐藏层有 4 个节点。并且最终输出是 1D 矢量或标量。
因此,如果我们将此视为一系列矢量变换,我们首先将 3D 输入映射到 4D 矢量空间,然后执行另一个到新 4D 空间的变换,最后的变换将它简化为 1D。这只是一个矩阵乘法链。正向传递执行这些矩阵点积,并将激活函数逐元素应用于结果。下图仅显示了正在使用的权重矩阵(非激活)。
Figure 3
输入向量 x 有 1 行 3 列。为了将其转换到 4D 空间,我们需要将其乘以一个 3x4 矩阵。然后到另一个 4D 空间,我们乘以一个 4x4 矩阵。最后,为了将它简化到 1D 空间,我们使用了一个 4×1 的 T21 矩阵。
请注意矩阵的维度如何表示层的输入和输出维度。具有 3 个节点和 4 个节点的层之间的连接是使用 3x4 矩阵的矩阵乘法。
这些矩阵代表定义人工神经网络的权重。为了使用 ANN 对给定的输入进行预测,我们只需要知道这些权重和激活函数(以及偏差),仅此而已。我们通过反向传播训练人工神经网络来“学习”这些权重。
如果我们把所有东西放在一起,它看起来像下图。
Figure 4
一个 3 个节点和 4 个节点之间的全连通层,就是 1x3 输入向量(黄色节点)和 3x4 权重矩阵 W1 的矩阵相乘。这个点积的结果是一个表示为蓝色节点的 1x4 向量。然后我们将这个 1x4 向量乘以一个 4x4 矩阵 *W2,*得到一个 1x4 向量,即绿色节点。最后,使用一个 4x1 矩阵 W3 得到输出。
为了简单起见,我们在上面的图中省略了激活功能。实际上,在每次矩阵乘法之后,我们将激活函数应用于结果矩阵的每个元素。更正式地说
Equation 2
矩阵乘法的输出通过激活函数 f 。对于 sigmoid 函数,这意味着取矩阵中每个元素的 sigmoid。我们可以在方程中更清楚地看到矩阵乘法链。
1.3)推理
到目前为止,我们讨论了什么是深度模型以及它们是如何工作的,但是为什么我们首先需要深入呢?
我们看到,人工神经网络层只是对其输入进行从一个向量空间到另一个向量空间的非线性变换。如果我们以一个分类问题为例,我们希望通过绘制一个决策边界来区分各个类别。给定形式的输入数据是不可分离的。通过在每一层执行非线性变换,我们能够将输入投影到新的向量空间,并绘制复杂的决策边界来分离类别。
让我们用一个具体的例子来形象化我们刚刚描述的内容。给定以下数据,我们可以看到它不是线性可分的。
所以我们通过进行非线性变换,把它投影到一个更高维的空间,然后它就变成线性可分的了。绿色超平面是决策边界。
这相当于在原始输入空间中画了一个复杂的决策边界。
因此,拥有更深入的模型的主要好处是能够对输入进行更多的非线性转换,并绘制更复杂的决策边界。
总之,人工神经网络是非常灵活而强大的深度学习模型。它们是通用函数逼近器,这意味着它们可以模拟任何复杂的函数。最近,由于几个原因,它们的受欢迎程度出现了令人难以置信的飙升:使训练这些模型成为可能的巧妙技巧,计算能力的巨大增长,特别是 GPU 和分布式训练,以及大量的训练数据。所有这些结合在一起,使得深度学习获得了巨大的牵引力。
这是一个简单的介绍,网上有很多很棒的教程,涵盖了深度神经网络。作为参考,我强烈推荐这篇论文。这是对深度学习的精彩概述,第 4 部分涵盖了 ANN。另一个很好的参考是这本书,可以在网上找到。
2.逻辑回归
尽管名字如此,逻辑回归(LR)是一种二元分类算法。这是最流行的 0/1 分类技术。在二维(2D)数据上,LR 将试图画一条直线来区分类别,这就是术语线性模型的来源。不过 LR 可以处理任意数量的维度,而不仅仅是二维。对于 3D 数据,它会尝试绘制一个 2D 平面来分隔类别。这推广到 N 维数据和 N-1 维超平面分隔符。如果您有一个监督二进制分类问题,给定一个具有多列的输入数据和一个二进制 0/1 结果,LR 是第一个尝试的方法。在本节中,我们将重点关注 2D 数据,因为它更容易可视化,在另一个教程中,我们将重点关注多维输入。
1.1)线性可分离数据
首先让我们从一个简单的例子开始。2D 线性可分数据。我们使用 scikit-learnmake _ classification方法来生成数据,并使用一个辅助函数来可视化数据。
scikit-learn 中提供了一个 LogisticRegression 分类器,我在这里就不赘述了,因为我们的目标是学习用 Keras 构建模型。但这里是如何训练一个 LR 模型,使用 fit 函数,就像 scikit-learn 中的任何其他模型一样。我们将线性决策边界视为绿线。
正如我们所见,数据是线性可分的。我们现在将使用 Keras 训练相同的逻辑回归模型来预测每个输入点的类成员。为了简单起见,我们现在不执行将数据分离到训练集和测试集的标准实践,或者执行 k-fold 交叉验证。
Keras 有很棒的文档,查看它的 API 的更详细描述。这是训练模型的代码,下面我们一步一步来看。
我们将使用顺序模型 API,此处可用。顺序模型允许我们通过一层一层地堆叠来建立深度神经网络。由于我们现在正在构建一个简单的逻辑回归模型,我们将输入节点直接连接到输出节点,没有任何隐藏层。注意,LR 模型具有形式 y=f(xW) ,其中 f 是 sigmoid 函数。将单个输出层直接连接到输入反映了这一功能。
快速澄清以消除所用术语的歧义。在神经网络文献中,经常谈到输入节点和输出节点。乍一看,这听起来可能很奇怪,输入“节点”本身是什么?当我们说输入节点时,我们谈论的是给定训练示例的特征。在我们的例子中,我们有 2 个特征,即我们上面绘制的点的 x 和 y 坐标,因此我们有 2 个输入节点。你可以简单地把它想成两个数的向量。那么输出节点呢?逻辑回归模型的输出是一个单一数字,即属于类别 1 的输入数据点的概率。换句话说 P(class=1) 。属于类别 0 的输入点的概率为 P(类别= 0)= 1p(类别=1) 。因此,您可以简单地将输出节点视为一个 0 到 1 之间的单个数字(或简单的标量)的向量。
在 Keras 中,我们不添加对应于输入节点的层,我们只添加隐藏和输出节点。在我们当前的模型中,我们没有任何隐藏层,输入节点直接连接到输出节点。这意味着我们在 Keras 中的神经网络定义将只有一个层和一个节点,对应于输出节点。
model = Sequential()
model.add(Dense(units=1, input_shape=(2,), activation='sigmoid'))
Keras 中的 Dense 函数构建了一个完全连接的神经网络层,自动将权重初始化为偏差。这是一个超级有用的功能,你会看到它在任何地方都被使用。函数参数定义如下:
- 单位:第一个参数,表示该层的节点数。由于我们正在构建输出层,并且我们说它只有一个节点,因此该值为 1。
- input _ shape:Keras 模型中的第一层需要指定输入尺寸。后续层(这里没有,但我们将在后面的部分中)不需要指定此参数,因为 Keras 可以自动推断尺寸。在这种情况下,我们的输入维度是 2,x 和 y 坐标。input_shape 参数需要一个向量,所以在我们的例子中,它是一个只有一个数字的元组。
- 激活:逻辑回归模型的激活函数是逻辑函数,或者称为 sigmoid 。我们将在另一个教程中探索不同的激活函数,在哪里使用它们以及为什么使用它们。
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
然后我们用编译函数编译这个模型。这通过指定学习过程的细节来创建神经网络模型。模型还没有训练好。现在我们只是声明要使用的优化器和要最小化的损失函数。编译函数的参数定义如下:
- 优化器:使用哪个优化器来最小化损失函数。有很多不同的优化器,大多数都是基于梯度下降的。我们将在另一个教程中探索不同的优化器。现在我们将使用 adam 优化器,这是默认情况下人们更喜欢使用的一种。
- 损失:最小化的损失函数。由于我们正在构建一个二进制 0/1 分类器,要最小化的损失函数是 binary_crossentropy 。我们将在后面的章节中看到损失函数的其他例子。
- 指标:报告统计数据的指标,对于分类问题,我们将其设置为准确度。
history = model.fit(x=X, y=y, verbose=0, epochs=50)
现在有趣的部分来了,使用 fit 函数实际训练模型。论据如下:
- x :输入数据,我们定义为上面的 X 。它包含输入点的 x 和 y 坐标
- y :不要与输入点的 y 坐标混淆。在所有的 ML 教程中, y 指的是标签,在我们的例子中是我们试图预测的类:0 或 1。
- verbose :打印出损耗和精度,设置为 1 查看输出。
- 次数:查看整个训练数据的次数。当训练模型时,我们不止一次而是多次传递训练数据。
plot_loss_accuracy(history)
拟合方法的输出是每个时期的损失和精度。然后,我们使用自定义函数绘制它,可以看到损耗随着时间的推移下降到几乎为 0,而精度上升到几乎为 1。太好了!我们已经成功地用 Keras 训练了我们的第一个神经网络模型。我知道这是一个很长的解释,但我想第一次详细解释我们在做什么。一旦你明白发生了什么,并练习几次,所有这些都成为第二天性。
下面是一个决策边界图。蓝色和红色的不同阴影表示该区域中某个假想点属于 1 级或 0 级的概率。左上区域被分类为 1 类,颜色为蓝色。右下方区域被分类为 0 类,颜色为红色。在决策边界附近有一个过渡。这是可视化模型正在学习的决策边界的一种很酷的方式。
分类报告显示了我们模型的精度和召回率。我们接近 100%的准确率。报告中显示的值应该是 0.997,但它被四舍五入为 1.0。
混淆矩阵向我们展示了有多少类被正确分类和错误分类。对角线轴上的数字代表正确分类的点的数量,其余的是错误分类的点。这个特殊的矩阵不是很有趣,因为模型只错误分类了 3 个点。我们可以在混淆矩阵的右上角看到一个错误分类的点,真实值为 0 类,但预测值为 1 类。
2.2)复杂数据-卫星
以前的数据集是线性可分的,所以我们的逻辑回归模型分离类是微不足道的。这是一个更复杂的数据集,它不是线性可分的。简单的逻辑回归模型无法清楚地区分这些类别。我们使用 scikit-learn 的 make_moons 方法来生成数据。
让我们建立另一个逻辑回归模型,使用与之前相同的参数。在这个数据集上,我们得到了 86%的准确率。
当前的决策边界看起来不像以前那样清晰。该模型试图从中间分离出类,但有许多错误分类的点。我们需要一个具有非线性决策边界的更复杂的分类器,我们很快就会看到这样的例子。
模型的精度为 86%。它在纸上看起来不错,但我们应该很容易用更复杂的模型得到 100%。您可以想象一个弯曲的决策边界来分隔这些类,一个复杂的模型应该能够近似这一点。
分类报告和混淆矩阵如下所示。
2.3 复杂数据圈
让我们看最后一个例子,线性模型会失败。这次使用 scikit-learn 中的 make_circles 功能。
用相同的参数建立模型。
决策边界再次从数据的中间通过,但是现在我们有更多的错误分类的点。
准确率在 50%左右,如下图。由于数据集的性质,无论模型在哪里画线,都会对一半的点进行错误分类。
我们在这里看到的混淆矩阵是一个属于差分类器的例子。理想情况下,我们更希望混淆矩阵看起来像上面看到的那样。对角线上的高数字表示分类器是正确的,而其他地方的低数字表示分类器是错误的。在我们的视觉中,蓝色代表大的数字,黄色代表小的数字。所以我们更喜欢在对角线上看到蓝色,在其他地方看到黄色。到处都是蓝色是不好的迹象,意味着我们的分类器是混乱的。
无论输入是什么,总是预测 1 的最简单的方法将获得 50%的准确性。我们的模型也得到了 50%的准确率,所以一点用都没有。
3.人工神经网络
现在,我们将训练一个深度人工神经网络(ANN ),以更好地对逻辑回归模型难以处理的数据集,月亮和圆进行分类。我们还将对一个更难的正弦波数据集进行分类,以证明人工神经网络可以形成真正复杂的决策边界。
3.1)复杂数据-卫星
在为上述逻辑回归构建 Keras 模型时,我们执行了以下步骤:
- 步骤 1:定义一个顺序模型。
- 第二步:添加具有乙状结肠激活功能的致密层。这是我们需要的唯一一层。
- 步骤 3:用优化器和损失函数编译模型。
- 步骤 4:使模型适合数据集。
- 第五步:分析结果:绘制损失/准确性曲线,绘制决策边界,查看分类报告,了解混淆矩阵。
在构建深度神经网络时,我们只需要改变步骤 2,这样,我们将一个接一个地添加几个密集层。一层的输出成为下一层的输入。Keras 再次通过初始化权重和偏差来完成大部分繁重的工作,并将一层的输出连接到下一层的输入。我们只需要指定在给定的层中需要多少个节点,以及激活函数。就这么简单。
我们首先添加一个有 4 个节点和 tanh 激活函数的层。Tanh 是一个常用的激活函数,我们将在另一个教程中了解更多。然后,我们添加另一个层 2 节点再次使用双曲正切激活。我们最后添加最后一层 1 节点和 sigmoid 激活。这是我们在逻辑回归模型中使用的最后一层。
这不是一个很深的人工神经网络,它只有 3 层:2 个隐藏层,和输出层。但是请注意几个模式:
- 输出图层仍然使用 sigmoid 激活函数,因为我们正在处理二元分类问题。
- 隐藏层使用 tanh 激活功能。如果我们添加更多的隐藏层,他们也会使用 tanh 激活。我们有几个激活函数的选项:sigmoid、tanh、relu 和 relu 的变体。在另一篇文章中,我们将探讨每种方法的优缺点。我们还将演示为什么在隐藏层中使用 sigmoid 激活是一个坏主意。现在使用 tanh 是安全的。
- 我们在每个后续层中的节点数量更少。当我们将层堆叠在另一层之上时,通常会有较少的节点,有点像三角形。
我们没有在这里构建一个非常深的 ANN,因为这是不必要的。通过这种配置,我们已经实现了 100%的准确性。
人工神经网络能够提出一个完美的分隔符来区分类别。
100%精确,没有错误分类。
3.2)复杂的数据圈
现在让我们看看 Circles 数据集,其中 LR 模型仅达到 50%的准确率。模型同上,我们只使用当前数据集更改拟合函数的输入。我们再次达到了 100%的准确率。
类似地,决策边界看起来就像我们自己手绘的一样。人工神经网络能够找出最佳分离器。
就像上面一样,我们得到了 100%的准确性。
4.3)复杂数据-正弦波
让我们试着分类一个最终的玩具数据集。在前面的部分中,类可以通过一个连续的决策边界来分离。边界具有复杂的形状,它不是线性的,但是一个连续的判定边界就足够了。人工神经网络可以绘制任意数量的复杂决策边界,我们将演示这一点。
让我们创建一个正弦数据集,看起来像正弦函数,每个上下属于一个交替类。正如我们在图中看到的,一个单一的决策边界不能将类分开。我们需要一系列非线性分离器。
现在我们需要一个更复杂的模型来进行准确的分类。所以我们有 3 个隐藏层,和一个输出层。每层的节点数也有所增加,以提高模型的学习能力。选择正确的隐藏层和每层节点数是一门艺术,而不是科学,通常通过反复试验来决定。
人工神经网络能够模拟一组相当复杂的决策界限。
精确度是 99%,我们只有 2400 个错误分类点中的 14 个。非常好。
4.多类分类
在前面的章节中,我们研究了二元分类。现在,我们将研究一个多类分类问题,其中类的数量超过 2。我们将挑选 3 个类进行演示,但是我们的方法可以推广到任意数量的类。
这是我们的数据集的样子,螺旋数据有 3 个类,使用 scikit-learn 中的 make_multiclass 方法。
4.1) Softmax 回归
正如我们在上面看到的,逻辑回归(LR)是两类的分类方法。它适用于二进制标签 0/1。Softmax 回归(SR)是 LR 的一种推广,其中我们可以有两个以上的类。在我们当前的数据集中,我们有 3 个类,表示为 0/1/2。
为 SR 构建模型与 LR 非常相似,下面是我们如何构建逻辑回归模型的参考。
这就是我们将如何建立 Softmax 回归模型。
有几个不同之处,让我们一个一个来看:
- 密集层中的节点数:LR 使用 1 个节点,而 SR 有 3 个节点。因为我们有 3 个类,所以 SR 使用 3 个节点是有意义的。那么问题是,为什么 LR 只使用 1 个节点,它有 2 个类,所以看起来我们应该使用 2 个节点。答案是肯定的,因为我们只用一个节点就可以达到同样的效果。正如我们在上面看到的,LR 对属于第一类的例子的概率建模: P(class=1) 。我们可以通过*1p(class = 1)*计算 0 类概率。但是当我们有两个以上的类时,我们需要每个类有单独的节点。因为知道一类的概率并不能让我们推断出其他类的概率。
- 激活功能:LR 使用了 sigmoid 激活功能,SR 使用了 softmax 。Softmax 缩放输出节点的值,以便它们表示概率并且总和为 1。所以在我们的例子中P(class = 0)+P(class = 1)+P(class = 2)= 1。它不是用简单的方法,用个体概率除以总和,而是用指数函数。因此,较高的值得到更多的强调,较低的值受到更多的压制。我们将在另一个教程中详细讨论 softmax 的功能。现在,你可以简单地把它想成一个归一化函数,让我们把输出值解释成概率。
- 损失函数:在 LR 这样的二元分类问题中,损失函数是 binary_crossentropy。在多类情况下,损失函数是分类交叉熵。范畴交叉熵是二元交叉熵在两个以上类别上的推广。深入损失函数背后的理论超出了本教程的范围。但是现在只知道这个属性就足够了。
- Fit 函数:LR 在 fit 函数中直接使用了向量 y,该函数只有一列值为 0/1。当我们进行 SR 时,标签需要以一键表示。在我们的例子中,y_cat 是一个有 3 列的矩阵,其中所有的值都是 0,除了代表我们的类的值是 1。
花了一些时间来谈论 LR 和 SR 之间的所有差异,看起来有很多东西需要消化。但是再一次经过一些练习后,这将成为一种习惯,你甚至不需要考虑这些。
在所有这些理论之后,让我们后退一步,记住 LR 是一个线性分类器。SR 也是一个线性分类器,但是针对多个类。所以模型的“力”没有变,还是线性模型。我们只是推广了 LR,将其应用于多类问题。
训练模型给了我们 50%左右的准确率。无论输入是什么,总是预测类别 1 的最简单的方法将具有 33%的准确度。SR 模型并没有太大的改进。这是意料之中的,因为数据集不是线性可分的。
查看决策边界可以确认我们仍然有一个线性分类器。由于浮点舍入,这些线看起来参差不齐,但实际上它们是直的。
这是对应于 3 个类的精度和召回率。混乱矩阵到处都是。显然,这不是一个最佳的分类器。
4.2)深安
现在让我们为多类分类建立一个深度人工神经网络。记住从 LR 到 ANN 的变化是很小的。我们只需要增加更密集的层。我们将再次这样做。添加几个具有 tanh 激活功能的致密层。
请注意,输出层仍有 3 个节点,并使用 softmax 激活。损失函数也没变,还是分类 _ 交叉熵。从线性模型到深度人工神经网络,这些不会改变,因为问题的定义没有改变。我们仍在研究多类分类。但是现在使用一个更强大的模型,这种力量来自于给我们的神经网络增加更多的层。
我们在几个时期内就达到了 99%的准确率。
决策边界是非线性的。
我们得到了几乎 100%的准确率。1500 分中我们完全错分了 5 分。
5)结论
感谢您花时间阅读这篇文章,我知道这是一篇关于人工神经网络和 Keras 的相当长的教程。我想尽可能详细,同时保持文章长度可控。我希望你喜欢它。
这篇文章中有一个共同的主题,即我们首先介绍这个任务,然后使用一个简单的方法来完成它,并观察它的局限性。后来我们用一个更复杂的深度模型对它进行了改进,得到了更好的结果。我认为顺序很重要。没有一个复杂的方法是成功的,除非它是从一个简单的模型发展而来。
如果你想自己动手,这篇文章的全部代码可以在这里找到。如果你有任何反馈,请随时通过推特联系我。
应用深度学习-第 2 部分:真实世界案例研究
概观
欢迎来到应用深度学习系列的第 2 部分。第 1 部分是对人工神经网络的实际介绍,包括理论和应用,有很多代码示例和可视化。现在是最酷的部分,深度学习对真实世界数据集的端到端应用。我们将涵盖 3 个最常见的问题作为案例研究:二元分类,多类分类和回归。
- 案例分析:二元分类 1.1)数据可视化&预处理
1.2) Logistic 回归模型
1.3) ANN 模型
1.4)深层 ANN 可视化 - 案例分析:多类分类 2.1)数据可视化&预处理
2.2) Softmax 回归模型
2.3) ANN 模型
2.4)交叉验证 - 案例分析:回归 3.1)数据可视化&预处理
3.2)线性回归模型
3.3) ANN 模型 - 结论
这篇文章的代码可以从这里得到作为一个 Jupyter 笔记本,你可以随意下载并亲自试用。
1.案例研究:二元分类
我们将在 Kaggle 上使用人力资源分析数据集。我们试图根据各种特征来预测员工是否会离开,例如他们参与的项目数量、在公司呆的时间、上次绩效评估、工资等。数据集大约有 15,000 行和 9 列。我们试图预测的列称为“左”。这是一个具有 0/1 值的二进制列。标签 1 表示该员工已经离职。
1.1)数据可视化和预处理
首先,让我们在直接构建模型之前执行一些数据可视化和预处理。这一部分是至关重要的,因为我们需要知道我们正在处理什么类型的特性。对于每个 ML 任务,我们至少需要回答以下问题:
- 我们有什么类型的特征:实值的,分类的,还是两者都有?
- 是否有任何功能需要规范化?
- 我们有空值吗?
- 标签分布是怎样的,阶层不平衡吗?
- 特征之间有关联吗?
朱庇特笔记本包含了详细的分析。综上所述,既有真实特征,也有分类特征。没有空值,但有些要素需要规范化。76%的例子被标为 0,意味着员工没有离开。
让我们检查特征与标签的相关性(名为“left”的列)。我们将使用 seaborn 包来绘制相关图。
在该图中,正值表示与标签的相关性,负值表示与标签的反向相关性。当然“左”和它本身有很好的相关性,你可以忽略它。除此之外,只有一个特征有很强的信号,那就是“满意度”,与员工是否已经离职成反比。这很有道理。
现在,让我们来看看所有特性之间的成对相关性。
我们看到“平均 _ 月 _ 小时”与“数字 _ 项目”正相关,这也是有道理的。一个人参与的项目越多,需要投入的工作时间就越多。
现在我们来看看特征值的分布。通过检查特征的直方图,我们可以看到哪些特征需要归一化。这背后的动机是什么?规范化是什么意思,为什么需要规范化?如果实值特征被缩放到预定义的范围内,例如[0,1],大多数 ML 算法执行得更好。这对深度神经网络尤为重要。如果输入特征由大值组成,深度网络真的很难学习。原因在于,随着数据流经各层,伴随着所有的乘法和加法运算,数据会很快变大,这会使非线性饱和,从而对优化过程产生负面影响。我们将在另一篇文章中看到这方面的详细演示,因为现在我们需要注意特征值是小数字。
查看特征直方图,我们需要对其中的 3 个特征进行归一化:average_monthly_hours、number_project 和 time_spend_company。所有其他特征都在[0,1]内,所以我们可以不去管它们。
Scikit-learn 有几种归一化方法,我们将使用的是标准缩放器。它单独缩放要素,使其具有零均值和单位方差,因此它们都属于标准的正态(0,1) 分布。请注意,这不会改变特征值的顺序,只是改变了比例。这是一个简单却极其重要的技巧。
我们加载的数据在一个熊猫数据帧中。Pandas 是一个非常流行的处理表格数据的软件包,尤其是在像 jupyter 笔记本这样的交互式环境中。DataFrame 是 pandas 最常用的数据结构,它充当了我们数据的容器,并公开了几个内置函数,使我们的生活更加轻松(查看笔记本了解更多详细信息)。在下面的代码片段中,df 是我们数据的数据帧。
Scikit-learn API 设计得非常好,包含 4 个非常常用的方法。预测器是像逻辑回归这样的 ML 模型,转换器是像标准定标器这样的数据操纵器。
- fit : For 预测器对给定输入进行训练。For transformers 计算统计数据,如稍后要使用的输入的平均值和标准偏差。
- transform:For transformers 使用 fit 函数学习到的统计数据处理输入数据。我们在 fit 之后运行 transform 方法,因为存在依赖关系。预测者不支持这种方法。
- fit_transform :在一次调用中高效地执行 fit + transform。对于转换器,计算输入的统计信息并执行转换。这是变压器常用的方法。对于预测器,训练模型并对给定输入执行预测。
- *预测:*顾名思义,for predictors 使用用 fit 方法训练的模型来执行预测任务。非常常用于预测。变形金刚不支持这种方法。
既然我们已经将实值特征调整到了理想的范围内,那么让我们来处理分类特征。我们需要将分类数据转换成独热表示。例如,薪金列包含 3 个唯一的字符串值:低、中、高。一键转换后,我们将有 3 个新的二进制列:薪水 _ 低,薪水 _ 中和薪水 _ 高。对于给定的示例,它们中只有一个具有值 1,其他的都是 0。然后我们将删除原来的薪水栏,因为我们不再需要它了。
一键转换由熊猫的 get_dummies 执行。我们也可以在 scikit-learn 中使用onehotencode,它们都可以完成工作。因为我们的数据已经在熊猫的数据框架中,所以得到虚拟模型更容易。它还自动执行特征的重命名。
现在是创建训练和测试数据的最后一部分。该模型将在训练集上执行学习,并在保留的测试集上进行评估。Scikit-learn 有一个方便的 train_test_split 函数。我们只需要指定测试集的一部分,在我们的例子中是 30%。但是首先我们使用数据帧的 values 属性将数据从 pandas 数据帧转换为 numpy 数组。
1.2)逻辑回归模型
既然我们已经完成了数据预处理和训练/测试集生成,那么有趣的部分来了,训练模型。我们首先从一个简单的模型开始,逻辑回归(LR)。然后,我们将训练深度人工神经网络,并将结果与 LR 进行比较。
看完第一篇文章,构建模型应该很熟悉了。
我们得到了 79%的训练准确率。这实际上很糟糕,因为上面我们看到 76%的标签是 0。所以不管输入是什么,最简单的分类器总是输出 0,它能得到 76%的准确率,我们也没有比这更好的了。这意味着我们的数据不是线性可分的,就像我们在第一篇文章中看到的例子一样,我们需要一个更复杂的模型。
上图描述了训练损失和准确性。但更重要的是,我们对测试集的指标感兴趣。训练集中的度量标准可能会产生误导,因为模型已经在其上进行了训练,我们希望检查模型在保留的测试集上的表现。测试准确率为 78%,略低于训练准确率。ML 模型的测试精度几乎总是低于训练精度,因为在训练过程中测试数据对模型是不可见的。查看分类报告,我们看到属于类别 1 的示例中只有 60%被正确分类。相当糟糕的表现。混淆矩阵显示了许多错误分类的例子,看起来也不乐观。
1.3)人工神经网络模型
现在让我们建立一个深度神经网络进行二分类。这个模型将更加强大,能够模拟非线性关系。
模型构建过程也是非常熟悉的。我们有 2 个 64 和 16 节点的隐藏层,带有双曲正切函数。输出层使用 sigmoid 激活,因为这是一个二元分类问题。我们使用 Adam 优化器,学习率设置为 0.01。
这次我们达到了 97.7%的训练准确率,相当不错。
让我们比较一下 LR 和 ANN 模型。人工神经网络模型更优越,具有更低的损耗和更高的精度。
为了完整起见,这是测试集上人工神经网络模型的分类报告和混淆矩阵。与 LR 模型的 78%相比,我们实现了 97%的准确率。我们仍然对 4500 个例子中的 147 个进行了错误分类。
我们可以通过以下方法进一步提高人工神经网络的性能:
- 为模型定型更长时间(增加历元数)。
- 超参数调优:改变学习率,使用不同于 Adam 的优化器(比如 RMSprop),使用不同于 tanh 的另一个激活函数(可以是 relu)。
- 增加每层的节点数量:我们可以增加到 128–64–1,而不是 64–16–1。
- 增加层数:我们可以做 128–64–32–16–1 层。
不过,一个重要的警告是,随着我们使模型更强大,训练损失可能会减少,准确性会增加。但是我们会遇到过度拟合的风险。这意味着与简单模型相比,复杂模型在测试集上的表现更差,即使复杂模型的训练指标更好。我们将在另一篇文章中更多地讨论过度拟合,但记住这一点非常重要。这就是为什么我们不会为层数和每层节点数而疯狂。完成工作的最简单的模型就足够了。
1.4)深层人工神经网络的可视化
在上一篇文章中,我们了解到人工神经网络的每一层都执行输入从一个向量空间到另一个向量空间的非线性转换。通过这样做,我们将输入数据投射到一个新的空间,在这个空间中,类可以通过一个复杂的决策边界相互分离。
让我们直观地演示一下。我们在上面做的初始数据预处理之后的输入数据是 20 维的。为了形象化,让我们把它投射到 2D。请记住,一个层中有 k 个节点意味着该层转换其输入,从而输出是一个 k 维向量。我们上面训练的 ANN 有两个隐藏层,分别是 64 和 16 个节点。然后,我们需要一个有两个节点的新层,以便将我们的数据投影到 2D 空间。因此,我们在输出节点之前添加了这个新层。其余的完全没动过。
这是我们的输入数据从 20D 到 2D 空间的投影结果。决策边界对应于 ANN 的最后一层。人工神经网络能够很好地区分这些类别,尽管有一些分类错误。在 2D,许多数据点重叠,因此我们无法看到所有数据点,作为参考,该模型在 4500 个数据点中错误分类了约 160 个点(96%的准确率)。我们不关心这个模型的准确性,我们感兴趣的是高维输入到 2D 的投影。这是一个巧妙的小技巧,直观地展示了人工神经网络执行的投影的结果。
一种更有原则的可视化方法是使用 t-SNE ,这是一种用于可视化高维数据的降维技术。详情请点击这里。
2.案例研究:多类分类
我们现在将在著名的虹膜数据集上执行多类分类。它包含 3 类花,每类 50 个例子。总共有 4 个功能。所以它很小,但是很受欢迎。数据如下所示。
2.1)数据可视化和预处理
这部分现在更容易了,因为我们只有 4 个实值特征。同样,我们将特征归一化到[0,1]之间。特征值很小,我们可以不进行任何规范化,但是这样做是一个好习惯,而且这样做也没有坏处。
如果我们有少量的特征,Pairplot 是一个很酷的可视化技术。我们可以看到按类(数据集中的“标签”列)着色的要素的成对分布。我们使用 seaborn 包,对于一个信息丰富的情节来说非常简单。
我们可以看到“setosa”类很容易分开,但“versicolor”和“virginica”更容易混合。
2.2) Softmax 回归模型
我们现在将训练 Softmax 回归(SR)模型来预测标签。前一篇文章包含了详细的解释,构建模型也与上面非常相似。主要区别在于,我们使用 softmax 激活和分类 _ 交叉熵作为损失。
SR 模型已经达到了 97%的训练准确率和最小的损失,已经很不错了。
2.3)人工神经网络模型
现在让我们建立我们的人工神经网络模型。我们添加 2 个隐藏层,分别有 32 个和 16 个节点。注意我们也改变了这些层的激活函数为 relu 而不是 tanh。我们将在另一个教程中探讨各种激活函数及其差异,但 relu 可以说是最受欢迎的一个。那为什么我们没有使用它?嗯,只是因为 tanh 激活后决策边界图看起来更漂亮。说真的,没别的原因。
这次我们获得了 100%的训练准确率。
另外,随机共振和人工神经网络模型的测试准确率都是 100%。这是一个非常小的数据集,所以这些结果并不奇怪。不是所有的问题都需要深度神经网络才能得到好的结果。对于这个问题来说,这可能有点过了,因为线性模型也能很好地工作。
2.4)交叉验证
对于像我们目前这样的小样本情况,进行交叉验证以获得更好的准确性估计尤为重要。通过 k 折交叉验证,我们将数据集分成 k 个不相交的部分,使用 k-1 个部分进行训练,另一个部分进行测试。这样,每个例子都会出现在训练集和测试集中。然后,我们对所有 k 次运行中的模型性能进行平均,并获得模型准确性的更好的低方差估计。
通常在训练深度学习模型时,我们不会执行 k-fold 交叉验证。因为训练需要很长时间,而且从头开始训练模型 k 次是不可行的。但由于我们的数据集很小,所以它是一个很好的候选对象。
这是两个模型的 5 倍交叉验证准确度的曲线图。深度模型表现稍好,具有更高的准确性和更低的方差。在图中,精度有时似乎超过 100%,但这是平滑曲线的人工产物。我们得到的最大准确度是 100%。
3.案例研究:回归
我们现在将研究一个回归问题,预测一个实值输出而不是离散的类成员。我们将使用华盛顿州卡格尔市金县的房屋销售数据集。大约有 21,000 行 20 个特征。我们试图预测的值是一个标记为“价格”的浮点数。
3.1)数据可视化和预处理
首先让我们看看特性分布
现在你知道该怎么做了,我们需要做特征标准化和分类。例如,与 squarefoot 相关的要素肯定需要进行规范化,因为值的范围以千计,并且像 zipcode 这样的要素需要进行分类。
我们还需要做一种新的预处理, bucketization 。例如,包含房屋建造年份(yr _ built)的要素的范围从 1900 年到 2015 年。我们当然可以把它分类,每一年都属于一个不同的类别,但这样的话,它会相当稀疏。如果我们在不丢失太多信息的情况下取消这个特性,我们会得到更多的信号。例如,如果我们使用 10 年时段,则[1950,1959]之间的年份将折叠在一起。知道这栋房子建于 20 世纪 50 年代而不是 1958 年就足够了。
受益于分桶的其他特征是房屋的纬度和经度。确切的坐标没那么重要,我们可以把坐标四舍五入到最近的公里。这样,特征值将更加密集和信息丰富。在存储桶化中使用哪个范围没有硬性规定,它们主要是通过反复试验来决定的。
我们需要做的最后一个转换是关于房子的价格,我们试图预测的价值。目前,它的价值在 7.5 万美元到 770 万美元之间。试图在如此大的规模和变化范围内进行预测的模型将非常不稳定。所以我们也把它标准化了。有关详细信息,请随时查看代码。
在所有的转换之后,我们从 20 个特性增加到 165 个。让我们检查一下每个特性与价格的相关性。
最相关的特征是平方英尺,这是意料之中的,越大的房子通常越贵。看看这个列表,这些特性是有意义的。一些邮政编码与价格高度相关,例如 98039 对应于麦地那,那是比尔盖茨居住的地方,也是美国最昂贵的社区之一。还有另一个邮政编码 98004,它与贝尔维尤更相关。那里有许多高层建筑和技术办公室,这使得价格最近大幅上涨。我以前住在那个街区,但后来它变得太无聊和昂贵,所以我搬家了:)
3.2)线性回归模型
这是我们第一次建立回归模型。就像逻辑回归是我们在分类问题中首先尝试的最简单的模型一样,线性回归是我们在回归问题中开始的模型。
记住逻辑回归的方程式是 y=f(xW) 其中 f 是 sigmoid 函数。线性回归简单地说就是 *y=xW,*没有激活函数。为了简单起见,我再次省略了偏差项。随着偏差的增加,它们分别变为 y=f(xW+b) 和 y=xW+b 。
这里提醒一下我们如何建立逻辑回归(LR)模型
这是线性回归模型(LinR)的代码
有 3 个主要区别:
- LR 使用 sigmoid 激活函数,而 LinR 没有激活。
- LR 使用 binary_crossentropy 损失函数,LinR 使用 mean_squared_error。
- LR 也报告精度,但是精度不是回归问题的适用度量,因为输出是浮点数而不是类成员。
最重要的变化是损失函数均方误差 (MSE)。MSE 是用于回归的标准损失函数。公式很简单:
其中 y 为真值, ŷ 为预测值, n 为样本数。
我们还向 fit 函数传递了一个新的 validation_split 参数。它指定了在训练过程中用作保留验证集的训练数据部分,在我们的例子中是 20%。使用验证集,我们可以看到我们是否在训练中过度适应。但是不要混淆验证集和测试集。测试集是完全独立的,在训练过程中根本不会暴露给模型。
损失在最初几个时期减少,然后稳定下来。我们可能配置不足意味着我们的型号没有足够的容量,我们需要一个更复杂的型号。
这些是权重最高的前 10 个特征。分类邮政编码特征占主导地位。
3.3)人工神经网络模型
最后,让我们为回归建立一个人工神经网络。在前面的例子中,从线性模型到深度模型只涉及添加具有非线性激活函数的新层。这次也一样。
我们添加了 relu 激活的新层。损失图现在看起来很有趣。训练误差损失似乎仍在减少,但是验证误差在第 5 个时期之后开始增加。我们显然过度适应。人工神经网络正在记忆训练数据,这降低了它对验证集进行归纳的能力。
解决办法?有几种方法可以解决深度神经网络中的过拟合问题。大多数方法依赖于约束模型的容量。这可以通过例如限制重量、分享重量或者甚至在训练损耗达到稳定水平之前停止训练来实现。为了简洁起见,我们将使用最后一个,其余的将在另一篇文章中讨论。这意味着一旦确认损失停止改善,我们将简单地停止训练。这叫做提前停止,用 Keras 很容易实现。我们只需要修改对 fit 函数的调用,如下所示。如果两个时期的确认损失没有改善,我们停止训练。
验证损失在第 5 个时期停止改善,模型再等待 2 个时期,并在第 7 个时期完成训练。
LinR 模型的训练损失是 0.158,ANN 的损失是 0.086。我们比线性模型提高了 83%,相当不错。并且比较在测试集上的损失,LinR 模型得到 0.191,相比于 ANN 的 0.127,提高了 32%。下图比较了 LinR 与 ANN 的训练损失。
让我们做一个最后的比较,模型预测价格和实际价格之间的美元价值差异。最天真的模型总是预测训练集的平均价格(540,000 美元),在测试集上相差 229,000 美元,非常糟糕。线性回归模型的误差为 87K,而深度人工神经网络的误差为 68K。人工神经网络比线性神经网络好 21%。
4)结论
我希望这是一篇信息丰富的文章。我试图用现实生活中的数据集演示深度学习在 3 个常见机器学习问题上的一步一步的应用。
详细讨论了数据预处理和可视化。尽管它们不是解决一个 ML 问题的有趣部分,并且经常被忽视,但是它们是极其重要的。就像第 1 部分一样,我们首先用一个简单的模型解决问题,然后使用深度神经网络来获得更好的结果。
如果你想自己动手,这篇文章的全部代码可以在这里找到。如果你有任何反馈,请随时通过推特联系我。
应用深度学习-第 3 部分:自动编码器
概观
欢迎来到应用深度学习系列的第 3 部分。第 1 部分是对人工神经网络的实际介绍,包括理论和应用,有很多代码示例和可视化。在第二部分中,我们将深度学习应用于真实世界的数据集,涵盖了 3 个最常见的问题作为案例研究:二分类、多类分类和回归。
现在我们将开始深入具体的深度学习架构,从最简单的开始:自动编码器。
这篇文章的代码可以从这里获得作为一个 Jupyter 笔记本,你可以随意下载并亲自试用。
1.介绍
自动编码器是一种特定类型的前馈神经网络,其输入与输出相同。他们将输入压缩成一个低维的码,然后从这个表示中重建输出。代码是输入的一个紧凑的“总结”或“压缩”,也称为潜在空间表示。
自动编码器由 3 个部分组成:编码器、代码和解码器。编码器压缩输入并产生代码,然后解码器仅使用该代码重建输入。
要构建一个自动编码器,我们需要三样东西:编码方法、解码方法和一个损失函数来比较输出和目标。我们将在下一节探讨这些。
自动编码器主要是一种降维(或压缩)算法,具有几个重要属性:
- 特定数据:自动编码器只能有意义地压缩数据,就像它们被训练的那样。因为它们学习特定于给定训练数据的特征,所以它们不同于像 gzip 这样的标准数据压缩算法。因此,我们不能指望一个经过手写数字训练的自动编码器来压缩风景照片。
- 有损:自动编码器的输出将不会与输入完全相同,它将是一个接近但降级的表示。如果你想要无损压缩,他们不是出路。
- 无监督的:为了训练一个自动编码器,我们不需要做任何花哨的事情,只需要向它扔原始输入数据。自动编码器被认为是一种无人监管的学习技术,因为它们不需要明确的标签来训练。但更准确地说,它们是自我监督的,因为它们从训练数据中生成自己的标签。
2.体系结构
让我们来探讨编码器、代码和解码器的细节。编码器和解码器都是全连接的前馈神经网络,本质上是我们在第一部分中提到的神经网络。代码是人工神经网络的单层,具有我们选择的维度。代码层中的节点数量(代码大小)是我们在训练自动编码器之前设置的一个超参数。
这是一个自动编码器的更详细的可视化。首先,输入通过编码器,这是一个完全连接的人工神经网络,以产生代码。具有类似 ANN 结构的解码器仅使用代码产生输出。目标是获得与输入相同的输出。注意,解码器架构是编码器的镜像。这不是一个要求,但这是典型的情况。唯一的要求是输入和输出的维数需要相同。中间的任何东西都可以玩。
在训练自动编码器之前,我们需要设置 4 个超参数:
- 代码大小:中间层的节点数。尺寸越小,压缩越大。
- 层数:自动编码器可以有多深就有多深。在上图中,我们在编码器和解码器中都有两层,没有考虑输入和输出。
- 每层的节点数量:我们正在开发的自动编码器架构被称为堆叠自动编码器,因为这些层是一个接一个堆叠的。通常堆叠的自动编码器看起来像一个“三明治”。每层的节点数量随着编码器的每个后续层而减少,并在解码器中增加。就层结构而言,解码器与编码器也是对称的。如上所述,这是不必要的,我们完全控制这些参数。
- 损失函数:我们或者使用均方误差或者二元交叉熵。如果输入值在范围[0,1]内,那么我们通常使用交叉熵,否则我们使用均方误差。欲了解更多详情,请查看此视频。
通过反向传播,自动编码器的训练方式与人工神经网络相同。查看第 1 部分的介绍了解更多关于神经网络如何被训练的细节,它直接应用于自动编码器。
3.履行
现在让我们为下面的架构实现一个自动编码器,编码器和解码器中的一个隐藏层。
我们将使用非常流行的 MNIST 数据集作为输入。它包含手写数字的黑白图像。
它们的大小是 28x28,我们用它们作为[0,1]之间的 784 个数字的向量。查看 jupyter 笔记本了解详情。
我们现在将使用 Keras 实现自动编码器。超参数为:隐层 128 个节点,码长 32,二进制交叉熵为损失函数。
这非常类似于我们工作过的人工神经网络,但是现在我们使用的是 Keras 函数式 API。有关详细信息,请参考本指南,但这里有一个快速比较。之前,我们使用顺序 API 添加层,如下所示:
model.add(Dense(16, activation='relu')) model.add(Dense(8, activation='relu'))
使用函数式 API,我们可以做到:
layer_1 = Dense(16, activation='relu')(input) layer_2 = Dense(8, activation='relu')(layer_1)
这种定义复杂模型的方式更加冗长,但是更加灵活。我们可以很容易地获取模型的一部分,例如只有解码器,然后用它工作。 Dense 方法的输出是一个可调用层,使用函数 API 我们为它提供输入并存储输出。一层的输出成为下一层的输入。使用顺序 API, add 方法隐式地为我们处理了这个问题。
注意,所有层都使用 relu 激活函数,因为这是深度神经网络的标准。最后一层使用 sigmoid 激活,因为我们需要输出在[0,1]之间。输入也在相同的范围内。
还要注意对拟合函数的调用,之前我们用人工神经网络做过:
model.fit(x_train, y_train)
但是现在我们知道了:
model.fit(x_train, x_train)
请记住,自动编码器的目标与输入相同。这就是我们提供训练数据作为目标的原因。
形象化
现在让我们想象一下我们的自动编码器如何重构它的输入。
我们简单地通过使用 Keras 的预测功能在测试集上运行自动编码器。对于测试集中的每一幅图像,我们得到自动编码器的输出。我们期望输出与输入非常相似。
他们确实非常相似,但不完全相同。我们可以在最后一个数字“4”中更清楚地注意到这一点。由于这是一个简单的任务,我们的自动编码器表现得相当好。
建议
我们完全控制了自动编码器的架构。我们可以通过增加层数、每层节点数以及最重要的代码大小来使它变得非常强大。增加这些超参数将让自动编码器学习更复杂的编码。但是我们应该小心不要让它太强大。否则,自动编码器将简单地学习将其输入复制到输出,而不学习任何有意义的表示。它将只是模仿身份功能。自动编码器将完美地重建训练数据,但是它将过度拟合,而不能推广到新的实例,这不是我们想要的。
这就是为什么我们更喜欢“三明治”架构,并有意保持代码较小。由于编码层比输入数据具有更低的维度,所以自动编码器被称为欠完成。它将无法直接将其输入复制到输出,并将被迫学习智能特性。如果输入数据具有某种模式,例如数字“1”通常包含某种程度上的直线,而数字“0”是圆形,则它将学习这一事实,并以更紧凑的形式对其进行编码。如果输入数据是完全随机的,没有任何内部相关性或依赖性,那么欠完整自动编码器将不能完美地恢复它。但幸运的是,在现实世界中,有很多依赖。
4.降噪自动编码器
保持较小的代码层迫使我们的自动编码器学习数据的智能表示。还有另一种方法来迫使自动编码器学习有用的特征,即向其输入添加随机噪声,并使其恢复原始的无噪声数据。这样,自动编码器不能简单地将输入复制到其输出,因为输入也包含随机噪声。我们要求它减去噪音并产生有意义的数据。这被称为去噪自动编码器。
最上面一行包含原始图像。我们向它们添加随机高斯噪声,噪声数据成为自动编码器的输入。自动编码器根本看不到原始图像。但是我们期望自动编码器重新生成无噪声的原始图像。
去噪 autoencoder 的实现和常规的实现之间只有一个很小的区别。架构一点没变,只有 fit 功能。我们按如下方式训练常规自动编码器:
autoencoder.fit(x_train, x_train)
去噪自动编码器被训练为:
autoencoder.fit(x_train_noisy, x_train)
就这么简单,其他的都完全一样。自动编码器的输入是有噪声的图像,而预期目标是原始的无噪声图像。
形象化
现在让我们想象一下我们是否能够恢复无噪声的图像。
看起来不错。最下面一行是自动编码器输出。我们可以通过使用更复杂的自动编码器架构来做得更好,例如卷积自动编码器。我们将在下一篇文章中讨论卷积。
5.稀疏自动编码器
我们介绍了两种方法来迫使自动编码器学习有用的特性:保持较小的代码大小和消除自动编码器的噪声。第三种方法是使用正规化。我们可以通过使用稀疏约束来调整自动编码器,使得只有一小部分节点具有非零值,称为活动节点。
特别地,我们在损失函数中增加了一个惩罚项,使得只有一小部分节点成为活动的。这迫使自动编码器将每个输入表示为少量节点的组合,并要求它发现数据中有趣的结构。即使代码很大,这种方法也是有效的,因为在任何时候只有一小部分节点是活动的。
在 Keras 中,只用一个参数就可以很容易地做到这一点。提醒一下,之前我们创建了如下代码层:
code = Dense(code_size, activation='relu')(input_img)
我们现在通过指定正则化强度来添加另一个名为activity _ regulator的参数。这通常是一个在[0.001,0.000001]范围内的值。这里我们选择了 10e-6。
code = Dense(code_size, activation='relu', activity_regularizer=l1(10e-6))(input_img)
由于增加了正则化项,稀疏模型的最终损失比标准模型高 0.01。
让我们证明正则化模型生成的编码确实是稀疏的。如果我们查看测试集中图像的代码值的直方图,分布如下:
标准模型的平均值为 6.6,但正则化模型的平均值为 0.8,降幅相当大。我们可以看到正则化模型中的一大块代码值确实是 0,这正是我们想要的。正则化模型的方差也相当低。
6.用例
现在我们可能会问以下问题。自动编码器在压缩输入方面有多好?它们是常用的深度学习技术吗?
不幸的是,自动编码器在现实应用中并没有广泛使用。作为一种压缩方法,它们并不比它的替代品表现得更好,例如 jpeg 压缩照片比自动编码器更好。事实上,自动编码器是特定于数据的,这使得它们作为一种通用技术是不切实际的。不过,它们有 3 种常见的使用情形:
- 数据去噪:我们已经在图像上看到了这样的例子。
- 降维:可视化高维数据具有挑战性。t-SNE 是最常用的方法,但它的维数很大(通常在 32 以上)。因此,自动编码器被用作预处理步骤来降低维度,这种压缩的表示被 t-SNE 用于在 2D 空间中可视化数据。关于 t-SNE 的精彩文章,请参考这里和这里。
- 变型自动编码器(VAE):这是自动编码器的一个更加现代和复杂的用例,我们将在另一篇文章中介绍它们。但是作为一个快速的总结,VAE 学习了模拟输入数据的概率分布的参数,而不是学习普通自动编码器的任意函数。通过从该分布中采样点,我们还可以使用 VAE 作为生成模型。这里的就是一个很好的参考。
7.结论
自动编码器是一种非常有用的降维技术。它们作为深度学习入门课程的教材非常受欢迎,很可能是因为它们的简单性。在这篇文章中,我们详细介绍了它们,希望您喜欢。
如果你想自己动手,这篇文章的全部代码可以在这里找到。如果您有任何反馈,请随时通过推特联系我。
应用深度学习-第 4 部分:卷积神经网络
概观
欢迎来到应用深度学习系列的第 4 部分。第 1 部分是对人工神经网络的实际介绍,包括理论和应用,有很多代码示例和可视化。在第二部分中,我们将深度学习应用于真实世界的数据集,涵盖了 3 个最常见的问题作为案例研究:二分类、多类分类和回归。第三部分探索了一种特定的深度学习架构:自动编码器。
现在我们将讨论最流行的深度学习模型:卷积神经网络。
这篇文章的代码可以在这里获得作为一个 Jupyter 笔记本,请随意下载并亲自试用。
1.介绍
卷积神经网络(CNN)无处不在。它可以说是最流行的深度学习架构。最近对深度学习的兴趣激增是由于 convnets 的巨大普及和有效性。人们对 CNN 的兴趣始于 2012 年的 AlexNet,此后一直呈指数级增长。仅仅三年时间,研究人员就从 8 层 AlexNet 发展到了 152 层 ResNet。
CNN 现在是所有与图像相关问题的首选模式。就准确性而言,他们将竞争对手打得落花流水。它还成功地应用于推荐系统、自然语言处理等等。与它的前辈相比,CNN 的主要优势在于它自动检测重要特征,而无需任何人工监督。例如,给定许多猫和狗的图片,它自己学习每一类的不同特征。
CNN 的计算效率也很高。它使用特殊的卷积和池操作,并执行参数共享。这使得 CNN 模型可以在任何设备上运行,使它们具有普遍的吸引力。
总之,这听起来像是纯粹的魔术。我们正在处理一个非常强大和有效的模型,该模型执行自动特征提取以实现超人的准确性(是的,CNN 模型现在比人类更好地进行图像分类)。希望这篇文章能帮助我们揭开这项非凡技术的秘密。
2.体系结构
所有 CNN 模型都遵循类似的架构,如下图所示。
我们正在处理一个输入图像。我们执行一系列卷积+池操作,然后是一些完全连接的层。如果我们执行多类分类,输出是 softmax。我们现在将深入研究每个组件。
2.1)卷积
CNN 的主要构件是卷积层。卷积是一种合并两组信息的数学运算。在我们的例子中,使用卷积滤波器将卷积应用于输入数据,以产生特征图。使用了很多术语,所以让我们一个一个地形象化它们。
左侧是卷积层的输入,例如输入图像。右边是卷积滤波器,也称为内核,我们将互换使用这些术语。由于滤波器的形状,这被称为 3x3 卷积。
我们通过在输入上滑动该滤波器来执行卷积运算。在每个位置,我们做逐元素矩阵乘法,并将结果相加。这个总和进入特征图。发生卷积运算的绿色区域被称为感受野。由于滤光器的大小,感受野也是 3×3。
这里,过滤器位于左上角,卷积运算“4”的输出显示在生成的特征图中。然后,我们向右滑动过滤器,执行相同的操作,将结果添加到特征映射中。
我们继续这样做,并在特征图中聚集卷积结果。下面的动画展示了整个卷积运算。
这是 2D 使用 3×3 滤波器显示的卷积运算的一个例子。但实际上这些卷积是在 3D 中进行的。实际上,图像被表示为具有高度、宽度和深度维度的 3D 矩阵,其中深度对应于颜色通道(RGB)。卷积滤波器具有特定的高度和宽度,如 3x3 或 5x5,并且根据设计,它覆盖其输入的整个深度,因此它也需要是 3D 的。
在我们想象实际的卷积运算之前,还有一点很重要。我们对一个输入执行多次卷积,每次使用不同的过滤器,产生不同的特征图。然后,我们将所有这些特征图堆叠在一起,这就成为卷积层的最终输出。但首先让我们从简单开始,用一个滤波器来想象一个卷积。
假设我们有一个 32x32x3 的图像,我们使用大小为 5x5x3 的滤镜(请注意,卷积滤镜的深度与图像的深度匹配,都是 3)。当滤波器位于特定位置时,它覆盖一小部分输入,我们执行上述卷积运算。唯一的区别是这次我们在 3D 中做矩阵乘法的和,而不是 2D,但是结果仍然是标量。我们像上面一样在输入上滑动过滤器,并在每个位置执行卷积,将结果聚集在特征图中。该特征地图的大小为 32x32x1,如右边的红色切片所示。
如果我们使用 10 个不同的过滤器,我们将有 10 个大小为 32x32x1 的特征图,并将它们沿深度方向堆叠将得到卷积层的最终输出:大小为 32x32x10 的体积,如右侧的蓝色大框所示。请注意,特征图的高度和宽度没有改变,仍然是 32,这是由于填充造成的,我们稍后将对此进行详细说明。
为了有助于可视化,我们在输入上滑动过滤器,如下所示。在每个位置,我们得到一个标量,并在特征图中收集它们。动画显示了 4 个位置的滑动操作,但实际上是在整个输入中执行的。
下面我们可以看到两个特征图是如何沿着深度方向堆叠的。每个滤波器的卷积操作是独立执行的,并且所得到的特征图是不相交的。
2.2)非线性
对于任何一种强大的神经网络,它都需要包含非线性。我们之前看到的 ANN 和 autoencoder 都是通过激活函数传递其输入的加权和来实现这一点的,CNN 也不例外。我们再次通过 relu 激活函数传递卷积运算的结果。因此,最终特征图中的值实际上不是总和,而是应用于它们的 relu 函数。为了简单起见,我们在上面的图中省略了这一点。但是请记住,任何类型的卷积都包含一个 relu 运算,没有它,网络就不能实现其真正的潜力。
2.3)步幅和衬垫
步幅指定我们在每一步移动卷积滤波器的程度。默认情况下,该值为 1,如下图所示。
如果我们想减少感受野之间的重叠,我们可以有更大的进展。这也使得生成的特征地图更小,因为我们跳过了潜在的位置。下图演示了步幅为 2。请注意,特征图变小了。
我们看到特征映射的大小小于输入,因为卷积滤波器需要包含在输入中。如果我们想保持相同的维度,我们可以使用填充用零包围输入。查看下面的动画。
输入周围的灰色区域是填充。我们要么用零填充,要么用边上的值填充。现在,特征图的维度与输入相匹配。CNN 通常使用填充来保持特征图的大小,否则它们会在每一层收缩,这是不希望的。我们上面看到的 3D 卷积图使用了填充,这就是为什么特征图的高度和宽度与输入相同(都是 32x32),只有深度发生了变化。
2.4)联营
在卷积运算之后,我们通常执行池来减少维度。这使我们能够减少参数的数量,这既缩短了训练时间,又防止了过度拟合。池化图层对每个要素地图单独进行缩减采样,减少高度和宽度,保持深度不变。
最常见的池类型是最大池,它只取池窗口中的最大值。与卷积运算相反,池化没有参数。它在其输入上滑动一个窗口,并简单地取窗口中的最大值。类似于卷积,我们指定窗口大小和步幅。
这是使用 2x2 窗口和步幅 2 的最大池的结果。每种颜色代表一个不同的窗口。因为窗口大小和跨度都是 2,所以窗口不重叠。
注意,该窗口和步幅配置将特征图的大小减半。这是池化的主要用例,在保留重要信息的同时对要素地图进行缩减采样。
现在让我们算出合并前后的特征图尺寸。如果池化图层的输入维度为 32x32x10,使用上述相同的池化参数,结果将是 16x16x10 的要素地图。要素地图的高度和宽度减半,但深度不变,因为池化在输入的每个深度切片上独立工作。
通过将高度和宽度减半,我们将重量的数量减少到输入的 1/4。考虑到我们通常在 CNN 架构中处理数百万的权重,这种减少是相当大的。
在 CNN 架构中,通常使用 2x2 窗口、跨距 2 和无填充来执行池化。卷积是用 3×3 窗口、步长 1 和填充完成的。
2.5)超参数
现在,让我们只考虑忽略池化的卷积层,并检查我们需要做出的超参数选择。我们需要决定 4 个重要的超参数:
- 滤波器尺寸:我们通常使用 3x3 滤波器,但根据具体应用,也可以使用 5x5 或 7x7 滤波器。还有 1x1 滤波器,我们将在另一篇文章中探讨,乍一看可能很奇怪,但它们有有趣的应用。请记住,这些过滤器是 3D 的,也有深度维度,但由于过滤器在给定层的深度等于其输入的深度,我们忽略了这一点。
- 过滤器数量:这是最易变的参数,它是 2 的幂,介于 32 和 1024 之间。使用更多的过滤器会产生更强大的模型,但是由于参数数量的增加,我们有过度拟合的风险。通常,我们从初始层的少量过滤器开始,随着网络的深入,数量会逐渐增加。
- Stride:我们保持默认值 1。
- 填充:我们通常使用填充。
2.6)完全连接
在卷积+合并层之后,我们添加几个完全连接的层来包装 CNN 架构。这就是我们在第一部分中谈到的全连接人工神经网络架构。
请记住,卷积图层和池化图层的输出都是 3D 体积,但完全连接的图层需要数字的 1D 矢量。所以我们将最终池层的输出扁平化为一个矢量,它成为全连接层的输入。扁平化就是简单地将三维的数字排列成一个 1D 向量,这里没有任何奇特的事情发生。
2.7)培训
CNN 的训练方式和 ANN 一样,梯度下降反向传播。由于卷积运算涉及到更多的数学问题,这超出了本文的范围。如果你对细节感兴趣,请点击这里。
3.直觉
CNN 模型可以被认为是两个部分的组合:特征提取部分和分类部分。卷积+池层执行特征提取。例如,给定一幅图像,卷积层检测诸如两只眼睛、长耳朵、四条腿、一条短尾巴等特征。然后,完全连接的图层在这些特征之上充当分类器,并为输入图像分配成为狗的概率。
卷积层是 CNN 模型的主要动力。给定一幅图像和一个标签,自动检测有意义的特征并不是一件容易的事情。卷积层通过在彼此之上构建来学习如此复杂的特征。第一层检测边缘,接下来的层将它们合并以检测形状,随后的层将这些信息合并以推断这是一个鼻子。明确一点,CNN 不知道鼻子是什么。通过在图像中看到大量这样的东西,它学会了把它作为一种特征来检测。完全连接的层学习如何使用由卷积产生的这些特征,以便正确地分类图像。
所有这些现在听起来可能很模糊,但希望可视化部分会让一切变得更清楚。
4.履行
在这个冗长的解释之后,让我们编码我们的 CNN。我们将使用 Kaggle 的狗对猫数据集来区分狗和猫的照片。
我们将使用以下架构:4 个卷积+池层,然后是 2 个全连接层。输入是猫或狗的图像,输出是二进制的。
CNN 的代码如下:
在结构上,代码看起来类似于我们一直在工作的人工神经网络。有 4 种新方法我们以前没有见过:
- Conv2D :这个方法创建一个卷积层。第一个参数是过滤器数量,第二个参数是过滤器尺寸。例如,在第一个卷积层中,我们创建了 32 个大小为 3×3 的过滤器。我们使用 relu 非线性作为激活。我们还启用填充。在 Keras 中,填充有两种选择:相同或有效。相同意味着我们在边缘填充数字,有效意味着没有填充。默认情况下,卷积层的步幅为 1,因此我们不做更改。这一层可以用附加参数进一步定制,你可以查看文档这里。
- MaxPooling2D :创建一个 MaxPooling 层,唯一的参数是窗口大小。我们使用 2x2 的窗口,因为这是最常见的。默认情况下,步长等于窗口大小,在我们的例子中是 2,所以我们不改变它。
- 展平:在卷积+合并层之后,我们展平它们的输出,以馈入我们上面讨论过的完全连接的层。
- 辍学:我们将在下一节解释这一点。
4.1)辍学
对于深度神经网络,丢弃是迄今为止最流行的正则化技术。即使最先进的模型具有 95%的精度,仅通过增加压差也能获得 2%的精度提升,这在该水平上是一个相当大的增益。
辍学是用来防止过度拟合和想法非常简单。在训练期间,在每次迭代中,神经元以概率 p 被暂时“丢弃”或禁用。这意味着该神经元的所有输入和输出将在当前迭代中被禁用。在每个训练步骤中,被丢弃的神经元以概率 p 被重新采样,因此在一个步骤中被丢弃的神经元可以在下一个步骤中被激活。超参数 p 被称为辍学率,它通常是一个 0.5 左右的数字,对应于 50%的神经元被剔除。
令人惊讶的是,退学竟然行得通。我们故意禁用神经元,网络实际上表现更好。原因是 dropout 防止网络过于依赖少数神经元,并迫使每个神经元都能够独立运行。这听起来可能很熟悉,因为在第 3 部分中限制了自动编码器的代码大小,以便学习更智能的表示。
让我们把辍学形象化,这样会容易理解得多。
丢弃可以应用于输入或隐藏层节点,但不能应用于输出节点。已删除节点的内外边被禁用。请记住,在每个训练步骤中,被遗漏的节点会发生变化。此外,我们不会在网络训练后的测试时间内应用退出,我们只在训练中这样做。
现实生活中对辍学的类比如下:假设你是公司里唯一懂财务的人。如果保证你每天都在工作,你的同事就没有动力去学习金融技能。但是如果每天早上你都抛硬币来决定是否去上班,那么你的同事就需要适应了。有些日子你可能不在工作,但财务任务仍然需要完成,所以他们不能只依靠你。你的同事需要学习金融知识,这种专业知识需要在不同的人之间传播。工人需要与其他几个雇员合作,而不是与一组固定的人合作。这使得公司整体上更有弹性,提高了员工的素质和技能。
几乎所有最先进的深度网络现在都包含了 dropout。还有另一种非常流行的正则化技术叫做批处理正则化,我们将在另一篇文章中介绍它。
4.2)型号性能
现在让我们来分析我们模型的性能。我们将看看损失和准确性曲线,将训练集性能与验证集进行比较。
训练损失持续下降,但是验证损失在大约第 10 个时期之后开始增加。这是教科书上对过度拟合的定义。该模型正在记忆训练数据,但它无法推广到新的实例,这就是验证性能变差的原因。
尽管我们在使用辍学,我们还是过度适应了。原因是我们正在训练很少的例子,每个类别 1000 张图片。通常我们至少需要 100K 个训练样本才能开始思考深度学习。无论我们使用哪种正则化技术,我们都会在如此小的数据集上过度拟合。但幸运的是,这个问题有一个解决方案,它使我们能够在小数据集上训练深度模型,它被称为数据增强。
4.3)数据扩充
过度拟合是因为训练的样本太少,导致模型的泛化性能很差。如果我们有无限的训练数据,我们不会过度拟合,因为我们会看到每一个可能的实例。
在大多数机器学习应用中,尤其是在图像分类任务中,常见的情况是获得新的训练数据并不容易。因此,我们需要用手头的训练集来凑合。数据扩充是从当前数据集生成更多训练数据的一种方式。它通过对现有样本进行随机转换来生成新的样本,从而丰富或“增加”训练数据。通过这种方式,我们人为地增加了训练集的规模,减少了过度拟合。因此,数据扩充也可以被认为是一种正则化技术。
数据扩充是在训练期间动态完成的。我们需要生成真实的图像,转换应该是可以学习的,简单地添加噪声是没有帮助的。常见的变换有:旋转、移动、调整大小、曝光调整、对比度改变等。这样,我们可以从单个训练示例中生成大量新样本。此外,数据扩充只在训练数据上执行,我们不涉及验证或测试集。
可视化将有助于理解这个概念。假设这是我们最初的形象。
使用数据增强,我们生成这些人工训练实例。这些是新的训练实例,在原始图像上应用变换不会改变这仍然是猫图像的事实。我们可以推断它是人类,所以模型也应该能够学习。
数据扩充甚至可以将训练集的规模提高 50 倍。这是一种非常强大的技术,用于每一个基于图像的深度学习模型,没有例外。
有一些我们通常在图像上使用的数据清理技巧,主要是白化和意味着归一化。更多关于他们的信息可以在这里找到。
4.4)更新型号
现在让我们在 CNN 模型中使用数据增强。模型定义的代码根本不会改变,因为我们不会改变模型的架构。唯一的变化是我们如何输入数据,你可以查看 jupyter 笔记本这里。
用 Keras 做数据扩充很容易,它提供了一个类来为我们做所有的工作,我们只需要指定一些参数。文档可在这里获得。
使用数据扩充,损失和精度曲线如下所示。
这次没有明显的过度拟合。验证准确率从无数据扩充时的 73%跃升至有数据扩充时的 81%,提高了 11%。这是一件大事。准确度提高的主要原因有两个。首先,我们在更多不同的图像上进行训练。第二,我们使模型变换不变,这意味着模型看到了许多移动/旋转/缩放的图像,因此它能够更好地识别它们。
5.VGG 模型
现在让我们来看一个 2014 年的 CNN 模型的例子。VGG 是来自牛津视觉几何小组研究人员的卷积神经网络,因此得名 VGG。它以 7.3%的错误率获得了 ImageNet 分类挑战的亚军。 ImageNet 是最全面的手绘视觉数据集,他们每年都举办比赛,来自世界各地的研究人员参加比赛。所有著名的 CNN 建筑都在那次比赛中首次亮相。
在表现最好的 CNN 模型中,VGG 因其简单而引人注目。我们来看看它的架构。
VGG 是一个 16 层的神经网络,不包括最大池层和最末端的 softmax。它也被称为 VGG16。该架构是我们在上面工作过的架构。堆叠卷积+池层,然后是完全连接的人工神经网络。关于架构的一些观察:
- 它在整个网络中仅使用 3×3 卷积。注意,两个背靠背的 3×3 回旋具有单个 5×5 回旋的有效感受野。并且三个堆叠的 3×3 回旋具有单个 7×7 回旋的感受野。这是两个堆叠的 3x3 卷积形成 5x5 的可视化效果。
- 堆叠两个卷积而不是一个卷积的另一个优点是,我们使用两个 relu 运算,并且更多的非线性赋予模型更多的能力。
- 随着我们深入网络,过滤器的数量会增加。由于我们进行了汇集,特征地图的空间大小减小了,但是随着我们使用更多的过滤器,体积的深度增加了。
- 在 4 个 GPU 上训练了 3 周。
VGG 是一个非常基本的 CNN 模型。如果您需要为某个特定任务使用现成的模型,这是第一个想到的。这篇论文也写得很好,可以在这里找到。还有更复杂的模型表现更好,例如微软的 ResNet 模型以 3.6%的错误率赢得了 2015 年 ImageNet 挑战赛,但该模型有 152 层!详情可在报上这里。我们将在另一篇文章中深入讨论所有这些 CNN 架构,但是如果你想跳过这里是一个很棒的帖子。
6.形象化
现在是最有趣的部分,卷积神经网络的可视化。众所周知,深度学习模型非常难以解释,这就是为什么它们通常被视为黑盒。但是 CNN 模型其实是相反的,我们可以把各种成分可视化。这将使我们深入了解它们的内部工作方式,并帮助我们更好地理解它们。
我们将设想 VGG 模式的 3 个最重要的组成部分:
- 特征地图
- Convnet 滤波器
- 类输出
6.1)可视化要素地图
让我们快速回顾一下卷积架构作为提示。convnet 滤波器对输入执行卷积运算,结果得到一个特征图。我们使用多个过滤器,并将得到的特征图堆叠在一起,以获得输出体积。首先,我们将直观显示特性图,在下一节中,我们将探讨 convnet 滤波器。
我们将可视化特征地图,以查看输入如何通过卷积层进行转换。特征图也被称为中间激活,因为层的输出被称为激活。
请记住,卷积层的输出是 3D 体积。如上所述,高度和宽度对应于特征图的维度,并且每个深度通道是编码独立特征的不同特征图。因此,我们将通过将每个通道绘制为 2D 图像来可视化各个特征地图。
如何可视化特征地图实际上非常简单。我们通过 CNN 传递一个输入图像并记录中间激活。然后,我们随机选择一些特征地图,并绘制它们。
VGG 卷积层的命名如下:blockX_convY。例如,第三个卷积模块中的第二个滤波器称为 block3_conv2。在上面的架构图中,它对应于第二个紫色滤镜。
例如,第一层(block1_conv1)输出的一个特征图如下所示。
明亮的区域是“激活”的区域,这意味着过滤器检测到了它正在寻找的模式。这个过滤器似乎编码了一个眼睛和鼻子探测器。
与查看单个要素地图相比,从卷积图层中可视化多个要素地图会更有意思。那么让我们来可视化对应于每个块的第一个卷积的特征图,下图中的红色箭头。
下图显示了每个图层的 8 个要素地图。Block1_conv1 实际上包含 64 个特征图,因为该层中有 64 个滤波器。但是在这个图中,我们只可视化了每层的前 8 个。
随着我们对图层的深入了解,我们对特征地图有一些有趣的观察。让我们看一下每个图层的一个要素地图,以使它更明显。
- 第一层要素地图(block1_conv1)保留了图像中的大部分信息。在 CNN 架构中,第一层通常充当边缘检测器。
- 随着我们深入网络,特征地图看起来不太像原始图像,而更像它的抽象表示。正如您在 block3_conv1 中看到的,这只猫在某种程度上是可见的,但在此之后,它就变得不可识别了。原因在于,较深的特征地图编码像“猫鼻子”或“狗耳朵”这样的高级概念,而较低级别的特征地图检测简单的边缘和形状。这就是为什么更深的特征地图包含更少的关于图像的信息,而包含更多的关于图像类别的信息。它们仍然编码有用的特征,但是它们不太容易被我们从视觉上理解。
- 随着我们深入,特征图变得越来越稀疏,这意味着过滤器检测到的特征越来越少。这是有意义的,因为第一层中的过滤器检测简单的形状,并且每个图像都包含这些形状。但随着我们深入,我们开始寻找更复杂的东西,如“狗尾巴”,它们不会出现在每张图片中。这就是为什么在第一张图中,每层有 8 个过滤器,随着我们深入,我们会看到更多的功能图为空白(block4_conv1 和 block5_conv1)。
6.2)可视化 Convnet 滤波器
现在我们将想象 CNN 的主要组成部分,过滤器。不过,有一个问题,我们不会真正可视化过滤器本身,而是显示每个过滤器最大程度响应的模式。请记住,过滤器的大小为 3x3,这意味着它们的高度和宽度为 3 个像素,非常小。因此,作为可视化过滤器的代理,我们将在过滤器最活跃的地方生成输入图像。
如何做到这一点的全部细节有些技术性,你可以在 jupyter 笔记本中查看实际代码。但作为一个快速总结,它的工作原理如下:
- 选择一个损耗函数,使 convnet 滤波器的值最大化。
- 从空白输入图像开始。
- 在输入空间做梯度上升。这意味着修改输入值,使过滤器激活更多。
- 循环重复这个动作。
这个过程的结果是滤波器非常活跃的输入图像。请记住,每个过滤器都充当特定功能的检测器。我们生成的输入图像将包含许多这些特征。
我们将在每个卷积块的最后一层可视化滤波器。为了消除任何混淆,在上一节中,我们可视化了卷积运算的输出,即特征图。现在我们正在可视化滤波器,卷积运算中使用的主要结构。
我们将设想每层 8 个过滤器。
它们看起来很不真实!尤其是最后几层。以下是对过滤器的一些观察:
- 第一层过滤器(block1_conv2 和 block2_conv2)主要检测颜色、边缘和简单形状。
- 随着我们深入网络,过滤器在彼此之上构建,并学习编码更复杂的模式。例如,block5_conv3 中的滤波器 41 似乎是一个鸟类检波器。您可以看到不同方向的多个头部,因为鸟在图像中的特定位置并不重要,只要它出现在过滤器将激活的某个位置。这就是为什么过滤器试图通过在过滤器中的多个位置编码来检测几个位置的鸟头。
这些观察结果类似于我们在特征映射部分讨论的内容。较低层编码/检测简单的结构,随着我们深入,各层在彼此之上构建,并学习编码更复杂的模式。这也是我们人类在婴儿时期开始发现世界的方式。首先,我们学习简单的结构,通过实践,我们擅长理解更复杂的东西,建立在我们现有知识的基础上。
6.3)可视化类输出
让我们做最后一个可视化,它将类似于 convnet 过滤器。现在我们将在最终的 softmax 层可视化。给定一个特定的类别,如锤子或灯,我们将要求 CNN 生成一个最大限度地代表该类别的图像。基本上 CNN 会给我们画一幅它认为锤子的样子。
该过程类似于 convnet 滤波器步骤。我们从空白图像开始并进行修改,使得分配给特定类别的概率增加。该代码再次出现在笔记本中。
让我们形象化一些类别。
他们看起来很有说服力。一个对象在图像中出现多次,因为这样分类概率变得更高。图像中的多个网球比单个网球更好。
所有这些可视化都是使用库 keras-vis 执行的。
7.结论
CNN 是一种非常基础的深度学习技术。我们涵盖了广泛的主题,在我看来可视化部分是最有趣的。网上很少有资源对卷积滤波器和特征图进行全面的视觉探索。我希望它有帮助。
如果你想自己动手,这篇文章的全部代码可以在这里找到。如果你有任何反馈,请随时通过推特联系我。
8.参考
网上有大量的 CNN 教程,但最全面的是 Andrej Karpathy 的斯坦福 CS231N 课程。阅读资料在这里,视频讲座在这里。极好的信息来源,强烈推荐。
如果你想深入了解可视化,Deepvis 是一个很好的资源在这里。有一个交互工具,开源代码,论文和一篇详细的文章。
Keras 的作者提供了一个很棒的图像分类教程这里。这篇文章深受那篇教程的影响。它涵盖了我们详细讨论过的许多材料。
关于深度学习的非常全面的在线免费书籍可以在这里找到,CNN 部分可以在这里找到。
如果你对将 CNN 应用于自然语言处理感兴趣,这篇文章非常棒。另一个非常详细的是这里。
一个由 3 部分组成的系列文章,涵盖了 CNN 论文的现状,可以在这里找到。
Chris Olah 的所有文章都充满了丰富的信息和可视化效果。CNN 的相关帖子可以在这里和这里找到。
另一个受欢迎的 CNN 介绍文章是这里的。
这里有一个非常容易理解的关于 CNN 的三集系列。
垃圾邮件过滤中的文本分类应用(上)
Email-Spam Filtering
原创文章发表在我的网站。
从上个月开始,我开始在华盛顿大学提供的在线机器学习专业上工作。第一个课程是关于 ML 基础,第二个是关于线性回归,第三个课程是关于分类。我喜欢这些课程的各个方面,因为它们从头开始教授 ML 算法的实现。当我决定更深入地探索这个领域时,这就是我的目标。但是,老实说,我觉得有一个差距,因为许多问题都没有答案。然后,在阅读了关于如何开始机器学习的内容后,我发现大多数文章都强调了将课程与实践项目相结合的重要性,以便学以致用…而且是那么真实!你只要试着把两者结合起来,你很快就会注意到不同之处!
这是我的第一次实习申请!😄 我选择尝试 垃圾邮件过滤 ,因为这是应用分类中一个非常常见的话题。这很容易理解,因为我们每天都在经历电子邮件中的垃圾邮件过滤。
我遵循了一个简单的入门教程:电子邮件垃圾邮件过滤:使用 Scikit-learn 的 Python 实现。做完不久,我的大脑开始分析步骤,一堆问题轰炸我的脑袋!
为什么“垃圾邮件和非垃圾邮件数量相等”?什么是词干?除了删除停用词和词条化之外,还有其他清理数据的方法吗?训练集和测试集之间的划分是如何完成的?为什么没有验证集?为什么特别使用朴素贝叶斯分类器和 SVM(支持向量机)?是什么让朴素贝叶斯在文档分类问题上如此受欢迎?等等…
扮成威廉。巴勒斯说:“如果你学会放松并等待答案,你的大脑会回答大多数问题。”
我吸了口气,开始一个问题一个问题地回答,有时在网上搜索,试验一些代码的变化,并分析输出。我很高兴地分享结果:
1)我们需要的数据
-我们已经看到了多少封电子邮件(将在训练测试集中使用)
-每个标签中有多少封电子邮件(用于检测是否存在不平衡数据)
-一个单词与每个标签关联的频率(用于计算电子邮件是垃圾邮件或垃圾邮件(0 类或 1 类)的概率)
2)清理数据
**为什么要清洗单词表?**为了减少得到错误结果的可能性,清理数据是必不可少的,因为一些单词对分类没有影响(它们既不能与垃圾邮件类相关联,也不能与垃圾邮件类相关联),并且有一些单词可以被标准化,以便将意思相同的单词分组并减少冗余。通过对训练数据的质量采取行动,我们可以改变分类器的所谓的准确度。因此,移除停用词、词干和词条化有助于改善机器学习算法的结果。
3)朴素贝叶斯
**为什么使用朴素贝叶斯?**朴素贝叶斯具有高效的学习和预测能力,它经常被用来与更复杂的方法进行比较,因为它快速且高度可伸缩(适用于高维数据),正如吴恩达建议的那样,在处理 ML 问题时,从尝试简单快速的算法开始,然后从该点扩展。
**朴素贝叶斯如何简单易行?**朴素贝叶斯基于“贝叶斯”定理,之所以称之为“朴素”,是因为它假设在给定类的情况下要素是相互独立的(要素之间没有/几乎没有相关性),这是不现实的。因此,朴素贝叶斯可以学习单个特征的重要性,但不能确定特征之间的关系。此外,与其他方法相比,朴素贝叶斯的训练时间要短得多,并且不需要太多的训练数据。
为什么是多项朴素贝叶斯?其他模型比如高斯朴素贝叶斯或者伯努利朴素贝叶斯呢?
嗯, 多项式 NB 考虑的是特征(在我们的例子中是单词)的 频率 计数 (出现次数)而伯努利 NB 只关心文档中某个特定特征(单词)的存在与否。后者适用于二进制值*(伯努利,布尔)的特性。鉴于使用高斯 NB ,特征是实值或连续并且它们的分布是高斯的,Iris Flower 数据集是具有连续特征的例子。*
4)支持向量机(SVM)
为什么使用 SVM?我没有找到具体的原因,但据我所知,SVM 可以提供高精度的结果,因为它使用了优化程序。SVM 通过搜索最优的分离超平面(最优超平面)和最大化分离类别(在我们的例子中是垃圾邮件和火腿)的间隔来构建分类器。因此,当维数大于样本数时,SVM 具有一般稳健性和有效性的优点。
与朴素贝叶斯不同,SVM 是一种非概率算法。
【LinearSVC 和 SVC (Scikit-learn)有什么区别?区别在于它们不接受相同的参数。例如,LinearSVC 不接受内核参数,因为它被认为是线性的。SVC 支持更多的参数(C,γ,…)因为它保存了所有可能的核函数(线性、多项式、rbf 或径向基函数、sigmoid)。
**如何调整 SVM 参数?**调整 SVM 参数提高了算法的性能。其中一些影响更大:
-内核:内核就像一个相似度函数。这是一种在可能的高维特征空间中计算两个向量的点积的方法,使用基于一些提供的约束的数据转换到更复杂的空间。核函数有时被称为“广义点积”。
-Gamma:“RBF”、“poly”和“sigmoid”的核系数。更高的伽马值将试图按照训练数据集精确拟合,即泛化误差,并导致过拟合问题。
-C:(3.15)中的系数 C 是一个允许在训练误差和模型复杂度之间进行权衡的参数。小的值 C 将增加训练错误的数量,而大的值 C 将导致类似于硬边际 SVM 的行为。”约阿希姆(2002),第 40 页
5)分析不同情况下的输出
如果我改变字典的大小会怎样?
改变字典大小意味着改变特征(单词)的数量。因此,我想探索拥有更多功能的影响,以及基于混淆矩阵结果的好结果的限制。
我在 size= {3000,5000,6000,7000}上进行测试,发现在 size = 7000 时,SVM 分类开始略有下降(错误识别),而朴素贝叶斯尽管在大小上有所变化,但仍提供了相同的结果。
我认为,在这一点上,可能目标类开始重叠或训练数据过度拟合。我还不确定对这个结果的解释。
如果我尝试高斯和伯努利呢?
显然,引入伯努利不会有所帮助,因为正如我上面解释的,它在我们的情况下没有提供足够的信息,我们需要的是字数,而不是它的存在/不存在。
多项式 NB:
[[129 1]
【9 121]]
高斯 NB:
[[129 1]
【11 119]]
伯努利 NB:
[[130 0 0]
【53 77】]
如我们所见,多项式 NB 优于高斯 NB 和伯努利 NB。
如果我在 SVM 上尝试grid search来调整 SVM 参数会怎么样?
Params grid search:param _ grid = { ’ C ‘:[0.1,1,10,100,1000],’ gamma’:[1,0.1,0.01,0.001,0.0001]}
找到最佳参数:Gamma:0.0001;列车员:100 元
线性 SVM:
[[126 4]
【5 125】]
多项式 NB:
[[129 1]
【9 121】]
SVM:
[[129 1]
【62 68]]
grid search on SVM:
[[126 4]
【2 128】]
SVM 使用 GridSearch 调整参数,可以获得更好的结果。
结论
这就是我使用垃圾邮件过滤软件的第一步!如果你正在考虑开始一个文本分类项目,我希望它对你有所帮助!我会继续分享各种思考和实验。下一次,我将探索更多的训练数据和特征的改进/改变。
这个项目也在 Github 上。
有用的资源:
[1] 朴素贝叶斯和文本分类。
【2】朴素贝叶斯举例。
【3】吴恩达解释朴素贝叶斯视频 1 和视频 2
【4】请像我 5 岁一样解释 SVM。
【5】从实例理解支持向量机。
告诉我你在文本分类方面的经验?你用它做什么?你建议用什么方法?有哪些挑战?
应用 RFM 原理用 K-Means 聚类客户
从 2020 年 6 月起,我将不再使用媒体发布新故事。想继续看我的文章请访问我的个人博客:https://val lant . in。
谁是你的客户?有时候这个问题的答案不是很明显——或者很简短。有很多种方法可以对顾客进行分类和分组。但既然这里是讨论数据问题的地方,那就用数据的方法来回答这个问题吧。
当您拥有数据(如客户列表和他们购买的商品)并且需要使用这些数据创建具有相似特征的组时,您需要一种聚类方法。聚类是无监督机器学习技术组的一部分。我们称之为无监督的,因为计算机没有关于它应该如何分组实体的先前信息。事实上,它将试图通过分析相似实体之间的接近程度来创建具有相似实体的集群。
太宽泛?让我们开始讨论我们的学习案例。去 UCI 下载在线零售数据集。该数据集由 8 个属性和 541.909 个实例组成,显示了一家英国在线零售商在 2010 年 1 月 12 日和 2011 年 9 月 12 日之间发生的所有交易。据 UCI 称,该公司主要销售独特的全场合礼品,公司的许多客户是批发商。
我们的主要目标是通过使用聚类技术将这些客户分成不同的客户群。在这里,我们将使用 K-Means。但是,如何对这些客户进行分组呢?使用哪些变量?我们可以尝试使用 RFM(近期、频率、货币价值)方法来分析客户。这种方法是用来评估客户价值的,我们稍后会详细讨论。
所以首先要做的是加载我们的库和数据,并做一些探索性的数据分析。
我们稍后会详细讨论这些值。现在,让我们寻找空值并删除它们。让我们花一些时间来研究数据集上的唯一值。您将看到,我们现在拥有来自 37 个国家的客户(我们删除了一些空条目,之前我们有 38 个国家的客户)和 4,372 个独立客户。
我们可以做的一件事是借助describe()
检查数据集上的主要数字统计信息。当你这样做的时候,注意一些有趣的事情:数量的最小值是一个负数。为什么?我真的不知道。但是既然在这种情况下负数是没有意义的,我们也把它们排除掉吧。
从 RFM 开始
你记得我说过我们会用 RFM 来聚集我们的客户吗?让我们现在就开始吧。但是首先,为什么不谈谈这种方法呢?
根据维基百科,RFM 代表三个维度:
- R ecency — 客户最近购买了什么?
- 频率—他们多久购买一次?
- M 一元值— 他们花了多少钱?
我们可以对 RFM 做的一件事是在 1 到 5 的范围内为每个维度分配一个分数,5 是最想要的行为。我们稍后会计算分数。我们首先需要创建一个由新近性、频率和货币价值组成的新数据框架。
为了计算最近的时间,我们将调查发票日期。由于我们上一张发票的日期是 2011 年 12 月 9 日,我们会将其视为最近的一张。然后,我们将从第二天减去每一天来计算其他的“最近”。
为了计算频率,我们简单地将每个客户的发票号码相加。对于货币价值,我们将单位价格乘以购买数量,并对每个客户进行求和。
现在,我们要计算分数。我们是这样做的:首先,我们以降序方式按频率对数据进行排序。然后,我们将数据集上的客户数量除以 5。我们为之前创建的每一个段分配一个从 5 到 1 的数字。让我们对“货币”和“最近”列也这样做。
注意:对于“最近”一栏,由于最近的订单更好,我们将其排序为 升序 。
我将把分数添加到一个名为rfmTableScores.
的新数据集
因为我们的分数在 1 到 5 之间,所以我们不需要缩放数字。
我们现在可以开始考虑模型了。K-Means 模型只能对数据集上的信息进行聚类,但是您必须选择想要多少个聚类。你可以用 K-Means 模型本身来做这个决定。为此,让我们创建类内平方和(WCSS)来支持我们的决定。
我们的肘形图显示了最佳的集群数量是 4。这是直线开始柔和下降的点。现在,让我们建立模型。
我们已经完成了聚类过程。就是这样。如您所见,由于 R、F 和 M 分数分析,聚类被分配给每个客户。
为了便于您了解我们所做的工作,让我们绘制一个图表,显示聚类过程之前的数据点以及聚类过程之后的一些图表。所以你可以清楚地看到星团的形成。
给盒图着色
将自定义色标应用于绘图箱线图
我的老板最近要求我为一个破折号应用程序对一系列plottlyBox plots应用色标。这个想法是在同一个图上绘制多个盒状图,并根据每个盒状图与数据集中总体中值的距离,使每个盒状图变暗或变亮。
问题是
这里的问题是 Plotly 只支持热图的色标,散点图&等高线图。
我将通过绘制一些为加拿大人球员生成的数据来演示默认行为,如下所示:
注意:完整的代码在文章的最后
绿色虚线代表NHL league average +/- per game at +2.0
,我的老板想要的是根据each players median +/-
值与league average
的距离将每个方框图涂成更深或更浅的颜色。
解决方案
鉴于我已经处于 Python 环境中,我选择使用来自 Matplotlib Python 模块的colormap
& colormap normalizer
特性。
第一步是导入 Matplotlib:
import matplotlib.pyplot as plt
import matplotlib
import pandas as pd
然后确定数据集中的min
和max
值:
x_data = ['Henrik Sedin', 'Daniel Sedin',
'Brock Boeser', 'Elias Pettersen',
'Bo Horvat', 'Pavel Bure',]# Generate random data
y0 = np.random.randn(50)+4
y1 = np.random.randn(50)+4
y2 = np.random.randn(50)+2
y3 = np.random.randn(50)+2
y4 = np.random.randn(50)+1
y5 = np.random.randn(50)+3y_data = [y0,y1,y2,y3,y4,y5]df = pd.DataFrame(y_data)
vmin, vmax = df.min().min(), df.max().max()
初始化 Matplotlib cmap 和规格化器:
norm = matplotlib.colors.Normalize(vmin=vmin, vmax=vmax)
cmap = matplotlib.cm.get_cmap('GnBu') # green to blue color way
找到每个y_data
的中间值,并使用规格化器根据中间值将其映射到适当的颜色:
for xd, yd in zip(x_data, y_data):
median = np.median(yd) # find the median
color = 'rgb' + str(cmap(norm(median))[0:3]) # normalize
traces.append(go.Box(
y=yd,
name=xd,
boxpoints='all',
jitter=0.5,
whiskerwidth=0.2,
fillcolor=color, # add the box plot color
marker=dict(
size=2,
),
line=dict(width=1)
))
维奥拉。
players median +/-
离league average
越远,产生的图将呈现越暗的fillcolor
,反之亦然。
奖金
下面是获得上述结果的完整代码:
from plotly import __version__
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)
import plotly.graph_objs as go
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlibx_data = ['Henrik Sedin', 'Daniel Sedin',
'Brock Boeser', 'Elias Pettersen',
'Bo Horvat', 'Pavel Bure',]y0 = np.random.randn(50)+4
y1 = np.random.randn(50)+4
y2 = np.random.randn(50)+2
y3 = np.random.randn(50)+2
y4 = np.random.randn(50)+1
y5 = np.random.randn(50)+3y_data = [y0,y1,y2,y3,y4,y5]traces = []df = pd.DataFrame(y_data)
vmin, vmax = df.min().min(), df.max().max()norm = matplotlib.colors.Normalize(vmin=vmin, vmax=vmax)
cmap = matplotlib.cm.get_cmap('GnBu')for xd, yd in zip(x_data, y_data):
median = np.median(yd)
color = 'rgb' + str(cmap(norm(median))[0:3])
traces.append(go.Box(
y=yd,
name=xd,
boxpoints='all',
jitter=0.5,
whiskerwidth=0.2,
fillcolor=color,
marker=dict(
size=2,
color='rgb(0, 0, 0)'
),
line=dict(width=1),
))layout = go.Layout(
title='Canucks all time +/- per game',
yaxis=dict(
autorange=True,
showgrid=True,
zeroline=True,
dtick=5,
gridcolor='rgb(255, 255, 255)',
gridwidth=1,
zerolinecolor='rgb(255, 255, 255)',
zerolinewidth=2,
),
margin=dict(
l=40,
r=30,
b=80,
t=100,
),
paper_bgcolor='rgb(243, 243, 243)',
plot_bgcolor='rgb(243, 243, 243)',
showlegend=False,
shapes= [{
'type': 'line',
'x0': -1,
'y0': 2,
'x1': 6,
'y1': 2,
'line': {
'color': 'rgb(50, 171, 96)',
'width': 4,
'dash': 'dashdot'
}
}]
)fig = go.Figure(data=traces, layout=layout)
iplot(fig)