TowardsDataScience-博客中文翻译-2016-2018-十四-
TowardsDataScience 博客中文翻译 2016~2018(十四)
ELMo 有助于进一步提高你的句子嵌入

by https://pixabay.com/en/universal-studios-singapore-2413365/
在最后一个故事中,上下文化的单词向量 (CoVe)被引入,这是单词嵌入的增强版本。Peters 等人提出了深度语境化单词表征,旨在为不同语境下的自然语言处理任务提供更好的单词表征。他们称之为 ELMo(来自语言模型的嵌入)。
看完这篇帖子,你会明白:
- 语言模型设计中的嵌入
- 体系结构
- 履行
- 拿走
语言模型设计中的嵌入

Photo by Conor Luddy on Unsplash
ELMo 使用双向语言模型(biLM)来学习单词(例如,句法和语义)和语言上下文(即,对多义性建模)。在预训练之后,向量的内部状态可以被转移到下游的 NLP 任务。Peters 等人使用 6 个 NLP 任务来评估 biLM 的结果。
这些任务分别是问答、文本蕴涵、语义角色标注、指代消解、命名实体抽取和情感分析。他们都取得了优异的成绩。
体系结构
与传统的单词嵌入不同,ELMo 针对不同的场景,为每个单词生成多个单词嵌入。较高层捕获单词嵌入的上下文相关方面,而较低层捕获语法的模型方面。在最简单的情况下,我们只使用 ELMo 的顶层(只有一层),同时我们也可以将所有层合并成一个矢量。

Peters et al. (2018)
我们可以连接 ELMo 向量和令牌嵌入(单词嵌入和/或字符嵌入)以形成如下新嵌入:

在实验中,Peters 等人使用 L=2 (2 个 biLSTM 层),其中 4096 个单元和 512 个输出维度用于上下文相关部分,而 2048 个字符 n-gram 构成过滤器和 512 个输出维度用于上下文不敏感部分,以构建上下文化的单词嵌入。
履行
原作者是 McCann 等人,他们用 python 3.6 通过 Pytorch 实现了 ELMo。有 Tensorflow,chainer 和 Keras 版本可供选择。我将使用 Keras 版本来演示我们如何将文本转换为矢量。对于其他人,您可以查看参考资料部分提到的 githubs。
下面的例子展示了我们如何使用 keras 来实现它。 Tensorflow Hub 是一个模型 Hub,存储了大量不同的模型。如果您只需要一个预训练的嵌入,您可以使用下面的代码从 Tensorflow Hub 中检索它并传输到 Keras。
可以从 Tensorflow Hub 预训练模型中选择 2 个嵌入层(总共有 5 层)。第一个“elmo”是其他 3 层的加权和。第二个是“默认”,它是所有层的固定均值轮询。你可以从这里找到更多信息。
在我的演示中,有 3 种方法可以使用 ELMo 预训练模型。它们是:
- 具有单词嵌入的 3 层的加权和
- 没有单词嵌入的 3 层的加权和
- 不含单词嵌入的固定均值池
1。具有单词嵌入的 3 层的加权和
# Input Layers
word_input_layer = Input(shape=(None, ), dtype='int32')
elmo_input_layer = Input(shape=(None, ), dtype=tf.string)# Output Layers
word_output_layer = Embedding(
input_dim=vocab_size, output_dim=256)(word_input_layer)
elmo_output_layer = Lambda(
elmo_embs.to_keras_layer,
output_shape=(None, 1024))(elmo_input_layer)
output_layer = Concatenate()(
[word_output_layer, elmo_output_layer])
output_layer = BatchNormalization()(output_layer)
output_layer = LSTM(
256, dropout=0.2, recurrent_dropout=0.2)(output_layer)
output_layer = Dense(4, activation='sigmoid')(output_layer)# Build Model
model = Model(
inputs=[word_input_layer, elmo_input_layer],
outputs=output_layer)
model.compile(
loss='sparse_categorical_crossentropy',
optimizer='adam', metrics=['accuracy'])
model.summary()
model.fit(
[x_train_words, x_train_sentences], y_train,
# validation_data=([x_test_words, x_test_sentences], y_test),
epochs=10, batch_size=32)
结果
Accuracy:77.10%
Average Precision: 0.78
Average Recall: 0.77
Average f1: 0.76
2。没有单词嵌入的 3 层的加权和
# Input Layers
elmo_input_layer = Input(shape=(None, ), dtype=tf.string)# Output Layers
output_layer = Lambda(
elmo_embs.to_keras_layer,
output_shape=(None, 1024))(elmo_input_layer)
output_layer = BatchNormalization()(output_layer)
output_layer = LSTM(
256, dropout=0.2, recurrent_dropout=0.2)(output_layer)
output_layer = Dense(4, activation='sigmoid')(output_layer)# Build Model
model = Model(
inputs=elmo_input_layer, outputs=output_layer)
model.compile(
loss='sparse_categorical_crossentropy',
optimizer='adam', metrics=['accuracy'])
model.summary()
model.fit(
x_train_sentences, y_train,
# validation_data=([x_test_words, x_test_sentences], y_test),
epochs=10, batch_size=32)
结果
Accuracy:76.83%
Average Precision: 0.78
Average Recall: 0.77
Average f1: 0.77
3。不含单词嵌入的固定均值池
# Input Layers
input_layer = Input(shape=(None,), dtype=tf.string)# Output Layers
output_layer = Lambda(
elmo_embs.to_keras_layer,
output_shape=(1024,))(input_layer)
output_layer = Dense(
256, activation='relu')(output_layer)
output_layer = Dense(4, activation='sigmoid')(output_layer)model = Model(inputs=[input_layer], outputs=output_layer)
model.compile(
loss='sparse_categorical_crossentropy',
optimizer='adam', metrics=['accuracy'])
model.summary()
model.fit(
x_train_sentences, y_train,
# validation_data=([x_test_words, x_test_sentences], y_test),
epochs=10, batch_size=32)
结果
Accuracy:74.37%
Average Precision: 0.79
Average Recall: 0.74
Average f1: 0.75
拿走
要访问所有代码,您可以访问这个 github repo
- CoVe 需要标签数据来获得上下文单词向量,而 ELMo 则采用无监督的方式。
- CoVe 只使用最后一层,而 ELMo 使用多层来表示上下文单词。
- 无法解决 OOV 问题。它建议使用零向量来表示未知单词。ELMO 可以处理 OOV 问题,因为它使用字符嵌入来构建单词嵌入。
- ELMo 计算矢量很费时间。根据作者的建议,您可以离线预计算令牌,并在在线预测期间查找它,以减少时间开销。
关于我
我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。你可以通过媒体博客、 LinkedIn 或 Github 联系我。
参考
彼得斯 M. E .、诺依曼 m .、乌耶 m .、加德纳 m .、克拉克 c ...深层语境化的词语表达。2018.https://arxiv.org/pdf/1802.05365.pdf
py torch 中的 ELMo(原创)
埃隆·马斯克和推特
Elon 与 Twitter“麝香”关系的频率和情感分析
Twitter 是一个强大的微博工具,从一开始就改变了人们的对话——不管是好是坏。有如此多的数据可用,因为它有数百万全球活跃用户来收集和利用。
特斯拉和 SpaceX 的首席执行官埃隆·马斯克(Elon Musk)因其最近的推文而成为争议的焦点。我想既然他是一个在世的名人,分析他在 Twitter 上的行为和声誉会很有趣。

我把我的项目分成几个部分:对马斯克的推文频率的分析,对马斯克推文的情感分析,对关于马斯克的推文的情感分析,以词云为产品。
我用 R 和 Twitter 的 API 做了我的项目。链接设置 API 这里。
以下代码建立了 twitter 和 R Studios 之间的连接:
twitter_token<-create_token(app = "joysentiment1", api_key, api_secret, accessToken, accessTokenSecret, set_renv = TRUE)
之后我继续摘录了埃隆·马斯克的 5000 条推文。
em_tweets<-get_timeline("ElonMusk",n=5000)
第一部分:推文频率
我首先查看了埃隆·马斯克过去几年的推特习惯。他于 2009 年加入 Twitter,但只有他自 2016 年以来的推文可用。

Elon Musk’s 5000 Tweets Frequency
ggplot(data = em_tweets,
aes(x=em_tweets$month,group=factor(year(created_at)), color=factor(year(created_at)))) +
geom_line(stat="count") +
geom_point(stat="count") +
labs(x="Month", colour="Year",y="Number of tweets") +
theme_classic()
值得注意的是,埃隆·马斯克在 5 月和 6 月开始更频繁地发推特。他过去最令人难忘的一些推文可能包括宣布他为记者创建 Yelp 的想法。

Yelp for journalists…
我创建了另一个他在 12 个月内发推文频率的可视化,这也不奇怪,他在 5 月、6 月和 7 月在 Twitter 上最活跃。

Elon Musk’s Tweets Frequency over 12 months
ggplot(data = em_tweets, aes(x = em_tweets$month)) +
geom_bar(aes(fill = ..count..)) +
xlab("Month") + ylab("Number of tweets") +
theme_classic()
这引发了一个重要的问题:为什么马斯克比过去花更多的时间发推特?
第二部分:马斯克推文的情感分析
情感分析是针对特定情感/产品对词语进行量化和分类的过程。我在课堂上被介绍了这个概念,并且在阅读了这里的后变得更加感兴趣。
我对埃隆·马斯克的 5000 条推文进行了情绪分析,很想知道这种情绪在过去的一年里是如何变化的。我利用了“NRC”词典,它将单词归类为情绪,如“快乐”、“悲伤”等。
在我的第一次可视化中,我看到埃隆·马斯克的推文主要植根于积极、信任和期待的情绪。

Sentiment Analysis On Elon Musk’s Tweets
ggplot(data=primaryscores,aes(x=sentiment,y=Score))+
geom_bar(aes(fill=sentiment),stat = "identity")+
xlab("Sentiments")+ylab("Scores")+
ggtitle("Total sentiment based on scores")+
theme(legend.position="none")+
theme_minimal()
我还想看看他的情绪在 2018 年的过去几个月里有什么变化。

Sentiment Analysis on Elon Musk’s Tweets the past year
ggplot(data=monthly_sentiment,aes(x=month,y=value,group=sentiment))+
geom_line(aes(color=factor(sentiment)))+
geom_point(aes(color=factor(sentiment)))+
labs(x="Month", colour="Sentiment",y="Value")+
theme_minimal()
积极情绪在 4 月和 6 月间达到顶峰。但我们可以看到,愤怒、消极、期待和信任情绪也经历了类似的增长。鉴于他在 Twitter 上的多次公开争吵,这一发现是有道理的。

An example of a public dispute
埃隆经常以积极的态度在推特上谈论他的生活经历,特别是关于他的公司:特斯拉和 SpaceX。

An example of a positive tweet
我想涉及的另一个方面是他的词汇用法。最有效的方法是创建一个单词云,这是我在阅读了这个指南后意识到的。
这被证明是这项任务中最具挑战性的部分,因为我必须创建一个停用词列表,包括但不限于:just,like,way,also,其实。
停用词用于删除对分析没有价值的词。很难完全删除所有的停用词,因为这些词是他推文的主干。

Word cloud for Elon Musk’s tweets
wordcloud(em_text_corpus,min.freq=1,max.words=50,scale=c(2.5,1),colors=brewer.pal(8,"Accent"),random.color=T,random.order=F)
埃隆·马斯克(Elon Musk)使用他的 twitter 账户谈论他在无聊公司特斯拉(Tesla)和 SpaceX 的工作,这在这个词云中显而易见。他对自己公司的骄傲和对未来的乐观态度反映在他的推特上。
第三部分:关于埃隆马斯克 的推文情感分析
Twitter 的魅力在于能够加入其他人的对话。我利用这个功能来看看大多数用户是如何描绘埃隆·马斯克的。
为此,我做了另一项情感分析。我查看了我的 1000 条微博。
elon_raw<-searchTwitter("elon",lang="en",n=1000)
我进行了另一项情感分析,但这次是通过给每个词打分:正面词的分数大于 0,负面词的分数小于 0。关于伊隆的推文数量分布如下:

我通过实现我上面的技术创建了另一个单词云,来看看流行的单词是什么。

Word Cloud on tweets about Elon Musk
wordcloud(elon_text_corpus,min.freq=1,max.words=50,scale=c(2.5,1),colors=brewer.pal(8,"Accent"),random.color=T,random.order=F)
Twitter 用户似乎没有对埃隆·马斯克的积极情绪做出回应。大多数 Twitter 用户谈论他最近的追求、丑闻和个人生活,而不是他在公司的工作。俗话说,一枚硬币有两面。
Twitter 的有效性取决于用户本身。虽然有些人认为,如果不想伤害他的公司,埃隆·马斯克必须尽快改变他的推特习惯,但这种命运仍然不确定。很明显,尽管他发了积极的推文,但大多数人并不一定有同样的感觉。
这个项目很有趣,也很有挑战性。我会把扩展代码上传到我的 G itHub 上。如果你想了解更多关于它和我用于情感分析的代码,我在页面底部提供了一些参考。
最初,我在设置 API、创建停用词列表和实现代码时遇到了困难。我的发现有局限性,所以如果你愿意,请随时给我反馈。
总结一下,这是埃隆·马斯克最好的作品之一。

I guess he’s funny sometimes
重要包裹:
library(wordcloud)
library(httr)
library(rtweet)
library(twitteR)
library(plyr)
library(ggplot2)
library(devtools)
library(tm)
library(dplyr)
library(stringr)
library(tidytext)
library(lubridate)
参考:
为情感分析设置代码
https://www . slide share . net/ajayohri/Twitter-analysis-by-kaify-rais
示例项目
https://analyze core . com/2014/04/28/Twitter-情操-分析/
如何用机器学习算法设计垃圾邮件过滤系统
探索、绘制和可视化您的数据

作为软件开发人员,电子邮件是非常重要的沟通工具之一。为了进行有效的通信,垃圾邮件过滤是一个重要的功能。
那么垃圾邮件过滤系统实际上是如何工作的呢?我们能从零开始设计类似的东西吗?
概述
本文这两部分的主要目的是展示如何从头开始设计垃圾邮件过滤系统。
本文概述如下:
- 探索性数据分析
- 数据预处理
- 特征抽出
- 评分和指标
- 利用嵌入+神经网络进行改进(下)
- 最大似然算法与深度学习的比较(下)
我们开始吧!
探索性数据分析
探索性数据分析是数据科学中一个非常重要的过程。它帮助数据科学家理解手头的数据,并将其与业务上下文联系起来。
我将在可视化和分析我的数据中使用的开源工具是 Word Cloud。
Word Cloud 是一个用于表示文本数据的数据可视化工具。图像中文本的大小代表训练数据中单词的频率或重要性。
在这一部分要采取的步骤:
- 获取电子邮件数据
- 探索和分析数据
- 使用文字云和条形图可视化培训数据
获取垃圾邮件数据
在我们开发任何有意义的算法之前,数据是必不可少的成分。知道从哪里获取数据可能是一个非常方便的工具,尤其是当你只是一个初学者的时候。
下面是几个著名的仓库,在那里你可以很容易地免费获得上千种数据集
对于这个邮件垃圾数据集,是垃圾刺客分发的,可以点击这个链接去数据集。有几类数据,你可以阅读readme.html来获得更多关于这些数据的背景信息。
简而言之,这个存储库中存在两种类型的数据,即垃圾数据(非垃圾数据)和垃圾数据。此外,在垃圾邮件数据中,有简单和困难,这意味着有一些非垃圾邮件数据与垃圾邮件数据具有非常高的相似性。这可能会给我们的系统做出决定带来困难。
如果您使用的是 Linux 或 Mac,只需在终端中这样做, wget 只是一个命令,它可以帮助您下载给定 url 的文件:
wget [https://spamassassin.apache.org/old/publiccorpus/20030228_easy_ham.tar.bz2](https://spamassassin.apache.org/old/publiccorpus/20030228_easy_ham.tar.bz2)wget [https://spamassassin.apache.org/old/publiccorpus/20030228_easy_ham_2.tar.bz2](https://spamassassin.apache.org/old/publiccorpus/20030228_easy_ham_2.tar.bz2)wget [https://spamassassin.apache.org/old/publiccorpus/20030228_spam.tar.bz2](https://spamassassin.apache.org/old/publiccorpus/20030228_spam.tar.bz2)wget [https://spamassassin.apache.org/old/publiccorpus/20050311_spam_2.tar.bz2](https://spamassassin.apache.org/old/publiccorpus/20050311_spam_2.tar.bz2)wget [https://spamassassin.apache.org/old/publiccorpus/20030228_hard_ham.tar.bz2](https://spamassassin.apache.org/old/publiccorpus/20030228_hard_ham.tar.bz2)
让我们运行一些代码,看看所有这些电子邮件的内容!
探索和分析数据
让我们看一下邮件内容,对数据有一个基本的了解
火腿
这看起来像是给另一个人的普通邮件回复,这不难归类为一个火腿:
This is a bit of a messy solution but might be useful -
If you have an internal zip drive (not sure about external) and
you bios supports using a zip as floppy drive, you could
use a bootable zip disk with all the relevant dos utils.
硬火腿(火腿电子邮件是棘手的)
硬火腿确实更难从垃圾数据中区分出来,因为它们包含一些关键词,如限时订单、特殊“返校”优惠,这使其非常可疑!
Hello Friends!
We hope you had a pleasant week. Last weeks trivia questions was:
What do these 3 films have in common: One Crazy Summer, Whispers in the =
Dark, Moby Dick?=20
Answer: Nantucket Island
Congratulations to our Winners:
Caitlin O. of New Bedford, Massachusetts
Brigid M. of Marblehead, Massachusetts Special "Back to School" Offer!
For a limited time order our "Back to School" Snack Basket and receive =
20% Off & FREE SHIPPING!
罐头猪肉
其中一个垃圾邮件训练数据看起来确实像垃圾邮件文件夹中的垃圾广告邮件:
IMPORTANT INFORMATION:
The new domain names are finally available to the general public at discount prices. Now you can register one of the exciting new .BIZ or .INFO domain names, as well as the original .COM and .NET names for just $14.95\. These brand new domain extensions were recently approved by ICANN and have the same rights as the original .COM and .NET domain names. The biggest benefit is of-course that the .BIZ and .INFO domain names are currently more available. i.e. it will be much easier to register an attractive and easy-to-remember domain name for the same price. Visit: [http://www.affordable-domains.com](http://www.affordable-domains.com) today for more info.
可视化
Wordcloud
Wordcloud 是一个非常有用的可视化工具,可以让你粗略估计出在你的数据中出现频率最高的单词。

Visualization for spam email

Visualization for non spam email
从这个图像中,您可以注意到垃圾邮件的一些有趣之处。他们中的许多人有大量的“垃圾”词,如:免费,金钱,产品等。在设计垃圾邮件检测系统时,有了这种意识可能有助于我们做出更好的决策。
需要注意的一点是,单词云只显示单词的频率,不一定显示单词的重要性。因此,在可视化数据之前,有必要进行一些数据清理,例如从数据中删除停用词、标点符号等。
N 元模型可视化
另一种可视化技术是利用条形图并显示出现频率最高的单词。N-gram 的意思是,当你计算单词的频率时,你把多少个单词作为一个单位来考虑。
在本文中,我展示了 1-gram 和 2-gram 的例子。你绝对可以尝试更大的 n-gram 模型。

Bar chart visualization of 1-gram model

Bar chart visualization of 2-gram model
列车试分裂
将您的数据集分为训练集和测试集非常重要,这样您就可以在将模型部署到生产环境之前使用测试集来评估模型的性能。
在进行训练测试分割时,需要注意的一件重要事情是确保训练集和测试集之间的数据分布是相似的。
在这种情况下,这意味着垃圾邮件在训练集和测试集中的百分比应该相似。

Target Count For Train Data

Train Data Distribution

Target Count For Test Data

Test Data Distribution
训练数据和测试数据之间的分布非常相似,大约为 20–21%,所以我们可以开始处理我们的数据了!
数据预处理
文字清理
文本清理是机器学习中非常重要的一步,因为你的数据可能包含许多噪音和不需要的字符,如标点符号、空白、数字、超链接等。
人们通常使用的一些标准程序是:
- 将所有字母转换为小写/大写
- 移除数字
- 删除标点符号
- 删除空白
- 删除超链接
- 删除停用词,如 a、about、above、down、doing 等等
- 词干
- 单词词条化
对大多数人来说,这两种技术可能是陌生的,它们是单词词干和单词词条化。这两种技术都试图将单词简化为最基本的形式,但采用的方法不同。
-
词干提取—词干提取算法通过使用该语言中常见的前缀和后缀列表来删除单词的结尾或开头。英语单词词干的示例如下:
-
单词词汇化——词汇化是利用特定语言的词典,并试图将单词转换回其基本形式。它会试着考虑动词的意思,然后 conv 把它还原成最合适的基本形式。
实现这两种算法可能很棘手,需要大量的思考和设计来处理不同的边缘情况。
幸运的是 NLTK 库已经提供了这两个算法的实现,所以我们可以从库中开箱即用!
导入库,开始设计一些函数,帮助我们理解这两个算法的基本工作原理。
# Just import them and use itfrom nltk.stem import PorterStemmer
from nltk.stem import WordNetLemmatizerstemmer = PorterStemmer()
lemmatizer = WordNetLemmatizer()dirty_text = "He studies in the house yesterday, unluckily, the fans breaks down"def word_stemmer(words):
stem_words = [stemmer.stem(o) for o in words]
return " ".join(stem_words)def word_lemmatizer(words):
lemma_words = [lemmatizer.lemmatize(o) for o in words]
return " ".join(lemma_words)
词干分析器的输出非常明显,一些词尾被砍掉了
clean_text = word_stemmer(dirty_text.split(" "))
clean_text#Output
'He studi in the hous yesterday, unluckily, the fan break down'
词汇化已转换为研究->研究,休息->休息
clean_text = word_lemmatizer(dirty_text.split(" "))
clean_text#Output
'I study in the house yesterday, unluckily, the fan break down'
特征抽出
我们的算法总是期望输入是整数/浮点数,所以我们需要在中间有一些特征提取层来将单词转换成整数/浮点数。
有几种方法可以做到这一点,今天我将向大家介绍:
- 计数矢量器
- tfidf 矢量器
- 单词嵌入
计数矢量器
首先,我们需要将所有训练数据输入到 CountVectorizer 中,CountVectorizer 将保存每个单词及其各自 id 的字典,该 id 将与整个训练集中该单词的字数相关。
比如像‘我喜欢吃苹果,喝苹果汁’这样的句子
from sklearn.feature_extraction.text import CountVectorizer# list of text documentstext = ["I like to eat apple and drink apple juice"]# create the transformvectorizer = CountVectorizer()# tokenize and build vocabvectorizer.fit(text)# summarizeprint(vectorizer.vocabulary_)# encode documentvector = vectorizer.transform(text)# summarize encoded vectorprint(vector.shape)print(type(vector))print(vector.toarray())# Output# The number follow by the word are the index of the word
{'like': 5, 'to': 6, 'eat': 3, 'apple': 1, 'and': 0, 'drink': 2, 'juice': 4}# The index relates to the position of the word count array below
# "I like to eat apple and drink apple juice" -> [1 2 1 1 1 1 1]# apple which has the index 1 correspond to the word count of 2 in the array
tfidf 矢量器
字数不错,但我们能做得更好吗?简单字数统计的一个问题是,像“the”、“and”这样的词会出现很多次,它们并没有真正增加太多有意义的信息。
另一个流行的选择是 TfidfVectorizer。除了计算每个单词(经常出现在多个文档或句子中的单词)的字数,矢量器还会尝试缩小它们的大小。
关于 CountVectorizer 和 TfidfVectorizer 的更多信息,请阅读这篇伟大的文章,这也是我获得大部分理解的地方。
字嵌入
网上有很多很棒的文章解释了单词嵌入的细节和生成它们的算法。所以在这里,我将跳过其中的大部分,试着给你一个大概的概念。
单词嵌入试图将单词转换成矢量化格式,该矢量表示该单词在高维空间中的位置。
对于具有相似含义的单词,这两个单词向量的余弦距离会更短,并且它们会彼此更接近。
事实上,这些单词是向量,所以你甚至可以对它们进行数学运算!这些操作的最终结果将是映射到单词的另一个向量。出乎意料的是,那些操作产生了一些惊人的结果!
例 1:国王-男人+女人=王后
示例 2:马德里-西班牙+法国=巴黎
例 3:步行-游泳+游泳=步行
简而言之,单词嵌入是单词的一种非常强大的表示,生成这种嵌入的一种众所周知的技术是 Word2Vec。
呼!将所有的句子转换成某种形式的向量后,就到了我们文章最精彩的部分→ 算法实现!
算法实现
tfidf 矢量器+朴素贝叶斯算法
我采用的第一种方法是使用 tfidf 矢量器作为特征提取工具,并使用朴素贝叶斯算法进行预测。朴素贝叶斯是一种简单的概率型传统机器学习算法。
即使在过去,它在解决垃圾邮件检测等问题时也非常流行。朴素贝叶斯的细节可以在这篇由 Devi Soni 撰写的文章中查阅,这篇文章简明清晰地解释了朴素贝叶斯算法的理论。
使用 sklearn 库提供的朴素贝叶斯库,让我们自己实现这个算法省去了很多麻烦。我们可以用几行代码轻松完成这项工作
from sklearn.naive_bayes import GaussianNBclf.fit(x_train_features.toarray(),y_train)# Output of the score is the accuracy of the prediction
# Accuracy: 0.995
clf.score(x_train_features.toarray(),y_train)# Accuracy: 0.932
clf.score(x_test_features.toarray(),y_test)
我们达到了 93.2%的准确率。但是准确性并不是评价算法性能的唯一指标。让我们尝试其他评分标准,这可能有助于我们彻底了解该模型的表现。
评分&指标
准确度的缺点
在评估数据科学模型的性能时,有时准确性可能不是最佳指标。
我们在现实生活中解决的一些问题可能有一个非常不平衡的类,使用准确性可能不会给我们足够的信心来理解算法的性能。
在我们试图解决的垃圾邮件问题中,垃圾邮件数据约占我们数据的 20%。如果我们的算法预测所有的电子邮件都是非垃圾邮件,它将达到 80%的准确率。
对于一些只有 1%正面数据的问题,预测所有样本都是负面的会给他们 99%的准确率,但我们都知道这种模型在现实生活中是没有用的。
精度&召回
查准率和查全率是人们评价类不平衡分类模型时常用的评价指标。
让我们试着理解 Precision & Recall 试图回答什么问题,
精度:实际上有多少比例的肯定识别是正确的?
回忆:实际阳性中有多少比例被正确识别?
所以, precision 是评估,当一个模型预测某件事是肯定的,这个模型有多精确。另一方面, recall 正在评估一个模型在寻找所有正样本方面做得如何。
精确率和召回率的数学等式分别是


TP:真阳性
FP:假阳性
TN:真阴性
FN:假阴性
混淆矩阵
混淆矩阵是理解像真阳性、假阳性、真阴性等结果的一个非常好的方法。
Sklearn 文档提供了一个示例代码,说明如何绘制好看的混淆矩阵来可视化您的结果。你可以在这里查看,或者你可以在我在文章末尾分享的笔记本中找到代码。

Confusion Matrix of the result
Precision: 87.82%
Recall: 81.01%
该模型的召回率相当低,可能在发现垃圾邮件方面做得不够好。我们如何做得比这更好?
总结
在本文中,我向您展示了设计垃圾邮件检测算法所需的所有必要步骤。简单回顾一下:
- 探索和理解您的数据
- 将手头的数据可视化以获得更好的直觉——word cloud,N-gram 条形图
- 文本清理—单词斯特梅尔和单词词条化
- 特征提取—计数矢量器、Tfidf 矢量器、单词嵌入
- 算法—朴素贝叶斯
- 评分和指标——准确度、精确度、召回率
垃圾邮件检测算法设计演示的第一部分到此结束。
还有这篇文章的第 2 部分!我将展示如何通过使用单词嵌入和深度学习模型来提高模型的准确度、精确度和召回率。有兴趣的话在这里 阅读文章!
你可以从 Github 克隆笔记本,或者直接从 Colab 运行。请在下面的评论区留下你的任何问题。
开始探索学习更多的数学知识
我是一名工作中的“数据科学家”,我把它放在引号中,因为这个术语的意思几乎是人们希望它表达的任何意思。我所知道的是,我处理大量数据,我建立模型,有时制作漂亮的图表(有时很难看)。哦,我经常使用 SQL。我还患有冒名顶替综合征,这可能是因为我对学习(和了解)数学上难以理解的新事物有着巨大的兴趣,我总是把它内化为一个存在主义问题:
为什么除了我每个人都在做如此前沿的 ML 研究?
不要误解我,我有很好的应用数学和统计学知识。很明显,因为如果没有创建回归模型和执行基本统计计算的能力,就很难成为“数据科学家”。但当我阅读一篇关于新的机器学习算法的论文时,我通常会直接跳到结果,并检查是否有“完成它的包”,因为我通常无法掌握方法部分给出的足够多的实质性细节,更不用说自己想出类似的东西了。我大概是低估了我的理解,但最终结果是一样的。我经常觉得自己错过了在谋生的道路上做得更好的机会。
我的问题的根源,正如我所诊断的,是我没有足够好的“纯粹”的数学背景。我看过《概率论》和《统计学》的书,但没有看过《概率论》和《统计学》,我现在理解这两本书差别很大。人们可以应用前者的方法,而不理解后者。但是要深入挖掘并能够设计出新的方法,在某种程度上需要理论知识。现在,我没有时间去获得第二个数学博士学位,但我的希望是,我可以通过勤奋的自学来填补我的数学教育中的一些漏洞。

在确定了核心问题后,我决定需要为自己建立一个课程来保持这个旅程的专注。为了做到这一点,我基本上是从我想去的地方往回走。翻阅“概率论”和“统计学理论”书籍时,我意识到的第一件事是,在某个时候,我会想要解决测量理论,这似乎是这些学科的核心组成部分:
在数学分析中,集合上的度量是一种系统化的方法,用来给该集合的每个合适的子集分配一个数字,直观地解释为它的大小。从这个意义上说,度量是长度、面积和体积概念的概括。一个特别重要的例子是欧几里得空间上的勒贝格测度,它将欧几里得几何的常规长度、面积和体积分配给 n - 维欧几里得空间 R n 的合适子集。例如,实数中区间【0,1】的勒贝格测度就是它在这个词的日常意义上的长度——具体来说,就是 1。
所以,是的,很明显,在不知道什么是“数学分析”的情况下,我无法处理测量理论。相信我,我已经试着阅读测度论,但它就是不理解。所以我需要学习一些实分析,根据我的(元)研究,这似乎是大多数本科数学学位的一个非常基本的核心要求:
实分析(传统上,实变量函数的理论)是数学分析的一个分支,处理实变量的实数和实值函数。具体来说,是关于实函数和序列的解析性质,包括实数的收敛和极限序列、实数的微积分、以及实值函数的连续性、光滑性等相关性质。

显然,真正的分析就像我在类固醇上学的微积分。太棒了。对于数据科学家来说,还有其他一些潜在的有趣和有用的分析领域,尤其是向量空间和函数分析,这两个领域本质上是线性代数的理论基础。所以我决心从理论上从头开始学习线性代数(这在 ML 算法中是普遍存在的)。

作为一名“数据科学家”,我也写很多程序。再一次,因为我对事物非常好奇,我是一个喜欢学习编程语言和范例的普通人,只是为了好玩。好的一面是,我从这项练习中获得的知识往往会在我的日常工作中产生影响,并帮助我成为一名更好的程序员(至少,我喜欢告诉自己确实如此)。很长一段时间以来,我一直感兴趣的编程领域之一是函数式编程,并且在过去的一年左右的时间里尝试过(不是第一次!)拿起 Haskell ,一种近乎僧侣般的纯函数式编程语言。我提到 Haskell 的原因是,如果没有术语范畴理论的出现,你很难尝试学习这门语言:
范畴理论【1】将数学结构及其概念形式化为对象和箭头(也称为态射)的集合。一个类别有两个基本属性:能够组合箭头关联和每个对象存在一个标识箭头。范畴理论的语言已经被用于形式化其他高级抽象的概念,例如集合、环和组。
如果你认为这听起来很数学,那是因为它就是数学!我试着读了一些关于范畴理论的书,看了一些 YouTube 的讲座,但没有走得很远。这真的很抽象。但是最近我有了一个顿悟,那就是,正如我可能应该在进入度量理论之前处理实分析一样,为什么不在进入范畴理论之前学习抽象代数呢?
在代数中,它是数学、抽象代数(偶尔也叫近世代数)是对代数结构的研究。代数结构包括群,环,域,模,向量空间,格,以及代数。抽象代数这个术语是在 20 世纪早期创造的,目的是将这一研究领域与代数的其他部分区分开来。

嘿,看,“群”,“环”,呀,呀。看来我的方向是对的。
所以我挑选了几本书开始我的旅程(大多基于亚马逊、Quora 和 StackExchange 上的好评),我的计划是不时地发布我的进展更新(甚至可能是我处理的一些具有挑战性的证明!),让我坚持下去。欢迎在评论中发表书籍建议。感谢阅读!
将机器学习模型嵌入 Web 应用程序(第 1 部分)

Source (Pixabay)
学习数据科学的最佳方式是实践,没有其他选择。在这篇文章中,我将反映我如何开发一个可以将电影评论分为正面或负面的机器学习模型,以及如何将该模型嵌入到 Python Flask web 应用程序中。最终目标是完成一个端到端的项目。我坚信,在这篇文章的结尾,你将具备将 ML 模型嵌入 web 应用程序的所有必要技能。我遇到了这种情况,打算写一本书,由 Sebastian Raschka 和 Vahid Mirjalili 编写的“Python 机器学习:用 Python、scikit-learn 和 TensorFlow 进行机器学习和深度学习,第二版”。我发现这本书对我的数据科学之旅是一个很好的投资,我鼓励你试用这本书。
请注意,我不打算详细讨论理论和概念。为了让这篇文章简单易懂,我将简单地提供解释,并分享链接,这样你就可以在时间允许的情况下阅读更多的概念和理论。我的建议是,从头到尾跟着这篇文章,在你阅读的第二阶段重新审视新概念。
现在系好安全带,这将是一次奇妙的:D 之旅
这篇文章有两个主要部分
- 开发电影评论分类器(这篇文章)
- 开发 Python Flask web 应用程序并集成电影评论分类器(即将发布!)
开发电影评论分类器

Source(Pixabay)
我在 Paperspace 建立了我的开发者环境,这是一个云基础设施提供商(可能有其他用途,但我只用作 PaaS ,它提供基于 GPU 的计算能力来开发机器学习和深度学习模型。我在我选择的位置创建了一个单独的项目文件夹“情感分析”。这是项目的根目录。
下载电影评论数据
首先,让我们开始下载所需的电影数据。我创建了一个单独的文件‘download _ data . ipynb’。这会将电影评论下载并提取到“数据”文件夹中。当您在“数据”文件夹中导航时,您将能够看到一个名为“acllmdb”的文件夹。在“acllmdb”文件夹中,有“train”和“test”文件夹。“train”和“test”文件夹都包含两个子文件夹,分别名为“pos”和“neg”,前者包含正面评价,后者包含负面评价(图[1])。
download_data.ipynb

Image[1]: Inside data folder
你会注意到这些在‘pos’和‘neg’文件夹中的评论是文本文件的形式。为了方便我们进行数据处理和操作,我们的下一步是创建一个 Python Pandas 数据框。
从文本文件创建熊猫数据框
pandas_data_frame_from_text.ipynb
上面的脚本创建了一个 Pandas 数据帧“df ”,其中包含来自“train”和“test”文件夹中“pos”和“neg”子目录的文本文件的电影评论(这一步大约需要 10-20 分钟,取决于您的 PC 的性能)。如果电影评论是正面的,我们将情感标记为“1”,如果是负面的,我们将情感标记为“0”。在我们的数据框架“df”中,我们有两列,“review”列,它包含文本字符串形式的评论,以及“perspective”列,它包含评论的情绪,根据情绪的积极和消极程度,该情绪为“1”或“0”。图像[2]包含数据帧“df”的前五行。

Image[2] : Movie reviews in Pandas data-frame
在图[2]中,我们只能看到正面的影评。原因是,当我们创建数据框架时,该函数以一种排序的方式安排评论。为了更好地进行有用的数据操作,我们需要随机化电影评论的顺序(即,我们应该以不均匀的无序方式看到‘0’和‘1’)。为此,我们可以利用 NumPy 库的内置函数“置换”和“随机”。
随机化数据帧并保存为 CSV 文件
randomize_data_and_create_csv.ipynb

Image[3]: Unsorted movie reviews
正如您在图[3]中看到的,现在我们有了一个随机数据框,并将数据保存到一个名为“ movie_data.csv ”的 csv 文件中。
清理文本数据
我们的数据框中的“审查”有文本。非常仔细地看这些文本是极其重要的。让我们继续,从上一步准备的数据框中可视化最后 999 个字符。
movie_reviews_last_999_chars.ipynb

Image[4]: Reviews consists of HTML mark-up
很明显,“评论”栏包含 HTML 标记。这些标记并没有给评论增加任何有用的洞察力。因此,作为文本清理过程的一部分,我们必须确保在使用这些评论来开发模型之前,删除这些不需要的标记。
虽然 HTML 标记不包含太多有用的语义,但标点符号可以表示 NLP 上下文中有用的附加信息。为了简单起见,我们将删除除表情符号之外的标点符号,例如:),因为这些表情符号对于语义分析肯定是有用的。我们将使用 Python 的正则表达式 ( regex )来执行这项任务。
这些评论都是大段文字。为了让我们分析评论,我们需要将这些评论分成单独的元素。这个过程在 NLP 上下文中被称为“”[2]。有多种技术可以对给定的文本字符串进行标记。最简单的方法就是在 Python 中的内置函数中使用 split() 。下面是使用 split()函数将一组字符串标记为单个元素的简单示例,如图[5]所示。
tokenize_text_to_individual_element.ipynb

Image[5]: Tokenize words from text
在图[5]中,你可以看到我们已经成功地将文本标记为它的单个元素。在结果输出中,我们可以看到单词“running”和“run”。在 NLP 中,有一种技术可以将单词转换成它们的词根形式。这种技巧叫做 词干【3】。波特·斯特梅尔在自然语言处理领域的研究者中很受欢迎。在下面的代码段中,你可以看到我们如何使用 NLTK 包的 PorterStemmer 来获得单词的根形式(图[6])。
porter_stemmer.ipynb

Image[6]: Tokenize words in their root form
在这个项目中,我们不打算看单词的词根形式。原因是,已经证明它不会给我们将要建立的模型带来显著的改进。为了这篇文章的完整性,我与你分享了这些信息。
数据清理和预处理步骤中的另一个重要概念是被称为“停止字移除”的概念。“停用词”是在各种形式的文本中经常出现的词,可能没有任何有用的信息。几个“停用词”是,是、和、有、是、有、像……停用词去除使得我们的文本处理机制高效,因为它减少了我们需要分析的词的数量。Python NLTK 提供了一种有效的机制来从给定的文本语料库中移除“停用词”。你可以参考下面的代码片段和图片[7]来了解停用词移除的机制。
stop_words_removal.ipynb

Image[7]: Stop words removal results
注意 : 在上面的代码片段中,我们使用了在前面的代码片段中定义的‘tokenizer _ porter’函数。
如图[7]所示,打包的“停用词”去掉了最常出现的词,如“ a ”、“和”。这将减少我们的“单词袋”的大小(这将在本文后面说明),从而使计算更有效。
至此,您已经了解了清理文本数据的许多重要步骤。
- 移除不需要的 HTML 标记(通过正则表达式)
- 标记化(通过 Python split() 方法)
- 词干(如波特斯特梅尔)
- 停止单词删除(通过 NLTK 停止单词)
制作电影评论分类器
有了这些背景知识,我们现在可以继续开发情感分类器。我们将把上述步骤(除了词干处理)应用到我们创建的 movie_data.csv 文件中。
有两种方法来开发分类器。一种是一次利用整个数据集,或者换句话说,一次读取整个 movie_data.csv 文件,创建训练和测试集并拟合模型。这种方法的缺点是,我们需要高性能的 PC/计算能力。尽管我在试用本教程时使用了 Paperspace ,但是用这种方法构建分类器花了我将近两个小时。这是一种非常麻烦的体验。因此,在这篇文章中,我将继续第二种方法。
当处理大量数据时,机器学习从业者使用在线学习算法。同样,在我们的例子中,我们也将使用一种在线学习算法,称为" 【核外学习】【5】。简单来说,这就是我们在给定时间使用数据集的一部分,并从这部分数据中创建模型。我们将用我们输入的每个新数据部分来更新模型。通过遵循这种方法,我们可以很容易地在合理的时间框架内构建我们的模型。此外,我们将定义一系列函数来执行以下操作:
- stream_docs — read_csv(一次一个文档)
- get_minibatch —通过附加文档创建较小尺寸的文档
最后利用以上两个函数创建分类器。你可以参考图[8]和下面提供的代码片段来获得更多关于分类器构建过程的理解。

Image[8]: Classifier creation steps using out-of-core-learning approach
movie_review_classifier.ipynb
这就是创建电影分类器所需的全部内容。也许这现在看起来有点复杂,所以让我带您看一下代码。必要时你可以参考图[8]。
根据图[8],我们的第一步是读取我们在最开始创建的 csv 文件。在上面的代码片段中,第 16 行读取 csv 文件。它一次读取一行(文档),然后将该文档传递给(第 53 行) get_minibatch() 函数以创建一个迷你文档。我们创建一个迷你文档,直到迷你文档的大小达到 1000(第 53 行)。一旦在 get_minibatch() 函数中创建了这个迷你批处理,它就返回这个迷你批处理以供进一步处理(从第 36 行到第 53 行)。我们使用这个小批处理并创建训练集变量 X_train 和 y_train 。
然后,这个 X_train 变量被传递下去,以创建单词包(第 56 行)。因为我们使用的是核外学习方法,所以我们使用了 scikit-learn 的哈希矢量器。哈希矢量器负责创建单词包。在创建单词包时,它将对包含电影评论的【X _ train】、** 进行预处理,并在移除停用词(或对我们的文本语料库没有任何价值的频繁出现的词,如“ a ”、“like“is”等)的同时移除不必要的 HTML 标记。)(第 49 行和第 38–44 行)。**
我们用标记器函数初始化哈希矢量器,并将特征数量设置为 221 。此外,我们通过将SGD 分类器的 损失 参数设置为 日志 来重新初始化逻辑回归分类器。在 HashingVectorizer 中选择大量功能的原因是,在增加逻辑回归模型中系数数量的同时,减少导致哈希冲突的机会。**
使用 for 循环(第 52 行),我们迭代了 45 个小批量文档,其中每个小批量包含 1000 个文档。完成增量学习过程后,我们将使用 5000 个文档来评估我们模型的性能。下面我给出了关于测试集生成和准确性计算的代码片段。这几乎是不言自明的:)(你可以参考上面的详细解释来加深你的理解)。
test_set.ipynb

Image[9]
我们可以看到,我们的模型已经产生了 86.7%的准确率,这是相当不错的。到目前为止,我们已经完成了最重要的一步,下一步是保存这个模型供以后参考。否则,我们需要再次执行所有这些步骤来达到这一点。请保持您当前的 Python 会话打开。
PS:我们的 csv 文件包含 50K 记录,我们使用 45K 作为训练集,5K 作为测试集。你可以使用熊猫的“信息”功能来查看我们 csv 中的记录数量。
每当我们关闭 Python 会话时,对我们来说训练我们的模型将是一项相当忙碌的任务。因此,我们将保存我们训练和构建的分类器。为此,我们使用 Python 内置的 pickle 模块,它允许我们序列化和反序列化 Python 对象以压缩字节代码。当我们想要对新样本进行分类时,我们可以直接重新加载这些对象。
serialize_deserialize_objects.py
在上面的代码段中,我们创建了一个名为' movieclassifier 和' pkl_objects 子目录的文件夹来保存序列化的 Python 对象。' dump 方法所做的是,它序列化经过训练的逻辑回归模型以及 NLTK 库中的'停用词集。我鼓励你阅读 Python pickle 文档【6】来了解更多关于这个包的信息(如果我要在这里解释,那将是:D 的另一篇博文)
我们的下一步是创建一个新的 Python 脚本,我们可以使用它将矢量器导入到现有的 Python 会话中。让我们继续在上一步创建的 movieclassifier 目录中创建一个新的 Python 脚本 vectorizer.py 。
vectorizer.py
现在,在这一点上,我们应该能够使用我们创建的 Python 序列化对象,即使是在一个新的 Python 会话中(培训的麻烦将不再存在!耶!!!).让我们继续测试。导航到“电影分类器”文件夹。停止您当前的 Python 会话。让我们启动一个新的 Python 会话,看看能否从硬盘加载我们的模型。手指交叉!!!
unpiclked_classifier.py
上面的代码段负责加载我们创建的矢量器和分解分类器。现在我们可以使用这些对象和预处理文档样本,并对它们的情感做出预测。例如,让我们试着检查“我爱这部电影”是属于积极的还是消极的。

Image[10]
厉害!看来我们的模型工作正常。我们有能力将这种机器学习模型与我们将要开发的 web 应用程序集成在一起。这是这个两部分系列的第一部分的结尾。
开发 Python Flask web 应用程序
这将是这篇文章的第二部分。我鼓励您熟悉 Python Flask web 应用程序开发。大量的 Python Flask 足够让你阅读这篇文章的第二部分。如果你是新手,可以查一下 Traversy Media 的 Flask Web App 开发系列。
非常感谢你有兴趣阅读这篇文章。请给这篇文章一点掌声,留下你的评论和反馈,我总是欣赏和欢迎你的观点。如果你觉得这篇文章有用,那就和你的朋友:D 分享吧
礼貌:我想对塞巴斯蒂安·拉什卡和瓦伊德·米尔贾利利表示极大的感谢。我从他们身上学到了很多,并且还在学习。我从来不认为书籍是学习编程的好资源,因为我非常依赖在线视频教程。现在我觉得,书籍也是学习编程的一种很好的方式,而出版一本书需要付出巨大的努力。你可以做重点,边学边做笔记。这是一个很大的加分点,所以花你喜欢的书的钱真的是一个很大的时间投资。
参考资料:
[1]https://www . Amazon . com/Python-Machine-Learning-scikit-learn-tensor flow/DP/1787125939
【2】https://NLP . Stanford . edu/IR-book/html/html edition/tokenization-1 . html
【3】https://NLP . Stanford . edu/IR-book/html/html edition/stemming
用 Cosmo Tech 拥抱复杂性
我们被复杂的系统所包围,为了理解、管理和预测它们,我们必须拥抱复杂性并做出更准确的决策。许多人使用人工智能和大数据来简化复杂性。然而,Michel Morvan 在巴黎 Hello Tomorrow 主舞台上的主题演讲中提出,为什么我们需要拥抱复杂性,以及我们如何做到这一点。
我采访了 Michel Morvan, Cosmo Tech 的联合创始人兼执行主席,这是一家软件供应商,为复杂系统建模,以便进行预测模拟。他解释了如何使用增强智能——用人工智能增强人类的智能——使我们能够处理令人难以置信的复杂系统,这可以解决许多人工智能和大数据无法单独解决的问题。
米歇尔声称,虽然建模和模拟领域已经存在了 40 年,但 Cosmo Tech 是唯一一家能够模拟极端复杂性(如生命系统和不同的时间和空间尺度)的公司。他们的方法可以应用于几乎任何系统,例如流行病和所需的关键基础设施、智能能源规划、恐怖活动和多式联运系统。通常决策是基于系统某些方面的不同证据。元分析仅限于一个单一的现象,即使决策者正在考虑实施这一具体方面,它将如何与系统的其他部分相关的知识仍然是一种猜测。Cosmo Tech 的方法提供了所有相关组件及其交互方式的全球图景,这使得高管、政治家和决策者能够做出更准确的决策。

人工智能允许的可能性广为人知,但米歇尔鼓励我们考虑限制,以及如何克服它们。对于大数据,重点是可以在数据中发现什么,而不是理论测试和构建。这种理论上的方法,结合相关性分析(甚至包括复杂的算法,如神经网络),易于检测出虚假关系。因果关系不能从相关性分析中推断出来(很少有例外)。预测只能基于以前发生的事情,这意味着我们不能预测不寻常或罕见的事件。这些问题通过建模专家知识/理论和使用模拟的结合而减弱(但可能没有完全解决),因为这允许你改变参数并看到最有可能的结果。
在使用算法优化专家知识之前,需要对其进行建模和组合。系统可以如此之大和复杂,没有人能有一个完整的视图,即使是专家也只知道它的一部分。Cosmo Tech 首先创建单独的子模型,然后将这些子模型组合成整个复杂系统的完整模型。Cosmo Tech 的系统建模专家与客户公司的专家合作,并借鉴学术成果。模型化的知识利用了许多研究领域、理论、它们的推理和经验证据。例如,Cosmo Tech 的早期客户之一是法国电网公司 RTE ,它需要对电网本身、资产管理(如变压器、铁路线)、财务资源、人力资源以及财务投资和风险进行建模。
Cosmo Tech 流程的下一步是添加这些子模型之间的链接和交互。例如,他们添加了网格覆盖对客户满意度和收入的影响,以及这些子模型和相互关系如何随着时间的推移而发挥作用。这创造了一个巨大、复杂、多领域的模型。他们运行模拟操作所需的参数,以深入了解潜在的结果。Cosmo Tech 的软件 Studio 允许客户轻松地更改参数并直观地看到影响,如风险图、成本和风险成本。
模拟可用于创建“假设”情景,以进行预测。RTE 每年有 8 亿英镑的投资问题,所以 Cosmo Tech 用 Studio 来理解:如果 RTE 减少他们的投资,会发生什么?Studio 允许他们看到,例如,他们将无法更换导体,他们将不得不限制电网的覆盖范围,他们的碳排放量将增加,或者 10 年后将会停电。尽管预测只和模型一样准确,只和数据一样有代表性,但是这些可能的未来允许做出更明智的决策。
没有计算机的帮助,一个专家无法想象如此复杂和动态的模型,但是计算机需要理论和推理的输入。因此,人+机器是最佳组合,这就是为什么我们需要增强智能。此外,Cosmo Tech 的过程需要打破学术研究的筒仓。该公司是里昂商学院的一个学术分支,在里昂商学院,他们有一个由 200 名复杂系统专家组成的团队,他们来自生物学、物理学、数学、社会学和地理学。
客户工作室是 Cosmo Tech 的主打产品。他们与客户合作,在一个新的领域创造一个新的软件,然后与客户一起,把它卖给同一领域的其他公司。米歇尔说,他们正在努力向公司、大学和非政府组织提供软件许可证,这将允许他们自己模拟自己的复杂系统,创建自己的模拟和预测。尽管这还只是一个想法,但它将帮助米歇尔实现他最初的目标——促进基于证据的政策。预测和防止下一次经济危机是米歇尔的梦想,但如果决策是基于复杂系统如何运行的证据,他会很高兴。
米歇尔强调,我们需要改变我们使用数据和算法来洞察我们周围世界的方式。我们需要拥抱复杂性,而不是使用算法来简化。Michel 认为,对专家知识进行建模和算法优化是我们了解系统剪切复杂性的最佳方法,这是改进我们决策的核心要素。
新兴技术通过个性化为盈利的新闻业铺平了道路

Photo by Jamie Mink on Unsplash
在马克·扎克伯格看来,脸书的任务只完成了百分之一。2003 年开始作为学生平台的东西在 2006 年很快成为一个尖端的新兴平台。今天,高度个人化的数据收集使高度个性化的脸书新闻订阅源成为可能,不仅通过采用未来的新兴技术,而且通过开拓 it,这些订阅源抓住了内容消费者的心,使新闻提供商变得老派。
作为虚拟现实硬件公司 Oculus 的所有者和人工智能驱动的个性化的早期采用者,扎克伯格正在以身临其境和高度个性化的内容体验打破新闻提供商的心。他的秘诀是:不受约束地获取数百万份免费共享的个人数据,然后他将这些数据转换成充满读者想要的内容的新闻提要。脸书有能力把读者放在第一位,给他们所有的控制权,然后收获所有的参与回报。
为了竞争,三种新兴技术有潜力帮助新闻提供商将读者放在第一位,以获得高度个性化和沉浸式的体验。
虚拟现实广播让观众掌控一切。
虚拟现实(VR)讲故事公司 Greenfish Labs 与希望国际合作,讲述马拉维的故事,通过非营利组织提供的小额贷款改变了非洲人的生活。他们的伙伴关系意味着第一世界的捐助者走进第三世界非洲公民的生活,体验他们的生活转变,就好像他们就在那里一样。
“你可以看到护目镜下开始出现的泪水,顺着他们的脸颊滴落。你不会从照片或别人讲述的故事中获得那种情感体验。希望国际的首席执行官彼得·格里尔告诉 Inc 杂志的约翰·博特。
“虚拟现实和增强现实等新兴体验式技术迫使参与的观众停下手中的事情,参与到媒体片段中,创造传统媒体无法实现的对主题的更深层次的联系和理解,”GreenFish Labs 的执行制片人 Sovanna Mam 说。
VR 讲故事的开创性之处在于,它为消费者提供了所有的控制权。观众可以在体验中走来走去,选择与他们产生共鸣的部分,然后更深入地研究它们。通过虚拟现实,希望国际通过让捐赠者控制他们自己的内容体验来报道他们所服务的人的困境。
结果是:内容体验让观众感受到如此个性化的情感,让他们想要体验更多——这是记者的梦想。
区块链将更大的受众洞察转化为有利可图的内容个性化。
纳斯达克的安娜·格拉西克解释道新闻业目前陷入了一个难题。不久前,它还在蓬勃发展,每天有数百万份印刷材料分发出去。然后,万维网打乱了这一切。人们可以通过触手可及的网站免费了解最新最棒的新闻故事。此外,随着移动设备和社交媒体应用程序的结合,突发新闻可以实时获得。与此同时,尽管新闻提供商获得了数字读者,但他们却在赔钱。
然后是数字广告。人们非常兴奋,因为新闻业似乎可以恢复其收入流。问题是:消费者不再重要。“点击诱饵”标题意味着广告商得到了他们寻求的曝光率。随着新闻变成耸人听闻的标题,除了点击之外没有什么价值,读者变得越来越沮丧。
区块链可能会让读者第一的方法再次盈利。“每个人都可以为他们喜欢的每篇文章、系列照片或视频报道支付一小部分费用。我相信这将是一个时代的终结。报纸将不再依赖付费墙,甚至更糟,讨厌的广告,”区块链一家通讯公司 OST“简单令牌”的通讯主管沃特·弗胡格说。这对新闻业的未来意味着好消息:“新闻业可以再次盈利。”
好的新闻报道不仅会再次获得回报,而且随着内容消费者用他们的数字钱包投票,记者们将知道什么能与他们的观众产生共鸣,从而使更个性化的消费者体验成为可能,以迎合那些最积极参与的人的口味。
人工智能不仅能解读观众偏好趋势,还能预测它们。
人工智能(AI)提供了超越大数据能力的个性化潜力。它不仅有助于为独特的高质量内容揭露以前容易错过的故事,而且有助于揭示观众的意图和趋势,甚至预测他们。
“目前,记者文章面向消费者的大多数基于兴趣的目标是基于以前的兴趣。然而,人类的兴趣在不断变化,”英国 1plusX 的董事总经理 Fiona Salmon 说,这是一个人工智能数据创建和管理平台,由两位前谷歌董事,于尔根·加勒博士和托马斯·霍夫曼博士创建。
例如,在一个非常基础的层面上,Fiona 说,读者可能会在冬天开始阅读足球文章,但在春天会转向棒球文章。人工智能让记者不仅可以了解消费者现在可能想要什么,还可以了解他们未来的内容偏好。
“人工智能将对消费者在特定时间的特定兴趣和特征做出更详细和精确的预测。菲奥娜说:“它们将识别人们的特征和行为趋势,使出版商能够向消费者展示与每个读者在统计上相关的文章。
这是一种预测高度个性化体验的能力,然后在最能引起共鸣的时候把它们传递出去。因此,她总结道,人工智能平台对于用前瞻性的个性化策略规划编辑日程至关重要。

高度定制的新兴技术使用创造了竞争性的新闻消费体验。
鉴于个性化在新闻业未来的作用,记者们似乎应该立即开始将新兴技术应用到他们的报道中。但是,NBC 媒体实验室的副总裁 Sowmya Gottipati 提出了一些警告。在评估记者应该如何拥抱人工智能时,她说:“供应商提供的许多人工智能功能倾向于通用模型。这与成功的人工智能的一个基本方面相冲突:用例训练。”
人工智能需要培训来定制它,以满足特定用例的挑战。同样,当出于个性化目的使用区块链和虚拟现实等新兴技术时,应该根据新闻最佳实践和目标内容消费者进行高度定制。
这个难题的答案很简单,也很容易找到:“仅仅购买、采用或复制已经上市一年的东西是不够的。新闻编辑室必须与开发新技术的公司密切合作,以改善人们发现、消费和分享真正重要的故事的方式,”PressReader 首席内容官尼古拉·马尔亚罗夫说。
希望国际提供了一条前进的道路:寻求与科技公司的合作,这些公司将致力于彻底理解新闻和目标市场的用例,然后为他们定制新兴技术的新闻应用。新兴技术的定制应用将意味着针对受众需求和偏好的前沿个性化。
外卖
最终,正确的新兴技术应用将意味着有竞争力和有利可图的新闻业,为内容消费者提供会让他们再次购买的体验。
使用时间嵌入的表情预测

表情符号的使用已经成为一种新的社交形式,这很重要,因为它可以帮助改善聊天应用程序等通信系统。本文调查表情符号的用法和语义随时间的变化,分析表情符号用法的季节性变化。此外,作者开发了一个基于时间信息的表情预测模型。
贡献
过去已经进行了多种表情符号预测研究(参见 Felbo 等人的著名工作,2017 ),但没有考虑时间信息。探索表情符号和季节事件之间的时间相关性,并用于消除表情符号含义的歧义。
例题
考虑一下三叶草表情符号(🍀),它通常与一年四季的好运愿望有关,除了三月,在三月它主要用于表达与聚会和饮酒(由于圣帕特里克节)有关的事件情况。
挑战
- 这项研究表明,时间信息对于表情符号预测是有用的,即使对于与时间无关的表情符号(💪还有❤️).
- 表情符号天生是主观的,这就是为什么很难分析它们的语义。
数据集
Twitter 用于收集 1 亿条美国推文,组织如下:
- 季节性表情数据集 —数据按季节分为四个子集:春、夏、秋、冬(见下图)
- 表情符号预测数据集——数据减少到只包含一个常用表情符号的推文(表情符号必须属于 300 个常用表情符号)

季节性表情符号语义及用法
使用季节性数据集的四个子集来训练跳格词嵌入模型。这些模型提供的信息基本上有助于根据表情符号彼此之间的语义相似性来描述表情符号。(详见论文)
通过比较与嵌入空间中的每个表情符号相关联的前 10 个表情符号,发现与音乐、动物、糖果和情绪相关的表情符号不受季节性的影响(例如,🎶,🎼,🍦,🐠,😂,🎸).这意味着这些表情符号跨季节保留了意义。
相反,与运动相关的表情符号(例如,🏀,🏆)在不同的季节有不同的意思,可能是因为运动的高峰期。另一个与学校有关的有趣表情符号(🎓),跨季节变了意思;在春季,它与派对表情符号有关,在秋季,它与学校相关的表情符号有关。查看每一季松树表情符号的 10 大相关表情符号(🌲)在下图中——非常依赖于季节,你不觉得吗?你能猜到原因吗?(提示:户外 vs 圣诞节)。(参见论文中大量有趣的发现)

表情符号预测
第二个数据集包括 300 个表情类和总共 900,000 条推文(每个类 3,000 条推文),用于表情预测。表情预测模型的架构如下:通过早期融合方法和后期融合方法来组合字符嵌入、单词嵌入和日期嵌入。这就产生了两个型号( 前期 和 后期 )。第三个模型被训练( W/O ),其完全忽略日期嵌入。(参见论文,了解这些嵌入是如何构建的)

结果
下表中报告了所有型号的精确度、召回率和 F1 分数。我们可以观察到,通过使用早期融合来组合时间信息,早期模型优于其他模型。

F1 得分较高的表情符号(无日期对早日期)如下表所示。你肯定可以观察到许多表情符号是特定于季节的(例如,🍀,🌒)并因此受益于日期嵌入。甚至与时间无关的表情符号(例如,🖤,❤️,💪)受益于时间信息。

结论&未来工作
- 提出了一种基于深度神经网络进行表情预测的多通道架构。
- 对一天或一周中特定时间的表情符号语义和用法进行更多分析,可能有助于改善日期嵌入和整体预测模型。
- 这项工作有很大的改进空间,与情绪识别、事件检测和计算健康研究相结合可能是一个非常有趣的主题。
参考文献
- 参考:https://arxiv.org/abs/1805.00731——“通过时间变化透镜探索表情符号的使用和预测”
关于这篇论文还有其他问题吗?给我发个 DM@ Omar saro。
当没有数据时,历史学家如何处理古代帝国的数据
Seshat 轴向年龄数据集的探索性数据分析

Photo by Simon Matzinger from Pexels
"90% of the data ever created was created in the last two years."
这个Petter Bae brandtzg的引用,虽然令人恐惧,却暴露了一个更可怕的观察:我们在过去 280 万年的人类历史中记录的数据比我们在 2016-2018 年记录的数据少 10 倍。鉴于自计算机时代开始以来数据的估计指数增长率,从历史开始到柏林墙倒塌,我们拥有的 10^15 数据比我们过去 30 年所拥有的还要少。如果我们看看 17 世纪中叶现代统计学发明之前,我们能分析的数据量是微乎其微的。如果我们看看 1086 年的《末日审判书》,它会变得非常令人沮丧。

幸运的是,没有任何东西限制现代历史学家和学者创造关于过去的新数据。从数字化的照片和文本、关于考古挖掘的文档,甚至是关于历史时期的学术共识的众包聚合,历史学家(以及像我这样的爱好者)可以创建和探索数据集,使用尖端的分析工具得出关于过去的新理解,并帮助回答以下问题:
- 与其他社会相比,地中海和亚洲的不同社会随着时间的推移发展了什么样的社会政治规范?
- 在相同的时间和地点,最有可能和最不可能遵守的规范是什么?
- 有哪些相关规范的独特轨迹是某些社会群体而不是其他群体进化的轨迹?
数据
对于这个分析,我使用的是相对较小的轴向年龄数据集,由 Seshat 提供,“一个由进化科学家、历史学家、人类学家、考古学家、经济学家和其他社会科学家组成的大型国际多学科团队。”公开提供的数据集跟踪各种社会政治规范及其在非洲-欧亚大陆关键地区的发展。在 10 个 NGAs(自然地理区域)内,每个日期(在公元前 5300 年和公元 1800 年之间以 100 年为增量变化的时间跨度)的每个社会政治规范的具体得分由一组专家商定,并编入数据集。
但首先,作为使用他们数据集的回报,他们要求我包含的信息块:
*This research employed data from the Seshat Databank (seshatdatabank.info) under Creative Commons Attribution Non-Commercial (CC By-NC SA) licensing.*[Turchin P. et al. 2015\. “Seshat: The Global History Databank.” Cliodynamics 6(1): 77–107](https://doi.org/10.21237/C7clio6127917)[Mullins, D., Hoyer, D. et al. 2018\. “A Systematic Assessment of ‘Axial Age’ Proposals Using Global Comparative Historical Evidence.” American Sociological Review 83(3): 596–626](https://doi.org/10.1177/0003122418772567)
不幸的是,数据集中每一个 NGA 所涵盖的时间段各不相同,早至公元前 5300 年,晚至公元 200 年。它们也不会同时全部结束:

此外,随着时间的推移,社会似乎会积累文化特征,而不是让属性均匀地出现和消失,这也可能使我们的分析变得复杂,因为数量上的原因,我不会在这里讨论。

尽管如此,数据中的变化足以回答我们上面的三个问题。所以事不宜迟…

Source: pixabay.com
问题 1:与其他社会相比,地中海和亚洲的不同社会随着时间的推移发展了什么样的社会政治规范?
除了柬埔寨和卡奇平原,道德惩罚和相信无所不知的超自然生物的平均分数在古典世界是一个很强的特征,但在南亚和东亚社会不是。

道德规范,在较小程度上,促进亲社会,相信统治者不是神,正式的法律法规,法律的普遍适用性,对行政部门的约束,以及全职官僚是除关西以外所有 NGA 的共同特征,这可能是因为 NGA 的数据集中有大量的空值(本质上是空单元)(我仍然不确定为什么他们包括关西 5000 年的零和空单元)。

加利利、卡奇平原、科尼亚平原、苏西亚纳、上埃及,以及在较小程度上的克里特岛,所有这些地区在现代时期都处于伊斯兰统治之下,在将统治者和平民等同于精英方面得分明显较高。

对行政和弹劾的限制似乎是显而易见的罗马特征,Latium 遥遥领先,其次是前罗马统治的克里特岛,加利利,上埃及和科尼亚平原,尽管黄河流域的弹劾事件略多于上埃及。就全职官僚而言,这是颠倒的。出于前面提到的原因,除了关西以外,每个 NGA 都有比拉丁姆更多的全职官僚。


Photo by Ken Shirakawa from Pexels
为了克服空值导致的问题,如关西的情况,我还绘制了每个 NGA 相关要素的相对剖面图:
随着时间的推移,柬埔寨盆地的特点是促进群体超越自我,以及一个正式的、普遍适用的法律结构,在这个结构中,一个先进的官僚机构在运作。不平等似乎一直很严重,对权力结构的制约有限。

克里特岛同样有着全面和正式的法律,尽管个人利益比柬埔寨更受推崇。尽管在某些情况下统治者可以被罢免,但统治者和平民的价值观存在巨大差异。有时也有一些对全知的上帝的信仰。

加利利,再次,有一个高度结构化的法律框架,普遍适用和官僚化,但更强调集体善和道德惩罚。平等得到了更高的促进,高管受到了更多的约束,统治者不太可能被视为神,因为对无所不知的超自然存在的信仰非常普遍。尽管如此,一旦掌权,统治者很少能通过制度手段被罢免。

在卡奇平原上,社会相对不太可能因为道德原因而不是法律原因惩罚你,尽管坚持社会道德规范的压力非常大。尽管法律有一点可替代性,但在社会眼中,统治者、精英和平民有着显著平等的内在价值。

在关西,融入社会的社会压力很大,再加上正式且普遍适用的法律法规和强大的官僚机构,这可能意味着人们普遍知道社会对他们的期望。虽然精英和平民相对平等,但统治者是上帝。

科尼亚平原的轮廓很像加利利,有一些法治,强调集体利益,适度的平等,一个受约束的行政部门,以及对统治者不是神的信仰和对全知的超自然存在的信仰。然而,道德惩罚不像在加利利那么普遍。

拉丁姆是法治的缩影,正式的法典比道德惩罚更受青睐,对行政部门的约束,甚至是弹劾的强大传统。统治者不是神,人们普遍相信一个无所不知的超自然存在。然而,不平等现象猖獗,社会普遍认为平民不如精英或统治者有价值。

像柬埔寨和关西一样,黄河中游地区是亲社会规范、强有力的法律框架和官僚机构的混合体。然而,统治者通常不被认为是神圣的,有时会受到制度上的约束。黄河流域的社会分层也可能比关西更高,因为精英不太等同于平民。

尽管 Susiana 有强大的亲社会和道德规范,正式的法律法规,以及一大批官僚,但法律似乎不太普遍适用。高管受到适度约束,社会分层相对较低。

在埃及,道德规范非常重要,尽管存在一个正式的一般法律框架。有一个强大的官僚机构,精英和平民之间的平等程度相对较高。尽管统治者有时被认为是神圣的,但他们可能受到高度的制度约束。

咻!既然我们已经解决了最长、最复杂的问题,让我们继续…

Source: pixabay.com
问题 2:在相同的时间和地点,最有可能和最不可能遵守这些规范中的哪一个?
为了回答这个问题,我做了一个相关特征的关联矩阵。正如可以从数据集中预期的那样,要素往往会随着时间的推移而累积,相关性会偏向正相关。

正式的法律规范、亲社会的促进和法律的普遍适用性最有可能一起被观察到,并具有很强的正相关关系。在某种程度上,普遍适用的正式法律法规是对亲社会的一种促进,也是对“遵守规则”的一种激励,所以这是有意义的。弹劾是最不可能与精英和平民等同以及统治者和平民等同共现的特征,两者都有轻微的负面关系。弹劾还与全职官僚的存在负相关,尽管这种负相关要弱得多。看起来,强大的官僚机构和相对的社会平等可能已经消除了对一位高管的一些约束,这位高管远非全能,需要合法性和他人的合作才能统治。最不相关的特征是弹劾和无所不知的超自然存在,亲社会的促进和道德惩罚,这意味着后三者与前者的存在与否没有任何有意义的联系。

这让我们想到:

Photo by Zhang Kaiyv from Pexels
问题 3:一些社会群体而不是其他群体沿着哪些不同的相关规范轨迹发展?
基于我为 Udacity 的机器学习工程师 Nanodegree 做的一个早期项目,用代码对数据运行所谓的“主成分分析”,我能够得出三个独立的文化概况,数据中的社会在不同程度上符合或不符合,或者用技术术语来说,将维度折叠成三个维度,这三个维度最好地利用了数据中的差异。第一个维度解释了数据随时间变化的 48%的差异,这是一种抛弃,实际上只是表明 nga 倾向于随着时间积累越来越多的特征。然而,更有趣的是接下来的两个维度,分别反映了数据集 14%和 10%的方差。二维社会的特点是轻度缺乏对全知存在的信仰,并强烈认为统治者不是神,可以受到制度约束。尽管有一个强有力的法律框架,但社会分层很高,官僚机构很弱。这个维度对于许多古典主义者来说可能听起来很熟悉,是一种古典的古希腊政治哲学。相比之下,维度 3 的社会以强烈的道德规范和亲社会为特征。对全知上帝的信仰很低,但对神圣统治者的信仰很高,统治者比普通人更受尊重,相对不受约束,无可指责。有一个非常强大的官僚机构和高度复杂的法律框架。作为一种儒家政治哲学,这个维度对亚洲人来说也非常熟悉。这两种哲学被指定为独立的“维度”意味着它们并不相互排斥,因此不同的社会可以表现出一个、两个或两个维度都没有的混合特征(即一个社会可以同时受到希腊和儒家政治思想的影响。或者只有一个。或者都不是!).


Photo by Diego Cano from Pexels
评估和部署
尽管这些数据在主观性、简洁性、不同的时间线以及所有那些该死的缺失值方面有些问题,但 Seshat 的轴向年龄数据集确实证明了我们创造关于过去的新数据的能力,以便得出关于过去的新见解,这些见解可以导致关于过去的新理论,包括来自问题 2 的见解,即法律和亲社会倾向于一起出现, 虽然官僚主义和社会平等倾向于与弹劾或问题 3 的见解分开出现,但经典的希腊和儒家社会政治模式可能被认为是地中海和亚洲社会发展的独立维度,有时是同时和融合的。 数据集集合的协作性质赋予了更大的客观合法性,并且可以而且应该被复制,以围绕我们缺乏大量定量数据的其他历史主题创建更大的数据集。
至于这种分析,从关于历史的数据中收集的发现,以前不存在的数据,可以在以前探索不足的方向上指导未来的研究。我欢迎读者验证或挑战本文中的见解,并将数据科学的适用性扩展到前信息时代!
基于安然数据集的电子邮件分类实证分析

在本文中,我们将首先评估 3 种机器学习算法的性能,即逻辑回归、支持向量分类和随机森林分类器。在后一部分,我们将比较机器学习算法的性能与使用递归神经网络模型(LSTM)获得的结果。我们将在整个评估过程中使用安然数据集。
1。关于数据集
安然数据集包括主要由安然公司高级管理层发送的电子邮件。在这个实验中,我们使用了专门为垃圾邮件和火腿分类制作的数据集的处理版本。该数据集包含 30207 封电子邮件,其中 16545 封被标记为垃圾邮件,13662 封被标记为垃圾邮件。
2。 方法论
2.1 数据预处理
2.1.1 机器学习
对于机器学习算法,我使用了单词袋方法。这是一种从文本中提取特征以用于机器学习算法的方法[1]。在这种情况下,我们首先对电子邮件进行标记,并为所有电子邮件中的所有单词创建一个字典。然后,我们从其中选取最常见的 3000 个单词作为我们的最终词典。然后我们遍历每封邮件,记录邮件中每个令牌在字典中对应的令牌的出现频率。这样,所有电子邮件的最大序列长度变为 3000。
2.1.2 递归神经网络
RNN 模型使用了一种略有不同的单词包方法来预处理电子邮件。我们首先对电子邮件进行标记,并制作所有电子邮件中所有单词的字典,就像我们对机器学习模型所做的那样。那么所有的单词将从 1 开始被索引。然后,电子邮件集合将被迭代,对于电子邮件中的每个单词,将参考字典将该单词映射到相应的索引。这种方法确保了电子邮件中单词的顺序不变。但是我们现在有一个问题,每个电子邮件有不同的序列长度。为了减轻这一点,我们将得到最长的电子邮件的长度,并将所有电子邮件填充到该长度。填充将通过在每个序列的开头添加“0”来完成,以便它不会影响训练过程。在这个场景中,所有电子邮件的序列长度是 3425。
2.2 机器学习算法
安然数据集将用于训练机器学习模型,以将电子邮件分类为垃圾邮件或 ham。所有利用的机器学习算法都取自 scikit learn 库。所有算法的参数调整都是手动完成的。这是因为数据集的大小是 30207,运行网格搜索太耗费时间了
2.2.1 拆分数据
对于所有算法,数据被分成三组作为训练集、验证集和测试集。验证集用于调整参数。在参数调整过程之后,使用测试集来获得最终结果。训练集由 80%的数据组成,20%用于验证集。然后这 20%被进一步平均分配,50%用于验证,另外 50%用于测试。
2.2.2 支持向量分类
支持向量分类算法通过创建一个特征空间来模拟这种情况,这是一个有限维的向量空间,其中的每一维都代表特定对象的一个“特征”[2]。
首先,在没有任何优化的情况下进行观察。以下是初步结果:

在使用线性核获得初始结果之后,调整 C 参数以获得最终结果。下面显示的是收到的验证和测试集的最终结果。这些是观察期间获得的最高验证分数。

2.2.3 随机森林分类器
随机森林分类器从随机选择的训练集子集创建一组决策树。然后它聚集来自不同决策树的投票来决定测试对象的最终类[3]。
最初,观测是在没有任何优化的情况下进行的,就像 SVC 算法一样。以下是初步结果:

通过改变可能对最终结果产生最大影响的不同参数来改进初始结果。探索的参数是:n_estimators、max_features 和 Max_depth。下面显示的是最终结果:

2.2.4 逻辑回归
逻辑回归用于描述数据,并解释一个因变量与一个或多个名义变量、序数变量、区间变量或比率水平自变量之间的关系[4]。
该算法使用默认设置运行,因为没有要优化的参数。下面显示的是测试集获得的结果。

2.2.5 总结
在比较这些车型时,我们将主要关注 f1 的得分。根据观察,尽管对 svc 算法进行了优化,但仍无法实现显著的改进。但是随机森林分类器在调整参数值后显示出相当显著的改进。尽管这两种算法都给出了很好的结果,但是逻辑回归算法的最终结果是最高的。如您所见,逻辑回归算法和 svc 算法的最终结果相差不远,但我们必须让逻辑回归算法胜出,因为这是我们能够获得的最高结果。
我们将进一步探讨这个主题,看看我们是否可以通过使用不同的方法来改善最终结果。即递归神经网络。我们将用于这一观察的递归神经网络的类型是 LSTM 模型。
2.3 LSTM 车型
LSTM 代表长期短期记忆网络,这是一种特殊的 RNN,能够学习长期依赖关系。这些是专门设计来避免大多数模型中存在的长期依赖问题的。LSTMs 长时间记忆信息,有助于建立长期依赖性模型[5]。
采用张量流框架建立 LSTM 模型。LSTM 模型由几层组成。当将数据输入模型时,我们将首先通过嵌入层传递数据。嵌入层的功能是将代表字典中单词的每个索引表示为一个范围内指定大小的随机数值向量。这种方法有助于对单词之间的关系进行建模。那么嵌入层的输出将通过 LSTM 层发送。我们使用 Tensorflow 提供的“基本 LSTM 池”来完成这项任务。LSTM 层将在其输出中添加一个漏失,以随机抑制神经网络中的一些神经元,从而降低过拟合的可能性[6]。然后,隐藏图层将消耗 LSTM 图层的输出,并生成最终输出。
当计算成本函数时,logit(没有通过激活函数发送的最终结果)将被传递给它。使用的成本函数是“softmax 交叉熵与 logits”。然后,优化函数将用于降低成本。所利用的优化功能是 Adam 优化器。
通过激活函数传递获得的 logit 值进行预测。为此使用了 Sigmoid 函数,因为相关的任务是二元分类。
2.3.1 拆分数据
数据被分成 3 组,作为之前在机器学习方法中提到的训练、验证和测试集。在获得初始结果后,验证集用于调整超参数以提高最终得分。然后使用测试集进行最终评估。训练、验证和测试数据的百分比与用于机器学习方法的百分比相同。
2.3.2 结果
下面显示了使用验证数据集获得的初步结果:

以下结果显示了调整超参数后的最终输出

在使用上述模型获得令人满意的结果之后。通过叠加更多的隐藏层来进行观察,以查看结果是否可以进一步改进。
下面显示的是使用两个隐藏层得到的结果。

2.3.3 总结
为了评估该模型,我们将主要考虑 f1 分数,正如我们对机器学习算法所做的那样。考虑到优化参数后获得的结果,我们可以看到分数略有提高。
当试图通过添加更多的隐藏层来进一步改善结果时,正如你所看到的,它给出了一个低得多的输出。其原因是,即使在理论上,神经网络应该对堆叠层给出更好的分数,在这种情况下,我们缺乏数据。我们拥有的数据量不足以训练多个隐藏层。
3。谁做得更好?
如上所述,逻辑回归算法给出了比其他两种机器学习算法更好的结果。所以现在我们来了个问题,考虑到逻辑回归算法和 LSTM 模型,谁做得更好。下图是逻辑回归算法和 LSTM 模型的最终结果对比。

查看表格,我们可以清楚地看到,LSTM 的f1 得分优于逻辑回归算法。基本上所有的分数 LSTM 模型都优于逻辑回归算法。这让 LSTM 模式轻而易举地胜出。
4。结论
考虑到所获得的结果,LSTM 模型优于所有其他考虑的机器学习算法。其原因是 LSTMs 模拟长期依赖性的能力。安然是一个文本数据集,因此,能够记住整个电子邮件中单词之间的依赖关系增加了更好地猜测它是垃圾邮件还是火腿电子邮件的机会。由于 LSTM 设计擅长这项任务,它能够给出比其他机器学习算法更好的结果。
总之,我们可以说,LSTM 真正能够捕捉数据中的长期依赖性,并利用其在架构中的存储方面胜过其他机器学习算法。
5。参考文献
[1]https://medium . com/grey atom/an-introduction-to-bag-of-words-in-NLP-AC 967d 43 b 428
[2]https://mindmajix.com/support-vector-machine-algorithm
[3]https://medium . com/machine-learning-101/chapter-5-random-forest-classifier-56dc 7425 c3e 1
[4]http://www . statistics solutions . com/what-is-logistic-regression/
http://colah.github.io/posts/2015-08-Understanding-LSTMs/
注:本次评估使用的完整代码可以通过这个链接找到。请随意摆弄代码,亲自尝试一下。编码快乐!
利用 MLflow 增强 Spark
这篇文章旨在讲述我们使用 MLflow 的初步经验。
我们将通过记录所有探索性迭代,开始用自己的跟踪服务器发现 MLflow。然后,我们将展示使用 UDF 链接 Spark 和 MLflow 的经验。
语境
在 Alpha Health 我们利用机器学习和人工智能的力量,让人们能够控制自己的健康和福祉。因此,机器学习模型是我们正在开发的数据产品的核心,这也是为什么 MLFLow,一个覆盖 ML 生命周期所有方面的开源平台吸引了我们的注意力。
MLflow
MLflow 的主要目标是在 ML 之上提供一个额外的层,允许数据科学家使用几乎任何机器学习库(keras, mleap,【py torch,sk learn&tensor flow)
MLflow 提供了三个组件:
MLflow (目前处于 alpha 阶段)是一个管理 ML 生命周期的开源平台,包括实验、可复制性和部署。
设置 MLflow
为了使用 MLflow,我们首先需要设置所有的 Python 环境来使用 MLflow,我们将使用 PyEnv ( 来设置→Python in Mac)。这将提供一个虚拟环境,我们可以在其中安装运行它所需的所有库。
注意:我们使用 PyArrow 来启动模型作为 UDF。PyArrow 和 Numpy 版本需要修复,因为最新的版本之间有一些冲突。
启动跟踪用户界面
MLflow 跟踪允许我们使用 Python 和RESTAPI 来记录和查询实验。除此之外,还可以定义我们将模型工件存放在哪里( Localhost、 亚马逊 S3 、 Azure Blob 存储 、 谷歌云存储 或 SFTP 服务器 )。由于我们在 Alpha Health 中使用 AWS,我们将尝试用 S3 作为工件存储。
MLflow 建议使用持久文件存储。file-store是服务器存储运行和实验元数据的地方。因此,在运行服务器时,要确保它指向一个持久文件系统位置。这里,我们只是使用/tmp进行实验。
请记住,如果我们想要使用 mlflow 服务器来运行旧的实验,它们必须存在于文件存储中。然而,如果没有它们,我们仍然可以在 UDF 中使用它们,因为只需要模型路径。
注意: 记住跟踪 UI 和模型客户端必须能够访问工件位置。这意味着,不管 EC2 实例上的跟踪 UI 如何,如果我们在本地运行 MLflow,我们的机器应该可以直接访问 S3 来编写工件模型。

Tracking UI storing artifacts to a S3 bucket
运行模型
一旦追踪服务器开始运行,我们就可以开始训练我们的模型了。
作为示例,我们将使用 MLflow Sklearn 示例 中提供的葡萄酒示例的修改。
如前所述,MLflow 允许记录我们模型的参数、度量和工件,因此我们可以跟踪这些在我们不同的迭代中是如何发展的。这个特性非常有用,因为我们将能够通过检查跟踪服务器来重现我们的最佳模型,或者验证哪个代码正在执行期望的迭代,因为它记录了 (免费)git 散列提交*。*

Wine Iterations
为模特服务
使用“ml flow server”,启动的 MLflow 跟踪服务器也托管 REST APIs,用于跟踪运行并将数据写入本地文件系统。您可以使用"MLFLOW _ TRACKING _ URI"环境变量指定跟踪服务器 URI,ml flow 跟踪 API 会自动与该 URI 上的跟踪服务器进行通信,以创建/获取运行信息、日志度量等。
Ref:Docs//运行跟踪服务器**
为了服务一个模型,我们所需要的是一个跟踪服务器运行( 见 启动 UI )和一个模型运行 ID** 。**

Run ID
为了使用 MLflow serve 特性服务模型,我们需要访问跟踪 UI,因此它可以通过指定--run_id来检索模型信息。
一旦模型由跟踪服务器提供服务,我们就可以查询新的模型端点。
运行 Spark 的模型
虽然,仅仅通过训练模型和使用 serve 特性(ref:ml flow//docs//models # local)就能够实时地为模型提供服务是非常强大的,但是使用 Spark(批处理或流)来应用模型甚至更加强大,因为它加入了分布的力量。
想象一下,有一个离线训练,然后以一种更简单的方式将输出模型应用于所有数据。这是 Spark 和 MLflow 共同闪耀出完美光芒的地方。
安装 PySpark + Jupyter + Spark
展示我们如何将 MLflow 模型应用于 Spark 数据框架。我们需要在 Jupyter 笔记本上安装 PySpark。
从 PySpark 发射 Jupyter
由于我们将 Jupyter 配置为 PySpark 驱动程序 ,现在我们可以在笔记本上附加 PySpark 上下文来启动 Jupyter。

正如我们上面所展示的,MLflow 提供了一个将我们的模型工件记录到 S3 的特性。因此,一旦我们选择了一个模型,我们就可以通过使用mlflow.pyfunc模块将其作为 UDF 导入。

PySpark — Wine Quality Prediction Output
到目前为止,我们已经展示了如何将 PySpark 与 MLflow 结合使用,对所有葡萄酒数据集进行葡萄酒质量预测。但是,当您需要使用 Scala Spark 的 Python MLflow 模块时,会发生什么呢?
我们还通过在 Scala 和 Python 之间共享 Spark 上下文来测试这一点。这意味着我们在 Python 中注册了 MLflow UDF,然后在 Scala 中使用它( yeap,这不是一个好的解决方案,但至少它是个东西 🍭)。
Scala Spark + MLflow
对于这个例子,我们将把 Toree 内核 添加到现有的 Jupyter 中。
正如您在随附的笔记本中看到的,UDF 由 Spark 和 PySpark 共享。我们希望这最后一部分对那些热爱 Scala 并且必须将 ML 模型投入生产的团队有所帮助。
后续步骤
虽然 MLflow 目前在阿尔法(🥁),它看起来很有希望。凭借能够运行多个机器学习框架并从同一端点使用它们的能力,它将所有推荐系统带到了一个新的水平。
此外,MLflow 通过在数据工程师 和数据科学家之间建立一个公共层,拉近了和数据工程师的距离。
在对 MLflow 进行研究之后,我们确信我们将会更进一步,并开始在我们的 Spark 管道和推荐系统中使用它。
让文件存储与数据库同步而不是使用文件系统会更好。这应该允许多个端点使用同一个文件存储。比如让多个 Presto 和 Athena 实例使用同一个胶水 metastore 。
最后,感谢 MLflow 背后的所有社区,是他们让这一切成为可能,让我们的数据生活更加有趣。
如果您正在使用 MLflow,请随时联系我们并提供一些关于您如何使用它的反馈!甚至,如果你在生产中使用 MLflow。
赋权作为内在动力
在没有目标或奖励的情况下,被授权
有钱,有影响力的朋友,或者拥有一辆车意味着你更有权力决定你想要什么样的未来。这不一定意味着你知道哪些目标是正确的,但它肯定会让你处于一个权力的位置,在那里有许多可能的未来可供选择。
这种授权的概念是由 Klyubin 等人[1]在设计适应性代理的上下文中正式提出的。它旨在作为一种独立于目标的内在行为动机,并在机器人学、强化学习和自适应系统中产生了一些有趣的结果。例如,使用授权最大化策略来控制模拟双摆,Jung 等人[4]发现了以下行为:

Maximising empowerment in a double pendulum controller. The controller finds the most unstable point of the pendulum and keeps it there, even though there is no explicitly encoded goal of reaching this state. Image taken from Jung et al. [4]
双摆被控制到最不稳定的点(垂直 90 度)并保持在那里,即使控制器中没有编程找到这种状态的明确目标——它只是最大化授权,并且恰好钟摆的顶部是最授权的位置(这是因为从这个不稳定点可以到达更多可能的未来状态)。
授权是基于一种信息理论的形式主义,它将行动和未来的感觉视为一种信息传输渠道(就像 Claude Shannon 在他关于通信工程的开创性工作中描述的那样[5])。我在这篇文章中的目标是以最简单的方式解释授权,包括如何计算它的数学,以及它对强化学习和人工智能的影响。在文章的最后,我提供了一个到我的 GitHub 库的链接,在那里你可以找到在离散世界中实现授权的代码。
奖励和强化学习
强化学习是关于在一个不确定的世界中学习一个最佳的行动策略,它在每个时间步提供一个奖励信号。DeepMind 通过训练深度网络,使用游戏分数作为奖励信号,利用强化学习技术在雅达利游戏[2]上超过人类水平的表现。

Space Invaders Atari game. DeepMind’s Q-learning network outperforms human-level game play by training deep networks using the game pixels as input, and the game score as reward signal.
虽然这令人印象深刻,但现实世界中的生物面临着更加复杂和不确定的世界——将来自你眼睛和耳朵的感官刺激与用作 DeepMind 神经网络输入的简单像素和分数信号进行比较。但更关键的是,对于生物有机体来说,根本不存在明显的回报信号。当蚂蚁、松鼠或人类做出“好”或“坏”的举动时,没有全知的守护者或“神谕”来告诉他们。
事实上,像我们这样的生命体最令人印象深刻的品质是我们继续生存的能力。我们的内部器官不仅继续做着让我们生存的事情,而且我们通常会避免可能导致我们死亡的情况。为了增加我们继续生存的机会,我们的大脑/身体有没有可以遵循的一般原则?
内在动机
卡尔·弗里斯顿提出了一个雄心勃勃的框架,认为大脑的功能是最小化一个被称为自由能的量。不仅如此,他还提出,对于任何旨在避免宇宙无序化趋势的破坏性影响的有机体来说,将这个量最小化是必须的(热力学第二定律)。不过自由能框架不是本文的主题,这里就不赘述了。
我提到这一点是为了引入内在动机的概念。在基地,所有生物都必须抵抗宇宙的无序趋势,才能继续存在。大部分工作是由我们的新陈代谢完成的,新陈代谢为有用的工作收集能量,并排出高熵废物。但是,在行为的更高层次上,问题是:在没有具体目标或奖励信号的情况下,有没有可以指导行为的普遍原则?
例如,假设目前我没有要完成的目标或任务,但是我知道在将来的某个时候一个任务可能会出现。与此同时,有没有什么原则性的行为方式可以让我为未来的任务做好最充分的准备?
授权
根据克柳宾的说法,在其他条件相同的情况下,代理人应该最大化他们行为的未来可能结果的数量。以这种方式“保持你的选择余地”意味着当一项任务出现时,一个人尽可能地被授权去完成它所需要做的任何事情。Klyubin 等人在两篇标题恰当的论文中很好地提出了这一概念:“在其他条件相同的情况下,被赋予权力”[1]和“保持选择的开放性:感觉运动系统的基于信息的驱动原则”[3]。从那以后,机器人和强化学习领域的许多令人兴奋的工作都使用并扩展了这个概念[8,9]。
这里的主要创新是使用信息论正式授权。要做到这一点,世界必须被认为是一个将行为转化为未来感觉状态的信息理论通道。通过将动作和随后的感觉视为通过通道相关联,我们可以将授权精确量化为传感器-致动器通道的信息论通道容量。也就是说,通过我的行动,我能向未来的感官状态注入多少信息?说的更直观一点,我的环境有多可操控?
为了定义这一点,我们需要首先定义两个随机变量 X 和 Y 之间的互信息。假设 X 和 Y 通过一个通道 X→Y 相关联,由条件分布 p(y|x) 描述。也就是说,值 x 规定了在值 y 上的概率分布(记住,信道可能是有噪声的,因此 x 仅用某个概率来确定 y ,因此是概率分布,而不是与每个 x 相关联的精确值)。如果通道的输入 x 分布为 p (x),则 X 和 Y 之间的互信息由下式给出。

Mutual information between X and Y. Formally, it is the average reduction in uncertainty (entropy) in Y due to knowledge of X (and vice versa, although that may not be immediately clear).
互信息量化了已知 X 的 Y 的不确定性(熵)的减少,并且以比特来测量。事实证明,这种关系是对称的,因此I(X;Y)= I(Y;x)。
在我们的例子中,感兴趣的通道是传感器-执行器通道。让我们称 A 为致动器变量(描述动作),称 S 为定义下一时间步传感器读数的变量。给定一个主体/环境系统的状态,行动通过概率规则 p(s|a) 或渠道 A→S 导致未来的感觉,这是由世界上这个特定点的环境动态决定的。动作 p(a) 上的某个分布现在足以确定互信息I(A;S)* (与上面的 X 和 Y 完全相同)。信道容量,这里是授权,仅仅是动作分布上最大可能的互信息 p(a)。*

For a fixed channel p(s|a) empowerment is the maximum mutual information over actions distributions p(a).
类似地,我们可以将随机变量 A 视为描述 n 步动作,然后 S 在 n 个时间步之后读取传感器数据,因此定义了所谓的 n 步授权。
为了帮助思考这意味着什么,考虑一下这个。当我行动时,我改变了我的环境,并因此影响了我在下一个时间点的感知。当我所有可能的行动在下一个时间步骤导致完全相同的感官读数时,我完全没有控制,也就是说我没有权力,这反映在零的相互信息中(结果的不确定性没有减少)。当我的每一个动作都导致下一个时间步的一个明显的感官读数时,我就有了很大的控制力,所以我很有权力(体现在一个很高的互信息上)。
克柳宾的迷宫世界
如果你的眼睛刚刚变得呆滞,是时候醒来看一个启示性的例子了。如果你和我一样对这些信息论的形式主义感到兴奋,那就值得看一看 Cover & Thomas 的书[6],其中详细讨论了熵、互信息和信道容量等主题。
在 Klyubin 的论文“在其他条件相同的情况下被赋予权力”中,一个简单的迷宫世界的例子被用来说明这个概念。假设一个智能体存在于 2D 网格世界中,它可以做出向北、向南、向东、向西或停留的动作。然而,这个世界有墙,使它成为一种迷宫。命令代理进入墙壁的动作没有效果,并且世界的边缘被墙壁包围(即没有循环)。
假设代理的传感器只是报告代理在世界上的绝对位置。下图显示了世界上每个网格单元的赋权值,计算为将可能的 5 步操作与 5 步序列后的传感器读数相关联的通道的通道容量。

5-step empowerment value at each point in Klyubin’s deterministic maze world. Highly empowered positions are so because more future states are reachable from those states.
我们看到,在世界上代理更“卡住”的部分,授权更低(通道容量约为 3.5 位)。“停滞”意味着即使是最有希望的行为分布也只能导致有限数量的未来状态。高度授权的州(像地图中间附近)对应于代理人拥有许多可能性的州。
假设“一块食物”将在时间 t,出现在网格中的某个位置,但是在此之前,不知道关于该未来位置的信息。在此期间,一个人应该如何行动?嗯,移动到网格中心附近的位置[5,5]可能是您的最佳选择,因为从该位置可以获得更多的未来状态。
为人工智能赋能
大多数有趣的人类行为都不是基于奖励的学习的结果(尤其是不像标准的机器学习模型那样使用成千上万的例子)。心理学文献谈到“内在动机”,基本上是指为了自己内在的愉悦而做任务。这种行为是有用的,因为这些“天生令人愉快”的活动往往会教给我们有价值的、抽象的、可重复使用的概念,这些概念可以应用于大量潜在的未来任务(想象一个孩子在玩耍)。
对于任何旨在成为通用、通用或自主的人工智能来说,学习一般概念是必须的——这意味着信息具有内在价值。对于一个处于环境中的具体化代理人来说,了解环境中内在结构的唯一方式是通过与它互动— 因此授权位置,在那里行动的结果更加多样化,本质上是世界上更有趣/有趣的部分。随着我们从特定任务智能转向通用智能,授权和其他信息驱动的概念(查看预测信息和相关想法的顺势疗法)将是重要的工具。
感谢您阅读我关于授权的文章。查看 我的 GitHub 库 ,其中有实现任意离散环境授权的代码。
参考
[1] Klyubin,A.S .,Polani,d .和 Nehaniv,C.L .,2005 年 9 月。在其他条件相同的情况下,被赋予权力。在欧洲人工生命会议(第 744-753 页)。斯普林格,柏林,海德堡。
[2] Mnih,v .,Kavukcuoglu,k .,Silver,d .,鲁苏,a .,Veness,j .,Bellemare,M.G .,Graves,a .,Riedmiller,m .,Fidjeland,A.K .,Ostrovski,g .和 Petersen,s .,2015。通过深度强化学习实现人类水平的控制。性质, 518 (7540),第 529 页。
[3] Klyubin,A.S .,Polani,d .和 Nehaniv,C.L .,2008 年。保持选择的开放性:感觉运动系统的基于信息的驾驶原则。 PloS one , 3 (12),p.e4018
[4]t .荣格、d .波拉尼和斯通出版社,2011 年。连续智能体-环境系统的授权。适应行为, 19 (1),第 16–39 页。
[5]香农出版社,2001 年。交流的数学理论。 ACM SIGMOBILE 移动计算与通信评论, 5 (1),第 3–55 页。
[6]盖,T.M .和托马斯,J.A .,2012 年。信息论的要素。约翰·威利的儿子们。
[7]k .弗里斯顿,2010 年。自由能原理:统一的大脑理论?。《自然评论神经科学, 11 (2),第 127 页。
[8]穆罕默德和雷森德,司法部,2015 年。内在激励强化学习的变分信息最大化。在神经信息处理系统的进展(第 2125–2133 页)。
[9]g .蒙图法尔、k .加齐-扎赫迪和 n .艾,2016 年。信息理论辅助的具身智能体强化学习。 arXiv 预印本 arXiv:1605.09735 。
模仿世界如何创造…创造与世界的最佳互动。
如果与世界互动的最佳方式是用世界创造计算结构的方式来创造计算结构,那会怎样?
典型的人工智能和机器学习专注于有效地搜索最具预测性的“计算结构”。但是在现实世界中,我们又有多少次想要重新发明轮子呢?我们希望多长时间重复一次寻找解决方案的过程?不经常。也许包括标准化和重用的机制比快速创建预测结构更重要?
在现实世界中,创建一次并积极复制比一次又一次地创建要高效得多。然而,人工智能的叙事侧重于搜索最佳解决方案,有效地创建新的分层计算结构,而没有说太多关于标准化或重用已创建的计算结构。

Natural Creates” Structure” Efficiently Via Reuse and Reproduction
当我们积极地标准化和复制我们发现的东西时,我们与世界的互动会更有效率。同样的机制对于任何想要与世界有效互动的事物来说不也是至关重要的吗?当涉及到在现实世界中创作和与现实世界互动时,标准化、复制和重用等概念是否比最初的搜索和发现更重要?如果是这样的话,人工智能的叙述就缺少了一些重要的章节。模块化、标准化和重用难道不应该是人工智能解决方案领域的关键部分吗?
现实世界能否填补 Pedro Domingos 描述的主算法中缺失的部分?也许吧。
“计算结构”是什么意思?
“计算结构”是一个结构化的实体,可以改变它所在的世界或环境。换句话说,这是一个与世界的某个部分进行交互、观察和修改的构件。
计算结构可以连接、分层和聚合,以创建能够以不同方式改变世界的更大的计算结构。



世界如何创造计算结构,然后作用于世界?
让我们来看一些不同规模层次的世界计算或转换结构创造的例子。下面我举几个例子。
举例领域:社交→生物→化学→物理
社会的
制造业
让我们以汽车、螺母和螺栓为例。
汽车是人类用来作用于世界的工具。汽车本身作用于世界,改变你的位置。工厂根据原料生产汽车。等等。换句话说,汽车只是计算结构链或层次结构中一个计算结构的例子…这些结构有助于改变世界。
汽车是如何创造出来的?汽车是由发动机、车轮、螺母和螺栓等零件组装而成的。工厂本身是一个计算或转换结构,通过聚集零件(也称为子结构)来制造汽车。像螺母和螺栓这样的材料随着能量和时间进来,汽车出来了。
螺母和螺栓是怎么来的?早在汽车发明之前,螺母和螺栓就被发明了。早期,在汽车被标准化和大规模生产之前,螺母和螺栓仅仅是因为它们在如此多不同的机器上运行良好。在制造第一辆汽车时,不需要制造螺母和螺栓。螺母和螺栓已经存在,是制造第一辆汽车时使用的逻辑和事实上的子结构。
那么有哪些可能适用于人工智能的重要概念呢?
- 机器(像汽车、螺母和螺栓)是计算结构的形式,以有用的方式改变世界的一部分。
- 机器(和计算结构)是由子结构(例如。汽车使用螺母和螺栓。)
- 标准化和大规模生产都使得子结构对于快速创建和大规模生产新结构很有价值。
生物的
人类、其他动物、植物甚至细菌都是不断改造世界的结构。
如果没有一个元结构积极地管理和产生它们的存在,这些生物行为者是如何在世界上出现和繁殖的?
双重协同机制(双重计算结构)
每一个行动者,换句话说,每一个人、植物、动物或其他生命形式,都在进化,以实现两个主要目标的方式改造世界。
- 演员成功:让演员活着,在世界上茁壮成长。
- 物种成功:通过繁殖和优化未来的行动者,在世界上所有可能的地方茁壮成长,从而发展和维持物种。
本质上,有两种相互作用的机制(或计算结构)同时共存。这就是“演员成功”和“物种成功”机制。
此外,“物种成功”机制是超结构,而个体行动者是在时间和空间上实现“物种成功”目标的亚结构。人、植物等。作为个体行动者对“物种成功”做出贡献,但只是随着时间的推移对许多个体行动者起作用的更大机制的一个子部分。
“行动者成功”机制在行动者内部运作,以维持其存在。人类做出选择并采取行动来维持和改善自身的生存并帮助他人。“演员成功”机制通过“物种成功”机制(繁殖、遗传、自然选择等)随着时间的推移得以维持和改进。
重要的是演员(例如人、花、草叶)在他们的一生中负责维护他们自己,他们的实例。演员之间可以有一些合作(抚养孩子等。)但个人主要负责以保持世界活力的方式改造世界。
要点:您可以为一个参与者分配多个共生目标,这些目标在同一个参与者中同时执行。例如个人和物种的成功。我们能否将多个共生目标分配给一个代表计算结构的人工角色,以控制计算结构的增殖和适应?
世界的增长和效率
是什么限制了一个物种的生长?世界上个体演员的成功。以富有成效的方式改造他们所在区域的行动者(人、植物等)茁壮成长,并产生占据世界新区域的新行动者。物种呈指数增长,直到达到极限,世界上不再有更多的参与者。
以一种草为例。这种草在土壤、光照、温度和湿度好的地方生长茂盛。种子产生并被风传播到新的地区。在新草成功的地方,草的数量将继续增长和扩大。在有阴影、土壤不好或草的密度太高的地方,新草不会成功。
那么有哪些可能适用于人工智能的重要概念呢?
- 生物学展示了一种健壮的机制,用于建立和维护一组成功地改变世界局部的行动者(计算结构)。潜在地,个人的人工计算结构可以通过类似的机制来建立和维护。
- 生物机制使演员的影响最大化,但不需要中央控制机制来编排和驱动演员的产生或优化。在大型复杂的人工计算结构中,从中央控制机制解耦通常可能是关键的。
- 生物机制将世界视为一个搜索空间,并且搜索新的领域,在该领域中,行动者可以有效地改变世界。潜在的相同机制可以推动对人工计算结构有用的新领域的研究。
- 生物机制使用遗传学、自然选择等,随着时间的推移,优化演员以最佳匹配世界。类似的需求存在于不断改进和匹配人工计算结构,以适应世界的部分或它们在其中起作用的更大的计算结构。
- 生物行动者需要以富有成效的方式改造世界,以获得生存和繁荣所需的资源。我们可以定义一个人工计算参与者必须做什么才能获得生存的资源。
化学的
- 基于兴趣去做。
身体的
- 基于兴趣去做。
我们如何实现和测试它呢?
- 基于兴趣去做。
笔记
关于标准化对提高一群演员的表演和效用的重要性的想法,直接来自于詹姆斯·贝森(James Bessen)与鲁斯·罗伯茨(Russ Roberts)**和詹姆斯·贝森(James Bessen)的一个经济谈话播客。在文字记录中搜索“标准化”来聚焦相关的讨论。
观察:螺母和螺栓的价值在于它们将结构锁定在一起,在使用时基本上防止了某些变形。锁定它的自我似乎是一个基本概念。在以后的文章中会有更多的介绍。
用神经网络模拟逻辑门
在本教程中,我想告诉你如何训练一个神经网络来执行逻辑门网络的功能。我将深入研究网络中每个神经元的用途,并展示没有一个是被浪费的。我们将通过使用 Tensorflow Playground 中的一个问题示例来解决这个问题,这样您就可以自己实现和试验这个想法。
逻辑门是任何现代计算机的基础。你用来阅读这篇文章的设备肯定在使用它们。关于这些门的一个伟大的事情是它们容易解释。许多这样的门是用简单的英语命名的,比如 AND,NOT and OR 门。其他人写得不太熟悉,但仍然很简单。下表总结了这些逻辑门,以便我们以后可以参考它们。

Image borrowed from https://medium.com/autonomous-agents/how-to-teach-logic-to-your-neuralnetworks-116215c71a49
另一方面,神经网络被认为是任何现代(或其他)大脑的基础,并经常被认为是无法穿透的黑匣子。通常不清楚单个神经元在做什么,然而单个逻辑门在做什么却是显而易见的。然而,神经网络的内部工作不必如此神秘,在某些情况下,神经网络结构可以简单到足以完全掌握和设计。
在本教程中,我将使用一个神经网络来模拟逻辑门网络的行为。我们将确切地观察网络中每个神经元在做什么,以及它们如何融入整体。通过这个例子,我希望你能更好地了解神经网络内部的情况。
NB。如果你想直接进入 Tensorflow 游乐场实验,那么向下滚动到本文的“轮到你了”部分。
动机——一个经过训练的神经网络什么时候可以像一个逻辑门系统一样工作?
假设你有一个只有分类变量的数据集。可能是医疗记录,其中每个患者都有一个性别类别(男性、女性)、年龄段(0–5、5–10、10–15…45–50…)、白细胞计数(高、中、低)等。你的任务可能是利用这些信息来预测今年哪些病人有感染流感的危险,因此应该注射流感疫苗。像往常一样,对于分类变量,我们将使用 one-hot-encoding ,因此每个患者的记录是一个由 1 和 0 组成的向量。
现在我们可以想象为这些数据手工编码一个逻辑网络。我们会用我们的商业规则来定义我们认为谁有流感风险,谁没有。我们可能会得出如下结论,预测值为 1 表示患者有风险,预测值为 0 表示他们没有风险。
- 如果年龄为 25–30和 白细胞计数低 那么预测 1
- 如果年龄为 0–5那么 预测 1
- 如果年龄为 65–70且 性别为男性 则预测 1
- …
- 否则预测 0
在 Python 中,我们的逻辑网络可能看起来像这样,编码了所有可能使你面临流感风险的情况
at_risk = ( age_is_25_30 & white_blood_cell_is_low ) or ( age_is_0_5 ) or ( age_is_65_70 & sex_is_male ) or ...
如果我们有大量的领域专业知识,或者如果我们对医疗记录进行了大量的描述性分析,我们可以对这个逻辑网络进行编程。然而,试图避免对这个网络进行硬编码,这将使用大量的专家领域知识资源、开发人员时间,并且可能引入许多偏见,这就是我们作为建模人员首先构建模型的原因。
我们不想对这个逻辑网络进行硬编码,但是如果有人或其他人能够以系统的方式为我们做这件事,那就太好了。
(进入神经网络,舞台右侧)
那么神经网络是如何变成逻辑网络的呢?
在这一节中,我将假设你至少对神经网络的概念有些熟悉。我将抛出词语偏差、重量和激活功能,我不会花时间解释我在这个简单图表之外的意思。

为了使神经网络成为逻辑网络,我们需要证明单个神经元可以充当单个逻辑门。为了表明神经网络可以执行任何逻辑运算,只要表明神经元可以充当与非门(它确实可以)就足够了。然而,为了让事情变得更美好和更容易理解,让我们深入研究并展示神经元如何充当我们将需要的一组门中的任何一个——即 and 和 OR 门以及 x > 0 的比较门。
让我们用一个简单的具体例子来说明这一点。为了做到这一点,我想把你链接到 Tensorflow Playground 上的一个特定数据集。下面是从该分布中生成的一组数据的图像。橙色数据点的值为-1,蓝色数据点的值为+1。我将 x 轴坐标称为变量 x1,y 轴坐标称为变量 x2。

Example from Tensorflow playground
在上图中,您可以看到,当 x1 和 x2 都为正时,或者当 x2 和 x1 都为负时,目标变量为正。如果我们用一个逻辑网络来编码,我们可能会选择逻辑
- 如果(x1>0) 和 (x2 > 0) 那么预测+1
- 如果(x1 <0) 和 (x2 < 0) 那么预测+1
- 否则预测-1
在 Python 中,我们可以把这个逻辑写成
expression = lambda x1,x2 : \\
(( (x1>0) & (x2>0) ) or ( !(x1>0) & !(x2>0) ))*2 -1
如果你熟悉逻辑门,你可能会注意到,这个表达式的内部是一个 XNOR 门。
XNOR = lambda A,B : ( A & B) or ( !A & !B )
我想给大家展示的是,我们可以为这个逻辑表达式建立一个高效的神经网络。
当然,在这个例子中,最明显的是使用交叉特征 x1x2,并使用它进行预测。然而,我想展示的是,一个好的解决方案在不使用 x1x2 的情况下也是可能的,并深入研究当这一特征没有被创建时出现的网络的结构和解释。还要注意,我们要创建的逻辑神经网络可以扩展到使用 3 个或更多变量。你可以想象需要一个 3 输入 XNOR 门的变量,我们不能通过两个变量对之间的特征交叉来创建它。我们也不想做 3 个变量的所有交叉,即 x1x2x3,因为这可能会使我们的功能数量激增。
因此,让我们一项一项地通过逻辑表达式,这将为这个样本数据集做出正确的预测,并计算出我们的神经元将需要什么样的权重。记住我们想要用神经网络模拟的表达式是
(( (x1>0) & (x2>0) ) or ( !(x1>0) & !(x2>0) ))*2 -1
激活功能
我想快速说明我们将用于神经元的激活函数,Sigmoid 函数。我们这样选择的原因是因为 Sigmoid 函数的输出接近逻辑门的输出。对于 z 的所有值,逻辑门输出 1 或 0,Sigmoid 函数输出~1 或~0,其中 z 不接近 0。即。|z| >>0。这意味着 Sigmoid 函数将是一个很好的选择,可以帮助我们的神经元模拟我们需要的 AND 和 OR 门。

比较 x1 > 0
这是我们函数最里面的部分。我们可以使用单个神经元和 Sigmoid 激活函数很容易地计算这个表达式。在这种情况下,只有一个变量输入到神经元,x1,如果 x1 为正,我们希望神经元输出接近 1 的值,如果 x1 为负,则输出接近 0 的值。尽管这对于这个问题并不重要,但我们假设如果 x1 正好为零,那么我们希望输出为 0.5。
我们有 z = w1*x1 + b1 的激活函数的输入。查看上面的 Sigmoid 函数的图形,并考虑上面的标准,我们可以推断出我们想要 b=0,w1 应该是一个大的正数。事实上,随着 w1 趋向无穷大,该神经元的输出越来越接近逻辑比较 x1>0 的输出。然而,让我们取一个更适中的值,比如 w1=10。
在下表中,我们示出了不同 x1 值和 w1=10 时该比较神经元的输出(右手列)。您可以看到它的行为非常类似于 x1>0。

Neural comparison truth table
注意,可以应用相同的逻辑来计算比较 x2>0,并设置 w2=10 和 b2=0。
与门
现在,我们可以做更多的比较,目标逻辑表达式的下一个最内部的函数是 AND 运算符。在这种情况下,sigmoid 函数的输入将为 z=w3a1 + w4a2 + b3。这里 w3 和 w4 是权重,a1 和 a2 是第一层神经元的激活。如果 x1>0,变量 a1 非常接近 1,如果 x1 <0; the value of a2 is similar.
To emulate the AND operator we would like to set the weights and bias such that the output of the Sigmoid is very close to one if a1 and a2 are ~1 and zero otherwise. A good solution is to set b3=-3/2 * w3 and w4=w3. You can do some calculations yourself, and see how this choice in weights will fulfill our criteria (there are also some examples below). As w3 goes to infinity and w4 and b3 go to their corresponding limits, this neuron becomes more and more like a perfect AND gate. However we will choose a more moderate value of w3 = 10 and let b3 and w4 follow.
In the table below we show the output of this AND neuron (right hand column) for different values of a1 and a2 and for w1=10. You can see that it behaves very similar to an AND gate.

Neural AND gate truth table
或门,变量 a1 非常接近 0
我们逻辑表达式的下一个最内部部分是“或”门。对于或门,当一个或多个输入为~1 时,我们希望输出接近 1,否则输出为零。Sigmoid 函数的输入为 z=w7a3 + w8a4 + b5。这里 a3 表示 x1 和 x2 是否都是阳性,a4 表示 x1 和 x2 是否都是阴性。
通过与 Sigmoid 函数进行比较,并考虑上述标准,我们推断我们可以通过设置 b5=-1/2 * w7 和 w8=w7 来解决这个问题。当 w1 趋向于无穷大,b5 和 w8 趋向于它们相应的极限时,这再次接近完美的 OR 门。然而。让我们选择一个适中的值 w7=10,让 b5 和 w8 跟随。

Neural OR gate truth table
最终件-乘加
对于我们表达式的最外层部分,要么需要将神经网络的输出乘以 2,然后减去 1,要么需要一个具有线性激活函数、权重 w=2 和偏差 b=-1 的最终神经元。
把所有的放在一起
我们现在已经拥有了创建上述逻辑表达式的神经网络仿真器所需的所有部分。因此,将所有内容放在一起,网络的完整架构如下所示

Neural architecture for expression
其中权重和偏差的值是这样的

你可能会注意到非 a1 和非 a2 神经元的权重与 a1 和 a2 神经元的权重不同。这是由于“非”门,我不想陷入其中,因为再看到这个门就没意思了。然而,尝试自己解决这个问题可能会很有趣。
使用这个完整的网络,我们可以测试输入值来预测输出值。

看起来不错!它有我们想要的逻辑表达式的输出,或者至少非常接近。
培训和学习
现在我们已经证明这种神经网络是可能的,现在剩下的问题是,训练是可能的。如果我们在正确定义了层、神经元数量和激活函数之后,简单地输入从上图中提取的数据,我们能指望网络会以这种方式进行训练吗?
不,不总是,甚至不经常。像许多神经网络一样,这个问题是一个优化问题。在训练这个网络时,即使有一个近乎完美的解决方案,它也常常会陷入局部最小值。这就是你的优化算法可以发挥很大作用的地方,这是 Tensorflow Playground 不允许你改变的,可能是未来帖子的主题。
轮到你了
现在我建议你去 Tensorflow Playground 尝试自己构建这个网络,使用架构(如上图和下图所示)和上表中的权重。挑战在于仅使用 x1 和 x2 作为特征来实现,并且手动建立神经网络。请注意,由于 Tensorflow 游乐场的特性,您应该只添加前三层。发生缩放的输出层是模糊的,但是如果您构建前三层,然后在很短的时间内训练网络,您应该会得到如下结果。
在操场上,你可以通过点击连接神经元的线来编辑权重。你可以通过点击每个神经元左下角的小方块来编辑偏差值。你应该能做到亏损 0.000。记得将激活功能设置为 Sigmoid。

想法:
- 在你通过手动输入权重建立了这个网络之后,为什么不试着从头开始训练这个网络的权重,而不是手动构建它。经过多次尝试后,我成功地做到了这一点,但我相信它对播种非常敏感,经常会陷入局部最小值。如果你找到了一个可靠的方法来训练这个网络使用这些功能和这个网络结构,请在评论中联系我们。
- 试着用这个数量的神经元和层数来构建这个网络。在这篇文章中,我已经展示了只用这么多的神经元来做这件事是可能的。如果你引入更多的节点,那么你肯定会有一些冗余的神经元。虽然,有了更多的神经元/层,我在更持续地训练一个好模型方面有了更好的运气。
- 我已经向您展示了两个逻辑门所需的权重和偏差以及比较,您能找到表中其他逻辑门的权重和偏差吗?特别是与非门(非与),这是一个通用门,即。如果一个神经元可以实现这个门(或一个近似值),那么这就证明了神经网络能够完成任何计算任务。
下次
我希望你喜欢阅读这篇文章,就像我喜欢发现它一样。
我想通过制作一个 Jupyter 笔记本来进一步扩展这个演示,从而在 Keras 中实现一些类似的东西。然后你可以自己玩训练神经网络逻辑门仿真器。
参考文献
如果我不提及这些以前已经触及神经网络和逻辑门主题的文章,那将是不恰当的。
逻辑门即“与”、“或”、“非”是过去十年中每一项技术突破的组成部分…
towardsdatascience.com](/neural-representation-of-logic-gates-df044ec922bc) [## 如何向你的#NeuralNetworks 教授逻辑?
逻辑门是电子学的基本构件。它们几乎构成了复杂的架构…
medium.com](https://medium.com/autonomous-agents/how-to-teach-logic-to-your-neuralnetworks-116215c71a49)
编码分类特征

介绍
在机器学习项目中,一个重要的部分是特征工程。在数据集中看到分类特征是非常常见的。然而,我们的机器学习算法只能读取数值。将分类特征编码成数值是非常重要的。
在这里,我们将介绍分类特征的三种不同编码方式:
1.标签编码器和 OneHotEncoder
2.字典矢量器
3.熊猫有假人
为了您的方便,完整的代码可以在我的 github 中找到。
数据集
我们在这里使用的数据集来自 UCI 机器学习资源库。它用于以各种血液指标为特征,预测患者是否有肾脏疾病。我们用熊猫来读取数据。
# load data
df = pd.read_csv(‘datasets/chronic_kidney_disease.csv’, header=None,
names=[‘age’, ‘bp’, ‘sg’, ‘al’, ‘su’, ‘rbc’, ‘pc’, ‘pcc’, ‘ba’, ‘bgr’, ‘bu’, ‘sc’, ‘sod’, ‘pot’,
‘hemo’, ‘pcv’, ‘wc’, ‘rc’, ‘htn’, ‘dm’, ‘cad’, ‘appet’, ‘pe’, ‘ane’, ‘class’])# head of df
df.head(10)

从表中可以看出,我们有几个分类特征,如“rbc”(红细胞)、“pc”(脓细胞)、“pcc”(脓细胞团块)等。很明显,数据集包含缺失的值,但是因为这超出了本博客的主题范围,所以我们在这里不讨论如何进行。但是填充缺失的值是必要的,并且应该在编码分类特征之前完成。您可以参考我的 github 了解如何填写缺失值。准备好分类编码的完整数据集如下所示。

标签编码器& OneHotEncoder
labelEncoder 和 OneHotEncoder 只对分类特征有效。我们首先需要使用布尔掩码提取类别特征。
# Categorical boolean mask
categorical_feature_mask = X.dtypes==object# filter categorical columns using mask and turn it into a list
categorical_cols = X.columns[categorical_feature_mask].tolist()
LabelEncoder 将指定特征下的每个类转换成一个数值。让我们一步一步来看看怎么做。
实例化标签编码器对象:
# import labelencoder
from sklearn.preprocessing import LabelEncoder# instantiate labelencoder object
le = LabelEncoder()
对每个分类列应用标签编码器:
# apply le on categorical feature columns
X[categorical_cols] = X[categorical_cols].apply(lambda col: le.fit_transform(col))X[categorical_cols].head(10)
请注意,标签编码器的输出仍然是一个数据帧。结果如下所示:

正如我们所看到的,所有的分类特征列都是二进制类。但是如果分类特征是多类的,标签编码器将为不同的类返回不同的值。参见下面的示例,“邻域”功能有多达 24 个类。

在这种情况下,只使用标签编码器不是一个好的选择,因为它为不同的类带来了自然的顺序。例如,在“邻域”功能下,a 类的值为 5,而 b 类的值为 24,那么 b 类的值是否比 a 类大?答案显然是否定的。因此,允许模型学习,这种结果将导致较差的性能。因此,对于包含多类特征的数据帧,需要 OneHotEncoder 的进一步处理。让我们看看做这件事的步骤。
实例化 OneHotEncoder 对象:
# import OneHotEncoder
from sklearn.preprocessing import OneHotEncoder# instantiate OneHotEncoder
ohe = OneHotEncoder(categorical_features = categorical_feature_mask, sparse=False )
# categorical_features = boolean mask for categorical columns
# sparse = False output an array not sparse matrix
我们需要使用 OneHotEncoder 中的掩码来指定分类特征。sparse=False参数输出一个非稀疏矩阵。
对数据帧应用 OneHotEncoder:
# apply OneHotEncoder on categorical feature columns
X_ohe = ohe.fit_transform(X) # It returns an numpy array
请注意,输出是 numpy 数组,而不是 dataframe。对于分类特征下的每个类,都会为其创建一个新列。例如,为十个二元类分类特征创建了 20 列。

字典矢量器
正如我们所见,LabelEncoder 和 OneHotEncoder 通常需要作为两步程序一起使用。更方便的方法是使用字典矢量器,它可以同时完成这两个步骤。
首先,我们需要将数据帧转换成字典。这可以通过熊猫[to_dict](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_dict.html)的方法来实现。
# turn X into dict
X_dict = X.to_dict(orient='records') # turn each row as key-value pairs# show X_dict
X_dict
需要orient='records'将数据帧转换成{column:value}格式。结果是一个字典列表,其中每个字典代表一个样本。注意,在这种情况下,我们不需要提取分类特征,我们可以将整个数据帧转换成字典。这是与 LabelEncoder 和 OneHotEncoder 相比的一个优势。

现在我们实例化一个字典矢量器:
# DictVectorizer
from sklearn.feature_extraction import DictVectorizer# instantiate a Dictvectorizer object for X
dv_X = DictVectorizer(sparse=False)
# sparse = False makes the output is not a sparse matrix
sparse=False使输出成为非稀疏矩阵。
字典矢量器对转换后的字典进行拟合和转换:
# apply dv_X on X_dict
X_encoded = dv_X.fit_transform(X_dict)# show X_encoded
X_encoded
结果是一个 numpy 数组:

每行代表一个样本,每列代表一个特征。如果我们想知道每一列的特性,我们可以检查这个字典矢量器的词汇表:
# vocabulary
vocab = dv_X.vocabulary_# show vocab
vocab

拿假人
Pandas get_dummies 方法是一个非常直接的一步程序,用于获取分类特征的虚拟变量。其优势在于,您可以直接将其应用于数据帧,其中的算法将识别分类特征并对其执行获取虚拟对象操作。下面是如何做到这一点:
# Get dummies
X = pd.get_dummies(X, prefix_sep='_', drop_first=True)# X head
X.head()
prefix_sep='_'使得每个类都有一个唯一的名字,用分隔符隔开。drop_first=True从生成的虚拟特征中删除一列。目的是避免多重共线性。结果如下:

结论
LabelEncoder 和 OneHotEncoder 通常需要作为两步方法一起使用来对分类特征进行编码。LabelEncoder 输出 dataframe 类型,而 OneHotEncoder 输出 numpy 数组。OneHotEncoder 可以选择输出稀疏矩阵。DictVectorizer 是一种编码和支持稀疏矩阵输出的一步方法。熊猫得到假人的方法是迄今为止编码分类特征最直接和最简单的方法。输出将保持数据帧类型。
在我看来,第一选择是熊猫拿假人。但是如果分类特征的数量很大,DictVectorizer 将是一个很好的选择,因为它支持稀疏矩阵输出。
神经网络的编码概念、类别和分类

在之前的一篇文章中,我们解释了神经网络如何从几个特征中预测一个连续值(比如房价)。我们得到的一个问题是神经网络如何对概念、类别或类进行编码。例如,无论下面的图片是否包含一只猫,神经网络如何将大量像素转换为真/假答案?
首先,这里有一些观察结果:
- 二元分类问题是一个有“是/否”答案的问题。一些例子包括:这张图片包含一只猫吗?这是垃圾邮件吗?这个应用程序是病毒吗?这是个问题吗?
- 多分类问题是有几个类别作为答案的问题,比如:这是什么类型的车辆(轿车/公共汽车/卡车/摩托车)?
- 任何多分类问题都可以转化为一系列二元分类问题。(比如:这是车吗,是还是不是?这是一辆公共汽车,是还是不是?等等)
神经网络中分类的核心思想是将概念、类别和类转换成属于这些概念、类别或类的概率。
这意味着猫是 100%的猫。一只狗是 100%的狗。一辆车是 100%的车,等等。每个独立的概念本身就是概念空间中的一个维度。例如,我们可以说:
- 一只猫是:100%的“猫”,0%的“狗”,0%的“公交车”,0%的“汽车”。[1;0;0;0]
- 一辆车是:0%“猫”,0%“狗”,0%“公交车”,100%“车”。[0;0;0;1 ]
- 一个是就是 100%的“是”,0%的“否”->【1;0]
类别的矢量化表示在表示该类别的维度中为 1,在其余维度中为 0。这种模式被称为 1-hot 编码。
在 mid 中有了这个想法,我们现在有了一种新的方法来将类别编码成经典的多维向量。然而,这些向量具有一些特殊性质,因为它们需要表示属于这些类别的概率或置信水平:
- 向量长度定义了神经网络可以支持的类别数。
- 每个维度应该限制在 0 和 1 之间。
- 向量的和应该总是 1。
- 所选类别是具有最高值/置信度(arg max)的类别。
因此,例如,如果我们得到[猫,狗,公共汽车,汽车]的输出[0.6,0.1,0.2,0.1],我们可以说神经网络以 60%的置信度将这张图像分类为猫。
Softmax 图层
在为分类问题设计神经网络时,为了保持最后一层概率向量的性质,有一个特殊的激活叫做“softmax”。

Softmax converts any vector into probabilities vector (that sums to 1).
softmax 所做的是,它取任意一个数字向量,对所有内容进行指数运算,然后将每个元素除以指数的和。
[2 ;1;0.1] ->指数[7.3;2.7;1.1] ->和为 11.1 ->最终向量为0.66;0.24;0.1。
我们可以很容易地验证以下属性:
- 每个分量都在 0 和 1 之间,因为指数不能为负,除以和不能超过 1。
- 输出的总和总是等于 1。
- 顺序维持:初始分数越高,概率越大。
- 重要的是彼此的相对分数。例如,如果我们有这两个向量:[10;10;10]或[200;200;200],它们都将转换为相同的[1/3;1/3;1/3]概率。
最后一步是提供触发学习反向传播的损失函数。由于输出是 1-hot 编码矢量,如前所述,最合适的损失函数是对数损失函数:

The log-loss function definition
它来源于信息论和香农熵。由于实际输出 y 不是 0 就是 1,这种损失正在累积 NN 对已知类别的信心不足。
- 如果 NN 非常有信心->正确类的概率会接近 1-> log 会接近 0 ->无损失->无反向传播->无学习!
- 如果 NN 不是很有信心->类的概率将接近 0.5(完全犹豫)->对数损失将在其最大值->大损失->使用反向传播学习的大机会。
计算指数和对数的计算开销很大。正如我们在前两部分中所看到的,softmax 层将 logit 得分提升到指数级,以获得概率向量,然后损失函数对损失进行对数运算,以计算损失的熵。
如果我们将这两个阶段结合在一层中,对数和指数会相互抵消,我们可以用更少的计算资源获得相同的最终结果。这就是为什么在许多神经网络框架和库中有一个“softmax-log-loss”函数,这比将这两个函数分开要好得多。
原载于 2018 年 7 月 30 日medium.com。
使用具有交互代码的深度神经网络加密不同的医学图像

Gif from this website
因此,昨天我讨论了“ ”隐藏图像:深度隐写术 ”现在让我们将这个网络应用到医疗保健设置中。我们将利用这个网络对各种医学图像进行加密。
请注意,我们将只使用公开可用的医学图像,下面是我们将使用的数据集列表。
1。UCSB 生物分割基准数据集 2。驱动:用于血管提取的数字视网膜图像
3。超声波神经分割来自 Kaggle
4。人体模型 FDA 来自癌症影像档案
5。皮肤黑色素瘤(CPTAC-CM) 来自癌症影像档案
此外,所有的封面图像都来自这个数据集“语义图像分割的基准”。
可视化不同类型的医学图像/数据集


左图 →来自 UCSB 生物分割基准数据集
的乳腺癌细胞图像;右图 →来自 UCSB 生物分割基准数据集的 2D 细胞核图像






来自超声神经分割的超声图像



来自仿真模型 FDA 的拟人化胸部仿真模型图像



皮肤黑色素瘤(CPTAC-CM) 的脑部放射影像
网络架构



红框 →准备图像的神经网络(Prep Network)
黄框 →隐藏图像的神经网络(Hiding Network)
绿框 →显示图像的神经网络(Reveal Network)
主要有三个网络,一个是准备图像、隐藏图像和揭示秘密图像。我不会深入解释这个网络,因为我已经在这篇文章 中 介绍过了。
用例:通过万维网发送医学图像


男性图 →希望安全发送医学图像给爱丽丝医生的鲍勃医生
黑色圆圈 →原始医学图像
白色矩形 →准备/ 隐藏网络
红圈 →加密医学图像通过封面图像
云 →环球网敏感数据哪里会发生不好的事情
紫圈 →加密图像通过网络
蓝矩形 →揭露网络
天蓝色圈 →揭露医学图像
女图 →希望安全接收一些医学图像的爱丽丝博士
一个简单的用例可以是类似上面的,两个希望安全地交换医学图像的医学专家(或医生和病人)可能使用这个网络来加密和解密他们的图像。
结果





左上图 →原秘密图
右上图 →原封面图
左下图 →准备图
下中间图 →秘密+封面图
右下图 →揭露图
对于一些封面图像,网络实际上在隐藏秘密图像方面做得相当好。然而,如下图所示,在某些情况下,网络表现不佳。





左上图 →原秘密图
右上图 →原封面图
左下图 →准备图
下中间图 →秘密+封面图
右下图 →已曝光图
如上所述,隐藏秘密图像后,我们可以看到蜥蜴身上的一些文物,这可能会泄露原始图像。


左 GIF →网络如何在它的最后纪元
右 GIF →网络如何过度训练的汇编
以上是网络在最后一个时期以及随着时间的推移如何工作的汇编,随着训练的继续(通过增加时期可以看到),我们可以看到网络在隐藏图像方面做得更好。
不同类型医学图像的个体结果





乳腺癌细胞图像的加密/解密结果





细胞 2D 核图像的加密/解密结果





视网膜图像的加密/解密结果





超声图像的加密/解密结果





细胞拟人胸部模型图像的加密/解密结果





脑部放射图像的加密/解密结果
互动码

对于 Google Colab,你需要一个 Google 帐户来查看代码,而且你不能在 Google Colab 中运行只读脚本,所以在你的操场上复制一份。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!
要访问 Google Colab 上的代码,请点击这里。
注意:我不想托管不属于我的医疗数据,因为我可能会违反他们的数据使用政策。所以这段代码不能直接在线运行。
透明度

为了让这个实验更加透明,我上传了我所有的命令输出到我的 github,如果你想看的话,请点击这里。
最后的话
当然,网络并没有做得足够好以至于不能在现实世界中使用,但是这是一个开始。我很高兴看到人工智能如何影响计算机/网络安全。
如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你希望看到我所有写作的列表,请在这里查看我的网站。
同时,在我的 twitter 上关注我这里,访问我的网站,或者我的 Youtube 频道了解更多内容。如果你感兴趣的话,我还做了解耦神经网络的比较。
参考
- [NIPS 2017/Google] —在众目睽睽之下隐藏图像:使用交互式代码的深度隐写术[……]。(2018).走向数据科学。检索于 2018 年 4 月 5 日,来自https://towards data science . com/nips-2017-Google-hiding-images-in-plain-sight-deep-steganography-with-interactive-code-e 5 efecae 11 ed
- s . balu ja(2017 年)。隐藏图像:深度隐写术。神经信息处理系统进展(第 2066-2076 页)。
- 生物分割|生物图像信息学中心|加州大学圣巴巴拉分校。(2018).Bioimage.ucsb.edu。于 2018 年 4 月 5 日检索,来自https://bioimage.ucsb.edu/research/bio-segmentation
- CP tac-CM——癌症影像存档(TCIA)公共访问——癌症影像存档维基。(2018).Wiki.cancerimagingarchive.net。检索于 2018 年 4 月 5 日,来自https://wiki . cancer imaging archive . net/display/Public/CP tac-CM
- 幻影 FDA 癌症影像存档(TCIA)公共访问-癌症影像存档维基。(2018).Wiki.cancerimagingarchive.net。检索于 2018 年 4 月 5 日,来自https://wiki . cancer imaging archive . net/display/Public/Phantom+FDA
- 驱动:下载。(2018).isi . uu . nl . 2018 年 4 月 5 日检索,来自http://www.isi.uu.nl/Research/Databases/DRIVE/download.php
- “超声波神经分割| Kaggle”。2018.Kaggle.Com。2018 年 4 月 5 日访问。https://www.kaggle.com/c/ultrasound-nerve-segmentation。
- 惠,L. (2018)。语义图像分割的基准。Ntu.edu.sg .检索 2018 年 4 月 5 日,来自http://www . NTU . edu . SG/home/asjfcai/Benchmark _ Website/Benchmark _ index . html
端到端数据科学示例:用逻辑回归预测糖尿病
顾名思义,本教程是使用数据科学解决现实世界问题的端到端示例。我们将使用机器学习来预测一个人是否患有糖尿病,基于患者的信息,如血压、身体质量指数(身体质量指数)、年龄等。本教程介绍了数据科学工作流程的各个阶段。具体来说,本教程包含以下几个部分
- 概观
- 数据描述
- 数据探索
- 数据准备
- 训练和评估机器学习模型
- 解读 ML 模型
- 保存模型
- 用模型做预测
- 后续步骤

概观
数据由“国家糖尿病、消化和肾脏疾病研究所”收集并提供,作为皮马印第安人糖尿病数据库的一部分。从一个较大的数据库中选择这些实例有几个限制。特别是,这里的所有患者都属于皮马印第安人(美洲土著人的一个亚群),并且都是 21 岁以上的女性。
我们将使用 Python 和一些流行的数据科学相关包。首先,我们将导入pandas从一个 CSV 文件中读取我们的数据,并操纵它以供进一步使用。我们还将使用numpy将数据转换成适合我们的分类模型的格式。我们将使用seaborn和matplotlib进行可视化。然后我们将从sklearn引入逻辑回归算法。这个算法将帮助我们建立分类模型。最后,我们将使用sklearn中可用的joblib来保存我们的模型以备将来使用。
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
% matplotlib inlinefrom sklearn.linear_model import LogisticRegression
from sklearn.externals import joblib
数据描述
我们将数据保存在名为diabetes.csv的 CSV 文件中。我们首先将数据集读入名为diabetesDF的 pandas 数据帧,然后使用head()函数显示数据集中的前五条记录。
diabetesDF = pd.read_csv('diabetes.csv')
print(diabetesDF.head())

First 5 records in the Pima Indians Diabetes Database
以下特征有助于我们预测一个人是否患有糖尿病:
- 怀孕次数:怀孕次数
- 葡萄糖:口服葡萄糖耐量试验中超过 2 小时的血浆葡萄糖浓度
- 血压:舒张压(毫米汞柱)
- 皮厚:三头肌皮褶厚度(mm)
- 胰岛素: 2 小时血清胰岛素(μU/ml)
- 身体质量指数:身体质量指数(体重公斤/(身高米)2)
- 糖尿病谱系功能:糖尿病谱系功能(根据家族史对糖尿病可能性评分的功能)
- 年龄:年龄(岁)
- 结果:类别变量(0 表示非糖尿病,1 表示糖尿病)
让我们也确保我们的数据是干净的(没有空值,等等)。
diabetesDF.info() # output shown below<class 'pandas.core.frame.DataFrame'>
RangeIndex: 768 entries, 0 to 767
Data columns (total 9 columns):
Pregnancies 768 non-null int64
Glucose 768 non-null int64
BloodPressure 768 non-null int64
SkinThickness 768 non-null int64
Insulin 768 non-null int64
BMI 768 non-null float64
DiabetesPedigreeFunction 768 non-null float64
Age 768 non-null int64
Outcome 768 non-null int64
dtypes: float64(2), int64(7)
memory usage: 54.1 KB
请注意,在上图的样本中,数据确实有一些缺失值(参见胰岛素= 0)。理想情况下,我们可以将这些 0 值替换为该特性的平均值,但现在我们将跳过这一步。
数据探索
现在让我们研究一下我们的数据集,感受一下它的样子,并获得一些关于它的见解。
让我们从寻找每一对特征(和结果变量)的相关性开始,并使用热图可视化相关性。
corr = diabetesDF.corr()
print(corr)
sns.heatmap(corr,
xticklabels=corr.columns,
yticklabels=corr.columns)

Output of feature (and outcome) correlations

Heatmap of feature (and outcome) correlations
在上面的热图中,颜色越亮表示相关性越强。从表格和热图中我们可以看出,血糖水平、年龄、身体质量指数和怀孕次数都与结果变量有显著相关性。还要注意特征对之间的相关性,比如年龄和怀孕,或者胰岛素和皮肤厚度。
让我们看看数据集中有多少人是糖尿病患者,有多少人不是。下面是相同的柱状图:

Barplot visualization of number of non-diabetic (0) and diabetic (1) people in the dataset
可视化单个变量和结果之间的关系也是有帮助的。下面,我们将看到年龄和结果之间的关系。您可以类似地可视化其他特征。该图是每个输出类的平均年龄图。我们可以看到,糖尿病患者的平均年龄更高。

Average age of non-diabetic and diabetic people in the dataset
顺便提一句,这个教程摘自 Commonlounge 上的数据科学课程。该课程包括许多实践作业和项目。另外,80%的课程内容都是免费的!如果你对学习数据科学感兴趣,绝对推荐去看看。
数据集准备(拆分和归一化)
当使用机器学习算法时,我们应该总是将数据分成训练集和测试集。(如果我们运行的实验数量很大,那么我们应该将数据分成 3 部分,即训练集、开发集和测试集)。在我们的例子中,我们还将分离出一些数据用于人工交叉检查。
数据集包括总共 767 名患者的记录。为了训练我们的模型,我们将使用 650 条记录。我们将使用 100 条记录进行测试,最后 17 条记录用于交叉检查我们的模型。
dfTrain = diabetesDF[:650]
dfTest = diabetesDF[650:750]
dfCheck = diabetesDF[750:]
接下来,我们分离标签和特征(对于训练和测试数据集)。除此之外,我们还会将它们转换为 NumPy 数组,因为我们的机器学习算法处理 NumPy 数组格式的数据。
trainLabel = np.asarray(dfTrain['Outcome'])
trainData = np.asarray(dfTrain.drop('Outcome',1))
testLabel = np.asarray(dfTest['Outcome'])
testData = np.asarray(dfTest.drop('Outcome',1))
作为使用机器学习之前的最后一步,我们将标准化我们的输入。机器学习模型通常从输入标准化中受益匪浅。这也使我们在以后查看模型权重时,更容易理解每个特性的重要性。我们将对数据进行标准化,使每个变量的平均值为 0,标准差为 1。
means = np.mean(trainData, axis=0)
stds = np.std(trainData, axis=0)trainData = (trainData - means)/stds
testData = (testData - means)/stds# np.mean(trainData, axis=0) => check that new means equal 0
# np.std(trainData, axis=0) => check that new stds equal 1
训练和评估机器学习模型
我们现在可以训练我们的分类模型。我们将使用一个叫做逻辑回归的机器简单学习模型。因为模型在 sklearn 中很容易获得,所以训练过程非常容易,我们可以用几行代码就可以完成。首先,我们创建一个名为 diabetesCheck 的实例,然后使用 fit 函数来训练模型。
diabetesCheck = LogisticRegression()
diabetesCheck.fit(trainData, trainLabel)
接下来,我们将使用我们的测试数据来找出模型的准确性。
accuracy = diabetesCheck.score(testData, testLabel)
print("accuracy = ", accuracy * 100, "%")
打印语句将打印accuracy = 78.0 %。
解读 ML 模型
为了更好地理解逻辑回归模型内部的情况,我们可以直观地看到我们的模型如何使用不同的特性,以及哪些特性具有更大的影响。
coeff = list(diabetesCheck.coef_[0])
labels = list(trainData.columns)
features = pd.DataFrame()
features['Features'] = labels
features['importance'] = coeff
features.sort_values(by=['importance'], ascending=True, inplace=True)
features['positive'] = features['importance'] > 0
features.set_index('Features', inplace=True)
features.importance.plot(kind='barh', figsize=(11, 6),color = features.positive.map({True: 'blue', False: 'red'}))
plt.xlabel('Importance')

Visualization of the weights in the Logistic Regression model corresponding to each of the feature variables
从上图,我们可以得出以下结论。
- 血糖水平、身体质量指数、妊娠和糖尿病家系功能对模型有显著影响,尤其是血糖水平和身体质量指数。很高兴看到我们的机器学习模型与我们一生中从医生那里听到的相匹配!
- 血压对预测有负面影响,即较高的血压与没有糖尿病的人相关。(另外,注意血压作为一个特征比年龄更重要,因为血压的值更高)。
- 虽然年龄比身体质量指数与产出变量更相关(正如我们在数据探索中看到的),但该模型更依赖于身体质量指数。发生这种情况有几个原因,包括这样一个事实,即年龄捕捉到的相关性也被一些其他变量捕捉到,而身体质量指数捕捉到的信息没有被其他变量捕捉到。
注意,上面的解释要求我们的输入数据是标准化的。没有这一点,我们就不能说的重要性与的权重成正比。
保存模型
现在,我们将使用joblib保存训练好的模型以备将来使用。
joblib.dump([diabetesCheck, means, stds], 'diabeteseModel.pkl')
为了检查我们是否正确地保存了模型,我们将使用我们的测试数据来检查我们保存的模型的准确性(如果我们正确地保存了它,我们应该观察不到准确性的变化)。
diabetesLoadedModel, means, stds = joblib.load('diabeteseModel.pkl')
accuracyModel = diabetesLoadedModel.score(testData, testLabel)
print("accuracy = ",accuracyModel * 100,"%")
用模型做预测
我们现在将使用未使用的数据来看看如何进行预测。我们在 dfCheck 中有未使用的数据。
print(dfCheck.head())

我们现在将使用第一个记录来进行预测。
sampleData = dfCheck[:1]# prepare sample
sampleDataFeatures = np.asarray(sampleData.drop('Outcome',1))
sampleDataFeatures = (sampleDataFeatures - means)/stds# predict
predictionProbability = diabetesLoadedModel.predict_proba(sampleDataFeatures)
prediction = diabetesLoadedModel.predict(sampleDataFeatures)
print('Probability:', predictionProbability)
print('prediction:', prediction)
从上面的代码我们得到:
Probability: [[ 0.4385153, 0.5614847]]
prediction: [1]
数组的第一个元素预测概率 0.438 是类为 0 的概率,第二个元素 0.561 是类为 1 的概率。概率总和为 1。正如我们可以看到的, 1 是更可能的类别,我们得到【1】作为我们的预测,这意味着模型预测此人患有糖尿病。
后续步骤
有很多方法可以改进上述模型。这里有一些想法。
- 输入特征分块应该有所帮助,即创建特定范围内的血压、特定范围内的葡萄糖水平等的新变量。
- 您还可以通过用平均值替换 0 值来改进数据清理。
- 阅读一些关于医生诊断糖尿病患者最依赖的指标,并相应地创建新的功能。
看看你能否达到 85-90%的准确率。本教程可以用 jupyter 笔记本入门: pima_indians.ipynb 。
由 Keshav Dhandhania 和 Bishal Lakha 合著。
最初作为 的教程发表于 www.commonlounge.com作为 数据科学课程 的一部分。
使用 AWS EMR、Apache Spark (Pyspark)和 MongoDB Tutorial(包含百万首歌曲数据)的端到端分布式 ML

在这篇文章中,我将提到如何使用 Python Spark API pyspark 以分布式方式运行 ML 算法。我们还将了解如何设置 AWS EMR 实例以在云上运行我们的应用程序,如何设置 MongoDB 服务器作为 NoSQL 数据库以存储非结构化数据(如 JSON、XML ),以及如何通过使用 pyspark 功能快速进行数据处理/分析。
要求:
- AWS 帐户(或者您可以在本地运行)
- Python 2.7(用于运行将要提供的脚本)
1。设置 EMR 实例
什么是亚马逊 EMR?(网址:【https://aws.amazon.com/emr/ )
Amazon EMR 提供了一个托管的 Hadoop 框架,可以轻松、快速且经济高效地跨可动态扩展的 Amazon EC2 实例处理大量数据。还可以在亚马逊 EMR 中运行其他流行的分布式框架如 Apache Spark 、 HBase 、 Presto、和 Flink ,与亚马逊 S3、亚马逊 DynamoDB 等其他 AWS 数据仓库中的数据进行交互。
尽管这一步是可选的,以便运行脚本并自上而下地了解正在发生的事情,但我们可能需要分布式计算的主要原因通常是我们的本地机器规格无法进行我们想要的处理、分析或建模。
我们还可以启动多个 EC2 实例并配置主节点和工作节点,但所有这些步骤实际上都由 EMR 负责。简而言之,EMR 将允许我们在主实例上运行我们想要运行的作业后,自动分发这些作业。否则,我们应该在所有节点上配置和安装 Spark。
下面你可以看到 Spark 框架是如何分配工作的。驱动程序运行主进程,将其转换为任务,并为执行者安排任务。然后工人(执行者)运行这些任务。

Driver and Executor Architecture in Spark
为了启动我们的第一个电子病历实例,我们需要登录到 aws.amazon.com,然后控制台会出现。

select “EMR” here

click “Create Cluster”

Here we should select “Spark” under Applications and define how many instances we want for our application. For example 1 for master and 2 for core nodes (executors which will run tasks). So here we will be distributing the job into 2 worker nodes.
您还应该给出一个密钥对,以便以后 ssh 进入节点并运行您的应用程序。一旦你点击创建你的集群,它将开始引导,一旦一切准备就绪,主和核心将等待。关于电子病历的一个关键点是,一旦开始就无法停止。这意味着您不能像常规 EC2 实例一样停止和启动 EMR 实例。因此,运行所有应用程序,然后终止 EMR 是一个好的做法。如果你试图在工作没有完成的情况下停止,你将需要重新开始。数据处理或分析工作的另一个常见做法是使用亚马逊 S3。EMR、S3、Spark 在一起相处得很好。您可以将数据存储在 S3,然后读取和处理数据,而无需实际存储在您的节点中,通过 spark 处理后,您可以将数据写回 S3 并终止 EMR。
EMR 实例准备就绪后,您可以使用您的 pem 密钥和主服务器的公共 DNS 进入您的终端并进行 ssh。
$ ssh -i .ssh/mykey.pem hadoop@ec2–xx–xxx–xxx-xx.us-west-2.compute.amazonaws.com

EMR terminal
2.获取数据
在本教程中,我将使用百万首歌曲数据集的子集,但是任何超过几个 GB 的数据集都会支持我们的观点。下面是多种方式获取数据的链接:https://lab Rosa . ee . Columbia . edu/million song/pages/getting-dataset。尽管他们在 EC2 映像中提供了这个数据集,但为了完整起见,我们将假设这是我们自己的数据,我们试图将其导入 AWS。我们将在这里探索的数据称为 MillionSongSubset,它随机选择了百万首歌曲的子集,即 10,000 首歌曲的集合。你可以参考“百万歌曲子集”的链接,并从那里下载 tar.gz 的文件。您可以将数据下载到您的本地,然后再下载到主节点和工作节点的 scp,但这将花费 scp 很长时间。所以我在这里推荐使用一个通过 Chrome 的 curlwget 扩展,将 tar.gz 文件直接下载到主节点和工作节点。我在 Chrome 上使用的扩展叫做 CurlWget。尝试在你的节点中存储数据/mnt/
下载完数据后,您会看到有两个主文件夹 data/A/和 data/B/这些文件夹有子目录,最终在每个. h5 层次数据文件下有单首歌曲数据,关于数据的更多信息在获取数据集 url 中提供。
3.用派斯帕克把 H5 变成 RDD
到目前为止,我们已经启动了我们的 EMR 实例,并将数据放入所有节点的相同路径中,现在我们将数据转换为 Spark RDD,以便使用 pyspark 及其分布式计算功能。RDD(弹性分布式数据集)是 spark 表示数据并将其存储在分区中的方式。数据可以来自文本、csv、json 格式或数据库。
我找不到将 H5 文件转换成 RDD 的直接方法,但这个链接https://www . hdf group . org/2015/03/from-HD F5-datasets-to-Apache-spark-rdds/启发我编写自己的脚本,使用 pyspark 并行进行这种转换。基本思想是在一个 python 列表中收集所有 h5 文件,并根据这个列表创建一个 RDD。然后,我们可以很容易地做我们想要的转换使用地图功能在这个 RDD。
# 8 is number of partitions to distribute the data
# For local applications it will be distributed to 8 threadsfile_paths = sc.parallelize(h5_file_paths, 8)# Read and convert to python dict in parallelsongs_rdd = file_paths.map(lambda x: h5todict(x))
songs = songs_rdd.collect()
在这里,我们也收集歌曲作为 python 列表,以便创建我们的 MongoDB 数据库,因为教程的一部分也要显示 MongoDB,但我们可能只坚持使用包含 python 字典的 RDD(在这种情况下,每个元素都是一个 python 字典,它在层次关系中有一个歌曲数据)。拥有 RDD 就足以通过 pyspark 继续处理、分析和建模。
边注:这里提供了转换的完整脚本:https://github . com/KeremTurgutlu/distcomputing/blob/master/million songs-Project/H5 to mongo . py。所有节点都应该安装了所需的 python 包,比如 h5py、json、numpy…
为此,您需要 ssh 到您的工作节点和主节点。要 ssh 到 worker 节点,您应该在 master 中拥有您的 pem 密钥,并通过 master 终端使用该密钥进行 ssh。之后,您需要做的就是 pip 安装尚未提供的所需软件包。
4.设置 MongoDB
在这一步中,我们将在主节点中安装和设置 mongodb。可以按照这里的步骤https://docs . MongoDB . com/manual/tutorial/install-MongoDB-on-red-hat/进行安装。安装后,您应该创建一个目录,用于存储您创建的数据库。同样,在/mnt 下将它们创建为/mnt/mongo/db 更有利于磁盘的使用。您还需要通过运行以下命令来设置对此目录的权限:
$ sudo chown -R `id -un` /mnt/mongo/db/
运行此步骤后:
$ mongod --dbpath /mnt/mongo/db
现在 MongoDB 服务器应该在监听连接。在一个单独的终端上,您可以运行 mongo 并启动 mongo shell。在 mongo shell 中,您可以使用 show dbs 查看当前数据库。
现在,与 MongoDB 建立有效连接。接下来,我们需要在所有节点上安装 pymongo 包,它是 MongoDB 的 python API。之后,我们可以在我们的主机上运行通过 github repo 提供的脚本。为了运行该脚本,我们还应该在同一路径中有https://github . com/KeremTurgutlu/dist computing/blob/master/million songs-Project/user _ definition . py。在用户定义中,我们定义了执行器驱动内存、最大结果和开销内存,以便在运行应用程序时不会遇到内存问题。
这个脚本将读取 h5 文件,并在默认情况下在名为“MillionSongs”的数据库下创建一个名为“songs”的 mongoDB 集合(当然,您可以在 user_definition.py 中为数据库和集合指定其他名称)。你可能认为数据库是一个普通的 SQL 数据库,集合是一个 SQL 表,文档(单曲的 dict)是表中的一行。
5.分布式分析和 ML
此时,我们有一个名为“MillionSongs”的 MongoDB 数据库,并位于一个名为“Songs”的集合下(或者您指定的数据库和集合)。对于您自己的数据,为了有一个数据库和集合,例如来自位于您当前目录下的 json 文件,您可以从另一个终端运行这个命令,而 mongod 在另一个终端上运行:
$ mongoimport --db dbName --collection collectionName --file fileName.json
使用 mongodb,可以像在 SQL 中一样通过查询数据来非常容易地过滤、选择、聚集和执行许多其他操作。在我们的歌曲集合中,每首歌曲都被表示为一个文档(一个 python 字典),这是由于我们通过 h5tomongo.py 脚本创建和插入它们的方式。
我们的第一个任务是预测某首歌是在哪一个年代发行的。有关数据字段的更多详细说明,您可能会发现此链接很有帮助:https://lab Rosa . ee . Columbia . edu/million song/pages/field-list。这项任务在 Kaggle 和 UCI 网站上都有推广。我们将使用 segments_timbre 来完成我们的任务,segments _ timbre 是一种类似 MFCC 主成分分析的 2d 特征,涉及歌曲的纹理、歌曲的能量、歌曲的可跳性和歌曲的年份。

2d features for 12 segments
首先,让我们从 mongodb 中收集我们想要的数据:
我们通过定义具有分层字段名的字典来定义我们想要返回的字段(例如在我们的文档中 year 具有 analysis -> songs -> year 层次结构),1 表示我们想要返回的字段,0 表示我们不想要的字段。默认情况下,还会返回文档的 _id,这就是我们明确取消选择的原因。您可以看到,我们在 find 函数中定义了一个过滤器,其中创建了 train_year_data 和 test_year_data。测试数据将是缺少年份字段的数据(在原始数据中被估算为 0)。我们的任务可能是用训练数据建立一个好的预测模型,以便进一步估算这个测试集中缺失的年份。
from pymongo import MongoClientclient = MongoClient()
db = client[dbname]
collection = db[collection_name]fields = {'musicbrainz.songs.year':1, 'analysis.segments_timbre':1, 'analysis.songs.energy':1, 'analysis.songs.danceability':1, 'metadata.songs.title':1, 'metadata.songs.artist_name': 1,
'_id':0}train_year_data = collection.find({'musicbrainz.songs.year':{'$gte':1920}}, fields)
test_year_data = collection.find({'musicbrainz.songs.year':{'$eq':0}}, fields)
其次,让我们创建 rdd 和数据帧:
Spark SQL 支持我们将用于输入机器学习算法的数据帧,它也非常方便地支持 pandas 数据帧。从 MongoDB collection 过渡到 Spark RDD 非常简单:
# create train and test rdds
train_year_rdd = sc.parallelize(list(train_year_data))
test_year_rdd = sc.parallelize(list(test_year_data))
我们将通过取所有段的协方差和每个段的平均值,从 timbre _ segments 中创建一个 1d 特征向量。总计 12 个分段的 90 个特征。我们将通过 map 应用两个自定义函数,以获得创建 Spark SQL 数据框架所需的特性。因为 train_year_rdd 和 test_year_rdd 仍然是层次化的 python dict 格式,我们不能用它来创建数据帧以输入到 ML 算法中。你可以在这里找到这些步骤的源代码:https://github . com/KeremTurgutlu/distcomputing/blob/master/million songs-Project/predict _ year . py
# create train and test dataframestrain_full_df = train_year_rdd.map(lambda d: getYearFeatures(d)).\
map(lambda d: getDFeatures(d)).toDF()test_df = test_year_rdd.map(lambda d: getYearFeatures(d)).\
map(lambda d: getDFeatures(d, True)).toDF()
创建培训和验证集:
# split to train and validation dataframes
train_df, val_df = train_full_df.randomSplit([0.7, 0.3])
创建矢量汇编程序:
Vector assembler 获取所需列名的列表,这些列名将被输入 ML 算法,组合它们并为优化的 spark ML 做好准备。
# define vector assembler and transform dataframes into correct format
# cache train and validation dataframes for fast iterationsva = VectorAssembler(inputCols=x_cols, outputCol='features')
train_va=va.transform(train_df).select('features','decade').cache()
val_va=va.transform(val_df).select('features', 'decade').cache()
test_va=va.transform(test_df).select('features', 'decade').cache()
Pyspark ML 包提供了多种型号、变压器和许多选项。查阅文档就好:http://spark . Apache . org/docs/2 . 2 . 0/API/python/py spark . ml . html个人应用。几乎所有的分布式 ML 算法都是通过这个 API 提供的,而不是深度学习。对于深度学习,你可以检查 H20.ai 的苏打水:https://www.h2o.ai/sparkling-water/或者简单地使用现代的 GPU,甚至使用 Pytorch 的 nn.DataParallel 进行多次处理
既然我们有了向量组装器,现在我们可以进行实际的分布式训练。我将展示运行逻辑回归模型的代码,但是 repo 中提供的脚本同时运行逻辑回归和随机森林。
# define model and fit lr = LogisticRegression(featuresCol='features', labelCol='decade',regParam=0.01, maxIter=1000, fitIntercept=True)
lr_model = lr.fit(train_va)
或者我们可以简单地进行交叉验证的网格搜索
# create cross validation
cv = CrossValidator().setEstimator(lr).setEvaluator(evaluator).setNumFolds(5)
#ParamGridBuilder() – combinations of parameters and their values.
paramGrid = ParamGridBuilder().addGrid(lr.maxIter, [1000]).addGrid(lr.regParam, [0.0001, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5]).build()
#setEstimatorParamMaps() takes ParamGridBuilder().
cv.setEstimatorParamMaps(paramGrid)
cvmodel = cv.fit(train_va)
由于准确性不够好,我们通过使用多级 F1 分数来评估模型。
运行提供的脚本:
为了通过终端运行 spark 作业,您需要使用 spark-submit 命令。在将您想要的脚本克隆或获取到一个文件夹中,并在 h5toMongo.py 中定义了正确的 file _ roots 以及在 user_definition 中定义了所需的内存分配之后,您可以运行:
$ spark-submit h5toMongo.py
和
$ spark-submit predict_year.py
我希望这个简短的教程对你有所帮助,有很多内容需要你通过文档和经验来学习。因此,如果您有任何建议、推荐或问题,请告诉我。
感谢阅读!
端到端—使用 Python 框架的预测模型

预测建模总是一项有趣的任务。花费的主要时间是了解企业需要什么,然后确定您的问题。下一步是根据需求定制解决方案。当我们解决许多问题时,我们明白可以用一个框架来建立我们的第一批模型。这个框架不仅给你更快的结果,它还帮助你根据结果计划下一步。
在本文中,我们将看到如何将基于 Python 的框架应用于各种预测建模任务。这将涵盖/触及 CRISP-DM 流程中的大部分领域。那么什么是 CRISP-DM 呢?
数据挖掘的跨行业标准过程,称为 CRISP-DM,是一个数据挖掘过程模型,它描述了…
en.wikipedia.org](https://en.wikipedia.org/wiki/Cross-industry_standard_process_for_data_mining)
下面是代码的链接。在本文中,为了简洁起见,我跳过了许多代码。阅读本文时,请遵循边上的 Github 代码。
[## sundar 0989/EndtoEnd—-使用 Python 进行预测建模
通过在 GitHub 上创建帐户,为使用 Python 的端到端预测建模开发做出贡献。
github.com](https://github.com/Sundar0989/EndtoEnd---Predictive-modeling-using-Python)
本文中讨论的框架分为 9 个不同的领域,我将它们与它们在 CRISP DM 过程中所处的位置联系起来。
加载数据集— 数据理解
**import** **pandas** **as** **pd**
df = pd.read_excel("bank.xlsx")
数据转换— 数据准备
现在,我们有了熊猫数据框架中的数据集。接下来,我们分别使用 df.info()和 df.head()查看变量描述和数据集内容。使用下面的代码将目标变量(' Yes'/'No ')转换为(1/0)。
df['target'] = df['y'].apply(**lambda** x: 1 **if** x == 'yes' **else** 0)
描述性统计— 数据理解
探索性统计帮助建模者更好地理解数据。在这个框架中有一些这样的统计数据。首先,我们使用下面的代码检查数据集中每一列的缺失值。
df.isnull().mean().sort_values(ascending=**False**)*100
其次,我们使用下面的代码检查变量之间的相关性。
**import** **seaborn** **as** **sns**
**import** **matplotlib.pyplot** **as** **plt**
%matplotlib inline
corr = df.corr()
sns.heatmap(corr,
xticklabels=corr.columns,
yticklabels=corr.columns)

最后,在框架中,我加入了一个宁滨算法,该算法自动将输入变量纳入数据集中,并创建一个二元图(输入与目标)。
bar_color = '#058caa'
num_color = '#ed8549'
final_iv,_ = data_vars(df1,df1['target'])
final_iv = final_iv[(final_iv.VAR_NAME != 'target')]
grouped = final_iv.groupby(['VAR_NAME'])
**for** key, group **in** grouped:
ax = group.plot('MIN_VALUE','EVENT_RATE',kind='bar',color=bar_color,linewidth=1.0,edgecolor=['black'])
ax.set_title(str(key) + " vs " + str('target'))
ax.set_xlabel(key)
ax.set_ylabel(str('target') + " %")
rects = ax.patches
**for** rect **in** rects:
height = rect.get_height()
ax.text(rect.get_x()+rect.get_width()/2., 1.01*height, str(round(height*100,1)) + '%',
ha='center', va='bottom', color=num_color, fontweight='bold')

The values in the bottom represent the start value of the bin.
变量选择— 数据准备
请阅读我下面的文章,关于在这个框架中使用的变量选择过程。基于投票系统选择变量。我们使用不同的算法来选择特征,然后最后每个算法为他们选择的特征投票。最终投票数用于选择建模的最佳特征。
变量选择是预测建模过程中的关键步骤之一。这是一门艺术。简单来说…
medium.com](https://medium.com/@sundarstyles89/variable-selection-using-python-vote-based-approach-faa42da960f0)
模型— 建模
到目前为止,80%的预测模型工作已经完成。为了完成剩下的 20%,我们将数据集分成训练/测试,并对数据尝试各种算法,然后选择最佳算法。
**from** **sklearn.cross_validation** **import** train_test_split
train, test = train_test_split(df1, test_size = 0.4)
train = train.reset_index(drop=**True**)
test = test.reset_index(drop=**True**)
features_train = train[list(vif['Features'])]
label_train = train['target']
features_test = test[list(vif['Features'])]
label_test = test['target']
我们在训练数据集上应用不同的算法,并在测试数据上评估性能,以确保模型是稳定的。该框架包括随机森林、逻辑回归、朴素贝叶斯、神经网络和梯度推进的代码。我们可以根据需要添加其他型号。下面提供了随机森林代码。
**from** **sklearn.ensemble** **import** RandomForestClassifier
clf = RandomForestClassifier()
clf.fit(features_train,label_train)
pred_train = clf.predict(features_train)
pred_test = clf.predict(features_test)
**from** **sklearn.metrics** **import** accuracy_score
accuracy_train = accuracy_score(pred_train,label_train)
accuracy_test = accuracy_score(pred_test,label_test)
**from** **sklearn** **import** metrics
fpr, tpr, _ = metrics.roc_curve(np.array(label_train), clf.predict_proba(features_train)[:,1])
auc_train = metrics.auc(fpr,tpr)
fpr, tpr, _ = metrics.roc_curve(np.array(label_test), clf.predict_proba(features_test)[:,1])
auc_test = metrics.auc(fpr,tpr)
超参数整定— 建模
此外,还可以调整模型的超参数来提高性能。下面是一段代码。
**from** **sklearn.model_selection** **import** RandomizedSearchCV
**from** **sklearn.ensemble** **import** RandomForestClassifier
n_estimators = [int(x) **for** x **in** np.linspace(start = 10, stop = 500, num = 10)]
max_features = ['auto', 'sqrt']
max_depth = [int(x) **for** x **in** np.linspace(3, 10, num = 1)]
max_depth.append(**None**)
min_samples_split = [2, 5, 10]
min_samples_leaf = [1, 2, 4]
bootstrap = [**True**, **False**]
random_grid = {'n_estimators': n_estimators,
'max_features': max_features,
'max_depth': max_depth,
'min_samples_split': min_samples_split,
'min_samples_leaf': min_samples_leaf,
'bootstrap': bootstrap}
rf = RandomForestClassifier()
rf_random = RandomizedSearchCV(estimator = rf, param_distributions = random_grid, n_iter = 10, cv = 2, verbose=2, random_state=42, n_jobs = -1)
rf_random.fit(features_train, label_train)
最终模型和模型性能— 评估
目前,我们选择了能提供更高精度值的最终模型。然而,我们还没有完成。我们需要基于各种度量来评估模型性能。该框架包含计算实际与预测值交叉表、ROC 曲线、十分位数、KS 统计、提升图、实际与预测图、增益图的代码。我们将在下面逐一介绍。
- 交叉表
pd.crosstab(label_train,pd.Series(pred_train),rownames=['ACTUAL'],colnames=['PRED'])

Crosstab of Actual vs Predicted values
2。ROC/AUC 曲线或 c 统计
from bokeh.charts import Histogram
from ipywidgets import interact
from bokeh.plotting import figure
from bokeh.io import push_notebook, show, output_notebook
output_notebook()from sklearn import metrics
preds = clf.predict_proba(features_train)[:,1]fpr, tpr, _ = metrics.roc_curve(np.array(label_train), preds)
auc = metrics.auc(fpr,tpr)p = figure(title="ROC Curve - Train data")
r = p.line(fpr,tpr,color='#0077bc',legend = 'AUC = '+ str(round(auc,3)), line_width=2)
s = p.line([0,1],[0,1], color= '#d15555',line_dash='dotdash',line_width=2)
show(p)

3。十分位数图和 Kolmogorov Smirnov (KS)统计数据
在后端执行一个宏来生成下图。黄色突出显示的数字是 KS 统计值。
deciling(scores_train,['DECILE'],'TARGET','NONTARGET')

4。提升图、实际与预测图、收益图
与十分位数图类似,宏用于生成下面的图。
gains(lift_train,['DECILE'],'TARGET','SCORE')

保存模型以备将来使用— 部署
最后,我们开发了我们的模型并评估了所有不同的指标,现在我们准备在生产中部署模型。部署前的最后一步是保存我们的模型,这是使用下面的代码完成的。
**import** **pandas**
**from** **sklearn.externals** **import** joblib
filename = 'final_model.model'
i = [d,clf]
joblib.dump(i,filename)
这里,“clf”是模型分类器对象,“d”是标签编码器对象,用于将字符转换为数字变量。
评分新数据— 部署
为了评分,我们需要将模型对象(clf)和标签编码器对象加载回 python 环境。
*# Use the code to load the model*
filename = 'final_model.model'
**from** **sklearn.externals** **import** joblib
d,clf=joblib.load(filename)
然后,我们加载新的数据集并传递给评分宏。
**def** score_new(features,clf):
score = pd.DataFrame(clf.predict_proba(features)[:,1], columns = ['SCORE'])
score['DECILE'] = pd.qcut(score['SCORE'].rank(method = 'first'),10,labels=range(10,0,-1))
score['DECILE'] = score['DECILE'].astype(float)
**return**(score)
我们用下面的代码调用这个宏
scores = score_new(new_score_data,clf)
就是这样。我们已经给新数据打分了。本文提供了技术代码的高级概述。如果您需要讨论任何特别的事情,或者您对任何模块有反馈,请留下评论或通过 LinkedIn 联系我。
玩得开心!
我发布了一个 python 包,它将执行本文中提到的一些任务——WOE 和 IV,双变量图表,变量选择。如果你有兴趣使用软件包版本,请阅读下面的文章。
[## Xverse 介绍!—用于要素选择和变换的 python 包
Xverse 是 X Universe 的缩写,它是一个用于机器学习的 python 包,可以帮助数据科学家利用特性…
towardsdatascience.com](/introducing-xverse-a-python-package-for-feature-selection-and-transformation-17193cdcd067)
结束你对偏差和方差的偏见!!

所有的机器学习模型都不正确。句号!
但是偏差和方差的“正确”权衡是你的利益相关者可以接受的(至少)。有很多关于偏差和方差的文章,它们很好地解释了这个概念。因此,我会节省一些空间和时间来再次深入研究这些概念。但是让我们先回顾一下定义。
偏差 of 估计量是我们的估计量的预期或平均预测值与我们试图预测的正确值之间的差值。Sweet- >如果我一遍又一遍地更改训练数据集,我的 fit 不会剧烈移动。
苦- >它假定了过度简化的关系,而往往错过了真正的潜在关系。
方差是如果使用不同的训练数据,目标函数的估计将改变的量。甜蜜- >抓住了真实关系中的复杂性。Bitter - >不会对看不见的数据做出准确的预测。我们发现到处都写着这两者之间必须有所取舍。
本文的主要焦点是将不同算法的偏差和方差关系并列在一起。我将从对每一个问题的理论解释开始,然后通过分析一些数字来了解每一件事情的进展。
线性回归被理解为高偏差、低方差模型。这种说法部分正确。线性回归模型可以有高偏差-低方差,也可以有低偏差-高方差。这一切都归结于你在比较什么。
基于树的模型:尽管决策树模型是管理层最喜欢的时髦词,但它被诽谤为具有高方差和低偏差。这通常是正确的,因为树不会对目标函数做出假设,但是很容易“追逐”训练数据点。但是,当我说一棵树可以对相同的数据集有高偏差,而线性回归会有低偏差时,不要把这当成晴天霹雳!(我们将运行这些数字,看看这是如何发生的)。
为前面提到的震惊提供一个直接的答案——想想与线性模型相比,树模型太差,MSE 高,它抛出了偏差和方差的夸大值。每当我们拟合一个模型时,我们会查看一些误差度量,并不本质上将其分解为偏差和方差(通常情况下)。这是因为很难明确找到偏差和方差,因为它们是根据 统计期望 定义的。快速参考两者的数学表达式:

Fig.2 Formula for Error term decomposed as bias, variance and irreducible error
中间项是平方(偏差),最后一项是方差。你看到那个大的 E, 在计算这两个项时造成了障碍。这是因为要计算某项的期望值,需要有真总体的信息。我不能用波士顿房价数据集来做这个,因为我不知道 100%准确的潜在关系。因此,为了将我的预测误差分解为偏差和方差,我与旧的 sweet 模拟和随机数据发生器握手。下面是我这样做的步骤。)自定义一个关系,即定义我们称之为真实总体的系数。
2。)用它创建一个目标变量,并给它添加一些噪声。
3。)模拟 n 个不同的此类数据集,并在其上拟合 n 个不同的线性以及决策树模型。预测测试观察的结果。
4。)利用步骤 1 中的信息计算偏差和方差。下面提到的脚本执行上述所有步骤。
获得的结果总结如下:

Fig 3: Calculation of Bias, Variance and MSE for different models
你看 1 号模型是线性回归,恰好给出了最好的结果。然而,决策树通过模型编号 3 得到的最佳结果的特征是 max_depth=4。所以,我在这里的观点很清楚,与线性模型相比,我们的树模型偏差较低(预期)。与线性模型相比,我们也有偏差较高的模型(惊喜)。要注意的是,两个模型提供的最佳拟合确实遵循线性回归的高偏差-低方差和树的低偏差-高方差的一般惯例。我在这里的关键点是,一个人不应该有偏见,并持有关于这些算法的意见,这是上面反驳。基本事实:这是应该遵循的最佳匹配的权衡。选择一个特定的算法将永远不会保证两个讨论项的高/低值。
上面公布的代码是完全可复制的,人们可以尝试看看他们的“信念”是如何被其他算法揭穿的,如 KNN、逻辑回归、支持向量机在偏差-方差方面。需要记住的一点是,如果你碰巧在分类问题上尝试了这种方法,那么偏差和方差的公式将会改变,因为上面显示的公式对于最小二乘估计是有效的。如果 y'=y else 0,您可能会想到设计像 L(y ',y)= 1 这样得分度量。
PS:
1。)这篇文章将展示如何在给定模型的情况下计算预测误差并将其分解为偏差和方差。
2。)这篇文章旨在揭穿关于不同 ML 算法的偏差-方差的典型惯例的神话。
3。)这篇文章不是要解释机器学习中偏差-方差权衡的本质。
工程无摩擦注册体验
原载于 段的博客 并转载于此。我现在是 荣誉 的工程师。我们在招人!如果你有兴趣和我们一起工作, 在 Twitter 上 DM 我 !
像我们在 SaaS 领域的许多同行一样,Segment 的增长团队坚定不移地致力于提高我们销售团队的销售线索数量和质量。对我们来说,这意味着更多的公司完成我们的注册表格。但我们不仅仅希望有更多的公司签约,我们还希望我们的销售团队对我们的客户有更全面的了解。

为了提高转化率,缩短这些表格是有意义的。然而,这有丢失注册信息的风险,而这些信息在销售漏斗中至关重要。经过深思熟虑后,我们决定进行一项实验,我们称之为“无摩擦注册”。在这个实验中,我们使用 Segment 的数据丰富产品来预填充注册表单。
经过一个月的测试,结果出来了:在我们的主页上添加一个电子邮件捕获表单将转化率提高了 5.45%,在注册表单中预先填入 Clearbit 丰富的数据将转化率提高了 23.76%。
在不影响数据的情况下减少摩擦
无摩擦注册是使用公司数据(即公司名称、公司员工人数、公司资金总额等)预先填写注册表格或任何潜在客户生成表格的过程。当用户键入他们的电子邮件地址时,我们点击 Clearbit 的 Enrichment API,并使用返回的数据来完成表单的剩余部分。
正如您从下面的 GIF 中看到的,客户输入了他们的电子邮件地址,表单会自动预填充剩余的字段:

Notice how with a simple email address, we can prefill the name, company size, and role form fields
为什么效果这么好?
无摩擦注册和个人资料丰富为标准表单增加了四项主要改进:
1。表单预填充:我们正在减少用户在任何表单上遇到的麻烦。通过减少注册页面上的表单字段数量,我们使访问者更容易注册。
2。丰富的用户资料:当你点击 Clearbit 的 API,特别是通过细分市场的丰富集成,你会获得数百个关于你注册的额外数据点。例如,以下是我们的内部增长专家 Guillaume Cabane 返回的数据:

Response object from Clearbit’s API
3。数据验证:冗长的注册表单通常会产生虚假数据,因为用户在必填字段中填入任何内容以通过注册过程。预填充、丰富的数据允许用户查看、更正和验证,而不是从头开始输入数据。除此之外,如果用户更改表单中的任何字段,您可以自动丢弃 Clearbit 数据(因为这将表明 Clearbit 数据无效)。这是巨大的,因为我们不再冒假阳性匹配的风险。
4。动态内容:因为我们将 Clearbit 数据传回客户端(即浏览器),所以我们可以选择使用针对该用户的独特内容来定制入职流程。在上面的例子中,我们以引用我们一位亲爱的客户的话的形式展示社会证明。报价是特定于角色的,因此营销人员看到的是营销人员报价等等。
例如,这是我们默认的注册表单页面:

The box at the bottom is dynamic — it changes based on the info returned from the enrichment APIs
当我们根据 Clearbit 呼叫返回的数据对注册进行资格预审时,我们可以添加一个额外的表单字段,询问他们是否需要帮助:

The question at the bottom is dynamic — only highly qualified leads see this box
我们是如何做到的
为了帮助其他人达到同样的目标,我们开源了代码,并编写了这个如何在 Segment 使用它的分步指南。
在深入了解细节之前,这里有一个流程的高级概述:
- 客户输入他们的电子邮件地址
- 电子邮件地址随后被发送到 Clearbit 的 Enrichment API
- 表单域预先填充了从 Clearbit 返回的信息
- 通过细分市场识别和跟踪电话,丰富了客户档案,为您的销售和营销团队提供了更好的数据
如果以上听起来很新鲜或者很吓人,不要担心。我会带你走过每一步。
第一步:接受电子邮件地址
为了预填我们的表单,我们需要首先收集一个电子邮件地址。这就是 Clearbit 的 Enrichment API 所需要的,以便返回用户的特征,如名字、姓氏和公司角色。我们将电子邮件地址作为演示表单的第一个输入框,因为我们需要一些时间(几百毫秒)来点击 Clearbit 的 API 并预填充表单的其余部分。
因此,无摩擦注册的第一步是:你必须要求你的用户提供一个电子邮件地址,这样你就可以查询 Clearbit 的 API。
步骤 2:编写简单的 JavaScript 来监听电子邮件字段的变化
我们编写了几行 JavaScript 来监听电子邮件表单字段的变化,并捕捉用户的输入。这一步非常重要,因为当用户输入完他们的电子邮件地址时,我们需要立即点击 Clearbit 的 API。
在下面的代码中,我们获得了名为“email”的 HTML 元素,并向其中添加了一个“change”事件侦听器。这意味着无论何时用户离开电子邮件表单域,JavaScript 都会监听:
document.getElementById("email").addEventListener('change', () => {
// keep reading for the code that belongs here
});
完成这些后,现在您就可以查询 Clearbit API 并开始填充表单的其余部分了。
步骤 3:查询 Clearbit API
一旦我们捕获了潜在客户的电子邮件地址,我们就可以使用它来查询 Clearbit API,以获取该电子邮件地址的相关信息。我们只需用该电子邮件地址向 Clearbit 的 Enrichment API 端点发出一个 HTTP 请求。响应可以包括个人和公司信息,我们可以使用这些信息来填充所有表单字段。下面是您的客户端 JavaScript 代码的样子:
const request = require('visionmedia/superagent');
document.getElementById("email").addEventListener('change', () => {
// make a GET request to a clearbit route on your server
request.get('/contact/clearbit') // send in user’s email as a query param
.query({ email: event.target.value })
.end((err, res) => { // simply return if there is an error
if (err || !res.ok) return // capture the person & company object
const {person, company} = res.body // more code below on how to parse the response
});
});
就这么简单。前进!
这里最棘手的部分是您的 Clearbit 调用需要在服务器端进行,以避免暴露 API 键。您必须将响应数据传递给客户端 JavaScript。不过,不要担心:Clearbit 提供了一个节点、Ruby 和 Python 库来帮助您完成这项工作。在我们的实验中,我们使用了节点库。
下面是我们的节点服务器上的代码:
const clearbit = require('clearbit')('{clearbit_api_key}')// capture the email query parameter
const emailAddress = this.request.query.email;// hit clearbit enrichment API
clearbit.Enrichment.find({email: emailAddress, stream: true})
.then(response => {
return response
})
.catch(err => {
console.error(err)
});
Clearbit 响应对象将至少包含:
{
"person": {
"id": "a0dd5de3-b1ff-449d-85ab-4b2ffdfdca53",
"name": {
"fullName": "Alex Stein",
"givenName": "Alex",
"familyName": "Stein"
},
"email": "alex@example.com",
"location": "San Francisco, CA, US",
"employment": {
"domain": "example.com",
"name": "Example",
"title": "Digital Brand and Content Lead",
"role": "marketing",
"seniority": "manager"
},
},
"company": {
"id": "3f5d6a4e-c284-4f78-bfdf-7669b45af907",
"name": "Example",
"legalName": "Example Technologies Inc.",
"domain": "example.com",
"domainAliases": ["example.org"],
},
}
其实这只是很小比例的回应。通过这个电话,可以获得关于这个人及其公司的更多信息,例如社会概况和其他联系信息。结合上面的两个部分——点击 Clearbit 路径的客户端 JavaScript 和点击 Clearbit API 的服务器端 JavaScript——将使您完成 80%的任务。下一步是解析数据,以便预填充表单的其余部分。
步骤 4:自动更新表单
当 Clearbit API 返回时,您可以使用 person 和 company 对象来填充表单中的必填字段。用 JavaScript 做到这一点最简单的方法是使用与响应对象中的数据字段相对应的必需字段的元素 id:
document.getElementById("email").addEventListener('change', function() {
request.get('/contact/clearbit')
.query({ email: event.target.value })
.end((err, res) => {
if (err || !res.ok) return
... // set (prefill) the name form field
document.getElementById("fullName").value = person.fullName // set (prefill) the company form field
document.getElementById("company").value = company.name
});
});
步骤 5:将丰富的用户数据发送到下游集成
这一部分非常重要,尤其是如果你有一个 SaaS 产品,如果你已经在使用 Segment,这一部分尤其重要。对于那些不熟悉的人来说,细分市场的识别呼叫有助于将用户特征与他们在你的应用中的行为联系起来。例如,每次用户完成一个动作(称为“跟踪事件”),您可以自动将他们的个人资料附加到该事件。然后,这些数据会被发送到您在 Segment 上启用的任何其他工具,如电子邮件营销和分析。
通过将 Clearbit Enrichment 与您的细分市场账户集成,您的所有用户都将自动获得新数据。您所要做的就是在您的细分仪表板中打开 Clearbit 集成。它非常容易上手,你的营销和销售团队会喜欢你的!
高级:预测性销售线索评分
我们已经开始使用这些档案信息作为预测线索评分工具 Madkudu 的输入。这使用个人资料信息以及转化和应用内行为数据来区分高价值线索。使用来自 Madkudu 的实时结果,我们可以在注册过程的早期识别这种高接触率的线索。然后,这可以与定制结合使用,以允许客户成功团队在个人接触到产品之前进行接触,以帮助他们入职。
结果呢
在细分市场,除了预测性销售线索得分,这一技术还使我们的签约量增加了 20%以上。
不仅如此,由于无摩擦注册使我们能够验证数据,我们能够获得干净、准确的用户数据,以发送个性化的营销信息,并动态显示更多更好的页面内内容,以推动演示请求。我们还能够根据转化的可能性对销售线索进行适当的评分,然后将其传递给我们的销售人员,从而增加我们销售合格的销售线索。
我们不仅使潜在客户请求演示变得更加容易,还实现了我们的目标,即提高我们的营销网站所产生的销售线索的数量和质量。
工程意识:天堂文件

两周前,国际调查记者联盟发布了天堂文件,这是一份来自百慕大律师事务所艾波的文件集。这些文件由全球 380 名记者调查,揭示了精英们把钱藏在哪里。
昨天,他们发布了代表 77k 公司官员、25k 企业和他们之间 364k 连接的原始 CSV 文件。你能想到比使用图表更好的方法来分析这些数据吗?
我不想只是自己分析这些数据,而是想让世界更容易分析。
将所有的事情归档
Neo4j 通过分发官方 docker 图像使得在容器中运行图形数据库变得非常容易。虽然这些图像允许通过docker run选项传递配置和数据库,但我想让人们能够超级容易地访问天堂文件。
docker run -p 7474:7474 -p 7687:7687 ryguyrg/neo4j-paradise-papers
该图像包括 APOC 库和图形算法库。它还包含一个 bash 脚本来从 ICIJ 下载最新的 csv 数据,并调用neo4j-import来创建图形数据库。然后,脚本调用neo4j-shell来执行 Cypher 语句,这些语句会创建适当的索引。
下面是完整的Dockerfile,它还设置了EXTENSION_SCRIPT环境变量,以便在 Neo4j 启动之前执行上述脚本。
FROM neo4j:3.3.0
MAINTAINER Ryan Boyd, <ryan@neo4j.com>RUN apk update
RUN apk add --quiet openssl sed wget unzip
RUN cd /var/lib/neo4j/plugins/; wget "https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases/download/3.3.0.1/apoc-3.3.0.1-all.jar"
RUN cd /var/lib/neo4j/plugins/; wget "https://github.com/neo4j-contrib/neo4j-graph-algorithms/releases/download/3.3.0.0/graph-algorithms-algo-3.3.0.0.jar"COPY download_db.sh /download_db.sh
COPY configure.cql /configure.cqlENV EXTENSION_SCRIPT /download_db.sh
ENV NEO4J_AUTH=none

创建 Neo4j 沙盒
创建新的 Neo4j 沙箱的过程与创建 Docker 映像非常相似,只是我们通常为大多数沙箱使用标准 Docker 映像。这个标准映像复制了上面创建的 Neo4j 数据库,并在每次用户启动自己的沙箱实例时使其可用。
它还提供了来自 ICIJ 的交互式指南,该指南提供了关于要执行的查询类型的逐步说明。

Interactive Guide for ICIJ Paradise Papers on Neo4j Sandbox
前往 Neo4j 沙盒亲自体验一下吧。
分析数据
我的同事威尔·里昂(Will Lyon)和迈克尔·亨格(Michael Hunger)在两篇博客文章中对这些数据做了一些精彩的分析——第一篇是搜集来的数据,第二篇是由 ICIJ 公布的最终数据。
一个例子是,他们绘制了特定国家的居民最有可能持有海外资产的地点:

Officer Residence (bolded) and Offshore location (non-bold)
在其他分析中,他们还研究了雷克斯·蒂勒森和英国女王之间的最短路径。

更多他们的分析,请阅读他们的博客文章。
我的下一步是什么?
我计划为一些即将到来的演讲做一些额外的分析,所以请留意我的 Twitter 或 Medium 的更新。
从工程到数据科学预测的一生——我多么怀念物理

Finding oil is a long way from my jupyter notebook
在坚定地进入数据科学领域之前,我作为一名石油工程师在石油和天然气行业工作了 5 年。在几个国家和世界各地工作,从几内亚湾的海上平台到西非丛林中的办公室。这些经历塑造了我作为一名工程师和个人的形象,并对我的定量分析前景产生了巨大影响。
我的大部分工作是在生产优化和预测领域。本质上,我们如何利用现有资源(甚至更少)生产更多的石油,并预测未来我们将生产什么。所有这些都是为了了解油田资产的价值及其未来潜力。
我经常看到我作为一名石油工程师使用物理模型所做的事情,与我现在作为一名数据科学家预测消费者对电子商务的需求所做的事情有许多相似之处。然而,在预测模型中遇到的问题有很大的差异。最终,我意识到,即使作为一名工程师,我不得不管理所有可怕的肮脏数据,我仍然非常想念物理学的基础来帮助指导我的决策。当试图理解数据和信息告诉你什么时,工程和物理定律提供了已知的边界条件。当我们分析一个人购买消费品的理性时,这些物理定律有点难以定义。
石油和天然气行业的预测
作为一名在中非工作的工程师,我的工作本质上是获取大量实际测量的数据(特征),并将其转换为预测模型,通常是时间相关模型。这种分析以及需求预测的关键是理解数据,观察什么,如何有效地组合变量以最好地代表您的系统,以及处理不确定性的量化。然而,这两种方法有着根本的区别,一种是从使用物理模型开始的工程,另一种是使用统计模型。我个人认为,将两个阵营结合起来是行业前进的基础。
石油预测像任何其他预测一样需要数据,油井通常已经生产了许多年(0-40 年),大多数油井通常至少有一套标准数据:每天生产多少流体、地面压力和温度。有了这些要素,就可以直接进行预测了。问题是,虽然你有数据,但它在质量和数量上有很大差异。这是对工程师的真正挑战。这使它成为一项迷人的工作。
你的数据可能来自地下 3000 米深处的任何地方,每秒钟都会向你的笔记本电脑发送信号,也可能是一个人跳进一辆皮卡或一艘船去参观油井并读取一个量表——后一种情况比你想象的更常见。事实上,我一直是这样的家伙。因此,从收集数据的性质和收集的内容来看,数据是零星的,有时非常不可靠,有时甚至根本不存在。
这实际上是石油行业的症状,很少有一致性,特别是在数据方面,当你开始预测时,理解这一点是有用的。你会发现的为数不多的一致性之一是,随着油价的每一次下跌,你可能也会看到数据质量的下降。这对时间序列预测有重大影响,通常你的数据在油井寿命开始时是可靠的(这是最大的资本投资),然后随着时间的推移而退化,通过故障传感器、较差的监控和通常不再是公司投资组合中最性感的东西。
除了简单的数据可用性,实际测量还有巨大的不确定性。很难理解油藏及其产出的流体的复杂性,更不用说有时难以相信自己的测量结果了。最后,当你想到一个油藏时,你是在谈论将微小的针刺(井~12 英寸宽)放入 2-4000 米深的地球,然后使用这些作为你在可以跨越数十公里的东西中的唯一眼睛和耳朵。
因此,石油和天然气预测的困难很大程度上来自于您的数据质量和可用性。虽然我把它说得像一个可怕的问题,你会经常看到工程师们努力从他们的数据中获得意义,以表达他们对未来的看法。你也有一个物理系统!这意味着即使我花了几周/几个月的时间开发我的模型,我也可以给另一个工程师 5-10 个参数,他可以在他的计算器上检查我的预测是否在物理上合理。最后,我们试图预测的过程在宏观水平上受我们在中学物理中学到的简单压力、温度和体积关系的支配。有了物理学,你就有了一个基础真理,一根引导绳。当你告诉某人投资数千万美元时,这会给你更多的信心。
电子商务方面
现在,本周我一直在研究一个完全不同的问题,我为一家电子商务公司建立需求预测模型。本质上,我试图预测人们下周将在网站上购买什么,这样我就可以有足够的库存来满足他们的购买需求。这带来了许多限制,我不想买太多的股票(过度预测),因为这会花我的钱,我也不想低估太多,因为我会延迟履行客户订单(客户不太满意和/或失去客户)。这是一个财务权衡,我不会在这里深入讨论,但这是一个有趣的问题,研究什么是最佳库存数量。
我有一组来自销售端的简单数据(我们每天对给定产品的订单),从谷歌分析我可以得到网站的流量信息,通过结合这两个数据集,你可以得到转化率。我正在为大约 20 000 种产品这样做,所以它需要工业化。这也是一个不连续的数据集,你可能一周什么也没卖出去,突然之间就卖出了 10 件产品。
我意识到我有时会想念物理系统
因此,在我的电子商务案例中,与我在油田的生活相比,我正在处理难以想象的干净数据。我有“传感器”来测量人们在网站上做的一切,这些数据的质量很高,不仅是由谷歌收集的:-),而且最重要的是,这些数据不是由一个值夜班的人收集的,他花了 8 个小时开车或乘船到偏远的地方去读取仪表。更别说我在雨季的凌晨两点试图在笔记本上记下压力了。
所以当我最初开始解决这些问题时,我就像哇,我沐浴在良好的数据中。但当我开始了解预测的本质时,我很快意识到我没有事实依据,也没有指南。在预测油井时,你总是有物理学的手给你信心。当我向一个朋友寻求帮助,让他给我对下周股票预测的信心时,我突然发现这是一个非常孤独的地方。
问题是,没有物理学,很难知道你所做的是对的。明天我不知道我们会卖出更多还是更少,我可以说昨天我们卖出了 X,前天卖出了 y。但是明天我不知道任何具体的东西,我可以给你概率,告诉你我非常确定我们会卖出超过 1,但是我真的对我的系统没有什么限制。在石油预测中,我可以说“昨天我们生产了 200 桶,这意味着压力下降了 x,这意味着今天我可能会少生产 5 桶”来支持我的预测。
在油田的最后,你可以创建复杂的概率模型,但在这之后,你可以创建基于物理的确定性模型,给你信心。人口众多的购买心态,谷歌搜索算法或竞争对手广告活动的影响,以及这如何影响我的流量,我不知道。
有了需求预测,你可以而且必须继续创建更好的模型,试图捕捉更多可能的用户行为的代理。但最终,这会导致更复杂的模型,变得更难解释。尽管在历史数据上的性能可以得到很大的提高,但它永远不会给人同样的信心(至少对我来说)。我们在这里所做的在金融预测和其他概率系统中得到了广泛的应用和研究,它们可能会非常成功,但我们应该总是对你实际知道的和你的模型可能学到的东西持批评态度。因为最终至少对我来说,我担心那些大肥尾巴中的一个会打我的脸。
英语到粤语的翻译:一小时内快速破解
我想每个在小学学过第二语言的同龄人都记得用谷歌翻译做作业。几乎每个人都有一个关于谷歌翻译出错的有趣故事。我的故事版本涉及到七年级法语的服装单元。我们的家庭作业是写一篇关于我们喜欢穿什么衣服的短文。当时,我真的很喜欢背心。我交了作业,写了这样一段话,“我叫杰米·波特·德·查尔兹·豪特。”谢谢,谷歌翻译。那没有意义。应该是“J'aime porter des debradeurs”实际上应该翻译成“我喜欢穿高[军]坦克。”我的法语老师没有被骗。
幸运的是,谷歌翻译这些年来已经有了很大的改进。现在,如果你输入“我喜欢穿背心”,它不再犯和我七年级时一样的错误。对于学习语言的人来说,谷歌翻译实际上是一个非常有用的工具。截至目前,谷歌翻译支持超过 100 种语言。而 Google Translate 支持 拼音 (普通话罗马化),我发现它缺少了一个贴近我内心的东西:粤语罗马化,或者说Jyutping。
Google Translate does do a great job of differentiating between traditional and simplified Chinese characters (for those who are not familiar, traditional characters are used for Cantonese and Mandarin in Taiwan, while simplified characters are used for Mandarin in China). Type “horse” in English, and you’ll be given “馬” if you choose traditional characters, and “马” if you choose simplified. However, for both traditional and simplified characters, the romanization given with the character is “Mǎ”, and this is Pinyin. What we really should have is “馬, maa5” for Cantonese, and “马, mǎ” for Mandarin. Google translate incorrectly uses Pinyin for Cantonese. What we really want here is Jyutping.

Obligatory Great Wall of China pic!
谷歌翻译不支持粤语
繁体和简体汉字都使用拼音,这表明谷歌所说的“中文”是指“普通话”所以实际上,根本不支持粤语。我们不仅想添加 Jyutping,还想添加粤语作为支持的语言。遗憾的是,我在谷歌没有可以帮助我的直拨电话,所以我想出了一个变通的办法。
最棒的是:通过利用两个网站,我们不需要任何自己的数据,也不需要使用任何机器学习。这个黑客非常快,解决了我们的问题。不需要神经网络!
百度和 Chineseconverter 来救场了!
Baidu, which is pretty much China’s Google, has a great Baidu translate tool that we can take advantage of. Not only does it support English to Mandarin Chinese translations, but it supports English to Cantonese! Enter “horse” and you’ll get “馬”, but with no Jyutping to help a student actually pronounce it. We need another site to do this: Chineseconverter.com. This site allows us to enter traditional characters, and output Jyutping. Finally, what we want! Now let’s write some code to do this for us.
硒来救场了!
使用 Python 和 Selenium 包,我们可以自动将英文文本输入到百度翻译,将输出作为输入复制到 Chineseconverter.com,最后将结果作为我们的最终输出。
我们从初始化 webdriver 开始:
接下来,我们刮!这一部分涉及到进入两个网页的源代码和检索必要的元素。我发现,如果我把我的英文文本输入百度翻译后,没有让程序“休眠”3 秒,那么 Selenium 就找不到输出。除此之外,一切正常。
样品使用
让我们看看程序是如何运行的。这是从终端发出的。
Enter your input: I love eating noodles
Traditional characters: 我钟意食面
Cantonese Jyutping: ngo5 zung1 ji3 sik6 min6
If we had used Google Translate and traditional Chinese characters, we would’ve gotten “我喜歡吃麵條”, which is not Cantonese, since it gives us “吃, chī”. What we want is “食, sik6,” which is the Cantonese way of saying “to eat.” So this is great, it works!
运行时间的最终注释
因为我们只是自动化了从网页中输入和提取文本的过程,所以运行起来要花很长时间(大约 5 秒)。这种滞后给了一个粤语学生时间去思考他们的翻译应该是什么,但这肯定是太长了,以至于不能宣布它是谷歌翻译缺乏粤语的解决方案!

An interesting note- a lot of Chinese characters are actually pictograms!
结束语还有,为什么不用造字,而用造字呢?
使用 Python 和 Selenium,很快就找到了一种将英语翻译成粤语的方法。我不需要训练任何神经网络,甚至不需要获得任何训练数据——我只是使用了现有的数据。不过,你可能会问自己,为什么要这么做?为什么一个正在学习说广东话的人不能同时学习阅读呢?嗯,学习广东话和任何中文的问题是,如果你同时专注于学习读、写和说,你会不知所措。在我看来,学习这类语言的最好方法是先把注意力放在说上,阅读随后就会到来。如果你的目标是与人交流(当面!),你不需要会读会写。即使是在说中文的地区,年轻人也倾向于选择语音信息而不是短信,这更加证明了我的观点,你不需要一开始就能读或写。当然,这很好,但你必须做出选择。这是一种交换。
最初发表在我的博客 serena.mcdonnell.ca 上
用 ML、AI、IR 和 NLP 增强人类感知
工作中的交互式文本挖掘和信息检索

文本数据仍然是大数据分析环境中最重要的来源之一。正如任何传感器都可以感知环境状态并报告收集的数据一样,人类也能够感知周围的世界,然后将他们的理解表达为文本数据。从某种意义上来说,人类实际上已经将输入数据转化为某种有价值的信息。因此,人类生成的文本内容已经超越了“原始数据”的层次。文本内容已经嵌入了对现实的阐述和感知。

我们可以挖掘这种文本信息的内容,并提取关于所观察的世界、关于观察者(人类)以及关于所使用的语言的知识。除此之外,通过预测分析,人们可以推断出现实世界的变量。此外,您还可以添加可用的全部上下文数据和元数据(例如,时间戳、地理位置等)。
然而,执行真正的 NLP (自然语言处理)是一项艰巨的任务。这里我们说的不是基本的文本处理,它已经成为一种普遍的做法。我们说的是真实文本理解。
那么,我们如何利用 不完美的 NLP 来生成 完美的应用 ?简单:让人类参与进来!
正如你需要显微镜、望远镜或宏观镜,这取决于你想分析的真实世界,你需要一个文本显微镜来研究文本。这个工具必须是一个结合了信息检索、文本挖掘、数据分析和 人在回路 技术的智能交互式工具。

可以将几种技术结合起来:例如,实体提取、单词分类、将文本挖掘与时间序列上的因果分析(也包括非文本数据)相结合,等等。
在此图中,您可以看到优化因果关系(基于时间序列分析)和一致性(基于主题分析)的试探法
不幸的是,每个应用程序都需要对这种工具进行大量的定制和培训。我们需要抽象和统一来最小化覆盖不同领域和应用的学习努力。

这与我们对社会知识提取的研究非常相关,它分析人类生成的内容,目的是生成新的形式化知识(例如,整合现有的知识库,如 DBpedia)。
这个故事的灵感来自于伊利诺伊大学香槟分校(信息科学学院基因组生物学研究所统计系)ACM 研究员翟在IEEE big data Conference 2017上的主题演讲。
通过构建推荐引擎提升星巴克的顾客体验——第 1 部分

Photo by Hans Vivek on Unsplash
介绍
星巴克已经成为全球主要的咖啡公司,在全球拥有超过 15000 家门店,包括公司所有和特许经营的门店。这家公司能够实现这一壮举的主要原因之一是坚持不懈地关注客户体验。
给其客户最大的便利是星巴克卡的推出,后来扩展到星巴克 App。它支持无现金支付,因此根据观察,客户在支付过程中的等待时间可以显著减少。此外,星巴克应用程序使顾客能够收到促销优惠,这些优惠强调顾客在星巴克购买商品时的利益最大化。
向客户进行促销的挑战在于,每个客户对他们收到的优惠都有不同的偏好。如果他们收到他们不喜欢的报价,他们很可能不会尝试完成报价,尽管所有报价都对他们有利。随着人工智能(AI)和机器学习(ML)的进步,星巴克解决这个问题已经成为可能。
项目概述
推荐引擎是可以用机器学习来实现的系统之一。它能够预测顾客喜欢什么,不喜欢什么。因此,该系统将推荐更有可能被顾客购买的商品,并随后提高星巴克的商店业绩,例如销售额或顾客购买的商品数量。
在这个项目中,我基于 3 个数据集创建了两个推荐引擎,这些数据集是模拟星巴克奖励移动应用程序上的客户行为的模拟数据。第一个数据集(portfolio.json)包含向客户提供的促销。它包含 id、类型、持续时间、渠道和报价奖励。
第二个数据集(profile.json)是关于星巴克顾客的人口统计资料。它包含用户的年龄、性别、收入、id,以及这些用户何时成为星巴克应用程序的成员。第三个数据集(transcripts.json)包含第二个数据集中星巴克客户的交易记录。它有事件,告诉我们要约是否被接收、查看或完成,以及事件何时完成。它还有用户 id 和值,这是一个报价 id 或交易金额的字典,具体取决于记录。
问题陈述
这里的挑战是用这 3 个数据集创建一个推荐引擎。它必须考虑用户在接收报价时的偏好,以及用户是否喜欢被给予报价。我解决这个问题的方法是创建两个推荐引擎。第一种是基于聚类,第二种是基于用户相似度。
创建推荐引擎所涉及的任务有:
1 .清理给定的数据集,因为它包含许多 NaN 值和几个错误。
2。探索和可视化数据,以获得人口统计资料以及客户购买行为的良好画面。
3。用于创建推荐引擎的工程特征。生成的特征是出价-购买行为的比率数据。
4。基于特征创建客户细分。这是使用 KMeans 集群完成的。
5。创建基于聚类的推荐引擎。这需要一个用户 id,将用户 id 映射到该用户所属的集群,并推荐集群成员喜欢的前 3 个报价。
6。基于用户相似度创建推荐引擎。这需要一个用户 id,搜索与该 id 相似的 10 个用户,并推荐这 10 个用户最喜欢的 top 3。
韵律学
衡量一个推荐引擎的有效性并不容易。星巴克总是可以做一段时间的 A/B 测试。星巴克必须在应用程序中分配 cookies,将用户分为 2 组,控制组和实验组。对照组不会得到这个推荐引擎,实验组会得到。然后,星巴克需要观察不变指标和评估指标的差异。
不变度量
应该关注的不变度量有:
1。控制组和实验组的用户数量。这个至少应该差不多,接近五五开。
2。分配给每个组的 cookies 数量。
评价指标 应该关注的评价指标有:
1。平均交易金额。如果实验组有较高的平均交易量,推荐引擎可以被认为是有用的。
2。完成出价的百分比。如果实验组具有较高的完成要约百分比,则推荐引擎可以被认为是有用的。
3。来自要约的交易与收到要约的比率。对实验组来说越高越好。
4。非来自要约的交易与收到的要约的比率。实验组越低越好。
在评估推荐引擎的有效性时应该考虑的另一种方法是离线方法。这些方法应在将发动机部署到实验组的最初几个月后进行计算:
- 精准。这是一个衡量指标,表示在已经提供的促销中,用户喜欢的数量。
- 回忆一下。这是用户喜欢的推广优惠推荐给用户的比例。这两个指标应该最大化,因为它将告诉我们推荐引擎是否真正推荐了用户喜欢的项目,以及在推荐中,用户喜欢的促销报价的比例是多少。
数据探索
给出的 3 个数据集不干净。除了投资组合数据,在数据准备好用于创建推荐引擎之前,还有许多任务要做。

Fig 1. Portfolio Data
投资组合数据集非常简单。它包含促销渠道、难度、促销持续时间(天数)、优惠 id、优惠类型和完成促销的奖励。这里要打扫的东西不多,除了:
1。将渠道栏分为 4 个虚拟栏:网络、电子邮件、手机和社交。
2。创建一个字典,将 offer id 作为关键字和别名,以便简化以后 3 个数据集的合并。

Fig 2. Profile Data
要清理这个数据集,需要做几件事情。我检测到的是:
1。有一对夫妇已经 118 岁了
2。有几个人在性别和收入栏中缺少数据。这是一个问题,因为没有完整的数据,我不能创建一个良好的客户细分。我输入这个数据帧的方法是使用随机森林回归器和随机森林分类器创建机器学习模型。

Fig 3. Users with the Age of 118
从空值的数量和切片数据框的前几行判断,年龄为 118 岁的人没有记录性别和收入。这可能是因为注册问题或用户故意不填写栏。这使得为空值创建机器学习预测比我想象的要困难一些。

Fig 4. Transactions Data
交易数据在用于创建客户细分或推荐引擎之前也包含许多问题。事件列应该根据记录的事件进行分隔,包含优惠 id、奖励或交易金额的值列也应该进行分隔。
基于数据的最初外观,我决定在清理数据之前不创建数据可视化。主要原因是为了避免在问题仍然存在的情况下给读者错误的数据描述。
续第 2 部分
创建这一部分是为了让读者对数据有一个印象。第 2 部分将大量讨论这个项目的数据清理和特性工程阶段。如果有兴趣,请按照这个 链接 。
通过建立推荐引擎提升星巴克的顾客体验——第二部分

本系列的第二部分将关注项目的数据清理和特性工程方面。如果你还没有看过这个项目的介绍部分,我强烈建议你跟着这个 链接 读一读,让你对我在做的事情有一个更清晰的了解。
数据清理
本项目中数据清理的目的是为数据探索和可视化提供更清晰的信息。它还使我能够为星巴克应用程序的用户创建客户细分,然后基于聚类构建推荐引擎。
我清理的第一个数据是投资组合数据,因为它是最快的。使用来自 pandas 的 get_dummies 和 stack 方法,我在数据框中添加了几列以使其更加清晰。我还通过将 duration 列乘以 24 来创建 duration hours 列,duration 列是特定报价的持续天数。生成的数据帧如下:

Fig 1. Cleaned Portfolio Data Frame
清理另外两个数据帧有点困难。我做的第一件事是合并个人资料和交易数据。然后,我为 event 列创建了 3 个虚拟变量,根据发生的事件,它们的值分别为 1 和 0。
接下来,我将 value 列分成 4 个新列。第一个是要约 id。这告诉我们用户在特定时间收到、查看或完成了哪个报价。当用户进行交易而不是接收、查看或完成要约时,该列的值为 NaN,而不是要约 id。第二栏是交易金额。当用户进行交易时,该列保存交易的金额。否则,它包含 NaN 的值。我创建的第三列是事务列。根据用户是否进行了交易,该列的二进制值为 1 或 0。最后一个是奖励成就栏。如果用户完成了交易,则该列保存通过完成报价获得的奖励金额。
在创建了这 4 列之后,我决定将 person 列映射到 user id,以便简化以后将 user id 输入到推荐引擎的过程。生成的数据帧的前几行如下:

Fig 2. Cleaned Combination of Profile and Transactions Data Frame
这些数据的一个主要问题是,它没有告诉我们交易是否是因为报价而发生的。如果是,哪一个报价导致了交易?为了回答这个问题,我创建了两个专栏。第一个是来自要约的交易,根据交易是由要约引起的(1)还是由要约引起的(0)来保存值 1 或 0。第二个是已查看的交易报价,其中包含导致交易的报价 id,或者如果在此期间没有交易或者交易不是由特定报价导致的,则为“无交易”。
我基于这些机制创建了这两个专栏:
1。如果发生交易,我会检查它是否是由报价引起的。
2。我假设,如果一个用户查看了一个优惠,然后做了一笔交易,甚至几笔交易(以实现促销目标),那么这些交易就是由该优惠引起的。
3。要检查交易是否是由查看的报价引起的,我需要检查报价是否在交易时间和报价的最大持续时间内被查看。然后,我查看第一次出现的报价,并将其指定为导致交易的报价。逻辑是,如果用户首先查看交易,如果报价仍在时限内,他们会尝试完成报价。尽管该用户可能会收到另一个报价,但他会尝试完成查看的第一个报价。
我还使用之前创建的字典将优惠 id 映射到优惠别名。生成的数据帧的前几行如下:

Fig 3. Data Frame with Transaction from Offer and Transaction Offer Viewed
完成此操作后,我将结果数据框与投资组合数据框合并,以创建一个主数据框。之后,我继续清理数据框,为没有输入性别、收入和正确年龄的用户创建年龄、性别和收入列的预测。
预测年龄、性别和收入
在预测这些列的值时,我做的第一步是将主数据帧分成两个数据帧。这很容易做到,因为填错年龄的用户也没有填写性别和收入栏。因此,很容易将数据框划分为用于创建模型的数据框和用于预测值的数据框。
接下来,我从预测年龄开始。我使用随机森林回归器创建了一个预测模型。预测变量(X)是模型创建数据框中的列,除了“性别”、“收入”、“时间”、“报价类型”、“报价 id”、“交易报价查看”、“年龄”、“报酬实现”。目标变量(Y)是“年龄”。我得到的结果是:

Fig 4. Random Forest Regression for Age Result
结果不太好。因此,我利用 scikit-learn 的网格搜索 CV 创建了一个更好的模型。结果如下:

Fig 5. Random Forest Regression with Grid Search CV for Age Result
我意识到模型改进了,虽然改进没那么多。我应该可以调整更多的超参数。然而,由于时间限制,我选择使用这个模型来预测用户的年龄。之后,我再次使用随机森林回归器创建了一个收入预测。结果是:

Fig 6. Random Forest Regression for Income Result
这个模型比年龄预测模型要好,尽管还远远不够。我决定也使用这个模型,并在未来对其进行微调,以创建更好的预测。预测的最后一栏是性别。我使用随机森林分类器来创建预测模型,平均 f1 值“微观”为 0.831。
我用这些模型来预测没有填写或填写错误的人的年龄、收入和性别。然而,我注意到一些预测是错误的。

Fig 7. Data Frame with Age, Gender, and Income Already Predicted
图 7 是用户 id 为 1 的数据帧的前几行。年龄、性别和收入是不同的,这意味着模型没有做出很好的预测。例如,用户 1 的年龄被预测为 61、44、45 或 46 岁。性别预测为 F 和 m。这是正常的,因为每个用户在查看、接收和完成要约以及进行交易时的列值是不同的。
为了解决这个问题,我创建了更多的计算:
- 平均年龄值,以获得每个用户的预测年龄
- 收入值的平均值,以获得每个用户的预测收入
- 性别值模式,以获得每个用户的预测性别

Fig 7. Data Frame for User ID 1 After Adjustment
从用户 1 的年龄、性别和收入都相同的意义上来说,生成的数据框看起来比前一个更好。
特征工程
酒店业的大多数企业依靠比率数据来评估他们的业绩。例如,餐馆更喜欢使用促销完成率和促销成本,而不是仅使用促销完成数。因此,我为数据框中的每个用户创建了这些比率数据。
然而,在设计这些特性之前,我注意到交易报价视图列有一些不正确的值。无论用户没有进行交易还是用户进行了非要约交易,值“无交易”都是相同的。因此,我决定更改值。如果事务列的值为 1,我将“无事务”更改为“事务 _ 非 _ 来自 _ 报价”。
在区分非要约交易和无交易后,我为“transaction_offer_viewed”列中的每个值创建了虚拟变量,根据用户执行的交易类型,这些变量的值为 1 或 0。使用这些专栏,我创建了一个用户人口统计和购买行为的数据框架。
该数据框架由 21 列组成,包含用户人口统计资料(年龄、收入、性别)和用户促销购买行为。例如,列“bogo1”是用户从星巴克应用程序查看“bogo1”促销后完成的交易数量。以下是数据框中的前几行和前几列:

Fig 8. User Demographic and Promotion Purchase Behavior Data Frame
使用这个数据框,我创建了 3 个比率数据作为特征。第一个是完成要约的百分比,即完成要约与收到要约的比率。第二个是来自出价比率的交易。这是来自要约的交易和收到的要约之间的比率。最后,我创造了交易,而不是从出价比率。顾名思义,这是不是来自要约的交易和收到的要约之间的比率。我决定使用收到的报价而不是查看的报价作为分母,因为发送报价的“成本”需要考虑,尽管它可能不是金钱的形式。可能是时间或带宽。因此,我认为使用收到的报价作为比率数据的分母是合适的。

Fig 9. The Snapshot of The Ratio Data Features
我做的最后一件事是用 0 填充数据帧中的 NaN 值,用 999 填充 inf 值。理由是,NaN 值源自比率数据,其分子值为 0,分母值为 0。例如,完成要约百分比的 NaN 值源自未完成要约且未收到要约的用户。因此,用 0 填充它是合适的。
至于 inf 值,它出现在交易中,而不是来自出价比率。例如,一个有 3 笔交易并收到 0 个报价的用户将产生 inf 值。因此,我分配了一个大值(999)来替换 inf 值。我相信这也是合适的,因为它代表了一个没有看到报价就进行交易的用户。
续第 3 部分
这一部分是为了让读者了解我是如何为这个项目进行数据清理的。下一部分将重点关注用户人口统计的数据可视化,并提供购买行为。如果你有兴趣,请跟随这个 链接 。
如果你有建议或批评,请不要犹豫,发表意见。我仍然是,并将永远是这个领域的学生。如果你有任何问题或想知道我对你的项目的看法,请随时联系我。
通过建立推荐引擎提升星巴克的顾客体验——第三部分

Photo by Omar Lopez on Unsplash
本系列的第三部分关注项目的数据可视化。如果你还没有看过这个项目的介绍部分,我强烈建议你跟着这个 链接 读一读,让你对我在做的事情有一个更清晰的认识。
点击这里 这个链接 可以看到我用来清理数据的代码。
数据可视化
在获得用户人口统计和购买行为数据框架后,我决定探索这些数据并创建可视化效果,以更清晰地了解星巴克应用程序用户的人口统计概况和购买行为。我创建了一个额外的列是“加入年”。这一栏是某个顾客成为星巴克 App 会员的那一年的数据。

Fig 1. Histogram of User Age
星巴克应用程序的大多数用户年龄在 40-80 岁之间。这个结果与分子网站的发现有些一致。然而,主要的区别是分子发现星巴克的大多数用户年龄在 25-34 岁之间。其余的水桶也差不多。

Fig 2. Histogram of User Income
大部分用户的收入在 50000–78000 之间。这是有道理的,因为根据维基百科的数据,美国很多人来自收入在 35000 到 75000 之间的中下阶层。这也告诉我们,星巴克的应用用户以中低阶层为主。这有点有趣,因为星巴克的商品价格并不便宜。与中下阶层相比,上层阶级的用户并不多。也许,这是因为星巴克应用程序中的大多数用户实际上是为了促销优惠。这就是为什么创建推广推荐引擎是星巴克的一个好策略。自从用户成为星巴克应用程序的成员后,看到每个用户的交易金额的分布对我来说也很有趣。

Fig 3. Histogram of User Transaction Amount
大多数用户的交易金额在 0-200 美元之间。这实际上有点令人担忧,因为从 2013 年开始就有用户成为星巴克应用程序的会员。这些用户可能选择不打开该应用程序,或者他们已经删除了该应用程序,或者他们可能对优惠不感兴趣。因此,看看更早加入的用户是否花费更多将是有趣的。

Fig 4. Bar Chart of Amount of Transaction based on User Join Year
从图 4 可以看出,2013 年加入的用户交易量最少,其次是 2014 年加入的用户。为了进一步调查,我创建了一个条形图,显示每年加入星巴克应用程序的会员数量。

Fig 5. Bar Chart of Number of Members per Year
在 2013 年和 2014 年,成员人数似乎仍然很低。这可以解释为什么交易量也很低。然而,他们也有更多的时间来积累交易。似乎这些用户停止了会员资格,或者他们对促销根本不感兴趣。这也是星巴克创建推荐引擎进行推广的一个很好的理由。现在,看看这些用户的平均支出也会很有趣。

Fig 6. Bar Chart of the Average Amount of Transaction Based on User Join Year
尽管所有在 2013 年加入的用户在星巴克购物花费最少,但每个用户的花费都比 2018 年加入的用户多得多。根据平均交易,2016 年加入的每个用户每次购买花费最多。这告诉我们那些较早加入的人的消费能力。虽然他们不在平均消费最高的前三名之列,但他们确实花了相当多的钱购买星巴克的产品。这也是创建推广推荐引擎的原因之一。接下来,我查看了用户的性别分布。

Fig 7. Bar Chart of Users’ Gender Distribution
星巴克的顾客大部分是男性,其次是女性顾客和其他。之后,看看哪种性别会受到晋升机会的影响会很有趣。

Fig 8. Bar Chart of Number of Transaction from Offer Viewed by Gender
令人惊讶的是,填写“其他”的人在看到报价后会做更多的交易。女性用户受他们所看的报价的影响最小。接下来,我将按性别查看完成的聘用百分比。然而,必须指出的是,差别并不大。

Fig 9. Bar Chart of Percentage of Offer Completed by Gender
同样,性别为“其他”的人完成了最多的提议。男性客户,虽然他们做更多的交易,但他们并不真正试图完成报价。看看哪个性别花钱最多会很有趣。

Fig 10. Bar Chart of the Amount of Transaction by Gender
不出所料,女性用户花费更多。因此,尽管他们的交易次数最少,但他们往往比男性用户花费更多的钱来完成更多的报价。似乎女性和其他人都比男性更喜欢升职。

Fig 11. Histogram of User Transaction from Offer Viewed
大多数用户在查看报价后有 0-7 次交易。这意味着,当他们看到一个报价时,他们之后会进行交易,甚至可能不止一次交易。这表明,大多数星巴克应用程序用户喜欢促销优惠,如果他们得到优惠,他们会采取行动。
结论
数据探索/可视化的结果非常有趣。此外,他们都表示,建立一个推荐系统的推广产品。
我发现有趣的几件事是:
1。尽管星巴克的商品并不便宜,但大多数应用程序用户来自中下阶层。
2。早些年加入的用户可能已经终止了他们的会员资格。
3。2016 年加入的用户平均交易金额最高
4。2017 年加入的用户交易量最大,尽管他们个人并不真的花很多钱。
5。女性用户倾向于花更多的钱来获得奖励。
6。大多数应用程序用户都是男性,但他们不会真的尝试去完成一个报价。
续第 4 部分
这一部分旨在让读者了解人口统计概况,并通过数据可视化展示星巴克应用用户的购买行为。下一部分将重点关注星巴克应用用户的细分以及基于聚类的推荐引擎和基于用户的推荐引擎的创建。有兴趣的话请关注这个 链接 。
如果您有建议或批评,请不吝赐教。我仍然是,并将永远是这个领域的学生。如果你有任何问题或想知道我对你的项目的看法,请随时联系我。
通过建立推荐引擎提升星巴克的顾客体验——第四部分

Photo by Charles Koh on Unsplash
本系列的第四部分重点介绍该项目的机器学习部分,即聚类和构建推荐引擎。如果你还没有看过这个项目的介绍部分,我强烈建议你跟着这个 链接 读一读,让你对我在做的事情有一个更清晰的认识。
点击这里 这个链接 可以看到我用来清理数据的代码。
使聚集
在掌握了星巴克顾客的人口统计数据之后,我使用 KMeans 进行了聚类,将人口统计数据分成几个组。
方法论 在做聚类之前,我用标准的定标器来定标数据。这是必要的,因为有些列有很大的值,而有些列只有 0 和 1。换句话说,聚类中使用的每个特征的方差都有很大的差异。维护原始数据会导致方差较小的变量具有更大的权重。因此,产生的聚类将沿着具有更大方差的变量被分开。
实现
选择多少个簇(k)的方法我用的是肘法。我选择查看几个集群,从 1 到集群中使用的变量数量,并对每个数量执行 KMeans 集群。然后,我计算了每个 k 的误差平方和(SSE)分数,并将分数附加到一个列表中。后来,我创建了一个线图来查看肘部,并选择它作为进一步分析中使用的聚类数。

Fig 1. SSE vs K on KMeans Clustering
在 KMeans 的结果中没有明显的拐点,除了 SSE 从第 7 类到第 16 类稍微大幅度的减少。因此,我决定用 16 个聚类来拟合和预测哪个用户属于哪个聚类。我创建了一个可视化工具来绘制每个集群的用户数量,如下所示:

Fig 2. The Number of Users per Cluster
从图 2 中可以看出,每个集群的用户数量的分布变化很大。例如,属于集群 2 的用户超过 4000 个,属于集群 8 的用户不到 10 个。这可能影响推荐引擎的质量,因为大多数用户将被映射到集群 2、3、7 或 16。
接下来,我根据聚类对用户人口统计数据框进行分组。我最终得到了聚类数据框。这是数据框的前几行和前几列的快照。如果你想看完整的数据帧,请查看我的 github。

Fig 3. The Cluster Data Frame
描述第 3 集群 1。第一个群体是年龄在 49 岁左右、收入在 58052 美元左右的男性客户。比起其他类型的报价,他们更喜欢 bogo4。收到报价后,他们会进行大约 2-3 笔交易。他们也做适度交易,而不是从收到的报价开始,这表明他们确实喜欢在星巴克喝咖啡。
2。第二个群体也是年龄在 49 岁左右、收入在 56291 美元左右的男性客户。比起其他类型的优惠,他们更喜欢打折。收到报价后,他们只做 1 笔左右的交易。然而,他们确实在星巴克购物,尽管他们没有收到任何报价。我认为,这些客户并不真正忠诚。他们想什么时候买咖啡就什么时候买,而且他们更喜欢打折。
3。第三个群体是年龄在 60 岁左右、收入在 78141 美元左右的男性顾客。比起其他类型的报价,他们更倾向于 bogo1。收到报价后,他们会进行大约 2-3 次交易,尽管他们没有收到报价,他们也会购买咖啡。这个集群类似于第一个集群,只是他们的收入更高。
基于聚类的推荐引擎
在对客户进行细分后,我创建了第一个推荐引擎,它是基于集群的推荐引擎。本质上,该引擎将依赖于之前创建的集群,并且基于将被给予推荐的用户所属的集群中的用户的喜好来创建推荐。
方法论 在创建推荐引擎之前,我必须考虑几件事情,它们是:
1。哪些用户不喜欢被给予优惠。
2。创建集群促销矩阵。
3。检查用户属于哪个集群。
4。推荐该用户所属集群喜欢的前 3 个优惠,并获取这些优惠 id 的列表。
5。如果用户属于不喜欢被提升的用户群,我不会给任何推荐。
6。如果用户是新的,我会给所有用户最喜欢的前 3 名。
实现 我创建了一个数据帧,包含用户 id 和交易非来自报价比率,以找出哪些用户不喜欢被给予报价。如果比率大于所有比率的平均值,我会认为用户是不喜欢优惠或促销的用户。

Fig 4. The ‘Offer or Not’ Data Frame
之后,我创建了一个集群提升矩阵的数据框架。我使用的变量只有折扣和买一送一变量。我决定不包含信息变量,因为无论如何,信息应该提供给每个用户。生成的数据帧的前几行如下:

Fig 5. Cluster-promotion Matrix
我使用这个数据框架和“提供或不提供”数据框架来创建推荐引擎。我创建了一个函数,它执行以下操作:
1。获取用户 id
2 的输入。如果用户 id 在“提供或不提供”数据框中,不要推荐任何东西。
3。如果用户 id 不在“提供或不提供”数据框中,请检查该用户属于哪个集群。
4。使用集群促销矩阵,推荐集群中用户最喜欢的前 3 个产品。
5。将优惠别名转换为原始优惠 id。

Fig 6. Recommendation Result
推荐引擎设法推荐与用户 293 在同一集群中的用户喜欢的前 3 个提议。至于用户 20,由于该用户属于“提供或不提供”数据框,所以引擎不推荐任何东西。新用户将得到如图 6 所示的 3 个报价。
细化
总而言之,这个推荐引擎做了我想做的事情。然而,我确实有一个问题。如上所述,集群包含不同数量的用户。因此,大多数用户仅被放在 4 个集群中。这可能会导致推荐引擎给出不太个性化的报价。因此,我决定创建一个基于用户的推荐引擎。
基于用户的推荐引擎
我心目中的基于用户的推荐引擎更加个性化。基本上,该引擎依赖于在用户推广矩阵中找到相似的用户,并根据这些相似的用户最喜欢的优惠提供推荐。
方法论 创建基于用户的推荐引擎的方法论与基于聚类的推荐引擎非常相似。我不得不考虑几件事。哪些用户不喜欢被给予优惠。
2。创建用户推广矩阵。
3。检查与要推荐的用户 id 最相似的前 10 名用户。
4。推荐 10 个最相似的用户最喜欢的前 3 个优惠。
5。如果用户属于不喜欢被提升的用户列表,我不会给任何推荐。
6。如果用户是新的,我会给所有用户最喜欢的前 3 名。
实施 我仍然使用“提供或不提供”数据框架来找出哪些用户不喜欢被提供服务。因此,我没有为此创建新的数据框。我做的第一件事是创建用户推广矩阵。我使用了用户统计数据框架,以用户 id 作为索引,以折扣和买一送一作为变量。

Fig 7. User-promotion Matrix
我用这个来计算每个用户之间的相似度。我使用的方法是计算要给出推荐的用户 id 的相应行的转置矩阵和用户矩阵数据帧的转置矩阵之间的点积。通过对用户相似度列表+ 1 的负值执行 argsort 来获得最相似的用户。最后要做的事情是从列表中删除用户 id。
为了创建推荐引擎,我创建了一个函数,它执行以下操作:
1。获取用户 id
2 的输入。如果用户 id 在“提供或不提供”数据框中,不要推荐任何东西。
3。如果用户 id 不在“提供或不提供”数据框中,则查找与该用户 id 最相似的 10 个用户。
4。使用用户推广矩阵,推荐 10 个最相似的用户最喜欢的前 3 个产品。
5。将优惠别名转换为原始优惠 id。

Fig 8. User-based Recommendation Result
与之前的推荐引擎相比,基于用户的推荐引擎为用户 id 293 创建了略有不同的推荐。其中两项建议是相同的。对于用户 id 3,引擎不推荐任何内容,因为该用户属于“提供或不提供”数据框架。对于新用户,该算法产生的结果与它是同一算法产生的结果相同。
评估和验证
两个推荐引擎都成功地实现了我想要的结果:
- 它识别哪些用户不应该被给予优惠
- 它根据相似用户/集群的偏好推荐报价
- 它为新用户推荐最受欢迎的产品。
评估推荐引擎不是一件容易的事情。星巴克必须花费一定的时间对这些系统进行 A/B 测试。这些指标已经在本文的引言部分提到过了(第 1 部分)。然而,在组的数量上有微小的变化。星巴克应该有 3 组,1 个对照组和 2 个实验组来测试这些推荐引擎。
Justification 个人认为基于用户的推荐引擎比基于聚类的好。它更加个性化和多样化,因为我们可以决定我们想要使用多少类似的用户。此外,正如我在上面提到的,每个集群中的用户数量是相当不同的。最大数量在 4000 以上,最小数量只有 8 个。这将影响基于集群的推荐引擎,因为集群中的用户越多,偏好的方差就越高。
结论
反射
给定的数据集确实很难,从这个意义上说,数据集中只有基本的特征。大多数时候,酒店行业的企业倾向于依赖比率作为衡量标准,所以我必须用这些数据集创建这些比率数据。然而,这并不是最困难的部分。
这个项目最困难的部分是清理数据,特别是输入年龄、性别和收入。我可以使用统计数据估算这些变量,如年龄均值、性别模式和收入均值/中值。但是,结果会不太准确。当我决定为这个项目创建一个推荐引擎时,我意识到获得最准确的数据是至关重要的,尤其是对于集群部分。因此,我决定使用机器学习来估算缺失/错误的值。这对我来说并不容易,尤其是因为我必须确定插补的顺序。我决定先用 R2 分数高的那个。
输入数据后,创建推荐引擎的过程并不困难。然而,推荐引擎的问题是,它应该在现实生活中进行测试,看看它是否工作得很好。我将需要进一步学习,以深化我在机器学习和推荐引擎方面的知识,以确保我可以构建出色的性能模型。
改进
可以做几个改进来构建更好的推荐引擎。其中一些是:
- 建立一个更好的随机森林模型来预测年龄、性别和收入。R2 分数不够高,MSE 分数也不够低。如果我有更多的时间,我可以调整超参数,或者尝试使用其他算法,如 Ada Boost,甚至神经网络。
- 建立一个更好的推荐引擎,将促销信息分为明星、主力、谜题和狗。我会用菜单工程的概念,实施分类推广。明星促销将是那些低成本和高交易量产生。主力将是那些成本高、交易量大的公司。难题将是那些成本低,但产生的交易量低。狗将是那些具有高成本和低交易量的狗。通过这样做,我们可以一直推广明星或益智推广,调整主力推广以及摆脱狗推广。当然,我需要额外的数据来做到这一点。
如果您有建议或批评,请不吝赐教。我仍然是,并将永远是这个领域的学生。如果你有任何问题或想知道我对你的项目的看法,请随时联系我。
机器学习中的集成学习|入门

使用各种不同的模型比只使用一种模型要可靠得多。在单个集合上一起工作的几个模型的集合称为集合。这种方法被称为集成学习。
投票
您可以使用不同的算法训练您的模型,然后集成它们以预测最终输出。比方说,你使用随机森林分类器,SVM 分类器,线性回归等。;模型相互竞争,并通过使用来自sklearn.ensemble的VotingClassifier类投票选出最佳性能。
硬投票是从集合中选择一个模型,通过简单多数投票进行最终预测,以确保准确性。
软投票只能在所有分类器都能计算出结果的概率时进行。软投票通过平均各个算法计算出的概率来达到最佳结果。
代码:
VotingClassifier的准确率一般高于个体分类器。确保包含不同的分类器,这样容易出现类似错误的模型不会聚集错误。
装袋和粘贴
您可以在数据集的各种随机子集上使用单个模型,而不是在单个数据集上运行各种模型。替换随机抽样称为装袋,简称自举汇总。如果很难在脑海中想象,就想象一下忽略数据集中的几个随机条目,用其余的条目建模。在粘贴的情况下,同样的过程适用,唯一的区别是粘贴不允许为相同的预测器多次采样训练实例。
代码:
bootstrap=True参数指定装袋的用途。对于粘贴,将参数更改为bootstrap=False。
如果分类器可以计算其预测的概率,则 BaggingClassifier 会自动执行软投票。这可以通过检查你的分类器是否有一个predict_proba()方法来验证。
装袋通常比粘贴效果好得多。
袋外评估
当对训练集执行 Bagging 时,只有 63%的实例包括在模型中,这意味着有 37%的实例分类器以前没有见过。这些可以像交叉验证一样用于评估。
要使用这个功能,只需在前面示例中的BaggingClassifier类中添加一个oob_score = True参数。
密码
到目前为止,只对实例进行了采样。对于包含大量要素的数据集,还有其他方法。
随机补丁和随机子空间
随机补丁对训练实例和特征进行采样。
在BaggingClassifier()中设置某些参数可以为我们实现这一点:
随机子空间保留除样本特征之外的所有实例。
这是通过以下方式实现的:
随机森林
决策树的集合是一个随机森林。Random Forests 在内部执行装袋。随机森林创建几棵树,有时是几千棵树,并为给定数据集计算最佳可能模型。随机森林算法不是在分割节点时考虑所有特征,而是从所有特征的子集中选择最佳特征。这用较高的偏差换取了较低的方差,从而产生了更好的模型。
代码:
参数:n_estimators是森林中树木的极限数量。max_leaf_nodes用于设置端节点的最大数量,这样算法就不会深入单个特征并过度拟合模型(阅读关于决策树的详细解释)。n_jobs指定您的计算机要使用的内核数量;-1值意味着所有最大可能的核心。
使用网格搜索可以通过改变参数值来改进模型。
adaboost 算法
虽然 AdaBoost 技术的函数数学相当令人生畏,但其原理相当简单。首先,您选择一个基础分类器,它对给定的集合进行预测。记下错误分类的实例。错误分类实例的权重增加。用更新的权重在训练集上训练第二分类器。
简单来说,运行分类器并进行预测。运行另一个分类器来拟合以前错误分类的实例并进行预测。重复进行,直到所有/大部分训练实例都适合为止。
AdaBoost 使用的不是决策树,而是一个决策树桩,它是一个带有max_depth = 1的决策树,即一个决策节点和两个叶节点的树。AdaBoost 中的n_estimators参数设置决策树桩的数量。
密码
Scikit-learn 使用 Adaboost 的多类版本 SAMME ( 使用多类指数损失函数的阶段式加法建模)。如果预测器可以计算概率(有predict_proba()方法),Scikit Learn 使用 SAMME。R ( R 代表实数)依赖于概率,不容易过度拟合。
在过度拟合的情况下,尝试调整你的基本估计量。
梯度推进
与 AdaBoost 类似,梯度提升也适用于添加到集成中的连续预测模型。梯度提升不是像 AdaBoost 那样更新训练实例的权重,而是使新模型适合残差。
简而言之,使模型适合给定的训练集。计算残差,该残差成为新的训练实例。一个新的模型在这些上面被训练等等。选择所有模型的总和来进行预测。
密码
学习率参数缩小了每棵树的贡献。在learning_rate和n_estimator s 之间有一个折衷。降低 learning_rate 的值会增加集合中的树的数量。这叫做收缩。将估计数增加到一个较大的值可能会使模型过拟合。见早停。必须仔细监控这种权衡。
XGBoost
XGBoost 是一种最新、最受欢迎且功能强大的梯度增强方法。XGBoost 没有在叶节点上做出艰难的是或否的决定,而是为做出的每个决定分配正值和负值。所有的树都是弱学习者,并且提供比随机猜测稍好的决策。但是总的来说,XGBoost 的表现非常好。
密码
XGBoost 可以处理树和线性模型。我建议阅读 XGBoost 文档,了解更多的参数调优选项。
XGBoost 最近获得了很大的人气,并被用在了最获胜的 Kaggle 竞赛模型中。这是您数据科学工具箱中的强大工具。
下次见。建议编辑和改进。保持(机器)学习。
本文的灵感来自 Aurélien Géron 的书《使用 Scikit-Learn 和 TensorFlow 进行机器学习:构建智能系统的概念、工具和技术》。我已经尽力把事情简单化了。希望有帮助。在这里得到这本书:http://shop.oreilly.com/product/0636920052289.do
使用 Scikit-learn 构建集成学习模型

Ensemble Learning (image credit)
集成学习使用多个机器学习模型来尝试对数据集进行更好的预测。集成模型的工作原理是在数据集上训练不同的模型,并让每个模型单独进行预测。这些模型的预测然后在集合模型中组合,以做出最终预测。
每种模式都有其优点和缺点。集成模型可以通过组合单个模型来帮助隐藏单个模型的弱点。
在本教程中,我们将使用投票分类器,其中集成模型通过多数投票进行预测。例如,如果我们使用三个模型,并且它们预测目标变量为[1,0,1],集合模型做出的最终预测将是 1,因为三个模型中的两个预测为 1。
我们将使用三种不同的模型来输入我们的投票分类器:k-最近邻、随机森林和逻辑回归。我们将使用 Python 中的 Scikit-learn 库来实现这些方法,并在我们的示例中使用糖尿病数据集。
注:集合模型也可用于回归问题,其中集合模型将使用不同模型的平均输出或加权平均值进行最终预测。
读入训练数据
第一步是读入我们将用作输入的数据。对于这个例子,我们使用糖尿病数据集。首先,我们将使用 Pandas 库读入数据。
import pandas as pd#read in the dataset
df = pd.read_csv(‘data/diabetes_data.csv’)#take a look at the data
df.head()

接下来,我们来看看我们有多少数据。我们将在数据帧上调用“shape”函数,查看数据中有多少行和多少列。行表示患者的数量,列表示特征(年龄、体重等)的数量。)在每个患者的数据集中。
#check dataset size
df.shape

将数据集分成输入和目标
现在让我们把数据集分成输入(X)和目标(y)。我们的输入将是除“糖尿病”之外的每一列,因为“糖尿病”是我们将试图预测的。因此,“糖尿病”将是我们的目标。
我们将使用 pandas 的‘drop’函数从数据帧中删除列‘diabetes ’,并将其存储在变量‘X’中。
#split data into inputs and targets
X = df.drop(columns = [‘diabetes’])
y = df[‘diabetes’]
将数据集拆分为训练和测试数据
现在,我们将数据集分为训练数据和测试数据。训练数据是模型将从中学习的数据。测试数据是我们将用来查看模型在看不见的数据上表现如何的数据。
Scikit-learn 有一个我们可以使用的名为“train_test_split”的函数,它使我们可以很容易地将数据集分成训练和测试数据。
from sklearn.model_selection import train_test_split#split data into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y)
“train_test_split”接受 5 个参数。前两个参数是我们之前分开的输入和目标数据。接下来,我们将“测试大小”设置为 0.3。这意味着所有数据的 30%将用于测试,剩下 70%的数据作为模型学习的训练数据。
将“分层”设置为 y 会使我们的训练分割表示 y 变量中每个值的比例。例如,在我们的数据集中,如果 25%的患者患有糖尿病,75%的患者没有糖尿病,将“分层”设置为 y 将确保随机拆分有 25%的糖尿病患者和 75%的非糖尿病患者。
构建模型
接下来,我们必须建立我们的模型。我们建立的每个模型都有一组我们可以调整的超参数。调整参数是指通过一个过程来为您的模型找到最佳参数以提高准确性。我们将使用网格搜索来寻找每个模型的最佳超参数。
网格搜索通过在我们指定的参数范围内多次训练我们的模型来工作。这样,我们可以用每个超参数值测试我们的模型,并找出最佳值以获得最佳精度结果。
k-最近邻
我们将建立的第一个模型是 k-最近邻(k-NN)。k-NN 模型通过获取一个数据点并查看“k”个最接近的标记数据点来工作。然后,给数据点分配“k”个最接近点中大多数的标签。
例如,如果 k = 5,3 个点为“绿色”,2 个点为“红色”,那么所讨论的数据点将被标记为“绿色”,因为“绿色”占大多数(如上图所示)。
代码如下:
import numpy as np
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier#create new a knn model
knn = KNeighborsClassifier()#create a dictionary of all values we want to test for n_neighbors
params_knn = {‘n_neighbors’: np.arange(1, 25)}#use gridsearch to test all values for n_neighbors
knn_gs = GridSearchCV(knn, params_knn, cv=5)#fit model to training data
knn_gs.fit(X_train, y_train)
首先,我们将创建一个新的 k-NN 分类器。接下来,我们需要创建一个字典来存储我们将为‘n _ neighbors’测试的所有值,这是我们需要调优的超参数。我们将测试“n_neighbors”的 24 个不同值。然后,我们将创建我们的网格搜索,输入我们的 k-NN 分类器、我们的超参数集和我们的交叉验证值。
交叉验证是指数据集被随机分成“k”个组。其中一组用作测试集,其余的用作训练集。该模型在训练集上被训练,并在测试集上被评分。然后重复该过程,直到每个唯一的组都被用作测试集。
在我们的例子中,我们使用 5 重交叉验证。数据集被分成 5 组,模型被训练和测试 5 次,因此每组都有机会成为测试集。这就是我们将如何对使用每个超参数值运行的模型进行评分,以查看“n_neighbors”的哪个值给了我们最好的分数。
然后,我们将使用“适合”功能来运行网格搜索。
现在,我们将使用“best_estimator_”函数将最佳 k-NN 模型保存到“knn_best”中,并检查“n_neighbors”的最佳值。
#save best model
knn_best = knn_gs.best_estimator_#check best n_neigbors value
print(knn_gs.best_params_)

对于接下来的两个模型,我将不再赘述,因为有些部分重复了 k-NN 模型的构建。
随机森林
我们要建立的下一个模型是一个随机森林。随机森林本身被认为是一个集合模型,因为它是一组决策树的集合,这些决策树组合在一起形成一个更精确的模型。
代码如下:
from sklearn.ensemble import RandomForestClassifier#create a new random forest classifier
rf = RandomForestClassifier()#create a dictionary of all values we want to test for n_estimators
params_rf = {‘n_estimators’: [50, 100, 200]}#use gridsearch to test all values for n_estimators
rf_gs = GridSearchCV(rf, params_rf, cv=5)#fit model to training data
rf_gs.fit(X_train, y_train)
我们将创建一个新的随机森林分类器,并设置我们想要调整的超参数。“n_estimators”是我们的随机森林中的树的数量。然后,我们可以运行网格搜索来找到最佳数量的树。
就像之前一样,我们将保存我们的最佳模型并打印最佳的“n_estimators”值。
#save best model
rf_best = rf_gs.best_estimator_#check best n_estimators value
print(rf_gs.best_params_)

逻辑回归
我们的最后一个模型是逻辑回归。即使它的名字中有“回归”,逻辑回归也是一种分类方法。这个更简单,因为我们不会调优任何超参数。我们只需要创建和训练模型。
from sklearn.linear_model import LogisticRegression#create a new logistic regression model
log_reg = LogisticRegression()#fit the model to the training data
log_reg.fit(X_train, y_train)
现在,让我们检查所有三个模型在测试数据上的准确性分数。
#test the three models with the test data and print their accuracy scoresprint(‘knn: {}’.format(knn_best.score(X_test, y_test)))
print(‘rf: {}’.format(rf_best.score(X_test, y_test)))
print(‘log_reg: {}’.format(log_reg.score(X_test, y_test)))

从输出可以看出,逻辑回归是三者中最准确的。
投票分类器
现在我们已经建立了三个独立的模型,是时候建立我们的投票分类器了。
代码如下:
from sklearn.ensemble import VotingClassifier#create a dictionary of our models
estimators=[(‘knn’, knn_best), (‘rf’, rf_best), (‘log_reg’, log_reg)]#create our voting classifier, inputting our models
ensemble = VotingClassifier(estimators, voting=’hard’)
首先,让我们把我们的三个模型放在一个叫做“估值器”的数组中。接下来,我们将创建投票分类器。它需要两个输入。第一个是我们三个模型的估计数组。我们将投票参数设置为 hard,这告诉我们的分类器通过多数投票进行预测。
现在,我们可以将我们的集成模型拟合到我们的训练数据中,并根据我们的测试数据对其进行评分。
#fit model to training data
ensemble.fit(X_train, y_train)#test our model on the test data
ensemble.score(X_test, y_test)

厉害!我们的集成模型比单独的 k-NN、随机森林和逻辑回归模型表现得更好!
就是这样!您现在已经构建了一个集合模型来组合各个模型!
感谢阅读!本教程的 GitHub 库(jupyter 笔记本和数据集)可以在这里找到。
如果你想了解我的机器学习内容,请关注我:)
机器学习中的集成方法:它们是什么,为什么使用它们?

合奏方法,它们是什么?集成方法是一种机器学习技术,它结合了几个基本模型,以产生一个最佳预测模型。为了更好地理解这个定义,让我们回到机器学习和模型构建的最终目标。随着我深入到具体的例子和为什么使用系综方法,这将变得更有意义。
我将主要利用决策树来概述集成方法的定义和实用性(然而,重要的是要注意,集成方法不仅仅适用于决策树)。

决策树基于一系列问题和条件来确定预测值。例如,这个简单的决策树决定了一个人是否应该在户外活动。该树考虑了几个天气因素,给定每个因素要么做出决定,要么提出另一个问题。在这个例子里,每次阴天的时候,我们都会在外面玩。但是,如果下雨了,一定要问有没有风?如果刮风,我们就不玩了。但是如果没有风,把鞋带系紧,因为我们要出去玩。

决策树也可以用同样的格式解决定量问题。在左边的树中,我们想知道是否投资商业房地产。是写字楼吗?一个仓库?一栋公寓楼?经济条件好?经济条件差?一项投资会有多少回报?这些问题都是用这个决策树来回答和解决的。
当制作决策树时,有几个因素我们必须考虑:我们根据什么特征做决策?将每个问题分类为是或否答案的阈值是什么?在第一个决策树中,如果我们想问自己是否有朋友一起玩呢?如果我们有朋友,我们每次都会玩。如果不是,我们可能会继续问自己关于天气的问题。通过添加一个额外的问题,我们希望更好地定义是和否类。
这就是集合方法派上用场的地方!集成方法允许我们考虑决策树的样本,计算在每次分裂时要使用的特征或要问的问题,并基于样本决策树的聚合结果做出最终预测,而不是仅仅依赖于一个决策树并希望我们在每次分裂时做出正确的决策。
集合方法的类型
- ing,或BootstrapAGGregating。 BAGG ing 得名于它将BBt【17】ot【19】agregion 组合成一个系综模型。给定一个数据样本,抽取多个自举子样本。在每个自举子样本上形成决策树。在形成每个子样本决策树之后,使用算法在决策树上聚集以形成最有效的预测器。下图将有助于解释:**

Given a Dataset, bootstrapped subsamples are pulled. A Decision Tree is formed on each bootstrapped sample. The results of each tree are aggregated to yield the strongest, most accurate predictor.
2.随机森林模式。随机森林模型可以被认为是 BAGG 模型,只是有一点小小的改动。当决定在哪里拆分以及如何决策时,袋装决策树具有可供选择的全部处置特征。因此,尽管引导样本可能略有不同,但数据在很大程度上会在每个模型中的相同要素处中断。相反,随机森林模型根据随机选择的要素来决定在哪里进行分割。随机森林模型实现了一定程度的区分,而不是在每个节点的相似特征处进行分割,因为每棵树都将基于不同的特征进行分割。这种程度的差异提供了一个更大的集合,因此产生了一个更准确的预测。请参考图片,以便更好地理解。

与装袋类似,自举子样本是从更大的数据集中提取的。在每个子样本上形成决策树。然而,决策树在不同的特征上被分割(在该图中,特征由形状表示)。
概括起来
任何机器学习问题的目标都是找到一个能够最好地预测我们想要的结果的单一模型。集成方法不是制作一个模型并希望这个模型是我们能够制作的最好/最准确的预测器,而是考虑无数的模型,并对这些模型进行平均以产生一个最终模型。值得注意的是,决策树并不是集成方法的唯一形式,而是当今数据科学中最流行和最相关的形式。
使用 Keras 组装 ConvNets

编辑:2019 年 2 月
微小的代码更改。改进的体验篇Jupyter 笔记本版。
介绍
在统计学和机器学习中,集成方法使用多种学习算法来获得比单独从任何组成学习算法获得的性能更好的预测性能。与统计力学中的统计集成(通常是无限的)不同,机器学习集成仅由一组具体的有限备选模型组成,但通常允许在这些备选模型中存在更加灵活的结构。【1】
使用集成的主要动机是找到一个假设,该假设不一定包含在构建它的模型的假设空间内。从经验上看,当模型之间存在显著差异时,集成往往会产生更好的结果。【2】
动机
如果你看看一场大型机器学习比赛的结果,你很可能会发现,最好的结果是由一群模型而不是单个模型实现的。例如,ILSVRC2015 上得分最高的单一模型架构排在第 13 位。第 1-12 名由不同的组合占据。
我还没有看到关于如何在集成中使用多个神经网络的教程或文档,所以我决定就这个主题制作一个实用指南。
我将使用 Keras ,特别是它的功能 API ,重新创建三个小型 CNN(与 ResNet50、Inception 等相比)。)来自相对知名的论文。我将在 CIFAR-10 训练数据集上分别训练每个模型。【3】然后,将使用测试集对每个模型进行评估。之后,我会把这三个模型放在一个合奏中进行评估。预计集成在测试集上将比集成中单独的任何单个模型表现得更好。
有许多不同类型的合奏;堆叠就是其中之一。它是更一般的类型之一,理论上可以代表任何其他的系综技术。堆叠包括训练一个学习算法来组合其他几个学习算法的预测。【1】为了这个例子,我将使用一种最简单的叠加形式,它包括取集合中模型输出的平均值。由于平均不需要任何参数,所以不需要训练这个集合(只需要它的模型)。

This post’s ensemble in a nutshell
准备数据
首先,导入依赖项。
from keras.callbacks import History
from keras.callbacks import ModelCheckpoint, TensorBoard
from keras.datasets import cifar10
from keras.engine import training
from keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D, Dropout, Activation, Average
from keras.losses import categorical_crossentropy
from keras.models import Model, Input
from keras.optimizers import Adam
from keras.utils import to_categorical
from tensorflow.python.framework.ops import Tensor
from typing import Tuple, List
import glob
import numpy as np
import os
我使用 CIFAR-10,因为相对容易找到描述在这个数据集上运行良好的架构的论文。使用一个流行的数据集也使得这个例子很容易重现。
在这里,数据集被导入。训练和测试图像数据都被归一化。训练标签向量被转换成独热矩阵。不需要转换测试标签向量,因为它不会在训练中使用。
def load_data() -> Tuple [np.ndarray, np.ndarray,
np.ndarray, np.ndarray]:
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train = x_train / 255.
x_test = x_test / 255.
y_train = to_categorical(y_train, num_classes=10)
return x_train, x_test, y_train, y_testx_train, x_test, y_train, y_test = load_data()
该数据集由来自 10 个类别的 60000 幅 32x32 RGB 图像组成。50000 幅图像用于训练/验证,另外 10000 幅用于测试。
print('x_train shape: {} | y_train shape: {}\nx_test shape : {} | y_test shape : {}'.format(x_train.shape, y_train.shape, x_test.shape, y_test.shape))
>>>x _ train shape:(50000,32,32,3) | y_train shape: (50000,10)
>>>x _ 测试形状:(10000,32,32,3)| y _ 测试形状:(10000,1)
由于所有三个模型都使用相同形状的数据,因此定义一个供每个模型使用的输入图层是有意义的。
input_shape = x_train[0,:,:,:].shape
model_input = Input(shape=input_shape)
第一个模型:ConvPool-CNN-C
我要训练的第一个模型是 ConvPool-CNN-C。
这个模型非常简单。它有一个共同的模式,即几个卷积层之后是一个池层。对于这个模型,有些人唯一不熟悉的是它的最后几层。不是使用几个完全连接的层,而是使用一个全局平均池层。
这里有一个全局池层如何工作的简要概述。最后一个卷积层Conv2D(10, (1, 1))输出对应十个输出类的 10 个特征图。然后,GlobalAveragePooling2D()层计算这 10 个特征地图的空间平均值,这意味着它的输出只是一个长度为 10 的矢量。之后,对该向量应用 softmax 激活。如您所见,这种方法在某种程度上类似于在模型顶部使用 FC 层。你可以在 Network paper 中阅读更多关于全球池层及其在 Network 中的优势。【5】
需要注意的重要一点是:没有激活函数应用于最后一个Conv2D(10, (1, 1))层的输出,因为这个层的输出必须首先通过GlobalAveragePooling2D()。
def conv_pool_cnn(model_input: Tensor) -> training.Model:
x = Conv2D(96, kernel_size=(3, 3), activation='relu', padding = 'same')(model_input)
x = Conv2D(96, (3, 3), activation='relu', padding = 'same')(x)
x = Conv2D(96, (3, 3), activation='relu', padding = 'same')(x)
x = MaxPooling2D(pool_size=(3, 3), strides = 2)(x)
x = Conv2D(192, (3, 3), activation='relu', padding = 'same')(x)
x = Conv2D(192, (3, 3), activation='relu', padding = 'same')(x)
x = Conv2D(192, (3, 3), activation='relu', padding = 'same')(x)
x = MaxPooling2D(pool_size=(3, 3), strides = 2)(x)
x = Conv2D(192, (3, 3), activation='relu', padding = 'same')(x)
x = Conv2D(192, (1, 1), activation='relu')(x)
x = Conv2D(10, (1, 1))(x)
x = GlobalAveragePooling2D()(x)
x = Activation(activation='softmax')(x)
model = Model(model_input, x, name='conv_pool_cnn')
return model
实例化模型。
conv_pool_cnn_model = conv_pool_cnn(model_input)
为了简单起见,每个模型都使用相同的参数进行编译和训练。使用 20 个时段,批次大小为 32(每个时段 1250 步),对于三个模型中的任何一个来说,似乎足以达到一些局部最小值。随机选择 20%的训练数据集用于验证。
NUM_EPOCHS = 20def compile_and_train(model: training.Model, num_epochs: int) -> Tuple [History, str]:
model.compile(loss=categorical_crossentropy, optimizer=Adam(), metrics=['acc'])
filepath = 'weights/' + model.name + '.{epoch:02d}-{loss:.2f}.hdf5'
checkpoint = ModelCheckpoint(filepath, monitor='loss', verbose=0, save_weights_only=True,
save_best_only=True, mode='auto', period=1)
tensor_board = TensorBoard(log_dir='logs/', histogram_freq=0, batch_size=32)
history = model.fit(x=x_train, y=y_train, batch_size=32,
epochs=num_epochs, verbose=1, callbacks=[checkpoint, tensor_board], validation_split=0.2)
weight_files = glob.glob(os.path.join(os.getcwd(), 'weights/*'))
weight_file = max(weight_files, key=os.path.getctime) # most recent file return history, weight_file
使用单个 Tesla K80 GPU 在一个时期内训练这个模型和下一个模型大约需要 1 分钟。如果您使用 CPU,训练可能需要一段时间。
_, conv_pool_cnn_weight_file = compile_and_train(conv_pool_cnn_model, NUM_EPOCHS)
该模型达到了约 79%的验证准确率。

ConvPool-CNN-C validation accuracy and loss
通过计算测试集的错误率来评估模型。
def evaluate_error(model: training.Model) -> np.float64: pred = model.predict(x_test, batch_size = 32)
pred = np.argmax(pred, axis=1)
pred = np.expand_dims(pred, axis=1) # make same shape as y_test
error = np.sum(np.not_equal(pred, y_test)) / y_test.shape[0]
return errorevaluate_error(conv_pool_cnn_model)
> > > 0.2414
第二种模式:全 CNN-C
下一个 CNN,ALL-CNN-C,出自同一篇论文。【4】这款和上一款很像。实际上,唯一的区别是使用跨距为 2 的卷积层来代替最大池层。再次注意,在Conv2D(10, (1, 1))层之后没有立即使用激活功能。如果在该层之后立即使用 ReLU 激活,模型将无法训练。
def all_cnn(model_input: Tensor) -> training.Model:
x = Conv2D(96, kernel_size=(3, 3), activation='relu', padding = 'same')(model_input)
x = Conv2D(96, (3, 3), activation='relu', padding = 'same')(x)
x = Conv2D(96, (3, 3), activation='relu', padding = 'same', strides = 2)(x)
x = Conv2D(192, (3, 3), activation='relu', padding = 'same')(x)
x = Conv2D(192, (3, 3), activation='relu', padding = 'same')(x)
x = Conv2D(192, (3, 3), activation='relu', padding = 'same', strides = 2)(x)
x = Conv2D(192, (3, 3), activation='relu', padding = 'same')(x)
x = Conv2D(192, (1, 1), activation='relu')(x)
x = Conv2D(10, (1, 1))(x)
x = GlobalAveragePooling2D()(x)
x = Activation(activation='softmax')(x)
model = Model(model_input, x, name='all_cnn')
return modelall_cnn_model = all_cnn(model_input)
_, all_cnn_weight_file = compile_and_train(all_cnn_model, NUM_EPOCHS)
该模型收敛到约 75%的验证准确性。

ALL-CNN-C validation accuracy and loss
由于两个模型非常相似,错误率不会相差太多。
evaluate_error(all_cnn_model)
>>>0.260900000000002
第三种模式:网络中的网络 CNN
第三个 CNN 是网络中的网络。【5】这是一篇 CNN 的文章,介绍了全局池层。它比前两个型号小,因此训练起来更快。最后卷积层后没有relu!
我没有在 MLP 卷积层中使用多层感知器,而是使用了 1x1 内核的卷积层。这样,需要优化的参数更少,训练速度更快,我可以获得更好的结果(当使用 FC 层时,无法获得高于 50%的验证精度)。该论文指出,mlpconv 层所应用的功能相当于普通卷积层上的级联跨通道参数池,而普通卷积层又相当于具有 1×1 卷积核的卷积层。如果我对架构的解释不正确,请纠正我。
def nin_cnn(model_input: Tensor) -> training.Model:
#mlpconv block 1
x = Conv2D(32, (5, 5), activation='relu',padding='valid')(model_input)
x = Conv2D(32, (1, 1), activation='relu')(x)
x = Conv2D(32, (1, 1), activation='relu')(x)
x = MaxPooling2D((2,2))(x)
x = Dropout(0.5)(x)
#mlpconv block2
x = Conv2D(64, (3, 3), activation='relu',padding='valid')(x)
x = Conv2D(64, (1, 1), activation='relu')(x)
x = Conv2D(64, (1, 1), activation='relu')(x)
x = MaxPooling2D((2,2))(x)
x = Dropout(0.5)(x)
#mlpconv block3
x = Conv2D(128, (3, 3), activation='relu',padding='valid')(x)
x = Conv2D(32, (1, 1), activation='relu')(x)
x = Conv2D(10, (1, 1))(x)
x = GlobalAveragePooling2D()(x)
x = Activation(activation='softmax')(x)
model = Model(model_input, x, name='nin_cnn')
return modelnin_cnn_model = nin_cnn(model_input)
这个模型的训练速度要快得多——在我的机器上,每个时期 15 秒。
_, nin_cnn_weight_file = compile_and_train(nin_cnn_model, NUM_EPOCHS)
该模型实现了约 65%的验证准确率。

NIN-CNN validation accuracy and loss
这个模型比其他两个更简单,所以错误率有点高。
evaluate_error(nin_cnn_model)
> > > 0。0.3164000000000001
三模型集成
现在这三个模型将被组合成一个整体。
这里,所有三个模型都被重新实例化,并且加载了最佳保存的权重。
CONV_POOL_CNN_WEIGHT_FILE = os.path.join(os.getcwd(), 'weights', 'conv_pool_cnn_pretrained_weights.hdf5')
ALL_CNN_WEIGHT_FILE = os.path.join(os.getcwd(), 'weights', 'all_cnn_pretrained_weights.hdf5')
NIN_CNN_WEIGHT_FILE = os.path.join(os.getcwd(), 'weights', 'nin_cnn_pretrained_weights.hdf5') conv_pool_cnn_model = conv_pool_cnn(model_input)
all_cnn_model = all_cnn(model_input)
nin_cnn_model = nin_cnn(model_input)
conv_pool_cnn_model.load_weights(CONV_POOL_CNN_WEIGHT_FILE)
all_cnn_model.load_weights(ALL_CNN_WEIGHT_FILE)
nin_cnn_model.load_weights(NIN_CNN_WEIGHT_FILE)
models = [conv_pool_cnn_model, all_cnn_model, nin_cnn_model]
集合模型定义非常简单。它使用所有先前模型之间共享的相同输入层。在顶层,集成通过使用Average()合并层计算三个模型输出的平均值。
def ensemble(models: List [training.Model], model_input: Tensor) -> training.Model:
outputs = [model.outputs[0] for model in models]
y = Average()(outputs)
model = Model(model_input, y, name='ensemble')
return model
正如所料,集合的错误率比任何单一模型都低。
evaluate_error(ensemble_model)
> > > 0.2049
其他可能的合奏
为了完整起见,我们可以检查由两个模型组合组成的集合的性能。其中两个模型的错误率低于单一模型。
pair_A = [conv_pool_cnn_model, all_cnn_model]
pair_B = [conv_pool_cnn_model, nin_cnn_model]
pair_C = [all_cnn_model, nin_cnn_model]pair_A_ensemble_model = ensemble(pair_A, model_input)
evaluate_error(pair_A_ensemble_model)
>>>0.211999999999999
pair_B_ensemble_model = ensemble(pair_B, model_input)
evaluate_error(pair_B_ensemble_model)
>>>0.228199999999999
pair_C_ensemble_model = ensemble(pair_C, model_input)
evaluate_error(pair_C_ensemble_model)
> > > 0.2447
结论
重申一下引言中说过的话:每个模型都有自己的弱点。使用集成背后的原因是,通过堆叠表示关于数据的不同假设的不同模型,我们可以找到不在构建集成的模型的假设空间中的更好的假设。
通过使用非常基本的集合,与在大多数情况下使用单一模型相比,实现了更低的错误率。这证明了组合的有效性。
当然,当使用系综来完成机器学习任务时,有一些实际的考虑要记住。由于集成意味着将多个模型堆叠在一起,这也意味着每个模型的输入数据都需要向前传播。这增加了需要执行的计算量,从而增加了评估(预测)时间。如果你在研究或比赛中使用系综,增加评估时间并不重要。然而,在设计商业产品时,这是一个非常关键的因素。另一个考虑因素是最终模型尺寸的增加,这也可能是在商业产品中整体使用的限制因素。
你可以从我的 GitHub 获得 Jupyter 笔记本源代码。
参考
- 集成学习。(未注明)。在维基百科里。检索于 2017 年 12 月 12 日,来自https://en.wikipedia.org/wiki/Ensemble_learning
- D.Opitz 和 R. Maclin (1999 年)流行的集合方法:实证研究,第 11 卷,第 169-198 页(可在http://jair.org/papers/paper614.html获得)
- 从微小图像中学习多层特征 ,Alex Krizhevsky,2009。
- arXiv:1412.6806 v3【cs。LG]
- arXiv:1312.4400 v3【cs。NE]
熵是不确定性的度量
八个性质,几个例子和一个定理

假设你正在医生办公室的候诊室里与三个病人交谈。他们三人都刚刚完成了一项医学测试,经过一些处理后,得出两种可能的结果之一:疾病要么存在,要么不存在。让我们假设我们正在与好奇和面向数据的个人打交道。他们已经提前研究了他们特定风险状况的概率,现在急于找出结果。
患者 A 知道,从统计学上来说,他有 95%的可能性患有所述疾病。对于患者 B 来说,被确诊患病的概率是 30%。相比之下,病人 C 面临着 50/50 的可能性。

Uncertainty in the waiting room
我想着重谈一个简单的问题。在其他条件相同的情况下,三个病人中哪一个面临最大程度的不确定性?
我认为答案是明确的:病人 c。他不仅正在经历“许多不确定性”。他正在经历的是在这种情况下最大程度的不确定性:一个戏剧性的医学版的掷硬币游戏。
与病人 a 相比,当然,整体情况看起来相当严峻,但至少这个病人对他的医疗前景没有多少不确定性。
从直觉上讲,我们能说病人 B 什么呢?也许她的情况属于“中间某处”?
这就是熵产生的原因。将一种情况描述为“中间的某个地方”对于候诊室的谈话来说可能已经足够好了,但是对于机器学习的目的来说,这种描述肯定太粗糙了。
测量不确定性
熵允许我们对生活中最紧迫的问题之一做出精确的陈述和进行计算:不知道事情会如何发展。
换句话说,熵是对不确定性的一种度量。
(它也是一种信息的度量,但是,我个人更倾向于不确定性的解释。可能只是我,但当我不再试图将我对信息的先入为主的观念强加于方程式时,事情似乎变得清晰多了。)
在某种程度上,说熵是“不确定性的度量”是一种轻描淡写。给定某些假设(并预示着下面提到的一个重要结果),熵是不确定性的度量。
顺便说一下,当我使用熵这个术语时,我指的是香农熵。还有很多其他熵,但我认为可以肯定的是,香农熵是自然语言处理和机器学习中使用最频繁的熵。
事不宜迟,这里是一个事件的熵公式 X 有 n 个可能的结果和概率 p_1,…,p_n :

Shannon entropy
基本属性
如果你像我第一次看到这个公式时一样,你可能会问自己这样的问题:为什么是对数?为什么这是一个很好的不确定性的衡量标准?当然,为什么是字母 H ?(显然,使用英文字母 H 是从希腊文大写字母 Eta 演变而来,尽管历史看起来相当复杂。)
随着时间的推移,我学到的一件事是,一个好的起点——在这里和许多其他情况下——是问两个问题:(1)我试图理解的数学构造具有哪些理想的属性?以及(2)它们是具有所有这些期望特性的竞争结构吗?
简而言之,作为不确定性度量的香农熵的答案是:(1)许多和(2)没有。
让我们从愿望清单开始。
基本性质 1:均匀分布具有最大的不确定性
如果你的目标是最小化不确定性,远离均匀概率分布。
快速提醒:概率分布是一个函数,它为每一个可能的结果分配一个概率,使得概率总和为 1。当所有结果具有相同的概率时,分布是均匀的。例如,公平硬币(50%的尾部,50%的尾部)和公平骰子(六个面中的每一个面的概率为 1/6)遵循均匀分布。

Uniform distributions have maximum entropy for a given number of outcomes.
对于均匀分布,不确定性的良好度量达到其最高值。熵满足标准。给定 n 种可能的结果,最大熵由等概率结果最大化:

Equiprobable outcomes
这是应用于伯努利试验的熵函数图(具有两种可能结果和概率的事件 p 和 1-p ):

In the case of Bernoulli trials, entropy reaches its maximum value for p=0.5
基本性质 2:不确定性对于独立事件是可加的
设 A 和 B 为独立事件。换句话说,知道事件 A 的结果并不能告诉我们任何关于事件 B 的结果。
与这两个事件相关的不确定性——这是我们愿望清单上的另一个项目——应该是各个不确定性的总和:

Uncertainty is additive for independent events.
让我们用抛两枚硬币的例子来更具体地说明这一点。我们可以同时掷两枚硬币,或者先掷一枚硬币,然后再掷另一枚。另一种思考方式是,我们可以同时或分别报告两次抛硬币的结果。这两种情况下的不确定性是一样的。
为了使这一点更加具体,考虑两个特殊的硬币。第一枚硬币正面朝上( H )的概率为 80%,反面朝上( T )的概率为 20%。另一枚硬币的概率是 60%和 40%。如果我们同时抛两枚硬币,有四种可能的结果: HH 、 HT 、 TH 和 TT 。对应的概率由【0.48,0.32,0.12,0.08】给出。

The joint entropy (green) for the two independent events is equal to the sum of the individual events (red and blue).
将这些数字代入熵公式,我们看到:

就像承诺的那样。
基本属性 3:添加概率为零的结果没有效果
假设(A)每当结果#1 出现时你就赢了,并且(B)你可以在两个概率分布中选择, A 和 B 。分配 A 有两种结果:比如说 80%和 20%。分布 B 有三种结果,概率分别为 80%、20%和 0%。

Adding a third outcome with zero probability doesn’t make a difference.
给选项 A 和 B ,你会选哪个?此时一个合适的反应是耸耸肩或者翻白眼。包含第三种结果既不增加也不减少与游戏相关的不确定性。 A 还是 B ,谁在乎。没关系。
熵公式同意这种评估:

Adding a zero-probability outcome has not effect on entropy.
换句话说,添加一个概率为零的结果对不确定性的测量没有影响。
基本性质 4:不确定性的度量在其所有论证中是连续的
最后一个基本属性是连续性。
众所周知,对连续函数的直观解释是没有“间隙”或“洞”。更准确地说,输出中任意小的变化(在我们的例子中是不确定性)应该可以通过输入中足够小的变化(概率)来实现。
对数函数在为其定义的每一点上都是连续的。在子集上连续的有限个函数的和与积也是如此。由此可见,熵函数在其概率论证中是连续的。
唯一性定理
钦钦(1957) 表明,满足上述四个基本性质的唯一函数族具有以下形式:

Functions that satisfy the four basic properties
其中λ是正常数。钦钦将此称为唯一性定理。设λ = 1 并使用二进制对数,我们得到香农熵。
再次重申,使用熵是因为它具有令人满意的性质,并且是满足基本愿望清单(性质 1-4)上所有项目的家族函数中的自然选择。(以后我可能会在单独的文章中讨论这个证明。)
其他属性
除了钦钦唯一性定理中使用的四个基本性质之外,熵还有许多其他性质。让我在此仅提及其中一些。
性质 5:具有更多结果的均匀分布具有更多的不确定性
假设你可以在一枚漂亮的硬币和一个漂亮的骰子之间做出选择:

Fair coin or fair die?
假设硬币正面朝上或者骰子正面朝上,你就赢了。
这两个选项你会选哪个?如果你是利润最大化者,A 和 B 如果你喜欢更多的变化和不确定性。
随着等概率结果数量的增加,我们对不确定性的度量也应该增加。
而这正是熵的作用:H(1/6,1/6,1/6,1/6,1/6,1/6,1/6),H(0.5,0.5)。
一般来说,如果我们让 L(k) 是具有 k 个可能结果的均匀分布的熵,我们有

对于 m > n 。
属性 6:事件具有非负的不确定性
你知道什么是负面不确定性吗?我也不知道。
一个用户友好的不确定性度量应该总是返回一个非负的量,不管输入是什么。
这是熵满足的另一个标准。让我们再来看看这个公式:

Shannon entropy
根据定义,概率的范围在 0 和 1 之间,因此是非负的。概率的对数是非正的。概率的对数乘以一个概率不会改变符号。非正乘积之和为非正。最后,非正值的负值是非负值。因此,对于每个可能的输入,熵都不是负的。
特性 7:具有特定结果的事件没有不确定性
假设你拥有一枚神奇的硬币。不管你怎么抛硬币,它总是正面朝上。

A magical coin
你如何量化魔法或任何其他情况下某个结果肯定会发生的不确定性?嗯,没有。所以自然的答案——我想,你会同意——是 0。
熵是否认同这种直觉?当然了。
假设结果肯定会发生。由此得出 p_i ,结果 i 的概率等于 1。 H(X),由此,简化为:

The entropy for events with a certain outcome is zero.
属性 8:翻转参数没有效果
这是另一个明显可取的属性。考虑两种情况。第一种情况,正面和反面的概率分别是 80%和 20%。在第二种情况下,概率正好相反:正面 20%,反面 80%。

两次抛硬币的不确定性相同,熵相同: H(0.8,0.2) = H(0.2,0.8) 。
更一般地说,对于两种结果的情况,我们有:

Flipping arguments
这个事实适用于任何数量的结果。我们可以按照我们喜欢的任何顺序排列论点(即分布的概率)。熵函数的结果总是相同的。
摘要
概括地说,香农熵是不确定性的度量。
它被广泛使用是因为它满足某些标准(也因为生活充满了不确定性)。唯一性定理告诉我们,只有一个函数族具有我们提到的所有四个基本性质。香农熵是这个家族中的自然选择。
除了其他事实之外,熵对于均匀分布是最大的(属性#1),对于独立事件是可加的(#2),对于非零概率的结果数量增加(#3 和#5),连续的(#4),非负的(#6),对于某些结果为零(#7)和排列不变的(#8)。
感谢您的阅读!如果你喜欢这篇文章,请点击“鼓掌”按钮,跟随我了解更多关于自然语言处理和机器学习的知识。
此外,让我知道如果你有一个项目在这两个领域的交叉点,你想讨论。
使用 Conda 的 Python 环境管理(Python 2 + 3,使用多个版本的 Python)
Environment Management with Conda (Python + Configuring Ipython/Jupyter)
遇到类似下图中的 ImportError 可能会很烦人。

幸运的是,Anaconda 使得用 conda 的包管理器功能安装包变得很容易。如果您需要复习,软件包管理器是一个自动安装、更新和删除软件包的工具。虽然 conda 是一个包和环境管理器,但让我们首先回顾一下 Conda 的包管理器功能,然后重点介绍环境管理器功能。
安装包
打开命令提示符/anaconda 提示符(windows)或终端(mac/linux)并运行下面的命令。你可以用numpy替换任何你想安装的包。
conda install numpy
卸载软件包
运行以下命令卸载软件包。您可以用numpy替换您想要卸载的任何包。
conda uninstall numpy
更新包
运行下面的命令来更新包。你可以用scikit-learn替换任何你想更新的包。
conda update scikit-learn
康达 vs 皮普
Pip 是一个 Python 包管理器,代表“Pip 安装包”,通常与 virtualenv (一个用于创建隔离环境的工具)结合使用。
大多数时候(除了一些例外),通过 conda 或通过 pip 安装包没有太大的区别。这是因为 pip 包也可以安装到 Conda 环境中。
conda install numpy
pip install numpy
这不是一个关于 conda 与 pip 的讨论,因为 Jake VanderPlas 已经非常广泛地讨论了这个问题,而是为什么你可以通过 pip 或者 conda 来安装软件包。
为什么需要多个 Conda/Python 环境。
假设你有多个项目,它们都依赖于一个库(Pandas,Numpy 等)。如果您升级一个包,它可能会破坏依赖旧版本包的其他项目,因为旧项目的语法可能会被否决或过时。你该怎么办?建立一个虚拟环境。它允许你从一个项目到另一个项目中分离出将要使用的包、依赖项和版本。
对于 python 用户来说,虚拟环境的一个常见用途是拥有独立的 Python 2 和 3 环境。例如,我在加州大学圣地亚哥分校的几个同学最近开设了一门机器学习课,其中一位教授用 Python 3 来布置作业。不过另一个班有个教授在 Python 2 里布置作业。因此,他们不得不在不同的类项目中频繁地在 python 2 和 3 之间切换。至此,让我们进入 conda 环境命令。我建议您在单独的标签中打开视频,观看命令的运行。
创建新环境
下面的命令在 python 版中创建了一个名为subscribe的 conda 环境。您可以用subscribe来代替您想要命名的环境。
conda create --name subscribe python=3.6
请记住,一旦激活(进入)该环境,您将需要在该环境中安装额外的软件包。您在根环境中拥有的包不一定就是您将在新环境中拥有的包,除非您安装它们。
您还可以创建一个包含多个包的环境。这也让您可以选择在以后需要时安装额外的软件包。
conda create --name chooseAnotherName python=3.6 numpy pandas scipy
进入环境
如果您的环境名称不是subscribe,您将需要用subscribe替换您的环境名称。
窗口:
activate subscribe
Mac:
source activate subscribe
离开一个环境
如果您的环境名称不是subscribe,您将需要用subscribe替换您的环境名称。
窗口:
deactivate subscribe
Mac:
source deactivate subscribe
列出您的环境
这个命令向您展示了所有这是一个非常有用的命令,可以查看您有什么样的环境,也可以查看您处于什么样的 conda 环境中。
conda env list

移除一个环境
如果您想要删除的环境名称不是subscribe,您需要用subscribe替换您想要删除的环境名称。
conda env remove --name subscribe
如果你对这部分有疑问,请参考文档,留下评论或者参考上面的视频。
在 IPython 笔记本中同时使用 Python 2.x 和 Python 3.x 环境
虽然这篇文章的这一部分很大程度上是从 stackoverflow 中截取和改进的,但我觉得回顾一下人们遇到的一些技术问题是很重要的。主要思想是拥有多个 ipython 内核。包 nb_conda_kernels 会自动检测笔记本内核的不同 conda 环境,并自动注册。
- 确保您安装了 anaconda 4.1.0 或更高版本。打开一个新的终端,通过键入以下命令检查您的 conda 版本

checking conda version
如果你低于 anaconda 4.1.0,输入 conda update conda
2.接下来,我们通过键入以下命令来检查是否有库 nb_conda_kernels

Checking if we have nb_conda_kernels
3.如果没有看到 nb_conda_kernels 类型

Installing nb_conda_kernels
4.如果您正在使用 Python 2 并且想要一个单独的 Python 3 环境,请键入以下内容

py36 is the name of the environment. You could literally name it anything you want.
如果您正在使用 Python 3 并且想要一个单独的 Python 2 环境,您可以键入以下内容。

py27 is the name of the environment. It uses python 2.7.
5.关闭您的终端并打开一个新的终端。jupyter 型笔记本
6.单击 new,您将看到列出了您的虚拟环境。

如果你有任何问题,请在这里或者在 youtube 视频评论中告诉我!
纪元与批量大小与迭代次数
了解您的代码…
你一定有过这样的时候,你看着屏幕,挠着头想知道“为什么我在代码中输入这三个术语,它们之间有什么区别”,因为它们看起来都很相似。

为了找出这些术语之间的区别,你需要知道一些机器学习术语,如梯度下降,以帮助你更好地理解。
这里有一个关于梯度下降的简短总结…
梯度下降
它是一种 迭代 优化算法,用于机器学习中寻找最佳结果(曲线的极小值)。
坡度是指斜坡倾斜或下倾的速率。
下降表示下降的实例。
算法是迭代意味着我们需要多次得到结果才能得到最优结果。梯度下降的迭代质量有助于拟合不足的图形以最佳方式拟合数据。

梯度下降有一个参数叫做学习率。正如你在上面(左图)看到的,最初步长越大,意味着学习率越高,随着点的下降,步长越小,学习率越小。还有,成本功能在降低或者成本在降低。有时候你可能会看到有人说损失功能在减少或者损失在减少,两个 成本 和 损失 代表的是同一个东西(顺便说一句,我们的损失/成本在减少是件好事)。
只有当数据太大时,我们才需要像纪元、批量大小、迭代这样的术语,这在机器学习中是经常发生的,我们不能一次将所有数据传递给计算机。因此,为了克服这个问题,我们需要将数据分成更小的尺寸,并将其一个接一个地提供给我们的计算机,并在每一步结束时更新神经网络的权重,以使其适应给定的数据。
纪元
一个时期是整个数据集仅通过神经网络向前和向后传递一次。
由于一个时期太大,不能一次输入计算机,我们把它分成几个小批。
为什么我们使用一个以上的纪元?
我知道这在一开始是没有意义的——通过神经网络传递整个数据集是不够的。我们需要将整个数据集多次传递给同一个神经网络。但是请记住,我们使用的是有限的数据集,为了优化学习和图表,我们使用了梯度下降,这是一个 迭代 过程。因此,用单遍或一个历元更新权重是不够的。
一个时期导致图中曲线的欠拟合(下图)。

随着时期数的增加,神经网络中改变权重的次数越多,曲线从欠拟合到最优再到过拟合曲线。
那么,什么是时代的正确数字呢?
可惜这个问题没有正确答案。对于不同的数据集,答案是不同的,但是你可以说历元的数量与你的数据的多样性有关…举个例子-你的数据集中只有黑猫还是有更多的多样性?
批量
单个批次中存在的训练示例总数。
注意:批次大小和批次数量是两回事。
但是什么是批呢?
正如我所说的,你不能一次将整个数据集传递到神经网络中。因此,您将数据集分成若干批次、集合或部分。
就像你把一篇大文章分成多个集合/批次/部分一样,比如引言、梯度下降、纪元、批次大小和迭代,这使得读者很容易阅读整篇文章并理解它。😄
迭代次数
要得到迭代次数,你只需要知道乘法表或有一个计算器。😃
迭代是完成一个历元所需的批数。
注:批次数等于一个历元的迭代次数。
假设我们有 2000 个将要使用的训练示例。
我们可以将 2000 个例子的数据集分成 500 个一批,然后将需要 4 次迭代来完成 1 个时期。
其中批量大小为 500,迭代次数为 4,用于 1 个完整的历元。

关注我在媒体获得类似的职位。
在脸书、推特、 LinkedIn 、 Google+ 上联系我
如果你有任何意见或问题,请写在评论里。
鼓掌吧!分享一下!跟我来。
乐意帮忙。荣誉……..
你会喜欢的以前的故事:
每个数据科学爱好者的 MCTS
towardsdatascience.com](/monte-carlo-tree-search-158a917a8baa) [## 强化学习中的政策网络与价值网络
在强化学习中,代理在他们的环境中采取随机决策,并学习选择正确的决策…
towardsdatascience.com](/policy-networks-vs-value-networks-in-reinforcement-learning-da2776056ad2) [## 神经网络中的激活函数及其类型
它是一条曲线(sigmoid,tanH,ReLU ),用于映射有界值之间的网络值。这就完成了…
theffork.com](https://theffork.com/activation-functions-in-neural-networks/) [## 如何使用 Python 发送电子邮件
使用 Flask 设计专业邮件!
medium.com](https://medium.com/@sagarsharma4244/how-to-send-emails-using-python-4293dacc57d9) [## TensorFlow 图像识别 Python API 教程
在带有 Inception-v3 的 CPU 上(以秒为单位)
towardsdatascience.com](/tensorflow-image-recognition-python-api-e35f7d412a70)
错误分析拯救你!
修复算法中的错误时应遵循的策略
欢迎来到 ML 第三章 Ng 的经验教训!是的,这是完全基于吴恩达最近在 Coursera 上的课程的系列的延续。虽然这个帖子可以是一个独立的学习,但阅读前面的两篇文章只会有助于更好地理解这一篇。这里是这个系列的第一篇和第二篇的链接。我们开始吧!
当试图解决一个新的机器学习问题(已经没有太多在线资源可用的问题)时,吴恩达建议先快速构建一个系统,然后再迭代。建立一个模型,然后反复识别错误,并不断修正它们。如何发现错误以及如何修复它们?正当你这样想的时候,错误分析穿着一件巨大的长袍,长长的胡须插在腰带下,戴着半月形眼镜,说道——
“是误差,哈利,向我们展示了我们的模型到底是什么,远远超过了准确性”

为什么要进行误差分析?
当建立一个新的机器学习模型时,你应该尝试并遵循以下步骤
设置目标:设置开发/测试集,并选择一个评估指标来衡量性能(参见第一篇文章)
快速建立初始模型: 1。使用训练集进行训练—调整参数
2。开发设置—调整参数
3。测试集—评估性能
区分后续步骤的优先顺序: 1。使用偏差和方差分析处理欠拟合和过拟合(参考第二篇文章)2。分析导致错误的原因并修复它们,直到您准备好所需的模型!
手动检查算法正在犯的错误可以让你了解下一步该做什么。这个过程叫做误差分析。举个例子,你建立了一个显示 10%测试误差的猫分类器,而你的一个同事指出你的算法把狗的图像误分类为猫。你应该试着让你的猫分类器在狗身上做得更好吗?
要修复哪个错误?
与其花上几个月的时间去做这件事,冒着最后发现它没什么用处的风险,这里有一个错误分析程序,可以让你很快判断出这是否值得你去努力。
- 获取大约 100 个标签错误的开发集示例
- 数数有多少只狗
- 如果你只有 5%的狗图片,而你完全解决了这个问题,你的误差只会从 10%下降到 9.5%,最多!
- 相比之下,如果你有 50%的狗图片,你可以更乐观地改善你的错误,并有希望将其从 10%减少到 5%
这就是你如何评价错误修复的单一想法。以类似的方式,您可以通过创建一个网格来评估多个想法,并选择最能提高性能的想法-

The ceiling of error correction for blurry images is pretty good and should be fixed first
这个过程的结论给你一个估计,在这些不同类别的错误上工作是多么值得。例如,这里很明显,我们犯的很多错误是在模糊的图像上,然后是很棒的猫图像。这给你一种追求最佳选择的感觉。
它还告诉你,无论你在狗狗图片或 Instagram 图片上做得有多好,你最多只能提高 8%或 20%的表现。因此,根据你有多少提高大猫或模糊图像性能的想法,你可以从这两个中选择一个,或者如果你的团队有足够的人员,也许你可以让两个不同的团队独立研究其中的每一个。
现在,如果在模型构建过程中,您发现您的数据中有一些标注不正确的数据点,您该怎么办?
标签不正确的数据
训练集校正
深度学习算法对训练集中的随机错误非常鲁棒。只要这些错误是无意的,并且是随机的,就不要花太多时间去修复它们。举个例子,在我们的猫分类器的训练集中有一些错误标记的狗图像。
然而!然而,深度学习算法对系统错误并不鲁棒,例如,如果你将所有白色狗图像标记为猫,你的分类器将学习这种模式。
开发/测试集校正
您还可以选择在开发/测试集上进行错误分析,以查看有多少百分比的错误标签,以及是否值得修复它们。如果您的开发集误差为 10%,并且由于错误标记的开发集图像而导致这里有 0.5%的误差,那么在这种情况下,尝试修复它们可能不是很好的利用时间。相反,如果有 2%的 dev 集误差,0.5%的误差是由于错误标记的 dev 集,那么在这种情况下,修复它们是明智的,因为它占总误差的 25%。
对于错误标记的图像,您可以选择只修复训练集,而不修复开发/测试集。在这种情况下,请记住,现在,您的训练集和开发/测试集都来自稍微不同的发行版。这没关系。让我们谈谈如何处理训练集和开发/测试集来自不同发行版的情况
不匹配的培训和开发/测试集
不同发行版的培训和测试
假设你正在构建一个应用程序,从用户点击的图片中对猫进行分类。你现在有两个来源的数据。首先是来自网络的 200,000 张高分辨率图片,其次是用户点击的应用程序上的 10,000 张不专业/模糊的图片。
现在,为了让培训和开发/测试集具有相同的分布,您可以将来自两个源的图像混洗,并在两个组之间随机分布。然而,在这种情况下,您的 dev set 在 2500 个图像池中只有大约 200 个来自移动用户的图像。这将优化你的算法,在网页图像上表现良好。但是,开发/测试集的理想选择是拥有它们,以便反映您期望在未来获得的数据,并认为做好这些数据是重要的。
我们在这里可以做的是,让开发/测试集中的所有图像都来自移动用户,并将来自移动用户的剩余图像与 web 图像一起放入训练集中。这将导致培训和开发/测试集中不一致的分布,但从长远来看,这将让您达到您想要的目标。
数据分布不匹配时的偏差和方差
当训练集与开发集和测试集来自不同的分布时,分析偏差和方差的方法会发生变化。由于显而易见的原因(它们已经来自不同的发行版),您不能再将 train 和 dev 之间的误差称为方差。在这里,您可以做的是定义一个训练开发集,它将与训练集具有相同的分布,但不会用于训练。然后你可以分析你的模型,如下图所示-

Data mismatch error will get added to the variance if Training-Dev set is not defined
结论
了解你的机器学习算法的应用,相应地收集数据,随机拆分训练/开发/测试集。想出一个单一的优化评估指标,并调整你的旋钮,以改善这一指标。使用偏差/方差分析来了解您的模型是过拟合还是欠拟合,或者在那里工作得很好。跳到错误分析,确定修复哪个最有帮助,最后,努力把你的模型设置正确!
这是这个系列的最后一篇文章。感谢阅读!希望它能帮助你更好地处理你的错误。
如果您有任何问题/建议,请随时在这里提出您的意见或通过 LinkedIn / Twitter 与我联系
选民价值观的错误和不确定性
在过去的几个月里, Paula Surridge 写了两篇非常棒的博客 帖子探讨选民的价值观、他们在欧盟公投中的投票以及他们更普遍的投票模式之间的关系。Nick Barlow 有一篇关于中间派和自由民主党的类似文章,也很有趣。如果你还没有读过,它们非常值得你花时间去读。
我想谈谈 Paula 的一些观点,但更详细地谈谈我们如何衡量选民的价值观和态度。特别是,我想比较一下求和反应和项目反应理论(IRT) 方法。关于 IRT 是如何运作的,我就不多赘述了。如果你感兴趣,这本书提供了很好的介绍。
这两种方法都源于同一个问题:衡量态度真的很难。正如尼克所说,让受访者在左右、授权或其他尺度上自我认同充满了问题。更重要的是,它假设了一些人可能不具备的政治成熟度,并忽略了受访者更有可能选择中间或极端的价值观。
为了解决这个问题,调查设计者提出了一些问题,他们认为这些问题代表了他们要测量的东西。让我们以保拉讨论的威权-自由主义光谱为例。为了衡量这一点,BES 询问受访者对五种说法的认同程度,范围从“1。强烈不同意"对 "5。非常同意”。这些是:
- 今天的年轻人对传统的英国价值观不够尊重
- 对于某些罪行,死刑是最合适的判决
- 学校应该教孩子服从权威
- 对电影和杂志的审查是维护道德标准的必要手段
- 违法的人应该被判更严厉的刑罚
最常见的是,我们通过简单地将这些回答相加来得出总量表。虽然这很容易,并且经常提供足够好的结果,但是它有两个主要问题。首先,它只在回答者回答了所有问题的情况下有效。如果这样做需要政治上的老练,我们就冒着排除不太懂政治的受访者的风险。这反过来会使我们的结果产生偏差。第二,求和将有序分类变量视为度量变量,并假设所有项目提供相同数量的信息,以将受访者置于感兴趣的范围内。这种假设有时可能是正确的,但在问题的难度不同或回答模式有偏差的情况下就不太可能了。
IRT 采取了不同的方法。它使用了相当于豪华的逻辑回归来定位潜在规模的每个受访者。因此,IRT 没有很多与求和相关的问题。例如,它可以估计位置,即使回答者没有回答所有的问题。它还允许不同的项目在定位回答者时提供不同数量的信息。但在我看来,IRT 最好的一点是它是基于模型的。因此,它给出的估计是概率。这意味着我们不仅可以计算出我们认为某人坐在秤上的位置,还可以计算出我们对自己的计算有多确定。
一些实证结果
为了比较求和法和 IRT 法,我运行了三个逻辑回归来预测基于选民年龄、性别和授权位置的脱欧投票。模型 1 使用总和值,模型 2 使用分级反应模型(一种 IRT)的分数,模型 3 使用这些分数加上它们的测量误差。这些模型还不够强大,不足以出现在美国政治科学杂志上,但对我们的目的来说已经足够好了。
在这些模型中包括测量误差通常是困难的,如果不是不可能的话。幸运的是,R拥有优秀的brms包,让这一切成为可能(也很容易!).brms也有一个非常棒的功能,可以产生边际效应图,我已经在下面列出来了。为了便于比较,我对 auth-lib 总排名进行了 z 标准化。



Marginal effects of auth-lib scale placement on probability of voting Leave using Left — summed responses, Centre — factor scores from a graded response model, 3 — the same factor scores, plus measurement error.
从第一个和第二个图中可以看出,使用求和值和 IRT 分数的模型之间几乎没有区别。第一个模型中授权库位置的 1 个标准差变化导致离开投票的 1 个对数优势变化,相比之下,第二个模型中的 1.07 个对数优势变化。让我们暂时回到现实世界,这意味着这两个模型预测,auth-lib 值为 1 的人投票离开的可能性分别是得分为 0 的人的 2.7 倍和 2.9 倍。
然而,在模型中包含误差会导致不同的结果。不仅曲线更陡,而且我们的估计还包含更多的不确定性(如灰色置信带所示)。如你所料,更陡的曲线意味着更大的系数。在这种情况下,模型预测 auth-lib 位置中 1 个标准偏差的变化导致 1.51 个对数几率的变化。因此,我们应该预计 auth-lib 值为 1 的人投票脱离的可能性是 auth-lib 值为 0 的人的 4.5 倍。与之前模型的估计相比,这是一个很大的差异,并且表明 auth-lib 的放置比我们想象的更重要。
不仅影响更大,而且第三个模型的 R 值也更高,这表明它占了投票假期差异的更大部分。模型 3 解释了脱欧投票中约 25%的差异,而模型 1 和 2 分别为 21%和 20%。
“求和”完毕
我在这里的观点不是鼓吹测量。我确实认为它非常重要,但是,正如我前面所说的,总和值通常足够好,我不嫉妒任何人使用它们。然而,我确实希望这篇短文能激励研究人员对测量可能对他们获得的估计值的可靠性产生的影响保持谨慎。
这一点对于精确度尤为重要。例如,如果您的模型是一个政策决策的基础,您可能会考虑选择更接近模型 3 的模型,该模型利用了所有可用的信息。这可能很耗时,也更有技术含量,但可能会导致更可靠的估计。如果你有这样的倾向,这可能也值得考虑进行更多的一般性研究。你永远不知道,如果这种分析是可靠的话,这种影响可能比你最初想象的更重要!
每个 ML 工程师都需要知道的基本算法

在深度神经网络接管场景之前,机器学习作为一个领域已经存在了很长时间。这里有一个你需要知道的算法列表,这样你就可以解决任何遇到的问题。这不是一个详尽的列表,但是你的基础将会被覆盖。
我还想宣布,我的媒体博客将从一般的机器学习焦点转变为深度学习焦点。我现在的大部分工作都涉及到创建新颖的深度学习系统,所以我想花更多的时间来写这方面的东西!
回归算法

回归算法模拟变量之间的关系。最初是一种来自统计学的技术,它们已经成为每个机器学习工程师工具箱中的重要工具。
常见回归算法
- 最小二乘回归
- 线性回归
- 逻辑回归
约翰霍普金斯大学关于回归模型的 Coursera 课程
聚类算法

聚类算法可以将数据点分成具有相似属性的组。他们通过寻找数据中的内在结构来将数据组织到不同的组中。群体中的事物比其他群体中的事物相互之间的联系更紧密。
有两种类型的聚类算法。硬聚类是指数据点是否在一个组中。软聚类是指一个数据点可以不同程度地属于多个不同的组。
常见聚类算法
- k 均值
- 分层聚类
令人惊叹的集群介绍视频
降维算法

当特征的数量与数据点的数量相比非常大时。降维算法可以帮助您将特征的数量减少到手头问题所需的数量。它们可以删除多余或无用的功能,帮助您获得更好的结果。
降维算法有两种工作方式。第一种方法是通过特征选择,其中算法挑选可用特征的子集。第二种方法是特征提取,将高维空间中的数据降低到一个较低的维度。
常见的降维算法
- 主成分分析
- 低方差滤波器
- 高相关滤波器
- 随机森林
- 反向特征消除/正向特征构建
这不是一个详尽的列表,只是我用过的一些。如果你想进一步了解这方面的内容,也想看看这些算法的投资回报率,请查看 KDnuggets 的博客文章。
决策树算法

决策树根据数据中的值创建决策模型。在树结构中进行分叉,直到对每个数据点都有预测。与其他算法(深度学习)不同,他们的结果易于理解,并且易于在许多不同的数据类型上使用。
常见的决策树算法:
- 分类和回归树
- C4.5 和 C5.0
- 随机森林
- 卡方自动交互检测器
Analytics Vidhya 有一篇很棒的文章,深入探讨了决策树。列出不同的算法及其优缺点
深度学习

机器学习和“AI”背后的炒作是深度学习造成的。它们是人工神经网络的现代版本,利用廉价的计算来训练更大的神经网络。它们是强大的通用函数近似值,已经证明它们有能力解决一些最困难的问题。参见阿尔法围棋。
通用深度学习人工智能
- 堆叠式自动编码器
- 卷积神经网络
- 递归神经网络
- 胶囊网络(更多信息在此)
查看这本书的片段。它介绍了深度学习的主要架构。
减去
如果你对机器学习很认真,你必须了解你可以使用的工具。对这些工具有一个很好的理解将会帮助你解决你遇到的任何问题。
基本数据技能——就业市场上的供给和需求
深入了解 Kaggle 数据科学调查结果


The Data Science Community on Kaggle
Kaggle 数据科学调查
如果你错过了,不要担心,你可以明年加入我们。拥有超过 20,000 名受访者的 Kaggle ML & DS 2018 是迄今为止对数据科学界状况进行的最重要、最广泛的调查之一。该数据集包含超过 50 个问题的答案,其中许多是多项选择甚至是自由文本,因此对于数据爱好者来说有一个巨大的游乐场可以探索。这篇文章是我作为 Kaggle 调查 2018 年挑战的一部分所做的内核的抄本。
我们就业吧!
这项研究的主题是就业能力,所以我的大部分探索将集中在社区的一个相当大的子集:那些已经就业并目前活跃在数据科学领域主要角色之一的人。
就业能力 ,名词
拥有就业市场上急需的技能。
在第一部分,我将使用精选的调查数据回答如下问题:
- 在数据科学领域,哪些是最重要的角色?
- 这些角色的个性特征是什么?
- 是什么让他们与众不同,与众不同?
- 对他们中的每一个人来说,最需要的技术技能是什么?
我认为,这些问题的答案与学生、失业者以及任何计划职业转型或简单提升自己的人尤其相关。希望这个内核的读者不同意下面的观点:
“我是学生,请不要问这些问题”
27 号回应者以自由形式回应
在第二部分中,我将重点关注每个角色特定的技术堆栈,比较它们在就业市场上的供求,并确定最有用的技能。
选择正确的角色
如果你是一名学生或刚刚开始职业生涯,仍然不确定要瞄准的技术技能,或者如果你是一名经验丰富的数据科学家,正在寻找提高就业市场机会的方法,第一步是确定所有可能性,并探索它们之间的差异。
绘制社区地图
我通过输入缺失值、转换为虚拟变量和标准化数值来清理数据。然后,我使用 LDA 执行监督的降维并将结果特征向量映射到一个二维空间,同时马锡明聚类的分离。我在 LDA 中使用的特征集是基于我认为最能预测一个人日常工作活动的问题。
对产生的主成分的解释和轴的命名是高度主观的,因为它是多个特征的加权组合,并且可能太复杂而无法用简单的词语来描述。基于各个小组的最终位置,我喜欢将 PC1(水平)视为业务(左)对代码(右)轴,将 PC2(垂直)视为工程(底部)对研究(顶部)轴。
这些角色相对于彼此处于什么位置?
正如你可能注意到的第一张图片,集群明显重叠,这些角色的定义非常模糊。例如,数据分析师和业务分析师角色拥有大部分相同的特征,但在应用分析得出的结论方面略有不同。尽管有重叠,星团质心的位置揭示了一些有趣的模式。气泡的大小代表了群体的大小。

观察结果:
- 营销和业务角色在图表的中心左侧区域形成一个集群组,离密切相关的管理集群不远,这些集群使用数据分析师提供的报告和分析来做出数据驱动的业务决策。
- 学术角色,即首席研究员、研究研究员和研究科学家在图表的顶部中间部分形成一个紧密的集群组。从技术角度来看,他们与数据科学家的角色最为相似。
- 学生群体与其他学术角色关系密切,明显偏向于更实用的工程相关群体。
- 数据库工程师比预期的距离数据工程师集群更远。原因可能是这些角色包括大量的查询、报告生成和数据维护,这与业务集群组的工作更密切相关。
- 学生,以及首席执行官和顾问是数据科学社区中真正的多面手角色。我想象这些首席执行官作为前数据科学家现在领导一个人工智能或大数据驱动的创业公司。
他们每天都在做什么?
让我们通过工作方法来探讨这些角色。对于前 5 个类别,我计算了认为某项活动重要的人的百分比。
哪些活动是你工作中的重要组成部分?
由于代码编写的重要性,答案以百分比给出,所以我直接使用它们。
Q23:你在工作或学校中大约有百分之多少的时间是花在主动编码上的?
彩色条表示与平均值的偏差,单位为百分点。方框旁边的小圆点表示该值是相关行中的最大值(蓝色)或最小值(红色)。

Main Activities
观察结果
- 这两个问题完美地抓住了角色的本质。大多数角色都有一个优点,数据科学家是个例外。他们对每一项活动都给予了高于平均水平的重视,并且是构建和探索 ML 解决方案的明确领导者。这支持了数据科学家应该精通多个领域的先入之见。
数据管道
现在让我们看看数据管道的每一步花费了他们多少时间。
Q34 —在数据科学项目中,您大约有多少时间用于以下活动?

Working on the data pipeline
观察结果:
- 数据清理是数据管道中最重要的部分。研究科学家和软件工程师是幸运的人,他们的数据被端上了银盘。他们也是花最少时间分析它的人。
工具使用
他们使用什么样的工具和软件?
Q12 —您分析数据的主要工具是什么?

Tool Usage
观察结果
- 统计学家在高级统计学领域遥遥领先。
- 研究科学家是使用其他类型软件包的领导者,这些可能是他们用于生物信息学、物理学、数学的特定领域软件。
黑盒模型?
不要。你只是学习不够!

Black box models
观察结果
- 统计学家是拥有最多万事通和一无所知类型的领导者。
- 几乎每个数据科学家都对 ML 模型有多不透明或多黑有自己的看法,有点令人惊讶的是,数据分析师对这个问题最不感兴趣。
我离成为数据科学家还有多远?
让我们以数据科学家角色为参考,探讨其他角色与之相关的方式。问题 26 的答案有助于我们评估每个人的自我评估:
Q26 —你认为自己是数据科学家吗?

Self assessment
观察结果:
- 请注意,两个答案中的角色顺序完全相同。能够深刻理解机器学习模型是数据科学家的必备技能。
- 0 轴左侧的数据科学家是自我怀疑者。他们第一次被问到的时候挑了数据科学家的头衔,但是第二次面对问题的时候开始质疑自己的真实身份:“真的?你呢。看看你自己!你认为自己是数据科学家?”
我们可以通过计算聚类质心之间的欧几里德距离,使用我们的 LDA 特征空间来估计每个角色与数据科学家角色的相似性。
现在,我们已经对每个角色需要什么有了一个大致的概念,并且已经看到了他们看待自己的方式,让我们彼此对照一下“自我评估”、感知的相似性以及每个角色与数据科学家角色之间的实际相似性。
气泡的大小代表团队的规模,X 轴代表团队到数据科学家角色的距离,通过自我评估(Q26 —你是数据科学家吗?),Y 轴代表小组到数据科学家角色的距离。

Self assessment vs. workflow similarity
观察结果:
- 大多数统计学家似乎认为自己是数据科学家,尽管上面的图表强调了这些差异。
- 另一方面,数据工程师似乎没有意识到他们的工作与 T42 的数据科学家有多么相似。
选择正确的技能
在接下来的几行中,我将深入挖掘关于数据科学就业市场的数据。我将 Kaggle 的调查数据与我目前正在处理的一个更大的数据集的一部分结合起来,这个数据集由 1500 多个与技术栈信息相关的数据职位组成。这些帖子是从过去两年的 StackOverflow 中搜集来的。我保留的唯一信息是标题和技术栈。将这组数据与调查结果进行比较,给了我一个绝佳的机会来探索社区如何满足数据工作市场的技能需求。
数据科学家的进化
数据科学是一个蓬勃发展、快速发展的领域,大多数相关技术和框架都是最近才出现的,尚未成熟。例如 Tensorflow ,符号数学和神经网络技术的领导者,仅在 3 年前发布。鉴于数据科学技术堆栈的极度动态性,我将只关注 10 年经验以下的开发人员。我认为,在这个水平之上,技术栈在就业能力中发挥的作用越来越小,对掌握一套特定语言和技术的期望让位于不太可测的技能,如架构、管理、特定领域的经验等等。
因此,让我们看一下数据科学家的技能堆栈如何随着时间的推移而发展。我假设从零技能的“空白页面”开始,但是很少出现这种情况。通常,在开始使用代码进行数据分析之前,人们已经熟悉了一些编程语言。
我根据个人经历创建了 5 个小组:
- 实习生—不到 1 年
- 初级——1-2 岁
- 中级—3-5 年
- 高年级—5-10 岁
- 经验丰富—超过 10 年

Number of tech skills per experience level
观察结果
- 学习曲线在开始时非常陡峭,但在高级阶段达到平稳。
- 有趣的是,编程语言是知识不会随着年龄增长而减少的一个类别。数据科学中使用的大多数语言已经存在了很长时间。 SQL (1974) , [Python (1991)](https://en.wikipedia.org/wiki/Python_(programming_language) , [Java (1995)](https://en.wikipedia.org/wiki/Java_(programming_language) 。
他们需要的技能
为了了解故事的另一部分,我们来看看与数据相关的职位发布的要求。我使用的原始数据集包含 30,000 多个条目。选择与数据科学领域相关的数据并不是一个简单的过程。我试图将选择限制在那些包含机器学习、数据科学或大数据相关术语的范围内。过滤后的结果可以在我发布在 Kaggle 上的数据集里找到。以下是需求数量百分比的细分:

Number of skills required in job postings
观察结果:
- 快速浏览一下数据就会发现,超过 88%的职位描述要求至少具备 3 种不同的技能。超过 60%的人提到了申请人应该熟悉的 5 个不同的术语。
时间是有限的,所以我们必须仔细决定在哪些技能上投资,以使我们在就业市场上的机会最大化。下一节将通过分析这些技能在数据集中的出现频率来帮助我们选择这些技能。
学习 Python。没有借口。
我按照熟悉相关技术的用户百分比(供应)和提及该技术的工作需求百分比(需求)来可视化前 50 项技术。出现在两个列表中的技术用灰色丝带连接。灰色的技能是供应或需求栏中缺少的技能。
我决定不包括一些我觉得过于笼统的术语,但尽管如此,这些概念仍然是雇主要求的 50 件最重要的事情之一。按重要性排序:Machine Learning、Big Data、Cloud、Sys Admin、Agile、Algorithm、NoSQL、Database、Data Science、REST、Deep Learning、Artificial Intelligence、Web-Services、Testing、Computer Vision、QA、Security、Automation、Design、Microservices、DevOps、Data Warehouse、NLP、Statistics、ETL、Data、ETL、Data

Supply and Demand of tech skills for data-related jobs
按角色划分的技能重要性
每项技能的重要性因角色而异,因此,尽管有一个概述很有用,但按职位细分供应和需求给了我们更有价值的洞察力:

Supply and Demand by role
观察结果:
- 学习 Python 。没有借口。熊猫和 Numpy ,它最重要的数据争论库也出现在 50 强名单中。
- 大多数 T42 IDE、笔记本和数据可视化库在工作要求中从未提及。
- 另一方面, Hadoop 、 Spark 和 Elasticsearch 是就业市场上最受欢迎的技术,但在调查中没有提到。其他出现在前 50 名的大数据技术还有: Hive 、 Cassandra 、 Kubernetes 和 Kafka 。
- Java 很重要,但是它在全球排名中的重要性可能被数据集中的大部分软件工程工作夸大了。同样的还有 Javascript 、 React 和 Angular 。之所以选择这些职位,是因为它们在某种程度上构成了数据管道的一部分,但它们往往夸大了一些技术在名单中的存在。
- 没有对操作系统的使用情况进行调查,但是需要注意的是,在所有与数据相关的工作需求中,超过 5%的需求提到了 Linux。
- Tableau 在数据可视化工具的调查中没有被提及,尽管基于 Google Trends ,它比最受欢迎的 Python dataviz 工具 Matplotlib 受欢迎程度高两倍多。它不受语言限制,用途广泛,易于学习,并且正在崛起。
- Git 和 T42 Docker 在我看来是不可或缺的工具。尽管它们只出现在列表的下半部分,但它们应该是开发人员首先需要掌握的技能之一。
学习顺序
没有哪个头脑正常的人会通过使用 MapReduce 或 Hadoop 来开始学习编程。他们说,在开始写小说之前,你首先需要学习 ABC。那么,如果学习这些技能有一个自然的顺序,我们能从数据中揭示这种潜在的顺序吗?
关联规则可能会给我们一些答案。关联规则挖掘的目标是根据项目的单独出现概率和同时出现概率来识别项目之间的共现模式。例如,如果 RStudio 出现在几乎所有出现 R 的堆栈中,但反之则不成立,我们可以假设 R 是 RStudio 的先决条件。这是一个在预定义的置信度阈值之上识别的关联的图表,边的权重表示置信度,节点的大小和垂直位置都表示特定技能的出现频率。

Tech skill learning order
观察结果
- 大多数确定的关联似乎是有效的先决条件关系,例如 Seaborn 是作为对 Matplotlib API 的抽象构建的,没有 RStudio 就没有 Shiny 。其他的,例如张量流 — Caffe 是竞争关系,其中更受欢迎的选择(在这种情况下张量流)通常在学习不太受欢迎的之前已经被探索过。
- Xgboost 、 lightgbm 和 catboost 是先进的合奏工具,可以等到你觉得受到 ScikitLearn 提供的可能性的限制。
数据科学家技术堆栈
现在让我们来看看每个经验等级最有可能的筹码数量。我们将使用一个简单的指标来衡量这一堆人的就业机会:我们得到1 分了解需求集的第一个技能,2 分第二个,3 分第三个,依此类推。这样更深的堆栈将得到适当的推动。最终得分是候选人在每项工作要求中得到的所有分数的总和。
当然,对少数技术的深入了解总是胜过对几种技术的肤浅熟悉,但是深度比广度更难衡量,所以我将坚持根据符合要求的技能数量来比较堆栈。

观察结果:
- 从初级到中级和级之间,最重要的改进是学习第二个数据库提供商。
- 在中级水平和高级水平之间,学习 R 开启了可能性。
现在让我们来看看数据分析师

观察结果:
- 在初级和中级之间张量流给予最大的推动。
- 在中级和高级等级之间,增加了 R 似乎是进步,分数上升到 1500 以上。
我们来玩个游戏吧!
让我们以一个技能数量适中的初级数据工程师的身份开始游戏。我们知道下一级(中级)人员的平均技术水平,所以让我们从每个类别中挑选相同数量的技能,并尝试最大化我们的就业能力。然后,我们会将我们选择的结果与下一个级别人员的平均分数进行比较。

观察结果
- 一个中级数据工程师在 Kaggle 上的平均分是 2198 。另一方面,根据实际需求挑选的技能会得到 2304 的分数。
- Java 显然是新堆栈中得分最高的技术。
- 增加的PostgreSQL和 AWS 红移是一个数据工程师的绝佳选择。
- 将 D3 添加到堆栈中打开了数据可视化的可能性。
- 用 Keras 进行深度学习也是一项抢手的技能。
数据科学技术栈的皇家同花顺
如果我们从一张白纸开始,从零开始选择所有技能来填充高级数据科学家的堆栈,会发生什么?

观察结果:
- 一个资深数据科学家在 Kaggle 上的平均分是 1735 。根据技能需求分数 2469 自由选择相同大小的筹码。
- 栈的核心是 Python 、 Java 和 SQL 。这三项涵盖了所有工作要求的 50%以上。
- 亚马逊网络服务也给了这个堆栈一个很好的提升。
- D3 、 Matplotlib 和 Shiny 涵盖了 Javascript 、 Python 和 R 中最重要的 dataviz 工具。
- PostgreSQL 和 MySQL 是最流行的开源数据库,它们最大化了我们在这个领域的机会。
结论
- 选择合适的角色。如果你喜欢写代码,就成为软件工程师,如果你喜欢数学,就成为统计员,如果你是 DevOps 一类的人,就做数据工程,如果你喜欢数据可视化,做 EDA,就做数据分析师。如果这些你都想要,那就成为数据科学家!
- 选择合适的技能。 Python 、 Java 和 SQL 需求量大。 Git 、 Docker 和 Linux 必不可少。 ScikitLearn 、 Tensorflow 和 Keras 是 ML 库的领导者。 Hadoop 、 AWS 和 Spark 不容忽视。
数据科学的基本数学
成为更好的数据科学家需要掌握的关键主题

Photo: Pekic/E+/Getty Images
数学是任何当代科学学科的基石。几乎所有现代数据科学的技术,包括机器学习,都有深厚的数学基础。
不用说,你绝对需要所有其他的知识——编程……
NLP 任务的基本文本更正过程

“person walking on sea near bridge during daytime” by frank mckenna on Unsplash
在之前的故事中,引入了 Norvig 的算法来纠正拼写错误。它使用了 4 种操作(即删除、转座、替换和插入)。在这个故事中,我想介绍另一种方法,只使用删除操作来找到潜在的正确单词。
在处理文本时,我们可能需要处理不正确的文本。尽管我们仍然可以使用字符嵌入和单词嵌入来计算类似的向量。它对看不见的数据和词汇表之外的东西很有用(OOV)。不过如果能纠正错别字就更好了。
看完这篇帖子,你会明白:
- 对称删除拼写纠正(SymSpell)
- 履行
- 拿走
对称删除拼写纠正(SymSpell)
Garbe 引入了对称删除拼写纠正(SymSpell)。这是一种简单但有用的纠正拼写错误的方法。
在离线训练期间,需要执行预先计算来建立语料库。用编辑距离生成 word(仅删除操作)并将它们与原始项目连接。换句话说,它使用额外的存储和内存资源来节省在线预测时间。如果匹配,新生成的单词将用于搜索并返回原始单词。在线预测时,输入单词经过同样的计算,然后从预先计算的结果中查找。你可以查看这个故事的细节。
速度方面的性能非常好,因为:
- 预计算是离线完成的。
- 在线预测只涉及删除操作和索引搜索(哈希表)

https://github.com/wolfgarbe/symspell
履行
为了方便拼写检查,需要语料库。为了便于演示,我简单地使用了 sklearn 库中的数据集,没有进行预处理。您应该使用特定领域的数据集来为您的数据构建更好的语料库。
建立语料库
from collections import Counter
from sklearn.datasets import fetch_20newsgroups
import recorpus = []
for line in fetch_20newsgroups().data:
line = line.replace('\n', ' ').replace('\t', ' ').lower()
line = re.sub('[^a-z ]', ' ', line)
tokens = line.split(' ')
tokens = [token for token in tokens if len(token) > 0]
corpus.extend(tokens)corpus = Counter(corpus)corpus_dir = '../../data/'
corpus_file_name = 'spell_check_dictionary.txt'symspell = SymSpell(verbose=10)
symspell.build_vocab(
dictionary=corpus,
file_dir=corpus_dir, file_name=corpus_file_name)symspell.load_vocab(corpus_file_path=corpus_dir+corpus_file_name)
修正
results = symspell.correction(word='edwarda')
print(results)
输出是它将“edward”和“edwarda”标识为 1 个距离,而“count”是指原始语料库的频率。
[{'distance': 1, 'word': 'edward', 'count': 154}, {'distance': 1, 'word': 'edwards', 'count': 50}]
除了单词校正,Symspell 还提供了一个复合词的距离计算。
results = symspell.corrections(sentence='Hello I am Edarda')
print(results)
与单字校正不同,复合函数支持拆分和分解操作。有关详细信息,您可以查看符号拼写 API 。
下面的输出计算与原始句子的总距离。给出“你好我是 Edarda”,它发现如果修正为“你好我是 ed 区”最短距离是 3。
[{'distance': 3, 'word': 'hello i am ed area'}]
拿走
要访问所有代码,你可以访问我的 github repo。
- 和拼写校正器一样,符号拼写不考虑上下文,而仅仅考虑拼写。
- 由于方法简单,搜索时间复杂度为 O(1) 为常数时间。
- 允许更大的编辑距离会引入更大的词汇,并导致更大的硬盘和内存消耗,但在当前的资源规模下应该没问题。
关于我
我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。你可以通过媒体博客、 LinkedIn 或 Github 联系我。
参考
C #中的符号拼写(原始)
通过抓取推文找到 2018 年 FIFA 世界杯最喜欢的球队

source: blog.cpdfootball.de
足球运动员和数据科学家的工作展示了相同的工作-生活设置,即技能和意志的组合。
6 月 14 日前夕,一个备受赞誉的所有足球爱好者的宗教节日——2018 年 FIFA 世界杯在俄国拉开帷幕。这个月久负盛名的体育盛宴将在全球范围内庆祝,直到 7 月 15 日的大结局。
抓住这个机会,我测试了我新发现的技能,以判断在给定的比赛中两个竞争团队中谁将是最受欢迎的。
你将在这里学到的东西 :
- 如何从 Twitter 上抓取数据?
- 数据挖掘
先决条件:
- Tweepy 库应该安装在您的计算机上。
2.访问 Twitter。如果您还没有帐户,请创建一个帐户。
抓取文本数据是自然语言处理的一个组成部分。当手头的任务是分析情绪时,Twitter 是一个非常实用的平台。
思维过程:

source: www.nocodewebscraping.com
这就是我们的方法——首先,我们将生成所需的凭证以利用 Twitter API,然后我们将编写 python 代码来提取实时推文,最后我们将通过选择相关的关键字来分析推文。
让乐趣开始吧…
抓取推文的分步指南
A.为 Twitter API 生成凭据:
我。访问 https://apps.twitter.com/的T21,用你的 twitter 凭证登录。**
二。点击创建新应用****
三。输入必要的详细信息,然后点击“创建您的 Twitter 应用程序****
四。在下一页,点击“ API 密钥选项卡,复制您的“API 密钥”和“ API 秘密”。(建议:务必在桌面上贴上这些凭证的便笺)
V 。向下滚动点击“创建我的访问令牌,复制你的“访问令牌”和“访问令牌秘密”。**
B.通过 Python 代码连接到 Twitter API:
下面是您需要的代码,以便连接到 Twitter 上的实时推流,并将它们下载到您的机器上。
- 注意:编码时使用 Python 2.7 版本。
一旦您在命令提示符下执行代码(对于 windows 用户),您将看到下面的数据流。

Live Streaming Tweets
C.分析数据:
在命令行下输入保存下载的推文。
python Twitter _ streaming . py > Twitter _ data . txt
为了理解锦标赛揭幕战的极性方向,我定期(在 6 月 13 日和 14 日)运行该程序两天,以获得相当大且有意义的数据样本。我可以在上面提到的时间段内抓取 79,359 条大小为 450 MB 的推文。

您可以根据业务案例的需要从原始文本中提取尽可能多的见解。比如说。这是写推特的一种语言。在底部找到这个练习的 Jupyter 笔记本。

由于第一场比赛是在东道主俄罗斯和对手沙特阿拉伯之间,我选择了以下关键词。
- 国际足联,世界,世界杯,足球,国际足联世界杯,#FIFA2018
- 世界杯,#WorldCup2018,#FifaWorldCup,
- #FIFAWorldCup,RUSKSA,#RUSKSA,预测,赢,#FIFA。
为了估计这两个帖子中哪一个是最受欢迎的,用#RUS、#KSA 和#鲁斯卡作为目标推文,并分离结果。

Final Outcome
令人惊讶是,比赛结果也与公众情绪一致。当俄罗斯人痛击平庸的沙特人时!
俄罗斯 5 比 0 沙特阿拉伯
多么片面的事情啊!
你还在等什么,还有 63 场比赛要打。玩得开心!!下面是参加本届世界杯的球队的信息图。 在这里 你可以找到所有比赛的赛程。

FIFA WC 2018 Qualified Teams . source: www.Ivacy.com
朱庇特笔记本:
希望你喜欢这篇文章。所以,释放你的爱和情感吧,这将根据你点击拍手图标的次数来估算。# seeyou next time #直到那时***# KeepLearningNewThings*****
参考文献:
更多阅读:
如果你喜欢我的文章,那就花几分钟看看我的其他博客吧-
估计分布:非参数

Taken from here
这篇文章是我深入研究如何优化投资组合配置的系列文章的一部分。本系列解释了我的开源投资组合优化库 OptimalPortfolio 背后的数学和设计原则。第一篇文章是关于寻找市场不变量的。这样做之后,我们现在必须估计市场不变量的分布,以便从中提取有用的信息。
估计数据的统计特性是一个深入研究的领域。困难出现在几个方面:
- 选择我们假设数据是从哪个分布产生的。
- 使得估计器稳健,使得它们对数据的变化不太敏感。
- 将数据拟合到所选择的分布,以有效地获得最佳估计。
- 确保估计值能很好地推广到总体,而不仅仅是样本数据。
在我们进一步讨论之前,我们需要对这里的一些术语进行形式化。
估计量
给定从具有固定参数的某个分布生成的数据样本,

为简单起见,我们假设分布可以完全由均值和方差(或标准差)来表征。现在,估计量实质上是使用样本数据计算的分布的均值和方差的估计。可以想象,这个问题与数据的结构、数据点的数量、数据点是如何生成的以及是否有任何缺失值紧密相关。
考虑到这些问题,有许多方法可以从数据中找到估计值。我将它们分为如下三类:
- 非参数—当有大量数据时,这种方法很有效。
- 最大似然-当数据集较小时,这比非参数更有效
- 收缩-这最适用于高维或非常小的数据集
因为在一篇文章中讨论这三种方法会使文章太长,所以在这篇文章中,我们探讨非参数估计量。在后续文章中,我将深入讨论另外两种估算方法。
非参数的
非参数估计量顾名思义。这些估计量并不局限于任何特定的参数化分布。相反,只考虑数据,并将分布建模为经验分布。经验分布本质上是在每个数据点都有一个核函数的分布。这个核函数被经典定义为狄拉克δ函数。然而,由于使用 Dirac delta 函数进行计算的困难,现代实现考虑高斯核。换句话说,经验分布是对于每个数据点

在我们的例子中,我们让核函数 K 是高斯函数,所以

其中参数γ被认为是平滑参数,它可以被认为是每个数据点处的高斯分布。很容易证明,这种经验分布将产生与样本均值和方差相等的均值和方差。因此,


经验分布似乎很简单,很容易理解。这可以实现为
def sample_mean(invariants, frequency=252):
*"""
Calculates sample mean.
"""
* daily_mean = invariants.mean()
return daily_mean*np.sqrt(frequency)
def sample_cov(invariants, frequency=252):
*"""
Calculates sample covariance
"""*
daily_cov = invariants.cov()
return daily_cov*frequency
当我们试图改进它以解决各种错误时,困难就来了。首先,让我们关注经验分布的局限性。
限制
非参数估计受到许多限制。首先,为了获得真实均值和方差的合理估计,我们需要大量的数据。对数据的大量需求是由于大数定律。该定律指出,随着数据点的数量趋于无穷大,样本均值和样本方差将趋于总体均值和总体方差(有些情况超出了本文的范围)。换句话说,如果我们有一个无限的数据集,那么非参数估计量将是估计总体统计量的最佳方法。然而,在现实生活中,数据并不总是足够的(也不是无限的)。这导致非参数估计失去准确性,成为一个坏的估计。
非参数估计的另一个限制是对数据的敏感性。考虑添加或更改单个数据点会如何影响平均值和方差的估计值。直觉上,一个数据点的微小变化不会显著改变总体的均值和方差。然而,非参数估计的情况并非如此。因为它们完全依赖于数据来导出均值和方差,所以数据点的微小变化会导致估计值的不小变化。这可以用估计量的崩溃点来形式化。估计量的崩溃点被定义为为了改变估计量的值而要改变的数据点的最小比例。这实质上衡量了我们刚才讨论的内容。非参数估计量的崩溃点显然是 1/n,这在稳健统计领域被认为是不好的。
改进非参数
使用非参数估计量的好处是对基础分布的性质没有任何假设。所以,在寻找估计量时,这将给我们最一般的结果。虽然它有局限性,但我们想看看我们是否能保持它的一般性质。
一个可能的扩展是给不同时期的数据一些权重的概念。换句话说,我们对不同时间点的数据有不同的评价。这方面的一个例子是指数加权协方差估计。我最近在这篇文章中读到了这一点,看起来很有希望。这个概念类似于pandas.ewm ,其中每个先前的时间步长被赋予一个较小的权重,通常是小于 1 的某个数的幂。

这可以如下实现
def exp_cov(invariants, span=180, frequency=252):
*"""
Calculates sample exponentially weighted covariance
"""*
assets = invariants.columns
daily_cov = invariants.ewm(span=span).cov().iloc[-len(assets):, -len(assets):]
return pd.DataFrame(daily_cov*frequency)
注意,权重不需要总是指数的或有序的。考虑这样一种情况,您可能想要估计协方差矩阵,但是数据部分中存在一些波动性聚类。一种方法可能是对聚类内的值给予较大的权重,而对聚类外的值给予较小的权重。这种方法的局限性在于,它需要针对每个数据集进行调整,当数据集非常大时,这可能会变得计算量很大。
结论
总的来说,我们发现定义的估计量是生成数据的基础分布的参数的“估计”。然后,我们讨论了有三种类型的估计:非参数,极大似然和收缩估计。我们探讨了非参数估计量以及如何在 python 中实现它。考虑到它的一些局限性,我们从一篇文章中得到启发,提出了指数加权协方差的扩展,并实现了它。
展望未来,我们将探索最大似然估计量,它们如何优于非参数估计量,以及在什么情况下应该使用它们。
估计深度神经网络的最佳学习速率
学习率是用于训练深度神经网络的最重要的超参数之一。
在这篇文章中,我正在描述一个简单而强大的方法来找到一个合理的学习率,这是我从 fast.ai 深度学习课程中学到的。我正在三藩市大学亲自参加新版本的课程。它还没有对公众开放,但将于今年年底在 course.fast.ai (目前有去年的版本)上发布。
学习率如何影响培训?
深度学习模型通常由随机梯度下降优化器训练。随机梯度下降有很多变种:Adam,RMSProp,Adagrad 等。它们都可以让你设定学习速度。该参数告诉优化器在与小批量梯度相反的方向上移动权重的距离。
如果学习率低,那么训练更可靠,但是优化将花费大量时间,因为朝向损失函数的最小值的步骤很小。
如果学习率很高,那么训练可能不收敛,甚至发散。重量变化可能如此之大,以至于优化器超过了最小值,使损失更严重。
训练应该从相对较大的学习率开始,因为在开始时,随机权重远非最佳,然后学习率可以在训练期间降低,以允许更细粒度的权重更新。
有多种方法可以为学习速度选择一个好的起点。一个天真的方法是尝试几个不同的值,看看哪个给你最好的损失,而不牺牲训练速度。我们可以从一个像 0.1 这样的大值开始,然后尝试指数级的低值:0.01、0.001 等等。当我们以较大的学习率开始训练时,当我们运行训练的最初几次迭代时,损失不会改善,甚至可能增加。当以较小的学习速率训练时,在某个点,损失函数值在最初几次迭代中开始下降。这个学习率是我们可以使用的最大值,任何更高的值都不会让训练收敛。甚至这个值也太高了:它不足以训练多个时期,因为随着时间的推移,网络将需要更细粒度的权重更新。因此,开始训练的合理学习率可能会低 1-2 个数量级。
一定有更聪明的方法
Leslie N. Smith 在 2015 年的论文“训练神经网络的循环学习率”的第 3.3 节中描述了一种为神经网络选择学习率范围的强大技术。
诀窍是从低学习率开始训练网络,并为每一批以指数方式增加学习率。

Learning rate increases after each mini-batch
记录每批的学习率和培训损失。然后,画出损失和学习率。通常情况下,它看起来像这样:

The loss decreases in the beginning, then the training process starts diverging
首先,在低学习率的情况下,损失改善缓慢,然后训练加速,直到学习率变得太大,损失增加:训练过程出现偏差。
我们需要在图上选择一个损失减少最快的点。在这个例子中,当学习率在 0.001 和 0.01 之间时,损失函数快速减小。
查看这些数字的另一种方法是计算损失的变化率(损失函数相对于迭代次数的导数),然后在 y 轴上绘制变化率,在 x 轴上绘制学习率。

Rate of change of the loss
它看起来太吵了,让我们使用简单移动平均来平滑它。

Rate of change of the loss, simple moving average
这个看起来更好。在这张图上,我们需要找到最小值。接近 lr=0.01。
履行
杰瑞米·霍华德和他在 USF 数据研究所的团队开发了 fast.ai ,这是一个深度学习库,是 PyTorch 之上的高级抽象。这是一个易于使用但功能强大的工具集,用于训练最先进的深度学习模型。杰里米在深度学习课程的最新版本( fast.ai )中使用该库。
该库提供了学习率查找器的实现。您只需要两行代码来绘制您的模型在学习率上的损失:
该库没有绘制损失函数变化率的代码,但计算起来很简单:
请注意,在训练之前选择一次学习率是不够的。最佳学习率在训练时下降。您可以定期重新运行相同的学习率搜索过程,以便在培训过程的稍后时间找到学习率。
使用其他库实现方法
我还没有看到像 Keras 这样的其他库准备使用这种学习率搜索方法的实现,但是写起来应该很简单。只需多次运行培训,一次一个小批量。每次小批量后,通过乘以一个小常数来提高学习率。当损耗大大高于先前观察到的最佳值时(例如,当当前损耗>最佳损耗* 4 时),停止该程序。
事情还不止这些
选择学习率的起始值只是问题的一部分。另一个需要优化的是学习进度:如何在训练中改变学习率。传统观点认为,学习率应该随着时间的推移而降低,并且有多种方式来设置这一点:当损失停止改善时的逐步学习率退火、指数学习率衰减、余弦退火等。
我上面提到的论文描述了一种循环改变学习率的新方法。该方法提高了卷积神经网络在各种图像分类任务中的性能。
如果你知道训练深度神经网络的其他有趣的技巧和诀窍,请给我发消息。
另请参见:
Fast.ai 是一个非常棒的深度学习课程,适合那些喜欢通过做来学习的人。与其他课程不同,在这里您将…
hackernoon.com](https://hackernoon.com/fast-ai-what-i-learned-from-lessons-1-3-b10f9958e3ff) [## 深度学习新闻的最佳来源
深度学习领域非常活跃,可以说每周都有一两个突破。研究论文…
medium.com](https://medium.com/@surmenok/best-sources-of-deep-learning-news-fbc98815bad3) [## 杰夫·迪恩关于大规模深度学习的演讲
杰夫·迪恩是谷歌高级研究员。他领导谷歌大脑项目。2017 年 8 月在 Y Combinator 演讲。的…
becominghuman.ai](https://becominghuman.ai/jeff-deans-talk-on-large-scale-deep-learning-171fb8c8ac57)
用 Python 中的贝叶斯模型估计概率

(Source)
概率编程在 Python 中的一个简单应用
像最好的项目一样,它从几条推特开始:
Twitter is a great resource for data science!
这似乎是一个简单的问题——患病率与观察到的数据完全相同(50%的狮子,33%的老虎和 17%的熊),对吗?如果你相信我们所做的观察是对潜在真理的完美再现,那么是的,这个问题再简单不过了。然而,作为一个贝叶斯,这种世界观以及随后的推理却令人深感不满。
首先,我们如何确定这一次去保护区的旅行代表了所有的旅行?如果我们在冬天熊冬眠的时候去呢?考虑到有限的数据,我们需要将不确定性纳入我们的估算中。第二,我们如何将先前对形势的信念整合到这个估计中?如果我们从朋友那里听说保护区里每种动物的数量相等,那么这肯定会在我们的估计中起一些作用。
幸运的是,有一个解决方案可以表达不确定性并且将先验信息整合到我们的估计中:贝叶斯推理。
在本文中,我们将在学习概率分布、贝叶斯推理和基本概率规划以及 PyMC3 的过程中,探索在贝叶斯框架中从数据中估计概率的问题。完整的代码可以从 GitHub 上的 Jupyter 笔记本中获得。

PDF and trace values from PyMC3
背景:概念
通常,特别是在统计学中,我发现解决方案背后的理论比实际解决问题更令人困惑。(我相信统计学家为了证明统计数据的存在而将其复杂化。)对我来说,编码一个答案并可视化解决方案通常比阅读无尽的方程更有用。因此,当我着手解决这个问题时,我研究了足够的想法来编码一个解决方案,只有在之后的我才重新挖掘概念。
这反映了我一般的 自上而下学习新话题的方法。不要从基础开始——这通常是乏味和难以理解的——找出如何实现一个想法,这样你就知道为什么它是有用的,然后回到形式主义。所以,如果你觉得自己对这个理论感到沮丧,继续寻找解决方案(从下面的推理部分开始),如果你仍然感兴趣,再回到概念上来。
(这种自上而下的哲学在关于深度学习的优秀 fast.ai 课程中得到了体现。除了有效地教授神经网络之外,这些课程还对我学习新技术的方法产生了影响。)
贝叶斯模型
因为我们想用贝叶斯方法解决这个问题,所以我们需要构建一个情境模型。基本的设置是我们有一系列的观察结果:3 只老虎,2 只狮子和 1 只熊,从这些数据中,我们想估计野生动物保护区中每个物种的流行程度。也就是说,我们正在寻找在给定数据的情况下看到每个物种的后验概率。
在我们开始之前,我们想建立我们的假设:
- 把对一个物种的每一次观察当作一次独立的试验。
- 我们最初(先前)的信念是每个物种都有平等的代表。
整个系统是一个多项分布,其中我们有 3 个离散的选择(物种),每个选择具有未知的概率和 6 个总观察值。多项式分布是二项式分布在有两个以上结果的情况下的扩展。多项式的一个简单应用是掷骰子 5 次,每次有 6 种可能的结果。
具有 3 个离散结果的多项式的概率质量函数如下所示:

Probability Mass Function (PMF) of a multinomial with 3 outcomes
多项式分布的特征是 k,即结果的数量,n,即试验的数量,以及 p ,即每个结果的概率向量。对于这个问题, p 是我们的终极目标:我们想从观测数据中算出看到每个物种的概率。在贝叶斯统计中,多项式的参数向量从形成参数先验分布的狄利克雷分布中提取。
反过来,狄利克雷分布的特征在于,k(结果的数量)和α(称为浓度参数的正实值向量)。这被称为超参数,因为它是先前 的参数。(这个链可以继续下去:如果 alpha 来自另一个发行版,那么这就是一个超优先级,它可以有自己的参数称为超超参数!).我们将通过显式设置 alpha 的值来停止我们的模型,每个结果都有一个条目。
超参数和先验信念
将 Dirichlet 参数向量视为伪计数的最佳方式是,在收集实际数据之前对每个结果进行观察。这些假计数捕捉了我们对情况的先验信念。例如,因为我们认为在进入保护区之前,每种动物的流行程度是相同的,所以我们将所有的阿尔法值设置为相等,比如说阿尔法=【1,1,1】。
相反,如果我们希望看到更多的熊,我们可以使用像[1,1,2]这样的超参数向量(顺序是[狮子,老虎,熊])。伪计数的确切值反映了我们对先前信念的信心水平。较大的伪计数将对后验估计值产生较大的影响,而较小的值将产生较小的影响,并将让数据支配后验估计值。当我们进入推理时,我们会看到这一点,但现在,记住超参数向量是伪计数,反过来,它代表我们先前的信念。
具有 3 个结果的狄利克雷分布如下所示,具有不同的超参数向量值。颜色表示浓度权重。

Effect of the hyperparameter vector alpha on the Dirichlet Distribution (source).
还有很多细节我们不需要在这里深入讨论,但是如果你仍然好奇,可以看看下面列出的一些资源。
我们的最终目标是根据数据和超参数,估计观察到每个物种的概率的后验分布, p :

The posterior distribution of the parameter is our objective. X is observations and alpha is hyperparameters.
我们的最终模型由具有狄利克雷先验的多项式分布组成,称为狄利克雷多项式,如下所示:

Model of problem
下面是问题细节的摘要:

Model specifics
如果你还想要更多的背景细节,这里是我所依赖的一些来源(第一个可能是最有价值的):
来源:
- 狄利克雷多项式的贝叶斯推断
- 分类数据/多项式分布
- 狄利克雷-多项式维基百科文章
- 多项分布维基百科文章
- 狄利克雷分布中的阿尔法
- 狄利克雷分布维基百科文章
- 超参数维基百科文章
- 推导狄利克雷多项式的 MAP 估计
还有其他方法来解决这个问题;艾伦·唐尼的解决方案产生了类似的结果。
推论:从数据中做出估计
现在我们有了问题的模型,我们可以使用贝叶斯方法来求解后验概率。统计学中的推断是从数据中估计(推断)一个概率分布的未知参数的过程。我们的未知参数是每个物种的流行程度,而数据是我们从野生动物保护区观察到的一组数据。我们的目标是找到看到每个物种的概率的后验分布。
我们推导后验概率的方法将使用贝叶斯推理。这意味着我们建立模型,然后用它从后验数据中取样,用马尔可夫链蒙特卡罗 (MCMC)方法近似后验数据。当难以进行精确推断时,我们使用 MCMC,并且随着样本数量的增加,估计的后验收敛于真实的后验。
MCMC 的结果不仅仅是我们答案的一个数字,而是一系列样本,让我们量化我们的不确定性,尤其是在数据有限的情况下。我们将很快看到如何在 Python 中执行贝叶斯推理,但是如果我们想要一个单一的估计,我们可以使用分布的期望值。
预期值
期望值是后验分布的平均值。对于狄利克雷多项式,它可以用解析地表示为:

Expected value of a Multinomial with Dirichlet priors.
一旦我们开始输入数字,这个问题就很容易解决了。n 是试验次数,6,c_i 是每个类别的观测计数,alpha_i 是每个类别的伪计数(超参数)。设置所有α等于 1,可以计算预期物种概率:
species = ['lions', 'tigers', 'bears']
# Observations
c = np.array([3, 2, 1])
#Pseudocounts
alphas = np.array([1, 1, 1])expected = (alphas + c) / (c.sum() + alphas.sum())**Species: lions Prevalence: 44.44%.
Species: tigers Prevalence: 33.33%.
Species: bears Prevalence: 22.22%.**
这代表了考虑了伪计数的预期值,伪计数代表了我们对情况的初始信念。
我们可以通过增加伪计数的大小来调整我们对这个先验信念的置信度。这迫使期望值更接近我们最初的信念,即每个物种的流行程度是相等的。几个不同超参数的预期值如下所示:


Expected values for different pseudocounts.
我们对超参数的选择有很大的影响。如果我们对自己的信念更有信心,那么我们就增加超参数的权重。另一方面,如果我们希望数据有更大的权重,我们就减少伪计数。
虽然这个结果提供了一个点估计,但它具有误导性,因为它没有表达任何不确定性。我们只去过一次野生动物保护区,所以在这些估计中应该有很大的不确定性。通过贝叶斯推理,我们可以得到点估计和不确定性。
用 PyMC3 实现 Python 中的贝叶斯推理
为了得到一个估计范围,我们使用贝叶斯推理,构建一个情境模型,然后从后验样本中取样以近似后验。这是通过 PyMC3 中的马尔可夫链蒙特卡罗(或一种更有效的变体,称为不掉头采样器)实现的。与模型背后的理论相比,在代码中设置它很简单:
然后,我们可以从后面取样:
此代码在 2 个不同的链中从后部抽取 1000 个样本(丢弃 500 个用于调整的样本)。我们剩下一个trace,它包含了运行过程中抽取的所有样本。我们用这个轨迹来估计后验分布。
PyMC3 有许多方法来检查轨迹,如pm.traceplot:

PDF and trace of samples.
左边是采样参数的核密度估计——事件概率的 PDF。在右边,我们为模型中的每个自由参数绘制了完整的样本。我们可以从 KDE 看到,正如预期的那样,熊 pm.posterior_plot:

Posterior plots from PyMC3
下面是直方图,显示了从后验概率中采样每个概率的次数。我们有概率的点估计值——平均值——以及置信区间的贝叶斯等价值——95%的最高概率密度(也称为可信区间)。我们在这些估计中看到了极端程度的不确定性,这与有限的数据相符。
为了量化不确定性水平,我们可以得到结果的数据框架:

这显示了患病率的最佳估计值(平均值),而且 95%可信区间非常大。根据我们对保护区的一次考察,我们只能确定狮子的患病率在 16.3%到 73.6%之间。
贝叶斯推理之所以如此强大,就是因为这种内置的不确定性。在现实世界中,数据总是嘈杂的,我们通常比我们想要的少。因此,任何时候我们根据数据进行估计,我们都必须显示这种不确定性。对于这个问题,如果我们得到的野生动物保护区的熊的百分比不正确,没有人会受到伤害,但是如果我们用医学数据做一个类似的方法来推断疾病概率,会怎么样呢?
从后面取样
一旦我们有了踪迹,我们可以从后面取样来模拟去保护区的额外旅程。比如我们再考虑去 1000 次。每次旅行我们能看到多少个物种?

1000 samples drawn from the estimated posterior.
根据证据,有时候我们去保护区看到 5 只熊和 1 只老虎!当然,这不太可能,像这样的图表显示了可能结果的整个范围,而不是只有一个。我们去保护区的一次旅行只是一个结果:1000 次模拟表明,我们不能指望每次去保护区都得到准确的观察结果。
如果我们想在采样后看到新的狄利克雷分布,它看起来像:

Dirichlet distribution after sampling.
纳入附加信息
当我们去了 4 次保护区,并想在我们的模型中加入额外的观察结果,会发生什么?在 PyMC3 中,这很简单:
通过更多的观察,后验概率的不确定性将会减少,事实上,这就是我们在数量和视觉上所看到的。直觉上,这又是有意义的:随着我们收集更多的数据,我们对世界的状态变得更加确定。在无限数据的情况下,我们的估计将收敛于真实值,先验将不起作用。


Posteriors with more data
增加和减少对先前信念的信心
前面我们讨论了超参数如何被认为是代表我们先前信念的伪计数。如果我们将 alpha 的所有值都设置为 1,我们将得到目前为止看到的结果。如果我们降低或增加我们对患病率相等的最初理论的信心呢?要做到这一点,我们所要做的就是改变阿尔法矢量。然后,我们再次从后验样本(使用原始观察)并检查结果。

超参数对结果有很大的影响!较低的值意味着数据本身在后验概率中具有较大的权重,而较高的值导致伪计数具有较大的权重。随着该值的增加,分布相互收敛。在最后一种情况下,我们需要大量的数据来克服我们强大的超参数。
我们可以比较α= 0.1 和α= 15 时的后验曲线:


最终,我们对超参数的选择取决于我们对信念的信心。如果我们有充分的理由认为物种的流行是相等的,那么我们应该使超参数具有更大的权重。如果我们想让数据说话,那么我们可以降低超参数的影响。
结论
那么,对于流行率这个问题,我们的最终答案应该是什么呢?如果我们是好的贝叶斯主义者,那么我们可以提出一个点估计,但只能附带不确定性(95%可信区间):
- 狮子:44.5% (16.9% — 75.8%)
- 老虎:32.7% (6.7% — 60.5%)
- 空头:22.7% (1.7% — 50.0%)
我们估计下一个观察对象是一头熊?基于后验抽样,大约 23%。虽然这些结果可能不会让想要简单答案的人满意,但他们应该记住现实世界是不确定的。
贝叶斯推理的好处是我们可以整合我们先前的信念,并通过我们的答案得到不确定性估计。世界是不确定的,作为负责任的数据科学家,贝叶斯方法为我们提供了处理不确定性的框架。
此外,随着我们获得更多的数据,我们的答案变得更加准确。与贝叶斯推理的许多方面一样,这符合我们的直觉和我们自然地看待世界的方式,随着额外信息的增加,错误变得更少。最终,贝叶斯统计是令人愉快和有用的,因为它是最终有意义的统计。
一如既往,我欢迎反馈和建设性的批评。可以通过 Twitter @koehrsen_will 或者通过我的个人网站 willk.online 找到我。
“使用随机森林估计和推断异质处理效果”论文综述
本文原载于【blog.zakjost.com】
我最近读了很多技术论文,觉得用比学术论文不那么正式的语言来总结会很不错。我可能会也可能不会这样做不止一次。
一.动机
本文是关于尝试使用随机森林(RF)进行因果分析。RF 在构建分类或回归预测模型方面非常流行,但是对结果做出经典的统计声明并不容易。例如,你的置信区间是多少?你如何得到 p 值?
再者,本文想对的因果的影响做出主张,或者说是一种治疗的效果。例如,大学对收入有什么影响?由于许多原因,这很难做到,但最根本的是,你没有你确切需要的数据,即每个人都上过大学和没上过大学时发生了什么的数据。这当然是不可能的,因为在现实中,个人要么上过大学,要么没有,你不知道如果另一种情况发生会发生什么——即反事实。这种构建问题的方式被称为“潜在结果框架”,本质上是假设每个人都有多种潜在结果,这取决于他们是否接受了治疗。
本文中的一个关键假设,以及这种类型的一般因果估计技术,是未发现中的一个。这意味着一旦你控制了感兴趣的变量,一个人是否接受治疗是随机的。这使我们能够将附近的点视为微型随机实验。在药物试验的情况下,你可以随机分配治疗,所以这不是问题,但如果你在分析观察数据,治疗已经被分配了——一个人上过大学或没上过大学。
为了支持无根据性,你需要选择和衡量所有会影响治疗分配的变量。对于四年制学位对收入的因果影响,你可能想要选择的协变量之一是家庭收入,因为某人是否上大学可能与其家庭收入相关。年龄可能是另一个因素,因为 18 岁的人比 50 岁的人更有可能上大学。这个想法是,当你看着绘制在你的家庭收入/年龄图上的两个相邻点时,是否上大学的决定应该是随机的。这是很有价值的,因为你可以把没有上过大学的人的收入减去上过大学的人的收入,你就可以估计出大学在家庭收入/年龄空间中的影响。
但是这很难,因为你可能会忘记一个重要的变量,或者你没有这个变量的数据。因此,这个假设肯定不完全正确,但它可能是正确的,足以给出有用的答案。
但是假设你有正确的协变量,作者使用随机森林将数据分成自相似的组。随机森林是一种自适应最近邻方法,它决定空间的哪些部分对您来说是相似的,而大多数最近邻技术倾向于平等对待所有距离。然后,他们添加了约束条件,即生成的叶子至少有处理和未处理两类,然后可以通过减去平均值来计算每个叶子的因果影响,就好像这是一个随机实验一样。一旦完成单棵树的评估,就可以对每棵树的评估进行平均。他们称这种实现为因果森林。
二。这里有什么新鲜事
如上所述,要在传统统计学中做出稳健的统计声明,您需要像 p 值和置信区间这样的东西。这就需要知道统计量的渐近抽样分布。在这种情况下,这意味着我们需要知道,如果我们在无限数量的树木/数据上对随机森林估计量的平均处理效果进行采样,分布会是什么样子。如果我们有这样的数据,那么我们可以这样说:“平均处理是 0.3,这种来自随机机会的可能性小于 0.1%”
这里的内在假设是,我们可以推导渐近/无限数据情况的属性,并将其应用于有限样本的真实情况,但这通常是传统统计中的情况。
先前的工作已经完成,使渐近分析的随机森林,但本文建立的限制,需要适用于他们的因果森林。其中一个约束需要“诚实的树”,他们提出了两种增长算法。
三。方法
完整的证明是非常复杂的,我不会试图在这里重新创建它,但我会简要概述一些约束和它们使什么。
首先,从传统随机森林的先前工作中重新创建了一个渐近理论,表明它是一个均值为零的渐近高斯估计量,这意味着它是无偏的。他们还提到了一种叫做无限小刀切的技术,用于估计方差,其中包括有限样本校正。
作者能够通过包含“诚实树”的概念来利用先前的工作。基本的想法是,你不能使用结果变量来分割和估计平均影响——你必须选择一个或另一个。他们提出了两种方法来做到这一点。第一种是双样本树,将数据一分为二:一半用于估计影响,另一半用于进行拆分。分割标准是最小化结果变量的 MSE。在双样本情况下,看起来您可能丢弃了一半的数据,但这种情况是针对单棵树的,随机森林正在对每棵树的新训练集进行采样,因此您最终将使用所有数据进行分割和估计。
另一种方法是通过生长“倾向树”,这是一种分类树,旨在预测治疗类别而不是结果,然后结果变量仅用于估计每片叶子内的影响。他们强加了一个停止标准,使你停止分裂,以保持任何叶中每个处理类的最小值。这是必要的,这样你就可以比较结果来估计效果。
通过使用诚实树并依赖于未发现的假设和树叶内的处理类别重叠,他们能够稍微修改传统的处理,以给出相同的无偏高斯渐近结果。
四。实验结果
他们的基线使用的是 k-NN 算法。他们用已知条件创建一些模拟实验,模拟常见问题,然后应用因果森林和 k-NN 方法。
第一个实验将所有 x 的真实治疗效果保持为零,但在结果和治疗分配之间建立了关联,从而测试算法校正协变量以消除偏差的能力。这就像让算法自动计算出年龄和家庭是重要的,以及如何将它们分开。他们在不同的训练数据维度上多次运行该实验。他们报告了 MSE 和覆盖率,即真实值在估计值的 95%置信区间内的频率。因果森林比 10-NN 有一个数量级的改进,比 100-NN 有 5 倍的改进。CF 维持~0.95 的覆盖率到 10 维之后开始降级。10-NN 在 0.9 范围内保持了合理的覆盖率,100-NN 表现很差。值得注意的是,k-NN 的置信区间比 CF 宽得多,因此改进的覆盖率更令人印象深刻。
第二个实验有恒定的主效应和倾向,但真正的治疗效果只取决于两个协变量。然后,他们对不相关协变量的数量进行了缩放,以了解该算法在不相关协变量存在的情况下发现这种异质性治疗效果的能力。令人惊讶的是,CF 在高维比低维表现更好。他们通过注意到森林的方差取决于树木之间的相关性来解释这一点,并提出树木之间的相关性以及总体方差在更高维度时会降低。结果与实验 1 相似,MSE 好得多,或者至少与随维度扩展的更一致的覆盖相当。
注意到置信区间的覆盖范围在特征空间的边缘开始退化,特别是对于高维。这被解释为是一种由偏差支配的情况,在无限数据的渐近极限中会消失。值得注意的是,在边界的偏差是典型的树木,特别是最近邻非参数估计一般。
动词 (verb 的缩写)讨论
虽然因果分析不是我的专长,但对于假设无发现的最近邻法来说,这似乎是一个很好的进步。在维持名义覆盖率的同时,MSE 的显著改善令人印象深刻。
然而,我发现这篇论文的几个方面令人困惑。特别是那些与树的分裂标准相关的。在倾向树的情况下,他们正在训练一个分类器来分离治疗类别,但他们反过来要求每个叶子中类别的异质性约束,这与分裂标准直接相反。
类似地,在双样本框架中,它们被分割以最小化结果 MSE,该 MSE 将具有相似结果值的点分组。但关键是,在通过治疗分类分离要点后,结果是不同的,这种差异就是平均治疗效果。再一次,分裂标准似乎与最终目标相反。为此,他们参考了一篇论文(Athey 和 Imbens [2016]),其中可能包含澄清。
最后,有一句话我不明白,但听起来很困扰。
备注 4。(多点测试)我们注意到,通常不可能同时为所有 x 构建定义 4b 意义上的正则因果树。在实践中,如果我们想要建立一个因果树,可以用来预测许多测试点,我们可能需要分配不同的树对不同的测试点有效。然后,当在特定 x 进行预测时,我们将在该 x 被指定为有效的一组球座视为相关的森林,并对其应用定理 11。(第 19 页)
我不确定这是运营开销,还是更基本的东西。
你怎么想呢?
评估者再探:深度神经网络
在这一集的云人工智能冒险中,学习如何通过将线性模型转换为深度神经网络来训练日益复杂的数据集!
随着线性模型中要素列数量的增长,在训练中实现高精度会变得越来越困难,因为不同列之间的交互会变得更加复杂。这是一个已知的问题,对于数据科学家来说,一个特别有效的解决方案是使用深度神经网络。
为什么要深入?
深度神经网络能够适应更复杂的数据集,并更好地推广到以前看不到的数据,主要是因为它的多层结构,因此它们被称为深度。与线性模型相比,这些图层允许它们适应更复杂的数据集。然而,代价是该模型往往需要更长的训练时间、更大的规模和更少的可解释性。那么为什么会有人想用它呢?因为它可以导致更高的最终精度。

Where will your deep learning journey take you?
深度学习的一个棘手问题是让所有参数“恰到好处”。根据您的数据集,这些配置看起来几乎是无限的。然而,TensorFlow 内置的深度分类器和回归器类提供了一组合理的默认值,您可以立即开始使用,从而快速轻松地开始使用。
从线性到深度
让我们看一个如何将 iris 示例从线性模型更新为深度神经网络(通常缩写为 DNN)的示例。
我不打算展示一个 DNN 可以利用的 2000 列模型…所以我只使用我们在本系列中一直使用的 4 列。(要么全有,要么全无,对吧?)两种方式的机制都是一样的。
主要的变化来自于用 DNNClassifier 替换我们的 LinearClassifier 类。这将为我们创建一个深度神经网络。

Replace LinearClassifier with DNNClassifier
其他变化
事实上,其他一切都保持不变!深度神经网络需要一个额外的参数,这是我们之前没有包括的。
由于深度神经网络有多层,并且每层有潜在的不同数量的节点,我们将添加一个hidden_units参数。

Add your hidden units argument to wrap things up
hidden_units参数允许您为每个层提供一个包含节点数量的数组。这使你可以简单地通过考虑它的大小和形状来创建一个神经网络,而不是手工从头开始连接整个网络。添加或删除层就像在数组中添加或删除一个元素一样简单!

Changing your network configuration is a one-line change!
更多选项
当然,对于任何预先构建的系统,您在便利性方面获得的好处往往会在可定制性方面失去。DNNClassifier 试图通过包含一些您可以选择使用的附加参数来解决这个问题。如果不考虑,会使用一些合理的默认值。例如,优化器、激活函数和掉线率都可以和许多其他参数一起定制。

Yes, there’s an activation function called ‘ELU’
仅此而已
为了将我们的模型从线性转换到深度,你还需要做什么?没什么!这就是使用评估者框架的美妙之处:一种组织数据、训练、评估和模型导出的通用方法,同时仍然给你试验不同模型和参数的灵活性。
深入,简单的方法
有时,深度神经网络可以胜过线性模型。在这些情况下,TensorFlow 通过利用估算器框架来替换一个函数调用,可以很容易地从线性模型切换到深度模型,并且只需很少的代码更改。这意味着有更多的时间来处理数据、模型和参数,而不是建立训练循环。对于简单的深度神经网络,使用张量流估值器!
感谢阅读深度模型!如果你想了解更多,请务必订阅频道来了解云人工智能冒险的其余内容。
以太坊的 ERC-20 代币解释简单

区块链系列的未来
加密货币领域有很多缩写。这让新来者望而生畏。事实上,这个领域的首字母缩写有时甚至是字母和数字的组合,混淆了这种程度的恐吓。但是没有什么花哨的。长话短说,ERC-20 代币只是一种建立在以太坊平台上的加密货币。别担心,我会解释这是什么意思。

Review this image again after you read this article, and it’ll make much more sense to you if it doesn’t already.
许多人知道以太坊,因为它是一种可以在比特币基地交易的加密货币。比特币与众不同的一个独特之处(至少到目前为止)是它拥有编写智能合约的能力。智能合约只是营销用语,指你可以在区块链上运行的代码。本质上,你可以将代码写入以太坊区块链。因此,除了存储货币的历史交易,您还可以存储逻辑。逻辑的结合创造了我们熟悉和喜爱的程序和应用。

Cryptokitties has arguably been the most popular Dapp on Ethereum. You just breed and trade them.
但是,忠于行话,我们不能仅仅称它们为应用程序。毕竟,它们不像普通的应用程序——这些被写入以太坊区块链的应用程序本质上是去中心化的,因为以太坊本身就是去中心化的。因此,我们称它们为分散应用,简称 d apps(有些人说 d-apps ,其他人只是发音为 dapps )。
对于这些 dapp 中的大多数,创作者希望制作他们自己的硬币(统称为令牌),这意味着用户在与 dapp 互动时必须使用他们特定的硬币——这是好事还是坏事有待讨论,但我在这篇介绍性文章中不会回答这个问题。
ERC-20 是描述以太币的标准
人们很快意识到创造自己的硬币需要一定的标准。就像制作信用卡一样。每张卡的背面都有一个黑色的长条用来刷卡,大多数现代卡的正面都有一个芯片。到期日期、安全代码和所有者姓名都出现在卡上的标准位置,智能手机摄像头可以通过扫描快速识别它们。

但是想象一下,如果有人决定制作一张除了二维码之外没有任何信息的信用卡。当然,这听起来时尚简约,但没有商店会接受它,因为它不符合标准的信用卡设计规则,只是看起来很可疑。
ERC-20 正是应用于以太坊区块链智能合约代币创建的标准。这里有一个令牌必须遵守的规则列表,但是我不会在这个解释中涉及细节。如果你想更深入地了解 ERC-20 令牌标准的细节,请看一下维基百科的文章。
存储和交易 ERC-20 代币
因为 ERC-20 代币是在区块链以太坊上建造的,所以它们也可以在以太坊上兑换。你可以用你的以太坊钱包来存放它们,也可以发送到其他以太坊钱包。不过,有一点你应该小心,那就是永远不要使用交换地址。
不要纠缠于为什么不这样做的复杂细节,只要明白交换会为每枚硬币生成唯一的地址。换句话说,你的以太坊地址和你的 ERC 20 令牌地址是不同的。如果你试图发送一个 ERC-20 代币到你的交易所的以太坊地址,交易所不会识别它,你也不会得到 ERC-20 代币。不过,在你自己的钱包里,你可以存放任何你想要的以太币。你可能已经注意到我用了钱包和地址这两个词。如果你认为它们是一样的,那你就错了。在我的文章加密钱包与地址中了解更多信息。
为什么要在以太坊上建立 Dapps?
嗯,这是个好问题。简单的回答是,你不必。自从以太坊在 2015 年推出智能合约以来,许多其他区块链都出现了自己的智能合约功能。例如,NEO 是一个区块链,它使用 Java 等传统编程语言编写合同脚本,而以太坊有自己的语言 Solidity。但是如果我刚才说的对你没有意义,不要担心——只要知道除了以太坊,还有其他区块链可以托管智能合约。
不过,以太坊拥有先发优势,在所有支持智能合约的区块链公司中,它的市值仍然是最大的。简而言之,这意味着以太坊比其他竞争者得到了更多的支持。如果你试图建立一个 Dapp 和围绕它的公司,你可能会选择最安全的选择——一个可能在几年内仍然存在的选择。
当然,这并不是说竞争对手将不复存在。我当然相信并投资了其中的许多,尤其是因为以太坊确实有其自身的缺点。但是随着数千个 Dapps 的建立和对以太坊的大量投资,它在采用方面仍然远远领先于竞争对手。
每当有人说“以太坊令牌”或“ERC-20 令牌”或其他类似的东西,我希望你现在不会立即被吓倒,并在你的大脑中旋转加载屏幕,试图破译你刚刚听到的东西。这只是一种建立在以太坊区块链上的加密货币。
道德准则与道德准则
这就是为什么道德标准不起作用,而我们可以做的。

The current state (and usefulness) of ethical codes for AI.
在数据行业有很多关于道德的讨论,特别是当它涉及到算法的道德使用时。前美国首席数据科学家呼吁为数据科学家制定道德准则。美国统计协会和计算机械协会。谷歌提出了管理其人工智能努力的伦理原则,许多其他人也参与进来,从彭博到世界经济论坛的青年科学家小组,再到民主数据。
人们制定道德准则至少部分是因为他们对道德实践的状态不满意。但是道德规范并没有明显导致道德实践的增加。事实上,就像试图为任何事情创建标准一样,创建代码的唯一明确结果是额外代码的激增:

This applies to ethical codes as well. (Source: https://xkcd.com/927/)
简而言之,道德规范和实际的道德规范是有区别的。我想谈一谈前者,但主要是关于我们能做些什么来获得更多的后者。
我为什么关心道德
特别是在工业界,我认为看着这样一个话题,说“这种事情只是一个学术练习”或“这不是我的问题,因为我个人的行为是合乎道德的”这样的话是非常合理的因此,我想花点时间解释一下,作为一名在工业界工作的数据科学家,我个人为什么觉得我需要关注这个话题:
- 巴基斯坦。我曾经训练统计模型,为美国陆军提供战略情报。我模拟了巴基斯坦的军事和军事行动周期,我的结果与一个著名的政府政策声明相矛盾。我老板的老板把我叫进了他的办公室,痛骂了我半个小时后,叫我更改分析结论。这是我第一次被告知我需要伪造我的结果(也是第一次有人否认,老实说,我相信这是他们告诉我要做的)。
- 销售报告。我在一家学生旅游公司工作,我老板的老板想要一张显示十年收入的图表,但他只有其中四年的数据;他想让我插入缺失的数据。他画了一张图,画出了他希望趋势显示的东西,那张图给出了过去几年非常不切实际的数据,并极大地改变了过去几年的数据。这是我第一次被告知伪造数据。
- 妖冶。我在一家专注于投资当地消费品生产商的资产管理初创公司工作。我的老板真的想展示各国都符合 s 曲线——商业顾问对逻辑曲线的表述——有些国家消费水平非常低,有些国家正处于快速上升阶段,有些国家已经在高消费水平下趋于平稳。数据没有显示他想要显示的内容。他催促我尝试越来越复杂的模型,希望它们能显示出想要的模式。这是我第一次被告知要折磨数据,直到它承认为止。
- 教师工会、纽约时报和全美有色人种协进会。我得到了为一个特许学校网络创建数据科学团队的工作,这个团队如此突出,在政治上如此活跃,以至于在开始工作之前,我未来的雇主就被指控利用学生考试成绩拒绝、恐吓或清除不受欢迎的教师和学生。我做了尽职调查,认为这些攻击更多的是政治性的,而不是事实性的,我在那份工作中的经历证实了我最初的印象,但我知道,无论我建立了什么数据系统,都很容易被用来惩罚学生,而不是支持他们,即使我不是为此目的建立的。这是我第一次不得不不断地想象,在从设计到开发到部署的每一个阶段,有人如何利用我开发的东西来伤害其他人。
我认为数据科学有价值。我认为它值得吸引一些最优秀、最聪明的人进入劳动力市场。如果我们不坚持不懈地努力确保广泛的道德实践,并呼吁和纠正不道德的做法,越来越多的那些最优秀和最聪明的人将离开去做其他事情。理应如此。如果我们不建立一个道德的行业,那么我们就应该失去这些人,并看到我们的业务受到影响。我们个人保持道德是不够的:只有少数公司的行为不道德,所有公司都会因此受到影响。良好的道德规范在短期内往往是好生意。从长远来看,这总是一笔好生意。
道德规范既不必要也不充分
当试图让某人发展改变其行为的能力或意图,以避免道德陷阱时,在目前的讨论中,谈话是一种非常无效的交流方式。

Take a long time looking at this comic. Think about it until you understand it. It’s worth the effort. (Source: https://xkcd.com/1028/)
告诉人们危险很少能帮助他们避免危险。至少,它没有帮助他们这样做的任何一致性。道德准则从不出现。他们只会说。实际上,它们是目标陈述。这就是为什么他们不提高实践。它们本身引起了人们对问题存在这一事实的注意,但它们并不能阻止人们陷入危险,或者帮助他们脱离危险。道德规范不足以改善道德实践。
这当然不是新的信息——我还没有遇到任何人认为道德规范就足够了,尽管在参与撰写道德规范的社区时,我经常遇到像他们那样行事的人。问题是,如果我们可以展示危险而不是讲述危险,我们就可以避免或减轻危险而根本不用讲述。道德规范不仅不足以改善道德实践,也没有必要。
栅栏及其危险
不仅仅是道德规范对于道德实践来说既不必要也不充分。它们也有潜在的危害。道德准则是一个界限——一个人们不应该越过的界限。如果没有办法强制遵守准则,那么它就像沙子里的一条线——它在那里,但越过它不会带来任何后果,所以它还不如不在那里。
如果有一种方法来执行该准则,换句话说,如果有一个监管基础设施,那么它就像一个围栏。政策制定者喜欢围栏,因为它们是可扩展的。您所要做的就是以一种可以审计遵守情况的方式定义规则,然后培训和部署审计员。栅栏的问题在于它们引入了系统性风险:人们可以沿着栅栏的边缘建立各种各样的业务,甚至靠在栅栏上,而不用跨过它。当栅栏破裂时,其后果比栅栏一开始就不存在时更具破坏性。我以前写过这方面的文章。
有很多通过大规模围栏建设引入系统性风险的例子。2008 年金融危机前监管抵押贷款的规则就是一个例子,但也许更适合这一讨论的是区分 p 值低于 0.05 和高于 0.05 的围栏。这种限制已经在大学课堂、科学出版物以及(在较小程度上)行业标准中实施,并且这些法规已经与一整套实践一起发展,以选择模型特征或样本数据或两者,从而使结果符合这种限制。近年来,几个领域,最突出的是 T2 心理学和 T4 医学,都遭受了损失,因为太多的人认为结果是可信的,仅仅因为它们符合这个标准。
建围墙是有风险的,围墙越大,风险越大。除非别无选择,否则我们不应诉诸广泛的监管,即便如此,我们也应谨慎行事。
一组试验性的选择
现在让我用剩下的时间来谈谈道德准则和道德监管的替代方案。在这里我没有任何明确的答案可以提供。我认为有足够的理由相信,我们可以通过展示而不是讲述来建立一个更道德的行业,但我的想法仍然是初步的。如果作为一种职业,我们花同样多的时间和资源来开发这些想法,就像我们花同样多的时间和资源来开发道德准则一样,我们可能很快就有了可以实施的东西。我将从任何个体从业者都可以做的事情开始。那我就说一些团队或者公司可以做的事情。然后我会谈谈整个行业必须要发生的一些事情。
用于设计的工具。当我们训练一个预测模型时,有一些方法可以评估它的准确性,包括交叉验证等流程,这些流程有助于降低我们的方法提供过于乐观的结果的风险。有一些工具可以支持所有这些评估,它们跨许多不同的软件包和编程语言进行维护。新从业者接受这些工具的培训,并在他们不能使用这些工具时受到警告。我们做所有这些是因为我们训练模型和建立数据系统来完成某些目的,所以我们有一个有趣的评估我们的系统在多大程度上完成这些目的。
我们需要一个可比较的工具集来评估我们的系统会在多大程度上产生意想不到的后果。仅仅知道我们的工具做我们想让它们做的事情是不够的。我们需要确保他们没有做我们不希望他们做的事情。同样,这种道德要求也只是简单的商业意识:意想不到的后果会导致无法计划的成本。
有一些工具可以识别出意想不到的后果,但是它们远不如测量预期后果的工具数量多、用户友好或维护良好。例如,芝加哥大学数据科学和公共政策中心开发了一个名为 Aequitas 的工具,用户可以在其中指定算法的预期用途——例如,算法是否将用于惩罚或帮助人们——并将分析算法的结果,以查看一些子群体是否受到不成比例的影响。有一些工具可以自动搜索辛普森悖论的实例(这里有一个例子),当局限于某些子群时,整个数据集中显示的趋势会反转。
我们需要更多这样的工具。我们需要在工作流程中加入对意外后果的探索。这是每个数据从业者都能做到的。
本地(不可扩展)法规。大篱笆有风险。小栅栏没那么多。我说的不是自我调节。我说的是地方法规。地方法规可以依赖于展示道德问题,而不是告知,地方错误往往也停留在地方。
《华盛顿邮报》上有一篇很棒的文章,讲述了地方法规如何减少餐馆里的骚扰。员工们使用颜色编码系统将不舒服的客户行为分为黄色(令人毛骨悚然的氛围)、橙色(性暗示)或红色(明显的行为或重复的橙色事件)。一名员工所要做的就是报告颜色——“我在五号桌有一个橘子”——经理就采取了行动,没有问任何问题。红色意味着顾客被要求离开。橙色意味着经理接管了桌子。黄色表示如果员工愿意,经理可以接管桌子。
不难想象这在算法开发中是如何工作的。黄色表示员工感到不舒服,如果需要,它会提示转移到另一个项目,以及对该问题的团队审查。橙色表示员工可以指出具体的道德问题,它会提示转移到另一个项目以及团队评审。红色表示该员工有强烈的顾虑,它会将项目搁置,等待审核。不要怀疑员工的顾虑。只是行动。有可能。
声誉系统。已经有很多系统的例子了(Yelp,BBB,Glassdoor 等。)公开披露与公司私人互动的信息,这些系统改变了公司的行为。无论怎么想象,这些网站都没有给用户一个全面、客观的公司业绩/合意性/质量/良好性的观点。但是公司害怕差评。当一个不好的评论出现时,他们会花时间去解决它——证明事实上这个评论是错误的。没有真正解决问题的公司会得到更多的负面评价,因此吸引的顾客更少。这使得公司内部的做法影响了底线。当一家公司无法对 Glassdoor 上描述的问题给出令人满意的解释时,我个人已经退出了对某些工作的考虑。至少在一个案例中,引发危险信号的信息是关于道德问题的。声誉系统是改变行业行为的可行工具。
大多数这类系统的问题是它们试图适应所有的用例,所以差评可能是因为顾客受到性骚扰或者顾客没有意识到自己下错了订单。亚马逊上的书评,即使我们不考虑故意抬高或压低一本书声誉的暴民企图,也可以反映从论点结构到散文可读性到论文质量的任何东西。对于一个影响道德实践的声誉系统来说,范围需要更窄。
我们有工作要做
我理解这种渴望,当面对一个明确的道德问题时,就像那些经常成为新闻的问题,想要做些什么。我明白,试图制定清晰和令人信服的伦理原则是一件非常可行的事情。这是错误的。这解决不了我们的道德问题。在我看来,甚至没有任何帮助。事实上,它很可能会伤害。礼教实际上可以给不道德的演员提供掩护。我们不想那样。
我列出了以上三种解决不道德行为的方法,不是因为我认为它们能解决我们所有的问题(当然它们不会),而是因为它们给了每个人一些既现实又有效的事情去做。任何会编码和做分析的人都可以做设计工具。任何经理或高管都可以实施和执行关于道德审查和不报复提出问题的人的政策。如果你不在处理这些道德问题的地方工作,创建一个网站,让处理这些问题的人公开发布他们遇到的问题以及他们所在的公司。单独来看,这些事情都不会有太大的好处。综合起来,它们以及类似的想法可以让我们朝着正确的方向前进。
机器学习中的伦理
当我们读到这些领域的重大进展时,机器学习(ML)或人工智能(AI)系统如何运作的伦理是一个常见的想法。这种感觉会接管人类吗?还是会帮助我们到达一个乌托邦时代?绝对不是二元问题。但是,一个很少被问到的问题(也许是正确的)是“这是用正确的美德建造和建立的吗?”。这个问题并不像看起来那样关注建立一个 ML 系统背后的动机。
背景
如果你没有经验或者不知道什么是 ML 系统,就把它想象成一个黑盒。一个黑盒,当提出一个问题时,它输出一个正确概率很高的答案。为了得到这个高概率,我们需要首先设置黑盒。
在实践中,我们试图创建一组许多黑盒,并选择一个具有最高准确性的黑盒。为了建立这些模型,我们需要大量的数据和算法。把数据想象成一长串有正确答案的问题。算法从这些数据中学习。一组中的每个黑盒都有相同算法的稍微不同的版本。最后,我们选择最准确的版本(技术上称为调整超参数)。
问题
在 ML 中,作弊主要有三种可能的途径。它们是:
- 数据
- 算法
- 结果
1。数据
这可能是三个问题中最大的一个。一个好的 ML 系统需要大量的数据。但是我们从哪里获得这些数据呢?如果我们正在寻找的数据不存在,我们如何挖掘它?有时,所寻找的数据已经存在。它可能是开源和免费的。它可能会公开出售,但需要付费。或者数据可能被一群人私有。一切都很好,如果它是免费和开源的。即使可以买到,它也可能是好的。但是,如果你窃取了别人的私人数据,这是可以的吗?你可能倾向于“不”。但是,如果这些数据,目前只有少数人可以访问,可以帮助世界各地的数百万人与你的全新 ML 模型。那会不会被认为是对?突然间,这个问题似乎不再非黑即白了。
当我们谈论匿名跟踪人们,不经他们同意,收集数据时,答案变得更加模糊。这些数据也许可以用来探测不寻常的活动。我们已经知道我们的网络搜索正在被跟踪。如果你的 ML 系统可以通过跟踪普通人来帮助防止下一次恐怖袭击,那么跟踪他们是正确的吗?或者至少行动变得合理了吗?
2.该算法
许多重要而有用的算法都是开源的,这是一件好事。这意味着每个人都可以访问它,有些人甚至允许我们修改它并从中获利。这太棒了!现在,再一次,用数据想象同样的场景。如果一群人拥有一个专利算法,法律规定使用相同的算法是非法的。但是如果这个算法在合适的人手里可以帮助数百万人呢?自己的是非感可以用来逆向工程算法造福他人吗?这涉及窃取知识产权,但也是反洗钱的一个问题。
开发新算法的问题与数据集密切相关。如果你没有一个完整的数据集(也就是说,你有一个没有准确整合所有可能情况的数据集),那么你得到的 ML 系统可能会有偏差,并且它可能会开始辨别。例如,帮助银行决定是否投资某项特定业务的人工智能可以拒绝向所有信用记录不佳的人提供贷款,即使他们的业务潜力巨大(人类会注意到这一点并将其作为例外)。这是一个自动化人工任务的糟糕例子,而这些任务可能会在不被注意的情况下发生。
3.结果呢
前两个问题关系到大局。这个更孤立于 ML。在 ML 中,为了报告模型的准确性,我们将模型产生的结果与实际答案进行比较。它们越接近,精确度越高。有不同的方法来报告这个分数。
在这里,人们最常见的作弊方式是在数据集上训练他们的模型,并报告他们在同一数据集上得到的错误。这是初学者常犯的错误,因为他们不明白这是错的。这也是一个错误,有时是为了能够报告更高的准确性而故意犯的。
为什么这是错的?想象一下,你正在准备一场考试,有人给了你一份准备考试的问题和答案清单。如果你在考试中得到同样的问题,你的考试分数能很好地衡量你学到了多少吗?或者它是衡量你能记住多少的标准?电脑也是如此。如果您在您训练的同一数据集上测试该模型,您的模型将会产生很高的准确性,因为您的模型现在已经记住了数据集,并且知道所有的正确答案。但是如果我问它一个新的问题,很有可能答案是错的。这个问题被称为过拟合数据集。幸运的是,解决这个问题非常简单,但是超出了本文的范围。
另一种作弊方式是创建一个模型表现非常好的合成数据集,并使用它来报告准确性。
如果你想知道人们是否会这样做,看看一些 Kaggle 比赛的排行榜。在公共数据集(训练数据集)中,有许多具有高准确度的人。但是,当查看私有数据集(一个不可见的测试数据集)中的排行榜时,只有少数在早期排行榜中得分高的人得到了类似的结果。其他人的模型严重过度拟合了数据。这样的模式,如果付诸实施,只会对社会不利。
这似乎不是一个大的道德问题。唉!它仍然关注和质疑一个 ML 工程师的诚信。
一个版主?
我上面提出的很多问题都是主观的。对一个人来说可能是正确的,对另一个人来说可能是错误的。但是这些问题让我们思考我们愿意做什么来带来好的改变。我认为,我们需要的是一套规章制度,如果你愿意,一个行为准则,一个工程师在设计一个 ML 系统时应该遵守。违反本准则将导致禁止使用洗钱系统。
为什么所有这些都很重要?这很重要,因为有对错之分,我们必须确保始终选择正确的道路前进。
网络搜集中的伦理
我们都收集网络数据。我们这些处理数据的人会。数据科学家、营销人员、数据记者和数据好奇者都是如此。最近,我一直在思考这种做法的伦理问题,并对在这个问题上缺乏共识感到不满。
让我澄清一下,我说的是道德规范而不是法律。关于抓取网络数据的法律很复杂、模糊,改革的时机已经成熟,但那是另一回事。这并不是说没有人在思考或写作刮擦的道德问题,而是刮擦者和被刮擦者都无法就基本原则达成一致。
我两边都去过。我主要为个人项目收集数据,但我也把它作为工作中收集数据的一种形式。另一方面,我一直在纠结如何从我自己或我雇主的网络日志和分析中过滤掉“机器人”,以便专注于真正的客户。这是多年来生活的现实,与其与之抗争,不如让我们制定一些基本规则。
虽然我并不幻想这些规则是完整和绝对的,但它们涵盖了我多年来遇到的争论的关键点。
道德刮刀
我,web scraper 将遵循以下原则:
- 如果你有一个公共 API 提供我正在寻找的数据,我会使用它,避免拼凑。
- 我将始终提供一个用户代理字符串,使我的意图清晰明了,并为您提供一种有问题或疑虑时与我联系的方式。
- 我会以合理的速度请求数据。我将努力不被 DDoS 攻击所迷惑。
- 我只会保存我绝对需要的数据。如果我只需要 OpenGraph 元数据,那就是我要保留的全部。
- 我会尊重我保存的任何内容。我永远不会把它当成我自己的。
- 我会想办法把价值还给你。也许我可以给你的网站带来一些(真正的)流量,或者在一篇文章或帖子中表扬你。
- 我将及时回应您的请求,并与您合作解决问题。
- 我将为从数据中创造新价值的目的而努力,而不是复制它。
道德网站所有者
我,网站所有者将遵循以下原则:
- 我将允许道德刮刀访问我的网站,只要它们不会对我的网站的性能造成负担。
- 我将尊重透明的用户代理字符串,而不是阻止它们,并鼓励使用伪装成人类访问者的刮刀。
- 在永久屏蔽之前,我将联系刮刀的所有者(感谢他们的道德用户代理字符串)。出于现场性能或道德考虑,临时封锁是可以接受的。
- 我知道 scrapers 是开放网络的现实。
- 我会考虑使用公共 API 来提供数据,作为对抓取器的替代。
这给我们留下了什么?

The ease of scraping in Python
事实是,搜集数据很容易。有了几行 Python 代码和一些很棒的库的帮助,比如 urllib2 (或者 Requests ,如果你喜欢的话)和 BeautifulSoup ,你可以抓取并解析一个页面的 HTML。事实上,这很容易,负责任的使用比以往任何时候都重要。
当然,为一个周末项目搜集几千篇博文不是问题。见鬼,在我看来,即使是用于商业用途的刮痧也是符合道德的。对于我们这些依靠海量网络数据来创新、学习和创造新价值的人来说,最受关注的是针对可疑商业用途的大量网络抓取,这也带来了最高的风险。
只要有一点点尊重,我们就能让好事继续下去。
感谢阅读!你可以在我的网站上联系我或者阅读我的其他博客文章。
欧洲人工智能初创公司格局
欧盟人工智能初创企业资助研究

在看了欧洲的太空科技景观之后,我进一步探索前沿科技,深入挖掘欧洲的人工智能景观。我分析了 797 家总部位于欧洲的初创公司,它们来自我们在 Maxfield Capital 和 Pitch Book & Tracxn 数据库的网络。
这项研究的主要目标是概述:
- 人工智能创业公司中资金最充足的部门;
- 从受资助创业公司的来源来看,投资最活跃的国家
关于方法论的几句话:
- 初创公司根据以下几个方面进行细分:(1)垂直行业(如医疗保健或零售);㈡业务职能(如人力资源或营销);㈢产品类型
- 详述“产品类型”类别,我已经分离了“垂直和功能不可知”的部分,例如“人工智能工具”和“开发人员工具”,分别为开发人员提供核心人工智能应用程序(例如语音识别或计算机视觉)作为服务(针对 B2B)和 API 及其他产品
观察结果
- 欧洲人工智能初创公司中资金最充足的部门是:
(i)营销/广告;㈡安全;㈢人工智能工具;㈣医疗保健;㈤零售; - 虽然营销/广告和人工智能工具部门的资金由大量公司(分别为 40 家和 41 家)驱动,但安全和医疗保健主要由“大型轮次”驱动,如安全领域的 Darktrace (总资金 1.045 亿美元)和 Onfido (总资金 3030 万美元)以及医疗保健领域的慈善人工智能(总资金 1 亿美元);
- 就人工智能初创公司融资而言,英国是欧洲最发达的国家,融资额为 7.5511 亿美元,其次是德国(1.2558 亿美元)、法国(1.1342 亿美元)和北欧(1.0042 亿美元)。爱尔兰、比利时和西班牙紧随其后,分别融资 4629 万美元、3709 万美元和 3082 万美元
总而言之,这是包含所有数据的电子表格(链接),如果我错过了什么或者你想在 AI 上聊天,请发微博给我 @GalyaDegtyareva !此外,如果你想要更详细的概述,可以看看这些由法比安、大卫·凯尔纳和克里斯·奥布莱恩创作的德国、英国和法国人工智能风景。
推荐系统的评价指标

推荐系统在在线零售中越来越受欢迎,因为它们能够为独特的用户提供个性化的体验。K 处的平均精度(MAP@K)通常是用于评估推荐系统性能的选择度量。然而,使用额外的诊断指标和可视化可以对模型的性能提供更深入的、有时令人惊讶的见解。本文探讨了 K(MAR @ K)个性化列表内相似度的平均召回率,并使用这些指标来比较三个简单的推荐系统。
如果您想使用本文中讨论的任何指标或图表,我已经在 python 库 recmetrics 中提供了它们。
*$ pip install recmetrics*
Movielens 数据集
本例中使用的数据是流行的 Movielens 20m 数据集。该数据包含用户对电影的评级,以及电影类型标签。(为了增加训练时间,对该数据进行了缩减采样,以仅包括来自对超过 1000 部电影进行评级的用户的评级,并且移除了少于 3 颗星的评级。)

Example of user movie ratings
模型
测试和比较了三种不同的推荐系统。
- 随机推荐器(向每个用户随机推荐 10 部电影)
- 受欢迎程度推荐器(向每个用户推荐 10 部最受欢迎的电影)
- 协同过滤(使用奇异值分解矩阵分解方法)
让我们深入研究指标和诊断图,并比较这些模型!
长尾图
我喜欢通过查看长尾理论来开始每一个推荐项目。该图用于探索用户项目交互数据(如点击、评级或购买)中的流行模式。通常,只有一小部分项目具有高的交互量,这被称为“头部”。大多数项目都在“长尾”中,但它们只占交互的一小部分。

Long tail plot. (Sample of Movielens 20m ratings data)
因为在训练数据中有许多流行项目的观察值,所以推荐系统学习准确预测这些项目并不困难。在电影数据集中,最受欢迎的电影是大片和经典。这些电影已经为大多数用户所熟知,对它们的推荐可能不会提供个性化的体验或帮助用户发现新的、相关的电影。相关推荐被定义为用户在测试数据中正面评价的项目的推荐。这里确定的指标提供了评估建议的相关性和有用性的方法。
地图@K 和标记@K
推荐系统通常为测试集中的每个用户产生一个有序的推荐列表。MAP@K 提供了对推荐项目列表的相关程度的洞察,而 MAR@K 提供了对推荐者能够回忆起用户在测试集中正面评价的所有项目的程度的洞察。我不会详细描述 MAP@K 和 MAR@K,因为在这里可以找到很好的描述:
(好吧,这里有一个双关语。)既然你正在读这篇文章,你可能刚刚遇到了“平均精度”这个术语,或者…
sdsawtelle.github.io](http://sdsawtelle.github.io/blog/output/mean-average-precision-MAP-for-recommender-systems.html)
MAP@K 在 ml_metrics 库中可用,我已经让 MAR@K 在 recmetrics 中可用。

By MAR@K, the collaborative filter is able to recall the relevant items for the user better than the other models.
新闻报道
覆盖率是模型能够在测试集上推荐的训练数据中的项目的百分比。在这个例子中,流行度推荐器只有 0.05%的覆盖率,因为它只推荐了 10 个项目。随机推荐器具有预期的接近 100%的覆盖率。令人惊讶的是,协作过滤器只能推荐 8.42%的经过训练的项目。

Coverage comparison for three recommender systems.
个性化
个性化是评估一个模型是否向不同的用户推荐了许多相同的商品的好方法。它是用户推荐列表之间的相异度(1 余弦相似度)。一个例子将最好地说明个性化是如何计算的。

Example list of recommended items for 3 different users.

First, the recommended items for each user are represented as binary indicator variables (1: the item was recommended to the user. 0: the item was not recommended to the user).

Then, the cosine similarity matrix is calculated across all user’s recommendation vectors.

Finally, the average of the upper triangle of the cosine matrix is calculated. The personalization is 1-the average cosine similarity.
高个性化分数表明用户的推荐是不同的,这意味着该模型为每个用户提供了个性化的体验。
列表内相似性
列表内相似度是推荐列表中所有项目的平均余弦相似度。该计算使用推荐项目的特征(例如电影类型)来计算相似性。这个计算也最好用一个例子来说明。

Example recommendations of movie ids for 3 different users.

These movie genre features are used to calculate a cosine similarity between all the items recommended to a user. This matrix shows the features for all recommended movies for user 1.
可以为每个用户计算列表内相似性,并对测试集中的所有用户进行平均,以获得模型的列表内相似性的估计。

如果推荐系统向单个用户推荐非常相似项目的列表(例如,用户只接收浪漫电影的推荐),那么列表内的相似性将会很高。
使用正确的训练数据
可以对训练数据做一些事情来快速改进推荐系统。
- 从培训数据中删除热门项目。(这适用于用户可以自己发现这些项目,并且可能不觉得这些建议有用的情况)。
- 根据用户的价值(如平均交易价值)调整项目评级。这可以帮助模特学会推荐能带来忠诚或高价值顾客的商品。
结论
一个优秀的推荐系统会提供相关和有用的推荐。使用多个评估指标的组合,我们可以开始评估一个模型的性能,而不仅仅是相关性。如果您想使用这些指标和图表来评估您自己的推荐系统,请查看我的 python 库。有问题吗?请随意向伸出手放松!*
基于困惑度和香农可视化方法的语言模型评估
你的自然语言处理模型有多好?
你的语言模型有多好?
为了回答语言模型的上述问题,我们首先需要回答下面的中间问题:与那些很少遇到或有一些语法错误的句子相比,我们的语言模型是否为语法正确和频繁的句子分配了更高的概率?为了训练任何模型的参数,我们需要一个训练数据集。在训练完模型之后,我们需要评估模型的参数被训练得有多好;为此,我们使用完全不同于训练数据集的测试数据集,因此模型看不到它。之后,我们定义一个评估指标来量化我们的模型在测试数据集上的表现。
语言模型的体内评估
为了比较两个语言模型 A 和 B,让这两个语言模型通过一个特定的自然语言处理任务并运行作业。之后,比较模型 A 和 B 的准确性,以评估相互比较的模型。自然语言处理任务可以是文本摘要、情感分析等。
限制:耗时的评估方式。
语言模型的内在评价:困惑
困惑是由语言模型分配给测试集的概率的乘法倒数,由测试集中的单词数归一化。如果语言模型可以从测试集中预测未见过的单词,即 P(测试集中的句子)最高;那么这样的语言模型更准确。


Perplexity equations. Image credit: Speech and Language Processing (3rd edition), Chapter 3 Language Modeling with N-grams, Slide 33, available at http://web.stanford.edu/~jurafsky/slp3/3.pdf
因此,对于测试集来说,更好的语言模型将具有更低的困惑值或更高的概率值。
使用来自华尔街日报数据集 的 3800 万个单词训练并使用 150 万个单词测试的不同 N 元语言模型的示例困惑值

Image credit: Speech and Language Processing (3rd edition), Chapter 3 Language Modeling with N-grams, Slide 36, available at http://web.stanford.edu/~jurafsky/slp3/3.pdf
困惑背后的直觉作为一个评价指标和香农可视化方法
下面这个例子可以解释困惑背后的直觉:假设给出一个句子如下:教授给我的任务是 ____。一个更好的语言模型将通过基于使用训练集分配的条件概率值放置单词来产生有意义的句子。因此,我们可以说,语言模型能够多好地预测下一个单词并因此生成有意义的句子是由基于测试集分配给语言模型的困惑值来断言的。
香农可视化方法
这是一种从经过训练的语言模型生成句子的方法。假设经训练的语言模型是二元模型,则香农可视化方法创建如下句子:
根据概率选择一个随机二元模型(
,w)现在根据概率选择一个随机二元模型(w,x)以此类推,直到我们选择然后将单词串在一起
这里的和分别表示句子的开始和结束。例如:

Image credit: Speech and Language Processing (3rd edition), Chapter 3 Language Modeling with N-grams, Slide 39, available at http://web.stanford.edu/~jurafsky/slp3/3.pdf
近似于莎士比亚


Sentences generated from unigram, bigram, trigram and quadrigram language models trained using Shakespeare’s corpus. Image credit: Speech and Language Processing (3rd edition), Chapter 3 Language Modeling with N-grams, Figure 3.3, available at http://web.stanford.edu/~jurafsky/slp3/3.pdf
莎士比亚的语料库和句子生成使用香农可视化方法的局限性
令牌数= 884,647,类型数= 29,066。然而,在 V * V = 844 亿个可能的二元模型中,莎士比亚的语料库包含了大约 300,000 个二元模型。因此,大约 99.96%的可能二元模型从未在莎士比亚的语料库中出现过。结果,那些看不见的二元模型的二元模型概率值将等于零,使得句子的总概率等于零,进而困惑度等于无穷大。这是一个限制,可以使用平滑技术解决。
Quadrigram 更糟糕,因为它看起来像莎士比亚的语料库,因为它是莎士比亚的语料库,这是由于 Quadrigram 语言模型中的依赖性增加到等于 3 而导致的过度学习。
逼近华尔街日报

Sentences generated from unigram, bigram and trigram language models trained using The Wall Street Journal’s corpus. Image credit: Speech and Language Processing (3rd edition), Chapter 3 Language Modeling with N-grams, Figure 3.4, available at http://web.stanford.edu/~jurafsky/slp3/3.pdf
面向体貌特征抽取的无监督注意模型评估
1 背景
最近我在研究方面术语抽取问题。以无监督的方式提取体貌特征是一个非常具有挑战性的课题,大多数无监督的方法都是基于规则的。但是这些方法并没有达到良好的性能。你可以在 BiLSTM-CRF 中找到 1.1~1.3 的详细任务描述,用于方面术语提取。
在 Google 发表了“注意力是你所需要的一切”一文之后,注意力模型显示了它的无限潜力。所以我想知道如果使用注意力模型以一种无监督的方式提取体项会怎么样。然后我发现了这篇论文,一个用于方面提取的无监督神经注意模型。本文满足三个要求,无监督的方式,注意模型和方面提取。
在这篇文章中,我将展示我对这个无监督注意模型的实验过程。
2 无监督注意模型
这个注意力模型使用自动编码器架构,该架构分为两个部分。编码器部分是从嵌入层到编码器层(p_t),解码器是从编码器层到解码器层(r_s)。在编码器部分,注意力层会给每个句子中的每个单词分配注意力分数。然后通过使用注意力得分计算加权句子嵌入(Z_s)平均句子嵌入。加权句子嵌入将编码为p_t。最后,p_t将被解码为r_s。我们可以认为r_s是Z_s的重构。

首先,我们看到基于注意力的编码器部分,它包括注意力层。

e_wi是每个单词在一个句子中的嵌入向量。y_s是一个句子中所有单词的平均值。d_i表示每个单词在句子中的权重如何,这是一个原始的注意力得分。最后用一个 softmax 层来标准化句子中的关注值,而a_i就是一句话中每个词的关注分数。

Z_s:注意力加权句子嵌入。

Z_s是自动编码器的输入层,p_t是编码器层,r_s是解码层。
句子的重构:编码表示的降维-> Softmax 以确定方面的权重->方面嵌入的线性组合,其中权重来自计算的 Softmax。
2.2 损失函数

铰链损失,以最大化样本的编码表示和重构表示之间的内积,并最小化负样本的内积。

鼓励方面嵌入唯一性的正则化术语。任何两个不同方面嵌入的点积应该为零。

这是最终的目标函数。
2.3 培训后我们得到了什么
经过训练,我们可以得到一些有用的信息。
a_i:每个词的注意力得分。我们可以用注意力得分来找出哪个词是体项。在下面的例子中,单词“beef”在句子中的值最大,所以体术语是“beef”。在找到方面项之后,我们将在后面为 clustring 使用它的嵌入。Z_s:注意力增强句子嵌入。每个句子可以表示为一个嵌入向量。这可以用于其他自然语言处理任务,如类别分类和情感分类。T:方面嵌入(k x d维度矩阵,其中k为训练前经验设定的推断方面类别数,d为嵌入维度)。体貌嵌入用于近似词汇表中的体貌词。

- 每个方面类别的排名靠前的方面术语。

2.4 评估指标
即使论文中有几个评价指标,但大多数都需要人来识别结果。例如,在提取了方面术语单词之后,有人会识别这个单词是否属于特定的方面类别。在这个过程之后,我们可以计算 f1 的分数。
人类的认识可能包括错误。为了做一个公正的评价,我们用我们的方式来评价模型。
3 模型性能分析
我们首先看到每个方面类别中的顶部单词,以便对性能有一个直接的印象。
我们选择 SemEval2016 task 5 餐厅数据集(2000 个样本)作为测试数据集。我们首先在训练数据上使用 word2vec 来获得单词嵌入。然后在训练数据上训练注意力模型。最后,我们得到每个类别中的前 100 个单词。您可以检查这个 aspect.log 文件中的顶级方面术语。

这里我们拿第一个方面范畴来分析。我们可以认为这个方面类别与“职员”相关,因为顶部的词包含“女主人”、“服务员”、“服务员”等等。结果看起来很好。但如果我们仔细观察,会发现一些奇怪的东西。首先,顶部的单词包含一些像“电话”、“请求”、“问题”、“杂耍”这样的单词。意思是这个体范畴包含了很多不相关的词。第二,还有一些像“道歉”、“知情”、“无礼”之类的词。通常,体术语是名词,但这一类别包含许多动词和形容词。这意味着模型不能区分词性。如果我们看看其他方面类别,我们会发现同样的问题。
从另一方面来说,这可能只能说明聚类过程没有很好地工作。我们要直接看每句话中提取了哪些词。下面是分析笔记本:attention-word-analysis . ipynb。我们举一些例子来看表演。

我列出了每个句子中得分最高的前 3 个单词,但结果看起来并不好。在每个句子中,动词往往具有较高的注意力得分。
有几种方法可以提高性能:
- 将嵌入层设置为“可训练的”
- 用 Word2Vec 嵌入替换手套嵌入
- 尝试不同的方面类别号
尝试了这些方法后,我们之前提到的两个问题还是没有解决。因此,我们可以认为,这个模型可能不会很好地执行提取方面的术语任务。但是在其他任务中会有帮助吗?接下来,我们将评估该模型在其他 NLP 任务上的表现。
3.2 特征类别检测
SemEval2016 任务 5 有三个槽位。槽 1 是方面类别检测任务。共有 12 个类别。SERVICE#GENERA, AMBIENCE#GENERAL, DRINKS#PRICES, DRINKS#QUALITY, DRINKS#STYLE_OPTIONS, FOOD#PRICES, FOOD#QUALITY, FOOD#STYLE_OPTIONS, LOCATION#GENERAL, RESTAURANT#GENERAL, RESTAURANT#MISCELLANEOUS, RESTAURANT#PRICES, SERVICE#GENERAL。我们需要给每个句子分类。
人工注意
槽 1 的基准 f1 分数是 0.59928。但我们不知道即使注意力模型工作得很好,注意力模型是否能改善槽 1 任务。因此,首先我们必须证明,如果方面术语具有“正确的”注意力分数,则槽 1 性能应该大于 0.59928。
我们用下面的等式计算嵌入的每个句子。w表示体项词嵌入的权重。我们使用 GloVe 来获得 word 嵌入文件。

在这个slot 1-GloVe-attention . ipynb笔记本中,我们使用了两个手套文件:
- 手套 6B.200d
- 手套 6B.300d
- 手套. 840B.300d
而我们设置权重为 1,1.5,2,2.5,3,找出哪个权重最好。
结果如下。基准 f1 分数为 0.5993。在我们尝试了不同的权重后,最好的结果是 0.6506。因此,我们可以确认,如果注意模型给予体项高的注意分数,体范畴检测的性能将会提高。


嵌入具有更好的性能,但加载时间比其他两种文件长得多。而glove.6B.200d的 f1-score 与glove.6B.300d非常接近,所以我们选择glove.6B.200d进行后面的实验。
真正的关注
在我们证明增强句子嵌入有效后,我们将在现实中测试注意力模型。
这个片段是模型架构的代码。Z_s是每个句子中嵌入单词的平均总和。如果特征词有正确的注意分数,最终的 f1 分数应该大于基线。
结果看起来不太好。考试成绩只有 0.2057。即使我们对训练数据进行测试,f1 值也只有 0.4177,这与基线值相差甚远。
但是结果并不乐观。考试成绩只有 0.2057。即使我们对训练数据进行测试,f1 值也只有 0.4177,这与基线值相差甚远。
只使用句子嵌入可能不是一个好主意,所以我们一起使用 GloVe 和Zs。
我们用三种方式(连接、乘、加)将手套词向量和注意句向量结合起来,然后在训练数据和测试数据上进行测试。训练数据上的 f1 值远大于测试数据上的 f1 值,因此我们认为该模型过度拟合。
对于测试数据的结果测试,最好的结果是 0.52,但仍然低于基线。并且该得分的最大贡献来自手套词向量。所以注意力增强句子嵌入仍然没有达到很好的效果。此时,有必要进一步测试该模型的性能。至少我们已经知道这个模型不是方面提取的好选择。
3.3 结果分析
为什么这个模型在其他数据集上如此有效?
一个原因是论文的评估过程是高度定制化的。在方面识别步骤中,作者将 9 个类别(方面)分成 3 个类别(黄金方面),以评估无监督注意模型的性能。这种分组过程可能会削弱评估的质量。
其次是损失函数。损失是通过重构句子向量(r_s)和加权句子向量(Z_s)来计算的,这意味着该模型是为了学习对于重构句子什么是重要的。我们不能保证体项是重构句子最重要的特征,动词和形容词也很重要。这就是为什么体术语有这么多动词和形容词的原因。
第三是 autoencoder 架构,我们认为这是最关键的原因。作者选择这种自动编码器来表达无监督的方法,因此不再需要设计损失函数。损失函数不能直接捕获教师信号。使用 autoencoder 来提取方面项是一个很好的尝试,但是并没有达到我们预期的效果。
4 试错法
这一节,我就说说实验中的试错过程。
在本地实现模型后,第一件事就是如何检查模型的性能。但是我不能得到和报纸上显示的一样的 f1 分数。原因是 k-means 初始化特征簇的方式。在评估代码中,群集名称是手动分配的。如果我们训练模型,方面顺序可能会变得不同。因此,如果我们想要评估结果,我们必须自己查看方面集群结果,并为每个方面分配方面类别标签。
根据该论文,大多数度量标准需要人工识别结果。但是这个过程会引入人为误差。而且在训练过程中,我们甚至看不到评估分数,因为评估是在训练之后。为了得到一个令人信服的分数来证明这个模型确实有很好的效果,我们决定使用一些客观的指标。换句话说,我们可以测试这个模型的可移植性。
更具体地说,我们可以使用模型在训练后学到的东西来测试其他任务。这就像单词嵌入技术。如果我们使用嵌入模型来学习一个好的单词表示,这将提高其他 NLP 任务的性能,如情感分析、命名实体识别等。在我们的例子中,如果无监督模型很好地提取了方面术语单词,那么该模型所学习的也应该促进其他 NLP 任务。如果其他 NLP 任务得到提升,也可以证明无监督注意模型工作良好。这就是我们选择 SemEval 2016 Task 5 Slot 1 进行性能测试的原因。如果这不起作用,就没有必要做其他实验。
正如结果显示的那样,结果看起来并不好。所以我们的实验在测试结束后就停止了。
5 一些建议
我在这个模型上花了很多时间和精力,但它真的让我心碎: (
幸运的是,我从这一课中学到了很多。我希望我的经历可以帮助那些遇到同样情况的人。
首先,当你在现实世界中遇到问题时,不要沉迷于新方法。我之所以实现这个模型,是因为它包含了注意力模型、无监督和特征提取等关键词。但是这种方法没有其他可行的方法。可能说明这条路并没有太大的潜力和研究价值。
第二,向工业界寻求建议。在实验过程中,我做了大量的研究,并从一家顶级 IT 公司的高级开发人员那里找到了一些有用的建议。一位开发人员告诉我,如果数据域有限,使用字典收集相关单词是简单但有用的方法。例如,我的数据集是基于餐馆评论的,我们可以只计算单词数,并选择常见单词作为方面术语。有时候,基于规则的方法并不是一个坏的选择。
第三,仔细思考哪种方法适合你的问题。这里的方法是指监督方法、半监督方法和非监督方法。首先,我想使用无监督的方法来提取方面术语。但这是错误的。我应该做的第一件事是做一些研究,看看哪种方法最适合这个问题。如果监督方法运行良好,您应该尽可能多地收集带注释的数据。这个过程可能会很乏味,但这将立即改善您的模型。至于无监督的方法,基于规则的方法在行业中非常常见。
总的来说,最重要的是做更多的研究,阅读一些调查/评论论文,然后再深入研究一个具体的问题。
查看我的其他帖子 中 同 一个分类查看 !
GitHub:bramble Xu LinkedIn:徐亮 博客:bramble Xu
即使是数据和技术工作,求职信也是推销你人际技能的最佳方式
我不从事数据科学领域的工作,所以如果你在寻找如何获得真正特定于技术的数据科学工作的建议,我不是你要找的人。酪我在数据科学的附近做的工作;我从事法律和政策方面的工作,与数据科学的交叉越来越多。如果我想在这个交叉领域找到一个合作伙伴,他们的人际技能对我来说比他们的数据技能更重要。
这就是为什么,在我看来,求职信是不可或缺的。这是向潜在雇主展示这些人际技能的最佳方式。
我先重复一下我哥哥在关于这个话题的帖子中所说的,千篇一律、标准格式的求职信是没有用的。他还说得对,大多数寻找候选人的人都能看出某人只是在说他们认为未来雇主想听的话。我看过很多求职信,告诉我申请的人渴望在不利的情况下为那些不幸的人努力工作;我很少在求职信中看到有人这样说是什么意思。
所以我不提倡在你的申请中附上一封平淡无奇的“正是因为这些原因,我相信我非常适合”风格的求职信。但是我提倡像写简历一样努力写求职信。因为有一些事情求职信可以做到,而简历做不到。
首先,一份简历不能向潜在雇主展示你能像人一样交流。简历是一份清单。但是人们不会在列表中说话。一页长的声望协会和先前工作的清单并不能告诉我你能写,比如,一封清晰简洁的更新邮件。在法律和政策领域,即使是最专注于技术的职位也不得不为一群非技术人员写更新邮件(事实上,最专注于技术的职位不幸地往往是在这方面最挣扎的人)。
简而言之,沟通是我工作领域的关键,你应该抓住每一个机会向潜在雇主展示你擅长沟通。(如果你不擅长,那就去做吧。像磨练技术技能一样磨练你的沟通技能。)
第二,如果没有像求职信这样的个人信息,你的简历只是一大堆看起来越来越相似的文件中的一张。你的材料会被技术人员看,但也会被人力资源部看,在我的世界里,至少会有几个律师。合格的技术人员在非技术人员(比如像我这样的人)看来都差不多。但是如果我看到一个真实的人,具有真实的人类特征,与那些合格的候选人混在一起,我就更有可能注意到。
第三,也许是最重要的,当我试图挑选一个人一起工作时,我总是在寻找那些已经知道我不能教的东西的人(或者至少是我不能轻易教的东西)。任何愿意的人都可以学习新的技能或主题。我花了一年时间向一位 IT 专家教授刑事诉讼和州政府基金(作为交换,我学会了 SQL 查询和数字法医调查)。人们可以学习他们需要学习的东西。
但在公共辩护领域工作多年后,我明白了最重要的事情是那些你教不了的。你不能教一个人去同情和他们不一样的人。你不能教人们放下自我去做艰苦的、朴实无华的工作。你当然不能轻易地教会人们如何在一个多样化的团队中有效地工作。
因为我一直在寻找那些已经有激情和能力与他人一起制定共同价值观的候选人,所以我一直在寻找一封展示这些东西的求职信。一份简历做不到这一点。
所以,如果你想推销你的人际技能,而不仅仅是技术技能,不要跳过求职信。
这是我哥哥乔丹·戈尔德迈尔(Jordan Goldmeier)一篇关于数据科学工作求职信的文章的对比。更多关于技术职位求职信的建议,请阅读他的文章。
事件驱动架构模式
入门和实践中的一瞥
这是用于开发高度可伸缩系统的最常见的分布式异步架构。该体系结构由单一用途的事件处理组件组成,这些组件监听事件并异步处理它们。
事件驱动架构中有两种主要的拓扑结构。
- 中介拓扑
- 代理拓扑
中介拓扑
中介拓扑有一个事件队列和一个将每个事件导向相关事件处理器的中介。通常,事件通过事件通道被送入事件处理器,以过滤或预处理事件。
事件队列的实现可以是简单消息队列的形式,甚至是大型分布式系统中的消息传递接口,该系统涉及复杂的消息传递协议,如 Rabbit MQ。下图展示了中介拓扑的架构实现。

Mediator Topology for Event Processing
代理拓扑
这种拓扑不涉及事件队列。事件处理器负责获取事件,处理和发布另一个表示结束的事件。正如拓扑的名称所暗示的,事件处理器充当链接事件的代理。一旦一个事件被一个处理器处理,另一个事件被发布,以便另一个处理器可以继续处理。
考虑下图。

Broker Topology for Event Processing
如图所示,一些事件处理器只是处理而不留下任何痕迹,一些倾向于发布新事件。这与我们在 NodeJS 应用程序中看到的非常相似。某些任务的步骤以回调的方式链接在一起,当一个任务结束时,就触发回调。所有的任务本质上都是异步的。
NodeJS 事件循环
下图展示了官方文档中描述的 NodeJS 架构。
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
所有传入的连接都被推入轮询,它们将被异步处理。这不会阻止正在处理的其他呼叫。因此,该架构提供了更大的单线程可扩展性。我们可以运行几个节点进程,在它们之上平衡负载,并相应地引导请求。
延伸阅读:https://nodejs . org/en/docs/guides/event-loop-timers-and-next tick/
少数事件驱动的 web 框架
- netty(JAVA)——https://netty . io
- 垂直。X (JVM 语言)— http://vertx.io
- spring Reactor(JAVA)——https://spring.io/guides/gs/messaging-reactor/
- http://reactphp.org
模式分析
该模式缺乏事务的原子性,因为不能保证事件的执行顺序。这是因为事件处理器被实现为高度分布式、解耦和异步的。结果预计将在未来某个时间提供,主要是以回调的方式。
易测性
由于处理的异步性质,测试具有事件驱动架构的系统并不容易
表演
由于任务本质上是异步和非阻塞的,所以执行是并行的。因此,这超过了提供高性能的排队机制的成本。
可扩展性和易开发性
尽管系统是高度可扩展的,但是开发工作是巨大的。这是因为单元测试和组件测试由于异步特性而变得困难,这使得系统具有可伸缩性。由于事件处理器的解耦特性,系统可以并行运行,从而提高可伸缩性和并行性。
秘密身份骗不了现代人脸识别

和我这个年龄的大多数人一样,我试图给我的孩子看 1978 年的原版《超人》,向他们介绍我最喜欢的超级英雄,这时我 4 岁的孩子大声问为什么没人认出克拉克·肯特就是超人:钢铁之躯。
这让我想到了超级英雄的秘密身份以及它们对现代人脸识别技术的有效性。
很有可能,如果一个 4 岁的孩子能认出某人,那么机器学习模型也能。所以我决定测试一下。
自然,我的第一个测试是看我能否训练一个模型来识别超人是克拉克·肯特。在电影中,他的伪装完美无缺。似乎没有人能看着克拉克的脸认出他是超人。在我的想象中,这是因为没有人真正看清楚超人(因为他总是飞来飞去什么的),所以很难回忆起他长什么样。但是面对现代 AI,要中止我的不相信越来越难了(哈哈)。
今天,几乎任何媒体公司都可以对其所有内容进行人脸识别,并注意到《星球日报》第二好的记者是来自氪星的外星人。下面是我如何进行测试的:
首先,我找了一张克拉克·肯特完全伪装的照片。

Christopher Reeve will always be Superman to me
我复制了照片的网址,并在我的电脑上打开了一个 Facebox 的实例。我在我的网络浏览器中打开控制台,向下滚动到/teach终点,并使用小演示工具教 Facebox 这张图片。我给它贴上标签克拉克·肯特。
然后,为了测试它,我打开了控制台的 live demo 部分,粘贴了一个 URL 到一个超人看起来最帅的屏幕截图(他是怎么卷曲的?):

Screenshot of the Facebox console
它立刻认出了他。我只训练了一个例子的人脸识别模型!超人的秘密身份看来不妙。也许他应该换个发型?

Still image from Superman III
不——那也不起作用。
所以我决定测试其他超级英雄的秘密身份,看看他们如何对抗 Facebox。
卡拉·丹弗斯怎么样?


没有。
奥利弗·奎恩怎么样?

用这张图片教了 Facebox,让我们看看结果:

没有——还是认出了他。即使戴着面具和兜帽。
Facebox 和其他好的人脸识别系统将能够理解人脸的结构,而不管假眼镜、面具或头发是否模糊。
深度学习模型模糊地受到生物神经系统中信息处理和通信模式的启发。神经网络寻找其他方法来识别人脸,类似于人类如何识别。这就是为什么这些伪装骗不了一个深度学习模型。


Taught Facebox Dick Grayson on the left, tested it with Robin on the right.
实际上,我有点惊讶,它仅仅用一张照片就能很好地识别出这些人。其实你可能根本不相信我,我也不会怪你。这就是为什么我鼓励你自己尝试一下。下载 Facebox ,右键点击上面的训练图像并保存到你的硬盘上,然后,按照 Facebox 控制台上的指示教脸。教学后,在控制台中打开现场演示,用你在互联网上(或在这篇博客中)找到的任何图像进行测试。

享受吧。
每个人都讨厌垃圾邮件,我们如何阻止它?

我讨厌垃圾邮件。你讨厌垃圾邮件。每个人都讨厌垃圾邮件。但是我们如何阻止已故亚瑟·范·杜克爵士的儿子试图把他们的财产寄给我们呢?嗯,最显而易见的解决方案是雇佣一组猴子来阅读和检查每封邮件中的垃圾邮件。但是我想我们都同意这不太实际,说实话,猴子并不真的那么聪明。相反,像谷歌这样的大公司所做的是使用机器学习来区分恶意发送的电子邮件和来自老板的电子邮件,老板对你错过昨天的会议非常不满。
我们如何检测垃圾邮件?
垃圾邮件检测使用一种机器学习算法,可以将电子邮件分类为垃圾邮件/非垃圾邮件,它从您训练它的数据中学习如何做到这一点。Gmail 每天都会收到大量数据,这些数据来自像你我这样的人,他们报告说,如果他们的收件箱收到了垃圾邮件。每次你这样做,Gmail 的预测模型在识别垃圾邮件时都会稍微好一点。你可以想象,制作一个真正好的垃圾邮件分类器需要大量数据,这就是为什么 Gmail 有最好的分类器之一——多年来,他们收集了大量数据,以帮助他们更好地识别垃圾邮件。

人们能够对垃圾邮件进行分类的一种方法是使用逻辑回归。逻辑回归是一种预测模型,当您试图预测的数据是分类数据(1 和 0、是和否等)时,您可以使用它。逻辑回归使用逻辑函数来进行预测。

Logistic Function(Sigmoid) — Source
这是一个被称为 Sigmoid 的逻辑函数的图形,它被用于二元分类预测。基本上将事物分为两类。这个函数需要优化,以适应我们的数据集,这样它就可以做出很好的预测。为了做到这一点,我们使用一种叫做成本函数的东西——它计算出与我们的预测模型有多大的误差,然后我们试图通过使用梯度下降来修正它。这些都是相当复杂的话题,我不会多谈。如果你想了解更多,可以查看这个链接。
我们自己做
现在我们知道了垃圾邮件分类器的基本工作原理,我们可以使用 Python 创建自己的程序,只用 10 行代码就可以对邮件进行分类。
我们将只使用 Scikit-Learn 和 Pandas 作为我们的依赖项,然而,在最后会有一个 Google Colab 链接,在那里你将能够跟随代码并在线运行一切。
如果您想自己编写代码,请确保从这个链接中获取数据集!该数据集包含几千封不同的邮件,这些邮件都被分类为垃圾邮件和非垃圾邮件。
我们需要导入 Pandas 来加载我们用来训练模型的数据。我们将使用 Scikit-Learn 的内置逻辑回归作为我们的预测算法——这非常容易使用,让我们只用一行代码就可以建立一个模型,但是,如果你想从头开始学习如何编写逻辑回归模型,请查看这个链接。我们还需要 CountVectorizer,它对单词的重复次数进行计数,并将该数字放入一个数组中,这样我们的算法就可以在数据中找到模式。
现在,我们使用 pandas 加载数据,并初始化我们的逻辑回归模型和计数矢量器。Scikit-Learn 的逻辑回归模型已经配备了我们使其工作所需的所有部件;逻辑函数、成本函数和梯度下降。所以我们需要做的就是运行一个命令。
数据集的“v2”列中的数据是我们想要分类的短语,而“v1”有标签(分别是“火腿”和“垃圾邮件”)。计算机计算单词的重复次数,并将它们插入一个数组,这基本上只是将这些短语变成数字。这样做之后,我们创建另一个数组,其中包含消息中数据的所有分类器。最后,我们可以使用数据和目标来训练我们的模型。
在我们将数据拟合到我们的模型之后,我们可以对它进行一些预测!您可以运行这个命令,用您自己的消息替换引号内的内容,看看它是否被归类为垃圾邮件。
就是这样!创建我们的机器学习模型来检测垃圾邮件只需要 10 行代码。如果你想玩玩它,去我的 Google Colab 大纲。
在本文中,我们介绍了机器学习如何用于分类垃圾邮件,这可能是比使用猴子更好的替代方法。这是一个很酷的话题,我们每天都在体验这种努力的成果,但机器学习的应用确实是无限的,随处可见。
数据安全、医疗保健和在线一切等巨大行业已经被机器学习彻底改变了。请记住,这只是我们通过机器学习可以实现的目标的开始,可以改变我们生活的新技术每天都在被发现。
感谢阅读!我希望你喜欢我的文章,并学到一些新东西。如果有,请务必通过以下方式与我联系:
- 或者发邮件给我:aryanmisra@outlook.com
首席执行官需要知道的关于人工智能的一切
人工智能是如何工作的。你能用它做什么。以及如何入门。

人工智能就是把 A 和 B 连接起来
关于人工智能的信息经常令人困惑,有时甚至是彻头彻尾的误导。不过艾对于商业很简单:
“今天人工智能创造的 99%的经济价值都是通过一种人工智能来实现的,这就是学习 A 到 B 或输入到输出的映射。” 吴恩达
今天,人工智能的几乎每一个商业应用都是关于学习从某些输入产生某些输出:

AI 如何学会预测正确的输出?
- 您收集了输入->输出对的示例(越多越好)。
- AI 算法学习输入和输出之间的联系(这就是神奇之处)。
- 你将训练好的算法(即“模型”)应用于新的输入数据来预测正确的输出。
就是这样!几乎所有用 AI 做$$的人都是完全这样做的。
当你有很多数据的时候使用 AI
人工智能需要数据
人工智能是强大的,因为它将数据转化为洞察力。但是人工智能的学习效率不如人(是的,效率更低),所以它需要大量的数据来学习。如果你有大量的数据,你应该考虑人工智能!
数据是竞争优势,不是算法。
这就是为什么谷歌和脸书对开源他们的算法没有任何问题。但是他们绝对不会公开他们的数据。如果你有很多别人没有的数据,那么这就是建立一个独特的人工智能系统的绝佳机会。
找到你的人工智能用例的 3 个最简单的方法
所以你有很多数据。现在你做什么?以下是我知道的发现人工智能用例的 3 种最佳方式:
1.改善自动化决策
您在哪里拥有自动化基于规则的决策的软件?
例如:
- 呼叫路由
- 资信评分
- 图像分类
- 市场细分
- 产品分类
人工智能很有可能提高这些决策的准确性,因为人工智能模型可以捕捉更多连接 A 和 b 的底层复杂性。相比之下,当你手动将规则写入软件时(传统方式),你只能编码基本的依赖关系。
对于我们的一个客户(ImmobilienScout24),我们的电子邮件收入增加了 250%。只需将基于规则的电子邮件分段替换为更智能、更精细的 基于人工智能的分段 。
2.人们可以在< 1 second
Another great heuristic I first heard from Andrew Ng is:
中做的事情“一个正常人在< 1 秒内可以做的几乎任何事情,我们现在都可以用人工智能来自动化。” 推特
那么在< 1 sec?
- Who’s in that picture?
- Do I have a good feeling about this potential customer?
- Does this look like a problematic CT Scan?
Also many jobs are 一系列< 1 秒决策中,人类可以决定哪些事情。喜欢开车:
- 那个人要过马路吗?
- 我离人行道太近了吗?
- 我应该慢下来吗?
- …还有很多很多。
你能在不到 1 秒钟内完成的任何事情,AI 很可能也能做到。(或者很快就能)。
3.从 Kaggle 竞赛中获得灵感

像 Zillow 、 Avito 、 Home Depot 、 Santander 、 Allstate 、 Expedia 这样的大公司正在 Kaggle 上举办数据科学竞赛。这些是他们希望外部数据科学家解决的挑战。因此,这些比赛让你了解他们正在开发什么类型的人工智能解决方案。这真的是一个很好的资源。
看看比赛并从中获得灵感。
TL;DR:寻找人工智能用例:
- 升级已经自动化的决策
- 自动化人们在< 1 sec
- Get inspired by Kaggle competitions
Don’t wait until you have a Data Science Team
Building a good data science team is super hard (and expensive!)
Many companies struggle (and ultimately fail) to build an 高效数据科学团队中做的事情。为什么这么难?
- 关于雇佣谁的错误信息
- 激烈的人才竞争
- 很少有管理者能够有效地领导数据科学团队
更重要的是…
你还不知道你是否需要一个数据科学团队
你可能有很多数据和想法,但这并不意味着你需要自己的数据科学团队。只有在你建立了你的第一个人工智能系统之后,你才会真正知道从长远来看你需要多少人力。所以…
快速构建有效的东西
你的第一个目标应该是摘下挂得最低的 AI 果并快速完成。这会让你遥遥领先:
- 你会取得切实的成功,让投资者、董事会和你的团队兴奋不已;
- 你将了解人工智能的味道,并获得什么有效什么无效的真实体验;
- 你会对下一步在哪里使用 AI 有更好的想法。
有了第一个完成的系统,您就能更好地雇佣和培训数据科学团队。或者也许你发现你不想(或不需要)雇用整个团队,因为那个容易摘到的果子已经占了你可以用人工智能做的事情的 80%。
人工智能团队应该在整个公司范围内工作
如果你确实建立了一个 AI 团队,你应该为整个公司建立,而不仅仅是一个部门。一支横艾的队伍。
不要在部门中思考
人工智能体验是非常可转移的:对一个数据科学家来说,你的 CRM 数据看起来和你的库存数据几乎一样。对于算法来说,它们看起来更相似。因此,为整个公司建立一个人工智能工作组是非常有意义的。
旁注:为了工作,你也应该把你的数据放在一个地方!
更多救生技巧

不要听别人推销“更好的算法”
要么他们没有经验,要么他们试图向你出售开源软件以获取利润。在人工智能中,每个人都在用水做饭,这意味着他们使用公开可用的算法。
关注业务体验和工程质量
与那些花时间真正理解你试图解决的业务问题并且在工程质量方面有高标准的人一起工作。如果你想得到更多的结果而不那么麻烦,那么管道比流过管道的可爱算法更重要。
魔力三角会议😋
当你把三种类型的人放在一个房间里时,最好的想法就产生了:
- 了解当前业务重点的人(你?),
- 知道你拥有的数据的人(你的数据库工程师),以及
- 一个在构建人工智能系统方面有丰富实践经验的人。
这三个人一起就能做出现实的计划,真的很快。
TL;速度三角形定位法(dead reckoning)
就这样:
- AI 就是把 A 和 b 连接起来。
- 研究涉及大量数据和不到 1 秒决策的流程。
- 在你制定大计划之前取得第一次胜利。
如果你一路上需要帮助,给我写信。我总是很高兴听到令人兴奋的挑战: m.schmitt 在 datarevenue.de
最初发表于T5【www.datarevenue.com】。
关于 AutoML 和神经结构搜索你需要知道的一切
想获得灵感?快来加入我的 超级行情快讯 。😎
AutoML 和神经架构搜索(NAS)是深度学习城堡的新国王。它们是在不做太多工作的情况下,为您的机器学习任务获得巨大准确性的快速而肮脏的方法。简单有效;这就是我们想要的人工智能!
那么它是如何工作的呢?你如何使用它?今天你有什么选择来驾驭这种力量呢?
这里是您需要了解的关于 AutoML 和 NAS 的所有信息。
神经结构搜索(NAS)
开发神经网络模型通常需要大量的架构工程。有时你可以通过转移学习,但是如果你真的想要最好的性能,通常最好设计你自己的网络。这需要专业技能(从商业的角度来看,这很昂贵,),总体来说具有挑战性;我们甚至可能不知道当前最先进技术的极限!这需要反复试验,而且实验本身既耗时又昂贵。
这就是 NAS 的用武之地。NAS 是搜索寻找最佳神经网络架构的算法。大多数算法都是这样工作的。首先定义一组可能用于我们网络的“构建块”。例如,最先进的 NASNet 论文提出了图像识别网络的这些常用模块:

NASNet blocks for image recognition network
在 NAS 算法中,控制器递归神经网络(RNN)对这些构建块进行采样,将它们放在一起以创建某种端到端架构。这种架构通常体现了与最新网络相同的风格,如 ResNets 或 DenseNets ,但使用了非常不同的块组合和配置。
然后,这个新的网络体系结构被训练收敛,以在保留的验证集上获得一定的准确性。由此产生的精度用于更新控制器,使得控制器将随着时间的推移产生更好的架构,可能通过选择更好的块或进行更好的连接。控制器权重用策略梯度更新。完整的端到端设置如下所示。

The NAS algorithm
这是一种相当直观的方法!简而言之:让一个算法抓取不同的块,并将这些块放在一起组成一个网络。训练并测试网络。根据您的结果,调整您用来制作网络的块以及如何将它们放在一起!
这个算法成功的部分原因是因为它的约束和假设。NAS 发现的体系结构是在比真实世界小得多的数据集上训练和测试的。这样做是因为在像 ImageNet 这样的大型系统上进行训练需要很长时间。但是,这个想法是,在较小但结构相似的数据集上表现更好的网络也应该在较大和更复杂的数据集上表现更好,这在深度学习时代通常是正确的。
第二,是搜索空间本身相当有限。NAS 旨在构建在风格上与当前最先进的体系结构非常相似的体系结构。对于图像识别,这是指在网络中有一组重复的块,同时进行逐步下采样,如下左图所示。在当前的研究中,选择一组积木来建造重复积木也是非常普遍的。NAS 发现网络的主要部分是块如何连接在一起。
在右下方查看 ImageNet 网络的最佳发现块和结构。有趣的是注意到它们是如何包含看起来相当随机的混合运算,包括许多可分离的卷积。


建筑搜索的进展
NASNet 的论文具有惊人的进步性,因为它提供了深度学习研究的新方向。不幸的是,它的效率很低,而且谷歌之外的普通用户无法访问。使用450 GPU花了3-4 天的训练才找到那个伟大的架构。因此,NAS 的许多最新研究都集中在使这一过程更加高效。
渐进式神经架构搜索(PNAS) 提出使用所谓的基于序列模型的优化(SMBO)策略,而不是 NASNet 中使用的强化学习。使用 SMBO,我们不是随机地从外部集合中抓取和尝试块,而是测试块并按照复杂度增加的顺序搜索结构。这不会缩小搜索空间,但它确实使搜索以更智能的方式进行。SMBO 基本上是在说:不要一次尝试所有的事情,让我们从简单开始,只在需要的时候变得复杂。这种 PNAS 方法的效率是原始 NAS 的 5 到 8 倍(因此成本更低)。
高效的神经架构搜索(ENAS) 是另一种尝试,试图使一般的架构搜索更有效,这一次普通的 GPU 从业者都可以使用。作者的假设是,NAS 的计算瓶颈是训练每个模型收敛,只测量其测试精度,然后扔掉所有训练的权重。
研究和实践已经反复表明,迁移学习有助于在短时间内达到高精度,因为为有些相似的任务训练的网络发现相似的权重;迁移学习基本上只是网络权重的转移。ENAS 算法迫使所有模型共享权重,而不是从零开始训练到收敛。我们以前在以前的模型中尝试过的任何块都将使用那些以前学习的权重。因此,每次我们训练一个新的模型,我们本质上都在做一个转移学习,收敛得更快!
论文中的表格显示了 ENAS 使用单个 1080Ti GPU 半天的训练效率有多高。

Performance and efficiency of ENAS
深度学习的新方式:AutoML
许多人将 AutoML 称为进行深度学习的新方式,这是整个系统的一种变化。我们不用设计复杂的深度网络,只需运行预设的 NAS 算法。谷歌最近将这一点发挥到了极致,推出了云自动化。只需上传你的数据,谷歌的 NAS 算法就会为你找到一个架构,又快又简单!
AutoML 的想法是简单地抽象出深度学习的所有复杂部分。你需要的只是数据。让 AutoML 来做网络设计的难点就好了!深度学习就像其他工具一样变成了一个插件工具。获取一些数据,并自动创建一个由复杂的神经网络驱动的决策函数。

Google Cloud’s AutoML pipeline
Cloud AutoML 的价格高达 20 美元,不幸的是,一旦你的模型被训练好,你就不能导出它;你必须使用他们的 API 在云上运行你的网络。有几个完全免费的替代方案,但是需要多做一点工作。
AutoKeras 是一个使用 ENAS 算法的 GitHub 项目。它可以使用 pip 安装。因为它是用 Keras 编写的,所以很容易控制和使用,所以你甚至可以深入 ENAS 算法并尝试做一些修改。如果你更喜欢 TensorFlow 或 Pytorch,这里还有那些这里和这里的公共代码项目!
总的来说,现在有几种选择来使用 AutoML。这只是取决于你是否会玩弄你想要的算法,以及你愿意付出多少来获得更多的代码抽象出来。
NAS 和 AutoML 的未来预测
很高兴看到过去几年在自动化深度学习方面取得的长足进步。它使用户和企业更容易接触到它;深度学习的力量变得越来越容易为大众所接受。但是,总有一些改进的空间。
建筑搜索变得更加高效;像 ENAS 一样在一天的训练中找到一个只有一个 GPU 的网络是非常令人惊讶的。然而,我们的搜索空间仍然非常有限。当前的 NAS 算法仍然使用手工设计的结构和构建块,它们只是以不同的方式将它们放在一起!
一个强大的和潜在的突破性的未来方向将是更广泛的搜索,真正寻找新的架构。这种算法可能会揭示这些庞大而复杂的网络中隐藏的更多深度学习秘密。当然,这样的搜索空间需要高效的算法设计。
NAS 和 AutoML 的这一新方向为人工智能社区提供了令人兴奋的挑战,也为科学领域的另一次突破提供了机会。
你想知道的关于纽约市餐馆等级的一切
任何去过纽约市的人都可能注意到几乎所有餐馆的餐馆字母等级。字母等级是在 2010 年引入的,范围从 A 到 C,A 是最高(最好)的评级。餐馆被要求清楚地展示字母等级,尽管一些机构很有创意。

The “B” is for Brunch!
我一直对收视率很好奇,既然数据可以在网上获得,我想我应该亲自测试一下。TLDR:检查员不喜欢给除了 As 以外的分数,不喜欢周末工作,连锁餐厅也很干净。还有一个我无法解开的谜团(跳到结尾,关于餐馆多久被评论一次)。所有的代码都可以在这里找到。
无聊的东西
数据(186,185 行,12 列):

DBA 是餐厅名称,其余部分不言自明。餐厅的命名并不总是一致的(例如星巴克和星巴克咖啡),所以我必须稍微清理一下。
数据集提供了每家餐厅的历史评分以及最近的评分。但是评级也分为重要和不重要两类。因此,一个评级将有两行,一行表示严重违规,另一行表示非严重违规。所以我删除了关于违规描述/类型的信息,并删除了重复的内容。
由于数据集包含历史信息,我还为每个餐馆创建了一个惟一的键。为此,我创建了一个结合了餐馆名称、建筑、街道和邮政编码的值(例如,DARKHORSE 17 MURRAY STREET 10007)。
成绩的分类是什么?
分数从 0 开始。低分数是好的,因为它表示没有违规。每个违规都有一定的分值,因此 0 分意味着没有违规。有三种类型的违规:
- 一般——例如,没有正确消毒烹饪用具——最低 2 分
- 关键——例如,提供生的食物,如沙拉,但没有先清洗干净——最低 5 分
- 公共健康危害——例如,未能将食物保存在合适的温度下——最低 7 分
最终成绩是基于所有分数的总和。
- 0 到 13 岁的学生得 A
- 14 岁到 27 岁可以得 B
- 28 岁或以上得 C
下面可以看到按百分比分列的成绩细目,按最近成绩和所有成绩分组。

我并不感到惊讶,大部分成绩是 As,只有不到 2%的检查结果是 C。数字分数的分布情况如何?

在从 A 到 b 的分界点上有 14 个点的急剧下降。来自城市的网站:
两种类型的检查会导致字母等级:餐厅获得 A 的初次检查和获得 A、B 或 c 的再次检查。餐厅在每个检查周期有两次获得 A 的机会。如果它在第一次检查中没有获得 A,它被计分但未被分级。检查员通常会在一个月内突然回到餐馆,再次检查,并对再次检查进行评分。如果等级为 B 或 C,餐厅将获得等级卡和等级待定卡。它可以邮寄任何一张卡片,直到它有机会在行政审判和听证办公室健康法庭得到听证。直到一家餐厅有了分级检查,才在卫生部门网站上列为尚未分级。
因此,非 A 级最初不会被报道,餐厅还有一次机会。这抑制了报告的 B 和 C 等级。但是在 A 到 B 的分界点上的高分数是很奇怪的。我的猜测是,视察员在接近禁产门槛时会表现出宽容。如果很接近,检查员会给餐馆更高的分数,因为字母分数对顾客来说是最明显的部分。它也可能是分配给每个违规的分数的结果。例如,严重违规最低为 5 次,公共健康危害最低为 7 次。所以 10 分或 12 分应该更常见,这就是我们看到的。
检查员什么时候检查?

看来食品检查员不喜欢周末工作,尤其是周日。哦,他们在七月也很放松。
这些年来有分数膨胀吗?

呃,也不尽然。第一年只有大约 80%的 A 评级,但样本量只有大约 100 人。B 级和 C 级评级分别稳定在 12%和 4%左右。今年到目前为止还有很多 Z 或者还没有评分。
哪些餐厅的菜肴评价最高?
数据集对美食描述的命名不一致(例如,16 柄有时归类为美式,有时归类为冰淇淋)。在这种情况下,我使用了最常见的美食描述。我也排除了评级总数少于 50 的公司。分数越低越好(违规越少)。

收视率出奇的好,但我想这是大型连锁店的预期。记住高分是不好的。一些机构像苹果蜂的,Panera 面包和白色城堡(!)除了 a 之外从来没有拿到过一个公开的成绩,其他像达美乐这样的团体很不一致,经常很差(他们拿到的成绩只有 81%是 a,5%是 c)。然而,麦当劳在所有大型餐厅中拥有最差(最高)分数 62 分的可疑荣誉。
个别餐厅的评分如何随时间变化?
考虑这个问题的一个方法是通过滚动率。滚动率是从一种状态转换到另一种状态(或停留在同一状态)的概率。我根据从一个等级到另一个等级的概率创建了一个滚动率(关于如何创建滚动率的更简单的通用示例,请参见这个堆栈溢出问题)。

大约 90%的情况下,A 评级会在下一次检查中再次获得 A。在下一次评级中,B 级餐厅有 71%的机会获得 A 级,C 级餐厅有 68%的机会获得 A 级。这对那些在 B 级和 C 级餐厅用餐的人来说应该是一种安慰。
餐厅多长时间保持一个给定的等级?
我查看了每家餐厅点评的时间间隔。我把它按等级分类,因为我发现等级低的餐馆更容易被评论。

从上面看不出来,但是 A 级有双峰分布。

我花了一些时间试图找出区别,但我从来没有找到一个令人满意的答案。A 级天数的分布在几年内和几个月内都是一致的。一般来说,所有菜系和所有行政区都是双模式的。
这多少与餐馆被分级的频率有关,但不是绝对相关(例如,像星巴克这样的餐馆几乎都在右峰)。我可能遗漏了一些显而易见的东西,但我猜测这是由于一些没有报告的分数。如前所述,如果一家餐馆得到了 B 以外的分数,分数不会被报告,餐馆在一个月内还有机会得到 A。我的猜测是,未能通过这一未被报道的评级会导致餐馆更频繁地被审查。这就解释了为什么评级高的餐厅很少得到评级。即使你看看那些从未被评为 A 级以下的餐馆,双峰分布也是存在的,但那可能只是因为非 A 级餐馆没有被报道。
我对其他想法持开放态度。

It always existed

Large chains are still somewhat bi-modal

Even those with perfect grades are bi-modal

Bi-modal across months

No clear pattern between A-grade consistency and time at grade
推销员的进化:Python 的完整遗传算法教程
从自然选择中汲取灵感,遗传算法(GA)是一种解决搜索和优化问题的迷人方法。虽然已经有很多关于遗传算法的文章(见这里的和这里的),但很少有人展示用 Python 一步一步实现更复杂问题的遗传算法。这就是本教程的由来!继续学习,到最后,您将完全理解如何从头开始部署 GA。

Photo by chuttersnap on Unsplash
介绍
问题是
在本教程中,我们将使用遗传算法来寻找旅行推销员问题(TSP)的解决方案。TSP 描述如下:
给定一个城市列表和每对城市之间的距离,访问每个城市并返回起始城市的最短可能路线是什么

Illustration of a potential solution to the TSP (By Xypron [Public domain], from Wikimedia Commons)
有鉴于此,有两条重要的规则要记住:
- 每个城市只需要被访问一次
- 我们必须回到出发城市,所以我们的总距离需要相应地计算
方法
让我们从几个定义开始,在 TSP 的上下文中重新表述:
- 基因:一座城市(用(x,y)坐标表示)
- 个体(又名“染色体”):满足上述条件的单一途径
- 群体:可能路线的集合(即个体的集合)
- 父级:两个路由组合在一起创建一个新路由
- 交配池:用于创建我们下一个种群(从而创建下一代路线)的亲代集合
- Fitness: 一个告诉我们每条路线有多好的函数(在我们的例子中,距离有多短)
- 变异:通过随机交换路线上的两个城市,在我们的人口中引入变异的一种方式
- 精英主义:将最优秀的个体带入下一代的一种方式
我们的 GA 将按以下步骤进行:

1.创造人口
2.确定适合度
3.选择交配池
4.类型
5.使突变
6.重复
现在,让我们来看看实际情况。
构建我们的遗传算法
虽然我们 GA 的每个部分都是从头开始构建的,但我们将使用一些标准包来简化工作:
import numpy as np, random, operator, pandas as pd, matplotlib.pyplot as plt
创建两个类:城市和健身
我们首先创建一个City类,它将允许我们创建和处理我们的城市。这些只是我们的(x,y)坐标。在 City 类中,我们在第 6 行添加了一个distance计算(利用毕达哥拉斯定理),并在第 12 行使用__repr__以更简洁的方式输出城市坐标。
我们还将创建一个Fitness类。在我们的例子中,我们将适应度视为路径距离的倒数。我们希望最小化路线距离,因此较大的适应值更好。基于规则#2,我们需要在相同的地方开始和结束,所以这个额外的计算在距离计算的第 13 行中被考虑。
创造人口
我们现在可以制造我们的初始种群(又名第一代)。为此,我们需要创建一个函数来生成满足我们条件的路线(注意:我们将在教程的最后实际运行 GA 时创建我们的城市列表)。为了创建个人,我们随机选择访问每个城市的顺序:
这产生了一个个体,但我们需要一个完整的群体,所以让我们在下一个函数中这样做。这就像循环执行createRoute函数一样简单,直到我们为我们的人口找到尽可能多的路线。
注意:我们只需使用这些函数来创建初始群体。后代将通过育种和突变产生。
确定适合度
接下来,进化的乐趣开始了。为了模拟我们的“适者生存”,我们可以利用Fitness对种群中的每个个体进行排名。我们的输出将是一个有序的列表,其中包含路线 id 和每个相关的健身分数。
选择交配池
对于如何选择将用于创建下一代的父代,有几个选项。最常见的方法是健身比例选择(又名“轮盘选择”)或锦标赛选择:
- 适应度比例选择(下面实现的版本):每个个体相对于群体的适应度用于分配选择的概率。把这想象成被选中的适应度加权概率。
- 锦标赛选择:从群体中随机选择一定数量的个体,选择群体中适应性最高的个体作为第一个父母。如此反复选择第二个亲本。
另一个需要考虑的设计特点是使用精英主义。在精英主义下,群体中表现最好的个体将自动延续到下一代,确保最成功的个体得以延续。
为了清楚起见,我们将分两步创建交配池。首先,我们将使用来自rankRoutes的输出来确定在我们的selection函数中选择哪些路线。在第 3–5 行,我们通过计算每个人的相对健康体重来设置轮盘赌。在第 9 行,我们比较随机抽取的数字和这些重量来选择我们的交配池。我们还想保留我们的最佳路线,所以我们在第 7 行引入了精英主义。最终,selection函数返回一个路由 id 列表,我们可以用它在matingPool函数中创建交配池。
现在我们已经从selection函数中获得了将组成我们的交配池的路由的 id,我们可以创建交配池了。我们只是从我们的人口中挑选出一些人。
类型
随着交配池的建立,我们可以在一个叫做杂交(又名“繁殖”)的过程中创造下一代。如果我们的个体是由 0 和 1 组成的字符串,而我们的两个规则不适用(例如,假设我们正在决定是否将一支股票纳入投资组合),我们可以简单地选择一个交叉点,然后将这两个字符串拼接在一起,产生一个后代。
然而,TSP 是独一无二的,因为我们需要一次包含所有的位置。为了遵守这个规则,我们可以使用一个叫做有序交叉的特殊繁殖函数。在有序交叉中,我们随机选择第一个父字符串的一个子集(见下面的breed函数中的第 12 行),然后用来自第二个父字符串的基因按照它们出现的顺序填充路径的剩余部分,而不复制来自第一个父字符串的所选子集中的任何基因(见下面的breed函数中的第 15 行)。

Illustration of ordered crossover (credit: Lee Jacobson)
接下来,我们将对此进行归纳,以创建我们的后代种群。在第 5 行中,我们使用精英主义来保留当前群体中的最佳路线。然后,在第 8 行,我们使用breed函数来填充下一代的剩余部分。
使突变
变异在遗传算法中起着重要的作用,因为它通过引入允许我们探索解空间的其他部分的新路径来帮助避免局部收敛。类似于交叉,TSP 在涉及到变异时有一个特殊的考虑。同样,如果我们有一条 0 和 1 的染色体,突变就意味着基因从 0 变为 1 的概率很低,反之亦然(继续前面的例子,包含在后代投资组合中的股票现在被排除在外)。
但是,既然需要遵守我们的规则,就不能掉城。相反,我们将使用交换突变。这意味着,在指定的低概率下,两个城市将在我们的路线上交换位置。我们将在我们的mutate函数中为一个人这样做:
接下来,我们可以扩展mutate函数来运行新的人口。
重复
我们快到了。让我们将这些片段组合在一起,创建一个产生新一代的函数。首先,我们使用rankRoutes对当前代中的路线进行排序。然后,我们通过运行selection函数来确定我们的潜在父母,这允许我们使用matingPool函数来创建交配池。最后,我们使用breedPopulation函数创建新的一代,然后使用mutatePopulation函数应用变异。
运动中的进化
我们终于拥有了创建 GA 的所有要素!我们所要做的就是创建初始种群,然后我们可以根据需要进行多次循环。当然,我们还希望看到最佳路线以及我们改进了多少,因此我们在第 3 行获取初始距离(记住,距离是适应度的倒数),在第 8 行获取最终距离,在第 9 行获取最佳路线。
运行遗传算法
一切就绪后,解决 TSP 就像两步一样简单:
首先,我们需要一个旅行城市的列表。对于这个演示,我们将创建一个 25 个随机城市的列表(看起来城市数量很少,但是蛮力将不得不测试 300 多条 sextillion 路线!):
然后,运行遗传算法就是一行简单的代码。这是艺术与科学相遇的地方;你应该看看哪些假设最适合你。在这个例子中,我们每一代有 100 个个体,保留 20 个精英个体,对给定的基因使用 1%的突变率,并运行 500 代:
额外功能:绘制改进图
知道我们的开始和结束距离以及建议的路线是很好的,但如果我们没有看到我们的距离是如何随着时间的推移而改善的,那将是我们的失职。通过对我们的geneticAlgorithm函数的简单调整,我们可以将每一代的最短距离存储在一个progress列表中,然后绘制结果。
以与之前相同的方式运行 GA,但现在使用新创建的geneticAlgorithmPlot函数:

Sample output from the geneticAlgorithmPlot function
结论
我希望这是学习如何构建自己的 GA 的一种有趣的实践方式。自己试试,看看你能找到多短的路线。或者更进一步,尝试在另一个问题集上实现 GA;看看如何改变breed和mutate函数来处理其他类型的染色体。我们只是触及了表面!
结束注释
你可以在这里找到一个合并的笔记本。
参考文献:
- http://www . the projectspot . com/tutorial-post/applying-a-genetic-algorithm-to-traveling-salesman-problem/5
- https://gist.github.com/turbofart/3428880
- https://gist . github . com/nicolle Louis/d4f 88 D5 BD 566298d 4279 BCB 69934 f 51d
- https://en.wikipedia.org/wiki/Travelling_salesman_problem
对科学家和研究主题的关注的演变
科学奖项影响力的数据科学研究

为了了解公众对科学和科学家的关注如何演变,对描述科学家和研究主题的维基百科页面进行了一项研究,以了解人们如何感知、更新和访问这些内容。
特别是,比较了获得某种奖项或奖励(诺贝尔奖、图灵奖等等)的科学家和没有获得任何奖励的科学家之间的注意力(尽管他们贡献了一个关键的科学进步)。
显然,一个奖项的存在对科学家的受欢迎程度和受关注程度有着深远的影响。获奖科学家的文章在可见性和更新方面也增长得更快,即使是在获奖多年之后。
令人难以置信的是,这些奖项并没有增加相应科学主题的知名度和关注度,如下所示:

另一个有趣的问题是,主题文章是在科学家的页面创建之前还是之后创建的。对于获奖科学家,维基百科上 27%的研究主题页面是在科学家页面创建之后创建的,而只有 10%的研究主题是在未获奖科学家之后创建的,如下所示:

这项研究已经在阿姆斯特达姆举行的 2018 年网络科学大会上发表,作者是 Claudia Wagner ,Olga Zagovora,Tatiana Sennikova,Fariba 卡利米(德国科布伦茨-兰道大学社会科学学院)。
完整的文章可以在这里找到。
游戏分析的平台演变

viSource: https://pixabay.com/en/joystick-controller-game-play-38228/
自从 Dreamcast 和调制解调器适配器发布以来,游戏开发商已经能够收集玩家在野外的行为数据。游戏分析实际上可以追溯到 1999 年发布的 EverQuest 等早期在线电脑游戏。游戏服务器对于认证用户和群体游戏世界是必要的,但也提供了记录游戏数据的能力。
自 1999 年以来,收集和分析数据的环境发生了显著变化。现代系统可以跟踪活动并近乎实时地应用机器学习,而不是通过日志文件在本地存储数据。以下是我在游戏行业任职期间注意到的游戏分析系统的四个阶段:
- 平面文件:数据保存在游戏服务器本地
- 数据库:数据存放在平面文件中,然后加载到数据库中
- 数据湖:数据存储在 Hadoop/S3 中,然后加载到数据库中
- 无服务器:托管服务用于存储和查询
这一演变中的每一步都支持收集更大的数据集,并减少了从收集数据到执行分析的延迟。在本文中,我将介绍每个时代的示例系统,并讨论每种方法的优缺点。
游戏分析真正开始获得动力是在 2009 年左右。在 Bioware,Georg Zoeller 建立了一个在开发过程中收集游戏遥测数据的系统。他在 GDC 2010 上展示了该系统:
由于已达到此帐户允许的最大用户数,您已从 GDC Vault 注销。要访问…
www.gdcvault.com](https://www.gdcvault.com/play/1012227/Development-Telemetry-in-Video-Games)
不久之后,艺电开始收集游戏开发后的数据,以跟踪玩家在野外的行为。
将分析应用于游戏遥测的学术兴趣也越来越大。该领域的研究人员,如 Ben Medler,建议使用游戏分析来个性化体验。
[## 一代又一代的游戏分析、成就和高分。用于…的日志
一代又一代的游戏分析、成就和高分
Medler |海达莫斯。为…一代游戏分析,成就和高 Scoreswww.eludamos.org 的日志](http://www.eludamos.org/eludamos/index.php/eludamos/article/view/vol3no2-4/127)
虽然在过去的二十年里,游戏性分析渠道有了总体的发展,但不同时代之间的进展并没有固定的时间表。一些游戏团队仍然在使用早期的系统,这可能是最适合他们用例的。也有许多供应商的解决方案可用于游戏分析,但我不会在这篇文章中涉及这些。我关注的是那些希望收集游戏遥测数据并拥有正在使用的数据管道的游戏团队。
平面文件时代

Components in a pre-database Analytics Architecture
我在 2010 年开始在艺电从事游戏分析,那时艺电还没有一个围绕数据建立的组织。虽然许多游戏公司已经收集了大量关于游戏的数据,但大多数遥测数据都以日志文件或其他平面文件格式的形式存储在游戏服务器上。没有什么是可以直接查询的,计算月活跃用户(MAU)等基本指标需要大量的工作。
在电子艺界,重播功能被内置到 Madden NFL 11 中,这提供了一个意想不到的游戏遥测源。每场比赛后,一份 XML 格式的比赛摘要被发送到一个游戏服务器,其中列出了每场比赛的叫牌、比赛过程中的走法以及比赛结果。这导致了数百万个文件可以被分析,以了解更多关于球员如何在野外与马登足球互动的信息。2010 年秋季我在艺电实习期间,我建立了一个回归模型,分析了哪些特征对留住玩家最有影响。

The impact of win rates on player retention in Madden NFL 11 based on preferred game mode.
大约在我开始在 EA 实习的十年前,索尼在线娱乐已经在使用游戏分析,通过存储在服务器上的日志文件收集游戏数据。直到几年后,这些数据集才被用于分析和建模,但它仍然是游戏分析的首批例子之一。包括 Dmitri Williams 和 Nick Yee 在内的研究人员基于对 EverQuest 系列的数据分析发表了论文。
在本地存储数据是目前为止收集游戏数据时最简单的方法。例如,我写了一篇关于使用 PHP 存储由无限马里奥生成的数据的教程。但是这种方法有明显的缺点。以下是这种方法的利弊概述:
优点 -简单:以你想要的任何格式保存你想要的任何数据
缺点 -无容错能力
-数据未存储在中央位置
-数据可用性存在巨大延迟
-没有用于分析的标准工具或生态系统
如果您只有几台服务器,平面文件可以很好地工作,但它不是真正的分析管道,除非您将文件移动到一个中心位置。在 EA,我编写了一个脚本,将 XML 文件从几十个服务器拉到一个服务器上,这个服务器解析这些文件并将游戏事件存储在 Postgres 数据库中。这意味着我们可以对 Madden 的游戏数据进行分析,但数据集是不完整的,并且有很大的延迟。这是下一个游戏分析时代的先驱。
这个时代使用的另一种方法是废弃网站来收集游戏数据进行分析。在我的研究生研究期间,我放弃了 TeamLiquid 和 GosuGamers 等网站,建立了一个专业的星际争霸重播集。然后,我为建立一个预测模型,以确定生产订单。这个时代的其他类型的分析项目包括废弃网站,如 WoW 军械库,以及最近的蒸汽间谍。
数据库时代

Components in an ETL-based Analytics Architecture
在一个中心位置收集游戏遥测数据的效用在 2010 年左右变得明显,许多游戏公司开始将游戏遥测数据保存在数据库中。许多不同的方法被用来将事件数据放入数据库供分析师使用。
当我在索尼在线娱乐公司时,我们让游戏服务器每隔几分钟就将事件文件保存到一个中央文件服务器。然后,文件服务器大约每小时运行一次 ETL 过程,将这些事件文件快速加载到我们的分析数据库中,该数据库当时是 Vertica。这个过程有一个合理的延迟,从游戏客户端发送事件到数据在我们的分析数据库中可查询大约一个小时。它还可以扩展到大量数据,但需要使用固定的事件数据模式。
当我还是一个 Twitch 时,我们对我们的一个分析数据库使用了类似的过程。与 SOE 的方法的主要区别是,我们没有将游戏服务器 scp 文件放在一个中心位置,而是使用 Amazon Kinesis 将事件从服务器流式传输到 S3 的一个集结地。然后,我们使用 ETL 过程将数据快速加载到 Redshift 中进行分析。从那时起,Twitch 转向了数据湖方法,以便扩展到更大的数据量,并为查询数据集提供更多选项。
SOE 和 Twitch 使用的数据库对两家公司都非常有价值,但我们在扩展存储的数据量时确实遇到了挑战。随着我们收集更多关于游戏的详细信息,我们不能再在表格中保存完整的事件历史,需要截断超过几个月的数据。如果您可以设置维护这些事件的最重要细节的汇总表,这很好,但是这不是理想的情况。
这种方法的一个问题是,临时服务器会成为故障的中心点。当一个游戏发送了太多的事件时,也有可能出现瓶颈,导致事件在所有游戏中被丢弃。另一个问题是当处理数据库的分析师数量增加时的查询性能。几个分析师组成的团队处理几个月的游戏数据可能会很好,但在收集了多年的数据并增加了分析师的数量后,查询性能可能会成为一个重大问题,导致一些查询需要几个小时才能完成。
优点 -所有数据都存储在一个地方,可以用 SQL 查询
-可用的好工具,如 Tableau 和 DataGrip
缺点 -将所有数据保存在 Vertica 或 Redshift
这样的数据库中成本很高-事件需要有固定的模式
-截断表可能是必要的
使用数据库作为游戏数据的主要接口的另一个问题是,Spark 的 MLlib 等机器学习工具无法有效使用,因为相关数据需要从数据库中卸载才能进行操作。克服这种限制的方法之一是以一种格式和存储层存储游戏数据,这种格式和存储层可以很好地与大数据工具配合使用,例如在 S3 上将事件保存为拼花文件。这种类型的配置在下一个时代变得更加普及,并且避开了截断表所需的限制,降低了保存所有数据的成本。
数据湖时代

Components in a Data Lake Analytics Architecture
当我在游戏行业的数据科学家那里工作时,最常见的数据存储模式是数据湖模式。一般模式是将半结构化数据存储在分布式数据库中,并运行 ETL 过程来提取与分析数据库最相关的数据。许多不同的工具可以用于分布式数据库:在电子艺界我们使用 Hadoop,在微软工作室我们使用 Cosmos,在 Twitch 我们使用 S3。
这种方法使团队能够扩展到海量数据,并提供额外的容错能力。它的主要缺点是引入了额外的复杂性,并且由于缺少工具或访问策略,可能导致分析师访问的数据比使用传统数据库方法时少。在这个模型中,大多数分析师会以同样的方式与数据交互,使用从数据湖 ETL 中填充的分析数据库。
这种方法的好处之一是它支持各种不同的事件模式,并且您可以在不影响分析数据库的情况下更改事件的属性。另一个优势是,分析团队可以使用 Spark SQL 等工具直接处理数据湖。然而,我工作过的大多数地方都限制了对数据湖的访问,消除了这种模式的许多好处。
优点 -扩展到海量数据
-支持灵活的事件模式
-昂贵的查询可以迁移到数据湖
缺点 -显著的运营开销
- ETL 过程可能会引入显著的延迟
-一些数据湖缺乏成熟的工具
数据湖方法的主要缺点是,通常需要整个团队来保持系统的运行。这对大型组织来说是有意义的,但对较小的公司来说可能有些矫枉过正。利用数据湖而不产生运营开销的方法之一是使用托管服务。
无服务器时代

Components in a managed Analytics Architecture (GCP)
在当前时代,游戏分析平台整合了许多托管服务,使团队能够接近实时地处理数据,根据需要扩展系统,并减少维护服务器的开销。我在游戏行业工作时从未经历过这个时代,但看到了这种转变正在发生的迹象。Riot Games 正在使用 Spark 进行 ETL 过程和机器学习,并且需要按需旋转基础设施。一些游戏团队正在为游戏服务使用弹性计算方法,利用这种方法进行分析也是有意义的。
在 GDC 2018 之后,我决定尝试构建一个样本管道。在我目前的工作中,我一直在使用谷歌云平台,它似乎有很好的工具来建立一个托管数据湖和查询环境。结果就是这个教程,它使用数据流来构建一个可扩展的管道。
优点 -与使用数据湖
相同的优势-基于存储和查询需求的自动缩放
-最小的运营开销
缺点 -托管服务可能很昂贵
-许多服务是特定于平台的,可能不可移植
在我的职业生涯中,我在使用数据库时代方法方面取得了最大的成功,因为它为分析团队提供了对所有相关数据的访问。然而,这不是一个可以继续扩展的设置,我工作过的大多数团队后来都转移到了数据湖环境。为了使数据湖环境取得成功,分析师团队需要访问底层数据,以及成熟的工具来支持他们的过程。如果我今天要构建一个管道,我肯定会从无服务器方法开始。
本·韦伯是意外收获数据的首席数据科学家,我们的任务是建立最准确和全面的净值模型。意外收获团队正在壮大,并正在招聘工程师和数据科学家。
“内核”的进化:团队的支柱
由于其以丰富的可能性改善我们生活的潜力,人工智能正在成为每个行业不可或缺的一部分。虽然,获得人工智能可能对一家公司来说很有吸引力;是 a)伟大的思想,b)发现,c)耐心和 d)完成任务的能力的结合使它成为现实。
在小队,我们正在变革在线分类广告和市场的内容审核。我们帮助在批准最近上传到网站的用户生成的列表和保持列表质量的高标准之间取得平衡。目前,我们的客户在不牺牲质量的情况下体验到了极高的效率,节省了高达 70%的成本。
除了我们的产品,我们使用人工智能来自动化我们客户的大部分工作,这进一步降低了成本,并将交付质量大幅提高到一个新的水平。
内容审核问题通常涉及高度主观的判断,这需要一个思维过程,我们的人力受过良好的训练,而机器可能不会产生自信的判断。正如我们的首席执行官 Apurv Agarwal ,“我们本质上并没有解决那些可以通过机器学习直接解决的问题”。
可以说,为了解决艰巨的自动化任务,我们需要人在回路中,帮助稳健地训练机器学习算法。
第一个大挑战
当我们收到为我们的一个客户自动执行内容审核任务的第一个挑战时,该客户恰好是美国前 5 大 C2C 市场之一,像任何其他机器学习团队一样,我们开始进行探索性数据分析,了解重叠的类并识别独特的类,可视化不同的簇并探索随时可用的工具和方法,这些工具和方法可用于解决涉及文本和图像分类的复杂问题。
我们在最先进的深度学习架构和迁移学习上使用预先训练的模型进行了初步实验,认为我们希望为我们的 C2C 客户端自动化的大多数类已经存在于 imagenet 对象类中,令我们惊讶的是,所有模型的准确率都超过了 95%。早期实验的成功让我们很高兴,我们觉得我们已经完成了挑战,但有趣的是,它花了 6 个月的时间来真正解决端到端的问题。
最终,我们了解了探索阶段和生产环境之间的区别(在生产环境中,每个模型都必须 99%精确)。对于我们这样一个非常年轻的团队来说,在一个创业环境中工作,一切都必须从费米能级开始,有一系列的打击在等着我们。
自动化的马拉松
从一开始,在我们的数据科学家 Sanchit Aggarwal 的指导下,所有崭露头角的机器学习工程师都直接或间接地致力于不同内容审核用例的自动化,探索相关的 ML 算法,编写代码以进行快速实验,并根据我们的 C2C 巨头共享的指南持续分析和学习适当的模型。
我们训练了许多性能良好的基于图像和文本的模型,建立了一个像样的训练和测试结构,并不断探索其他改进方法,如跳格法、单词嵌入、一类学习、GMMs 等。

Figure 1: Devil’s in the tail: Large number of categories with mostly small data for various classes in long tail distribution.
我们还深入了解了数据集分布不均匀、类重叠的问题,以及模型和工作流集合的需求。当期望是 99.5%的精确度和召回率时,另一个挑战是挑选高质量的训练数据,以从关于目标标签严重重叠的真实世界列表中获得高度自动化。

Figure 2: Tensorboard Visualisations for RESNET features for various classes (different colors) showing high magnitude of overlap.
一旦我们收集了所需的数据集,我们就可以连续成功地从实验中获得结果,并且越来越接近与客户达成一致的 SLA 数字。
我们都对我们采用的机器学习实践感到非常兴奋,并享受着处理大量机器学习算法来解决复杂问题的新鲜感。在几个月的专门实验中,我们有了许多模型,它们可以部署在生产环境中,并用于进行实时质量检查。但是我们的团队没有预料到一个非常重要的桥梁,在我们跨越为客户列表的内容审核做出高质量实时预测的里程碑之前,需要建立这个桥梁。

Table 1: Evaluation of some of our generic models.
内核的进化
在尝试了各种聚类方法、数据清理技术、数据扩充、监督和非监督算法(如 SMOTE、KM-SVM)之后,我们意识到我们总是可以改进我们的模型,而且没有停止的标准。但是,为了给企业带来真正的价值,我们还需要一个稳定、强大的基础设施。
这是我们开始深入研究可用基础设施的时候。我们开始探索模型版本控制和预测系统的可用工具,如厚皮动物、火花、数据版本控制、 HDFS 等等。所有这些系统都非常复杂,需要进行大量的修改才能与我们现有的人在回路框架集成。我们意识到,开发自己的内部系统,内核,来处理实时预测会更快更容易。这时,我们感觉到团队内部需要更多的工程带宽。我们请来了 Ketan Bhatt,用他的精力和经验为 SquadAI 创建一个强大的基础设施。
在 Squad,我们遵循求解团队的概念。
在我们新的 solver 团队基础设施中,我们中很少有人开始专注于机器学习来学习高精度模型,而其他人则探索基础设施主干所需的数据库设计和架构,内核。我们一步一步地计划和解决每个问题,采用集中的方法和适量的协作,以 1%的自动化和 99%的精确度开始。下面的图表显示了复杂 C2C 用例的自动化水平稳步提高。

Figure 3: Graph showing continuous improvement over time for automating content moderation for our C2C client after we had created the bridge, Kernel.
我们不断改进最新的最先进的方法、微调模型、深度学习优化、文本分类中的 CNN、定义的可扩展流程和基础设施,以实现 AI + HI 工作流 50%自动化的目标,而不会影响判断的精确度。
为了更深入地理解我们自动化框架的技术方面, SquadAI 及其骨干 内核、 请参考我们的博客- SquadAI:用于构建、管理和评估机器学习工作流的众包驱动平台
非常感谢所有参与构建内核的 ML 工程师: Aniket Bhatnagar 、 Medha Katehar a、 Pragya Jaiswal 和 Priyank Jain 。
目标检测和定位算法的发展
通过对基本概念的直观解释,理解对象检测和定位的最新进展。
目标检测是计算机视觉中发展非常迅速的领域之一。感谢深度学习!每年都有新的算法/模型不断超越以前的算法/模型。事实上,脸书人工智能团队上周刚刚发布了一个最新的物体探测软件系统。这款软件名为 Detectron ,整合了众多针对物体检测的研究项目,由 Caffe2 深度学习框架提供支持。
今天,有太多的预训练模型用于物体检测(YOLO,RCNN,快速 RCNN,掩模 RCNN,多框等)。).因此,只需要很少的努力就可以检测出视频或图像中的大多数对象。但是我博客的目的不是谈论这些模型的实现。相反,我试图以一种清晰和简洁的方式解释基本概念。
我最近完成了吴恩达的 卷积神经网络课程的第三周,他在课程中讲述了物体检测算法。这个博客的大部分内容都是受那门课的启发。
编辑:我目前在做 Fast.ai 的《程序员前沿深度学习》课程,老师是杰瑞米·霍华德。现在,我已经使用 PyTorch 和 fast.ai 库实现了下面讨论的算法。这里是链接到代码。如果你想了解下面讨论的算法的实现部分,可以看看这个。实现已借用 fast.ai 课程笔记本,有注释和笔记。
CNN 简介
在我解释对象检测算法的工作原理之前,我想花一些时间介绍卷积神经网络,也称为 CNN 或 ConvNets。在深度学习时代,细胞神经网络是大多数计算机视觉任务的基本构建模块。

Fig. 1. Convolution demo in Excel
我们想要什么?我们想要某种算法,它查看图像,看到图像中的模式,并告诉图像中有什么类型的对象。例如,是猫或狗的图像。
什么是计算机的图像?只是数字矩阵。例如,参见上面的图 1。左边的图像只是手写数字 2 的 28*28 像素图像(取自 MNIST 数据),在 Excel 电子表格中表示为数字矩阵。
我们怎样才能教会计算机学会识别图像中的物体?通过让计算机学习像垂直边缘、水平边缘、圆形以及许多其他人类未知的模式。
计算机如何学习模式?回旋!
(看这个的时候看上图)卷积是两个矩阵之间给出第三个矩阵的数学运算。较小的矩阵,我们称之为过滤器或内核(图 1 中的 3x3 ),对图像像素矩阵进行操作。根据滤波器矩阵中的数字,输出矩阵可以识别输入图像中存在的特定模式。在上面的例子中,滤波器是垂直边缘检测器,它学习输入图像中的垂直边缘。在深度学习的背景下,输入图像及其随后的输出从许多这样的过滤器中通过。滤波器中的数字由神经网络学习,而模式则自行产生。
为什么卷积有效?因为在大多数图像中,对象在相对像素密度(数量级)上具有一致性,这可以被卷积利用。
我知道对于一个不了解 CNN 的读者来说,CNN 上只有几行字是不够的。但是 CNN 并不是这篇博客的主要话题,我已经提供了基本的介绍,所以读者在继续阅读之前不必再打开 10 个链接来理解 CNN。
看完这篇博客后,如果你还想了解更多关于 CNN 的信息,我强烈建议你阅读亚当·盖特吉的博客。
计算机视觉任务的分类

Fig. 2: Common computer vision tasks
以图 2 中的猫和狗图像为例,以下是计算机视觉建模算法完成的最常见任务:
- 图像分类:这是最常见的计算机视觉问题,算法查看图像并对其中的对象进行分类。图像分类具有广泛的应用,从社交网络上的人脸检测到医学中的癌症检测。这种问题通常使用卷积神经网络(CNN)来建模。
- 物体分类与定位:假设我们不仅想知道图像中是否有猫,还想知道猫的确切位置。目标定位算法不仅标记目标的类别,而且在图像中围绕目标的位置画出一个包围盒。
- 多目标检测和定位:如果图像中有多个目标(如上图中的 3 只狗和 2 只猫)并且我们想检测它们,该怎么办?这将是一个目标检测和定位问题。这一点的一个众所周知的应用是在自动驾驶汽车中,其中该算法不仅需要检测汽车,还需要检测行人、摩托车、树木和帧中的其他物体。这类问题需要利用从图像分类和目标定位中学到的思想或概念。
现在回到计算机视觉任务。在深度学习的背景下,上述 3 种类型的任务之间的基本算法差异只是选择相关的输入和输出。让我用一个信息图来详细解释一下这条线。
1。图像分类

Fig. 3: Steps for image classification using CNN
图 3 中的信息图显示了用于图像分类的典型 CNN 的样子。
1。通过 n 个滤波器(图 3 中 n = 4)对具有一定高度、宽度和通道深度(上例中为 940、550、3)的输入图像进行卷积【如果您仍然不清楚卷积的确切含义,请查看此链接以了解深度神经网络中的卷积】。
2。卷积的输出用非线性变换处理,通常是最大池和 RELU。
3。卷积、最大池和 RELU 的上述 3 个操作被执行多次。
4。最终层的输出被发送到 Softmax 层,soft max 层将数字在 0 和 1 之间转换,给出图像属于特定类别的概率。我们使损失最小化,以便使最后一层的预测尽可能接近实际值。
2。物体分类和定位

Fig. 4: Input and output for object localization problems
现在,为了让我们的模型绘制对象的边界框,我们只需改变前面算法的输出标签,以便让我们的模型学习对象的类别以及对象在图像中的位置。我们在输出层增加了 4 个数字,包括物体的质心位置和图像中边界框的宽度和高度的比例。
简单吧?只需要加上一堆输出单位就可以吐槽出你要识别的不同位置的 x,y 坐标。这些不同的位置或标志对于我们所有的图像中的特定对象来说是一致的。例如,对于汽车,与图像中的其他点相比,高度将小于宽度,并且质心将具有特定的像素密度。
同样的逻辑,如果图像中有多个物体,我们想对它们进行分类和定位,你认为会发生什么变化?我建议你此刻停下来思考一下,你可能会自己找到答案。
3。多目标检测和定位

Fig. 5: Input and output for object detection and localization problems
为了检测图像中的各种对象,我们可以直接使用我们迄今为止从对象定位中学到的知识。不同之处在于,我们希望我们的算法能够对图像中的所有对象进行分类和定位,而不仅仅是一个对象。因此,这个想法是,只需将图像裁剪成多个图像,并对所有裁剪的图像运行 CNN 来检测对象。
算法的工作方式如下:
1。制作一个尺寸远小于实际图像尺寸的窗口。裁剪它并将其传递给 ConvNet (CNN)并让 ConvNet 进行预测。
2。继续滑动窗口,将裁剪后的图像传入 ConvNet。
3。在用该窗口尺寸裁剪完图像的所有部分后,再次重复所有步骤以获得更大的窗口尺寸。再次将裁剪后的图像传入 ConvNet,让它进行预测。
4。最后,你将得到一组裁剪区域,其中包含一些对象,以及对象的类和边界框。
这种解决方案被称为滑动窗口对象检测。这是一个非常基本的解决方案,有如下许多注意事项:
答:计算量很大:裁剪多幅图像并通过 ConvNet 传输,计算量非常大。
解决方案:有一个简单的 hack 来提高滑动窗口法的计算能力。它是用 1x1 卷积层替换 ConvNet 中的全连接层,并且对于给定的窗口大小,仅传递输入图像一次。因此,在实际实现中,我们并不是一次传递一个裁剪后的图像,而是一次传递完整的图像。
B .不准确的边界框:我们在整个图像上滑动正方形的窗口,可能对象是矩形的,也可能没有一个正方形与对象的实际大小完全匹配。虽然这种算法能够在一幅图像中找到并定位多个目标,但是包围盒的精度仍然很差。

Fig. 6. Bounding boxes from sliding window CNN
我已经谈到了对象检测问题的最基本的解决方案。但是它有许多注意事项,不是最准确的,并且实现起来计算量很大。那么,如何才能让我们的算法更好更快呢?
更好的解决方案?YOLO
原来我们有 YOLO(你只看一次),它比滑动窗口算法更准确,更快。它仅仅是基于我们已经知道的算法之上的一个小调整。这个想法是将图像分成多个网格。然后,我们更改数据的标签,以便为每个网格单元实现定位和分类算法。让我再用一个信息图来解释一下。

Fig. 7. Bounding boxes, input and output for YOLO
YOLO 轻松地说道:
1。将图像分成多个网格。为了便于说明,我在上图中画了 4x4 的网格,但是 YOLO 的实际实现有不同数量的网格。(7x7 用于在 PASCAL VOC 数据集上训练 YOLO)
2。标注训练数据,如上图所示。如果 C 是数据中唯一对象的数量,SS 是我们将图像分割成的网格数量,那么我们的输出向量的长度将是 SS(C+5)。例如,在上述情况下,我们的目标向量是 44(3+5),因为我们将图像划分为 44 的网格,并针对 3 个独特的对象进行训练:汽车、灯光和行人。
3。制作一个深度卷积神经网络,损失函数作为输出激活和标签向量之间的误差。基本上,该模型只需将输入图像通过 ConvNet 向前传递一次,即可预测所有网格的输出。
4。请记住,网格单元中存在的对象标签(P.Object)是由该网格中存在的对象质心决定的。这对于不允许一个对象在不同的网格中被多次计数很重要。
YOLO 的注意事项及其解决方案:
A .无法检测同一网格中的多个对象。这个问题可以通过选择较小的网格尺寸来解决。但是,即使选择较小的网格尺寸,该算法在物体彼此非常接近的情况下仍然会失败,例如一群鸟的图像。
解决方案:锚箱。除了每个网格单元有 5+C 个标签(其中 C 是不同对象的数量)之外,锚定框的想法是每个网格单元有(5+C)*A 个标签,其中 A 是必需的锚定框。如果一个对象被分配给一个网格中的一个锚定框,其他对象可以被分配给同一网格的另一个锚定框。

Fig. 8. YOLO with anchor boxes
B .多次检测一个物体的可能性。
解: 非 max 抑。非最大值抑制移除与高概率边界框非常接近的低概率边界框。
结论:
截至今天,在不同的深度学习框架中有多个版本的预训练 YOLO 模型可用,包括 Tensorflow 。最新的 YOLO 论文是:《yolo 9000:更好更快更强》。该模型在 9000 个类上进行训练。还有一些基于选择性区域提议的区域 CNN (R-CNN)算法,我没有讨论过。由脸书 AI 开发的软件系统 Detectron 也实现了 R-CNN 的变体,屏蔽 R-CNN。
参考资料:
-
更好、更快、更强
https://arxiv.org/pdf/1612.08242.pdf -
吴恩达的卷积神经网络(deep learning . ai) https://www . coursera . org/learn/卷积神经网络
Spark 分析的发展
Apache Spark 是一个开源、可扩展、大规模并行的内存执行环境,用于运行分析应用程序。
数据科学家主要负责构建预测分析模型和构建洞察力。他将分析数据工程师使用机器学习工具(如沃森机器学习)编目和准备的数据。他将使用 Jupyter 笔记本电脑构建应用程序,RStudio
在数据科学家分享他的分析结果后,应用程序开发人员可以像认知聊天机器人一样构建应用程序。随着聊天机器人与客户互动,它将不断完善自己的知识,并帮助发现新的见解。
让我们站在数据科学家的角度,看看作为一名数据科学家,我想做些什么:
- 我想运行我的分析工作,我想运行社交媒体分析或文本分析
- 我想按需运行查询
- 我想在 Spark 上运行 R,Python 脚本
- 我想提交 Spark 作业
- 我想查看我的应用程序的历史服务器日志,以便比较我的作业性能并进一步改进
- 我想为我的调试查看守护进程日志
- 我想写笔记本
现在你知道我想做什么,现在让我们看看我一直在做什么来实现我真正想做的事情。几年前,如果我需要做同样的事情,我通常会这样做
我自己的裸机上的 Spark Analytics
如果我需要在我自己的机器上运行 Spark,我需要首先获得硬件。一旦我有了合适的可用硬件,我需要准备好它,以便安装 Spark 和我的其他分析产品。我需要做很多工作来让硬件为运行我的 Spark 工作负载做好准备。如果你有兴趣知道在裸机上设置你自己的 Spark 运行时会遇到哪些挑战,请参考我的另一个博客。以下是其中的几个。
- 设置网络 : Spark 是一个集群软件,所以我需要多台机器来运行我的 Spark 作业。为了在这些机器之间建立网络,我需要在它们之间设置正确的线路,我需要配置网络接口以便它们被适当地调整。
- 安装盘:一旦联网完成,我就可以访问那些机器了,我需要格式化这些盘,给它们贴上正确的标签,配置它们,使它们在重启时不会被破坏。我需要设置 raid 控制器,创建分区,为所有磁盘创建挂载点,并正确配置它们
- 维护:安装火花簇是容易的部分,维护起来比较困难。我将需要应用常规的操作系统补丁,监视磁盘错误并在需要时替换它们,我已经花费了许多资源来维护 Spark 集群
- 监视器:我需要确保我的集群中的各种组件都是健康的,并且需要安装和配置一些监视解决方案来监视故障并通知我
- 扩展:我将需要添加更多的机器,并重复相同的过程在我现有的集群中添加新的节点。
- 合规:因为我是大企业的一部分,我需要确保我的分析管道中的所有组件都符合某些合规标准,如 ISO270001 等。
在我自己的虚拟机上激发分析
现在,我已经到了这样一个阶段,在我的组织中,运行分析工作的要求越来越高,我不能花费太多的时间和资源在裸机上设置 Spark 集群,我需要一种可以根据需要轻松快速扩展的产品。
为了满足不断增长的工作负载需求,我将寻求虚拟化解决方案。这当然会帮助我获得重复能力,但我仍然需要注意很多事情,如
- 维护
- 安全
- 监视器
- 升级
- 刻度
- 高可用性
对托管公共云产品进行 Spark 分析
许多云提供商,如 Google、IBM、Microsoft 和 Amazon,正在提供许多服务,这些服务将 Spark 运行时作为托管产品。
请参考以下大数据领域中流行的云服务的文档链接
- 亚马逊电子病历
- IBM 分析引擎
- 微软 Azure HDInsight
- 谷歌云 Dataproc
我可以从这些云提供商那里请求一个 Spark 实例,它为我解决了许多难题。比如说。我不需要担心购买硬件、准备机器、设置网络、安装和维护活动。
所有繁重的工作都由云提供商负责,但在这种情况下,我需要负责以下工作
- 配置:许多云提供商提供的集群都带有基本配置,我需要对它们进行调整以适应我的需求。
- 定制:我需要安装运行我的作业所需的库,这可能需要几个小时才能完成。
- 为闲置时间付费:使用托管服务的一个主要问题是成本。我并没有一直使用这些集群,但是我为资源付费,即使它们没有运行任何东西。
托管云产品对于运行批处理、流和其他生产场景有其明确定义的用例。
无服务器火花
作为一名数据科学家,我真正想做的是运行分析工作。我对购买、准备机器、建立 Spark 集群和维护它们并不感兴趣。

同时,如果我不使用这些资源,我也不想为它们付费。
我也不想为了 Spark 集群出现在流行的云产品中而等待很长时间(甚至几分钟)。
作为一名数据科学家,我真正想要的是什么?
—无服务器 Spark 运行时
根据 Wikipedia "的说法,无服务器计算是一种云计算执行模型,其中云提供商充当服务器,动态管理机器资源的分配。定价基于应用程序消耗的实际资源量,而不是预先购买的容量单位”

我有哪些选择可以尝试无服务器 Spark?
Qubole 做了一件了不起的工作,让 Spark 在 AWS lamda 函数上运行。如果你对更多细节感兴趣,这里是博客。许多云提供商正在提供服务,该服务提供一个平台,允许客户开发、运行和管理应用程序功能,而无需构建和维护复杂的基础设施。
但是这种采用无服务器 Spark 的方法存在一些挑战
对于功能即服务,我没有得到火花簇,我只得到执行者
我也得不到和以前一样的体验。这里缺少历史服务器日志和监控工具。
如果我想选择这个选项,我还需要考虑以下一些因素。
无法直接通信: Spark 使用 DAG 执行框架产生多阶段作业。对于级间通信,Spark 需要跨执行器进行数据传输。许多功能即服务不允许两个功能之间的通信。这给在这种环境下运行执行器带来了挑战。
极其有限的运行时资源:目前很多函数调用都被限制在最大执行时长 5 分钟,1536 MB 内存和 512 MB 磁盘空间。Spark 喜欢内存,可以占用大量磁盘空间,并且可以产生长时间运行的任务。这使得函数成为运行 Spark 的困难环境。
其他新选项?—星火环境
IBM 宣布 Spark 环境将在 IBM Watson Studio 中正式发布!
Spark 环境定义硬件和软件配置,按需启动定制 Spark 集群。Spark 环境可以针对资源快速扩大或缩小规模。这使得它们非常适合各种用例,从在样本数据集上尝试新的机器学习算法到在分布式计算引擎上运行大型生产工作负载。Spark 环境可以与工具一起使用,如笔记本、模型构建器,或 沃森工作室 中的流编辑器。
对于每个 Spark 环境,我都有一个专用的 Spark 集群和专用的资源,这保证了我的应用程序在每次执行时都能在同一时间完成。
Spark 环境提供了许多好处:
- Spark kernel on-demand—节省时间和精力,专注于您的分析;在 Watson Studio 中创建一个 Spark 环境,并直接启动到笔记本中。
- 可配置的弹性计算 —配置您的 Spark 环境,并从 Watson Studio 中选择您的内核硬件配置。
- 轻松共享您的环境— Spark 环境是项目资产,因此您的合作者可以轻松使用它们。
- 多语言支持——为您的 Spark 内核选择最流行的语言(Python 2、Python 3、R、Scala)。
Spark 环境正在提供一些特性,这些特性为我提供了我已经习惯的使用 Spark 的相同体验。IBM 正在添加许多令人兴奋的新功能,如定制软件包管理的软件定制,以及对 Spark 历史服务器和 Spark 应用程序 UI 的访问,这将使我的体验更好。
如果你想尝试 Spark 环境,请阅读这篇公告博客文章
摘要
Apache Spark 是数据科学家的一个基本工具,为从大规模数据转换到分析到机器学习的各种应用程序提供了一个强大的平台。
从在裸机上部署它到在容器上运行它,再到提供其 as 无服务器产品,它已经发展了很多,这在易用性、成本方面为其用户提供了好处,并且仍然提供与他们正在使用的 Spark 相同的使用体验。
试用 IBM 的 Spark environments ,在试用该功能后,请在下面的评论或推文中给出您对本文的反馈 Rachit Arora
随机森林在金融中的应用实例:期权定价
今天,【2018 年 9 月 9 日下午 1.56,在埃隆·马斯克被发现在电视直播中吸烟后,特斯拉的股票价值 263.24 美元。
假设我预计接下来几天还会有埃隆马斯克的丑闻。
我预见到上述股票价格的下跌,所以我给你提供一个购买的选择,在任何时候,一个月内,每股 264 美元。万一我错了,股价上涨超过 264 美元,你就可以在市场上买卖你的股票并赚钱!
但是,如果特斯拉股票不断减少,你将永远不会行使你的期权,我会积极的,感谢你为这个期权支付的溢价。
问题,你愿意为这样的期权支付多少钱?当我在这个选项中加入其他股票时会发生什么?
期权定价
这就是所谓的期权定价理论,自 1973 年 Black 和 Scholes 模型首次出现以来,这是文献中一个众所周知的主题。
上述期权被称为美式期权(实际上是百慕大期权,即你只能在 T2 时间{T0,T1,..其中 T 是到期日或期权到期日)。
常见的方法,特别是在银行中应用的方法,回忆动态规划和 Longstaff Schwartz 算法来解决这个问题。
直觉上,你可以把它想成一个逆向过程,你在 T 点的期权收益是

其中 X_T 是特斯拉到期时的股价。
动态编程完全是一个视角问题!
假设我们在一个月内只能行使两次期权(两周时间,用 2W 表示,一个月内,用 T=1M 表示)。
那么在时间 t=2W 时你只有两个选择:
- 你要么运动(如果 X(2W) > K)。然后,你将得到(X(2W)- K)\(投资于一个自由风险账户,每天支付无风险利率 r,并在时间 T=1M 时得到(1+r)⁴*(x(2w)-k)\) 14(账户每天支付的两周的指数),
- 或者你期望特斯拉份额在 T 点更高(你这个疯狂的傻瓜),因此增加你的期权价值(所以你会等到 T 点)。
设 Y 为该期权价值价格。你在直观地解下面的逆向方程,

上述方程没有封闭形式的公式,但我们可以在数值上提供近似值。
我们如何获得上述方程的近似值?
回归
假设我们知道特斯拉股票在 2W 的价格。
已知 t=2W 时的所有信息,我们唯一的未知数是未来期权价值(Y_T)。换句话说,如果你在两周内(即未来),你的投资组合的期望值是多少,由这一个美式期权组成。
这时回归就出现了。
你有 2W 的信息,你想预测 100 万英镑的期权价值。
输入/标签:t = 2W 时特斯拉股价的所有样本
输出【at t = T = 1M 时的选项值
正向模拟
事先,我们需要模拟特斯拉股价的多种情景。

Geometric Brownian Motion simulation applied on Tesla Share
为了简化模型,我们假设特斯拉股票遵循几何布朗运动路径,平均 r(无风险利率)和波动率适马= 20%(我们让感兴趣的读者参考随机过程理论)。
注意:1 个月的时间大约相当于 0.08 年的时间。因此在这张图上 T = 0.08,2W = 0.04。
数据可视化
在左边,我们画出了 T 时对特斯拉股价的回报(你可以在这里认出非线性的 max 函数,或者深度学习读者的 ReLu 激活函数),在右边,画出了 t=2W 时对特斯拉股价的回报。


Left : Payoff against Stock price at t=1M— — Right : Payoff against Stock price at t=2W
回归
存在多种回归方法,在准确性和时间方面表现良好,以解决这种预测问题。在一个维度上(即只有一只股票,这里是特斯拉),我们可以想到多项式回归(你可以查看比约恩·哈特曼关于此事的帖子),或者高斯核回归。
第一个会导致角点问题(见下文,在 240 之前,回归在拟合数据下开始),而第二个在计算上可能是昂贵的。
NB :如果上面的交互代码无法加载,我在下面添加了预期的输出(感谢 William Koehrsen ,他的文章“如何在一篇中等大小的文章中放置完全交互的、可运行的代码”)和 Jupyter 笔记本(使用 Vera Chernova 的建议)。


但是,你是一个真正的玩家!
你查看新闻,注意到大众和脸书的股票正在慢慢恢复过去的势头。
我阅读了我这边的新闻,决定值得冒险,并向你提供一个类似的美式期权,这次到期日为 1 年,可以行使 4 次,几何平均回报(即,当你行使时,如果你希望你的银行账户为正,你需要特斯拉 x FB x VW 立方根的乘积大于我们今天定义的罢工)。
- 如今,这一几何平均值将等于(263.24 x 158.97 x 165.94)^(1/3)~ 190.78 美元
- 让我们解决一个罢工 K = 191 美元(我们称之为货币期权,因为它几乎是今天的价格)。
在这种情况下,我们仍然可以利用多项式回归,但如果我们决定玩更多的份额,它就不是可伸缩的!
我们如何在高维空间(即多股)为期权定价?
我们叫一个朋友,随机森林!
我邀请你提前(为新人)阅读一下威廉·科尔森的这篇关于随机森林回归的杰出解释。
尽管在一维空间使用它听起来像使用核武器,但它显示了在解决高维情况时的高效性。
回到我们的一维模型(只有特斯拉份额),应用随机森林回归看起来像

它在精确地建模和预测(从图中),甚至可能太多(过度拟合)。
然而,使用一些方差减少方法(如 Picard 迭代),并调整随机森林超参数,我们可以与文献中提到的大多数方法竞争(例如 Gobet 的超立方体、 Glasserman 和 Broadie s' Mesh ,..).
当将随机森林应用于相关资产或超过 20 项资产的期权时,这一发现更加真实。
结论
我们在这里展示了机器学习方法如何应用于历史金融问题,如期权定价,以及它如何用于处理巨大的投资组合。
NB :下面是上面模拟用的 Jupyter 笔记本。
我向感兴趣的读者推荐 我在 2017 年 6 月提交给新加坡国立大学(应用概率统计系)的理学硕士论文 ,其中我们重点比较了用于期权定价的多种行业方法,包括随机森林、核回归、Mesh、…
如何将数据科学应用于真实的业务问题
专注于电子商务和医疗保健
*抬头,如果您想跳过简介直接进入示例,请滚动至第一个标题
数据科学和统计学不是魔法。他们不会神奇地解决公司的所有问题。然而,它们是有用的工具,可以帮助公司做出更准确的决策,并自动化团队需要做出的重复性工作和选择。
当提到自然语言处理、图像识别和聊天机器人时,机器学习和数据科学被引用了很多。
然而,你也可以应用数据科学技术来帮助你的经理做出决策、预测未来收入、细分市场、制作更好的内容和更有效地诊断病人。
下面,我们将讨论一些统计和应用数据科学算法的案例,它们可以帮助您的企业和团队产生更准确的结果。
这不需要复杂的 hadoop 集群和云分析。不是说这些不神奇。只是,让我们先从基础开始!
在我们跳进技术和炒作的兔子洞之前!

我们将举例说明电子商务和医疗操作。
我们的团队主要专注于实践和应用数据科学。因此,我们深入到我们过去的经验中,向你展示一些很棒但很容易应用的方法,你可以在今天利用统计数据开始做出更好的决策。
下面的方法通常只是一个更大系统的一小部分。我们相信获取这些小的部分和细节是开始构建准确有效的系统所必需的。
这些统计方法中的一些甚至不需要大量的编程或专业技术知识。然而,如果正确实施,这些基本技术可以在更大的系统中以更大的规模应用。
我们这样做是因为我们知道实现一个算法需要很大的努力。
团队必须适当地计划他们将如何集成数据库、业务逻辑、算法和新策略,以确保项目成功。
这需要大量的资源和时间。
欺诈检测和贝叶斯定理
无论您是一家处理医疗、财产或车辆索赔的保险公司。保险欺诈是一个大问题。
他们是怎么解决的?保险提供商必须要么建立一个算法,要么让审计员人工检查,看看索赔是否是欺诈性的。
信不信由你,仍有为数众多的保险公司手动完成这项工作(在这种情况下,我们正在考虑从数据库中获取一个数据,并手动在 excel 中过滤)。
保险提供商将在审计方面投入大量精力。至少出于这两个原因:
- 把钱拿回来
- 试图阻止未来的保险欺诈索赔
这里的问题是,这会占用宝贵的资源时间,如果他们错误地识别索赔,可能会在工资和其他资源方面花费更多的钱,而不是从欺诈性索赔中收回的钱。
在本例中,一家名为 Itena 的保险提供商创建了一种算法来帮助提高他们团队处理索赔的速度。
那么 Itena 如何知道他们开发的算法是否值得呢?
好吧,如果你有一个数学定理来分析你的算法呢!
哇哦。那太“元”了。
就当这是一次信心检查,以后可以帮助他们计算是否值得在算法上投资
在这种情况下,他们将使用贝叶斯定理

Original Post https://xkcd.com/1236/
贝叶斯最擅长的是提供统计数据来证明他们所得到的信息有多准确。
他们能有多信任自己的算法?因为它们很可能同时具有假阳性和假阴性。他们的算法到底有多准确?
假设 Itena 的数据科学团队知道收到的索赔中有 2%是欺诈性的。
他们计算出,如果他们能够正确识别所有欺诈性索赔,他们可以节省 100 万美元!
哇哦。他们刚刚让你所有的主管都签字同意了!我的意思是,这是 100 万美元!即使公司净赚 1 亿美元。这是一次伟大的拯救
厉害!
因此,Itena 数据科学团队开发了一种算法来检测欺诈性索赔。
它并不完美,但它是一个很好的开始!
但是,它到底有多准确呢?当然,他们知道 85%被预测为欺诈的欺诈性声明实际上是欺诈性的?

作为优秀的数据科学家和普通科学家。他们也知道你必须检查错误。比如误报。
对他们来说,去找管理人员说这个测试有 85%的准确性是不正确的!在正常索赔栏中查找。
他们也有 4%的假阳性率。这是怎么回事?
这时他们引入了我们的老朋友贝叶斯定理。
贝叶斯定理对于测试他们应该信任测试的程度非常有用。
像医学测试一样,算法也可能出现假阳性。
就像一些医学检查可能会返回癌症的假阳性一样。无论你是否应该获得贷款,以及当你访问 Amazon.com 时是否应该获得折扣,算法都可能对欺诈性索赔返回误报。
我们知道数据科学团队可能会为公司节省 100 万美元。然而,他们也将花费 Itena 的资金和资源小时。因此,他们需要确保回报大于成本!
那么这个算法有多精确呢?
他们可能会惊讶地发现这实际上是多么不准确!
这是一个粗略的数学公式:
P(欺诈索赔)= 2%
P(明确标记为欺诈|真实欺诈索赔)= 85%
P(非欺诈)= 98%
P(标记欺诈索赔|真实非欺诈)= 4%
P(欺诈索赔)*P(明确标记为欺诈|真实欺诈索赔)/
(P(欺诈索赔)*P(明确标记为欺诈|真实欺诈索赔)+ P(标记为欺诈索赔|真实非欺诈)+P(非欺诈))
在这种情况下,只有大约 30%被预测为欺诈的预测索赔实际上是根据贝叶斯定理。
为什么?
这是因为只有 2%的索赔是欺诈性的。也就是说尽管算法有 85%的准确率。对于 2%的数据,它只有 85%的准确率。
它还错误地将 98%的数据中的 4%分类。
他们的假阴性数据比真阳性数据多得多。
当你真正坐下来思考这个问题的时候,这很有趣。
现在的问题是,他们能证明节省的合理性吗?公司调查所有的索赔要花多少钱?这个真的要看索赔额度了。
如果他们处理的是医疗索赔中的 7 美元加价,可能就没那么多了。
另一方面,如果是 1 万美元的车祸理赔,公司还是会想扑上去的!
幸运的是,我们有可以快速运行这些算法的计算机,并且有望建立一个令人惊讶的过程,快速允许索赔得到裁定。
如果计算机不在那里,我们确实想把它放在正确的位置上。
如果取而代之的是,你有同样的准确性,并且让一个人来执行这项任务。假设他们花费了价值 200 美元的资源来对一项索赔进行分析!
如果索赔价值 500 美元,是否值得花费时间?
用户购买你的产品的可能性有多大
预计 2017 年电子商务的交易额将超过 2 万亿美元。虽然很多人直接通过亚马逊或阿里巴巴,但也有很多其他网站试图让顾客购买他们的产品。
这涉及大量的跨平台营销、内容营销和广告。
公司如何知道他们的广告或他们推广的网站实际上是否有效?他们得到的印象和参与真的变成了真金白银吗?
你如何开始回答这些问题?
假设你的公司在线销售厨房设备。
你支付几个网站交叉推广你的产品和电子商务网站。你知道你从每个网站获得的平均购买率,因为你一直在努力跟踪 cookies 并保持一个干净的数据库。
你想知道你应该在未来的活动中投入多少资金。根据目前的数据,你知道每小时有 10 个人购买来自“站点 A”的产品。你相信只要你有超过 80%的机会保持至少每小时 6 的速度。你可以证明市场成本的合理性。
我们该如何解决这个问题?

嗯,我们可以使用泊松分布来帮助我们。
如果你已经知道平均每小时有 10 个人从你的网站上购买产品,你可以计算出每小时有 n 个人出现的概率。
您可以将这些信息提升到更精细的层次。这将允许你利用季节性技术和泊松分布的组合来预测未来的收入和更有效地分配资金。
那将需要更详细的解释和大量的数据。现在,我们将关注第一个问题。
我们将利用泊松累积概率函数。本质上,你只是把泊松分布方程中每个大于 6 的概率相加。

如果你运行它的λ为 10,你会得到如下图。

使用泊松累积概率函数你会得到大约 94%
这样你的公司就可以继续支付网站 A 的营销费用了!
然而!
如果只有每小时 7 英镑的话。那么你只有 70%的机会在一小时内卖出至少 6 件商品!所以这个项目不得不被砍掉。
你可以很容易地设置这个阈值,并开始创建一个拍卖类型的系统,其中你的预算是自动分配的基础上,未来的回报和购买概率的比例!
那听起来像一个有趣的项目!
不要误解我们。归根结底,数据科学可用于创建与客户互动的系统。
然而,它也可以用来帮助提高准确决策的速度。以及开发具有故障保险的决策系统,限制由分析师和管理层做出的简单和复杂决策的数量。
应用线性回归
假设你在一家医院工作,你注意到在过去的几年里,某项手术的费用逐月上涨。
你想知道手术的月份和费用之间是否有线性关系。
你分析的第一步是弄清楚是否有一个模型可以用来预测手术费用的上涨。
还有第二步,我们不会再讨论,那就是找出原因!
数据科学不仅仅提供创建模型的工具。
它还提供了让人们找出原因的工具!所以当你完成这个模型后,你会想知道为什么。
也许你会认为这是因为工资、设备成本和步骤复杂性的增加,等等。与每次手术和每月的价格相比,这需要更复杂的数据。
如果您的散点图似乎遵循如下所示的线性模式。可以开始用线性回归或者甚至多元线性回归的概念来看问题。这取决于它看起来适合什么(或者更好的是,你的自动化系统检测哪个型号!)
这是一种最简单的预测形式,因为你只是试图创建一条趋势线。

尽管您可以使用 excel、python、R 或任何其他语言来找到线性回归模型。我们想给你看一段视频,教你如何手工制作。
这涉及到很多总结,但不要让这吓到你。最后,大多数人不动手做的原因不是因为数学很难
相反,数学非常简单。然而,很多事情都可能出错。尤其是简单的计算。
仅仅因为你完成了模型,并不意味着你完成了!您的数据集通常并不完全符合直线。所以测试你的模型的有效性是很重要的。
如何确定趋势线或线性回归模型的最佳拟合?
有几种方法。下面我们将讨论 R 平方误差。
什么是 R 平方?也称为决定系数。
大多数模型都有一种或几种方法来计算模型的精度。
在这种情况下,R 平方误差等于:

回归误差平方和是您正在检查的当前点与模型线上对应点之间的差值。
让你的趋势线上的点等于ŷ
((mx1+b)-ŷ )2+…((mxn+b)-ŷ )2
总变量是模型上的点和实际数据的平均值 y 之间的差。
(y1-y ) 2+ (yn-y )2
因此,在这种情况下,我们可以在 excel、R 或 python 中运行线性回归,并获得非常符合直线的模型。
在这种情况下,根据数据,R 平方误差为 0.93。这实际上只是说明了解释差异的数量。
重要的是要记住模型的用途!不是每条符合的线都是正确的!
尤其是当你开始开发更复杂的模型的时候!
这就是为什么数据科学家不仅仅是创造模型。他们也在寻找为什么!
这是近 20 年来最大的变化之一!我们有能力给出背景。在统计仅限于数字之前。
他们只能说出发生了什么和可能会发生什么。
关于需要改变什么的信息非常少!现在,数据科学家可以给出原因了!因此,当我们知道原因后,我们就有能力给出战略建议。
例如,在这种情况下,你可以向你的医疗主任展示这个简单的趋势,然后分析为什么!
当我们出去帮助团队的时候。我们的部分重点是帮助他们带着他们的分析去见他们的主管,以获得他们的批准。
这是数据驱动的开始。这需要好奇心和一点点创业精神。
有了上图的发现,如果你能发现你可以平均减少 5.37 美元的手术费用,医院每年做 100,000 例手术。
您可以证明您每年为公司节省了 537,000 美元。希望你能加薪!
记住“所有的模型都是错的,但有些是有用的”仍然很重要。
逻辑回归,二元评估
与线性回归不同,逻辑回归有一个二进制输出。通常是通过或失败,1 或 0。线性回归的输出是连续的,因为逻辑通常用是或否来定义。
这就是为什么它被大量用于商业任务,如决定你是否应该给某人贷款,我可以预测一个病人是否患有某种疾病,以及许多其他每天困扰我们的是或否类型的问题。
使用逻辑回归允许利用多个变量。因此,即使你有一个复杂的商业决策,需要考虑几个不同的变量,逻辑回归也是一个很好的解决方案。
我们可以回头看看欺诈索赔的例子。确定索赔是否欺诈的算法可以是逻辑回归模型?你可能对索赔是否欺诈有一定的了解。您可能有位置、患者信息、医院统计数据等。
假设你想知道一个医生是否真的在做心脏直视手术,而不仅仅是假装开账单(这有点牵强,但还是顺其自然吧)。
你可能知道,相同的心内直视手术索赔也应该包括特定设备的使用,如核磁共振成像或实验室工作。如果没有出现这种情况,很有可能是欺诈。
你也可以设计一些功能。您可以根据通过的索赔和审计,找到特定医生的心脏手术是虚假的可能性,您可以计算医生每天完成的手术数量,或者您的团队有主题专家或上下文数据支持的任何其他信息在虚假索赔中发挥作用。
这个模型很难手工计算。幸运的是!这就是为什么 R 和 Python 是令人惊叹的语言。下面是 R 代码实现(glm 代表通用线性模型库)。这基本上是一行实现
注意:这有点误导。虽然它看起来像一行实现。在使用之前的公式之前,可能需要进行大量的数据清理和标准化工作!
*model <- glm(formula = FraudulentClaim ~ ., family = binomial(link = "logit"),
data = train)*
来解释一下这个实现。公式变量的输出设置在左侧。那么波浪符号表示“欺诈性索赔”依赖于句点。在 R 中,句点表示训练集中除因变量之外的所有变量。
如果你的团队只认为这是另一组变量,那么他们可以使用下面的例子,而不是周期。
*model <- glm(formula = FraudulentClaim ~ income + age + X, family = binomial(link = "logit"),
data = train)*
数学模型看起来像这样:

图片来自http://www . saedsayad . com/logistic _ regression . htm[/caption]
这些“b”变量中的每一个都代表另一个可能的变量。可能是性别、年龄、收入(通常都是标准化)。)
这一统计学原理也可用于其他医院任务,如再入院、诊断和欺诈索赔
应用数据科学
这些是一些基本的案例研究,我们展示了如何在决策过程中实施一些定理和算法。
它们是一个很好的开始,可以用在更大的项目中,以帮助改善您的数据科学和公司的数据驱动文化!
随之而来的是一些我们想注意的事情
算法和数据科学使用的一些利弊
赞成的意见
关注数据驱动的决策,而不是政治和直觉
自动做出可能会造成财务和精神负担的决策
提高一致性、准确性,并迫使团队制定决策流程
减少花费在任务上的时间
骗局
如果算法不正确,团队可能会过度信任它
下一篇数据科学文章
我们的下一篇文章我们希望将重点放在一些更技术性和基于编程的实现和应用上!如果您有任何具体的案例需要我们探讨,请告诉我们!!
您可能喜欢的其他数据科学资源:
数据科学用 Excel?
了解最古老的分析工具之一如何促进您的数据科学工作

Microsoft Excel 可能是最知名的数据处理工具。几乎每个人都知道这一点,我们对表格、枢轴、VBA 脚本和图表有自己的恨或爱。我们做每月的业务电子表格,计算假期成本,甚至在 Excel 中处理联系人列表。“Excel”这个词甚至成了“表格”或一组表格的同义词,比如:“嘿,我能给你发一个 Excel 吗?”连你奶奶都用过。毕竟,它从 1987 年就存在了,而且它的网格和表格看起来仍然非常相似。他们可能在设计上做对了什么?
但是等等。数据科学?在 Excel 中??难道数据科学不是关于网络浏览器中大肆宣传的 Jupyter 笔记本,云中的大数据和 Hadoop,GPU 上的深度学习和高级交互图和可视化,以及…?这听起来可能和你所知道的 Excel 相差甚远。嗯,等一下…
获得物理学硕士学位后,我花了十多年时间应用“数据科学”来解决问题。从汽车行业的自动驾驶汽车,到保险领域的风险管理和医疗技术领域的预测性维护,Excel 一直紧随其后。现在,我想与你分享我的经验。
是时候振作起来承认:
Excel 是数据科学的强大工具。
对此可能有很多支持(和反对)的理由。但在开始之前,让我们先澄清一下:我和微软没有任何职业关系,从来没有。
这些是我自己的想法和经验——我可能错了,所以请纠正我!
2D 数据最佳编辑
没有比这更好的二维数据编辑器了。大概这就是为什么 Excel 这么多年来都是同样的布局。这些表格易于编辑、格式化、着色和共享。Google Sheets 是对 Excel 数据编辑设计的明确肯定——但也适用于多个用户。允许多个用户同时编辑是我在 Excel 中怀念的东西(在 SharePoint 和 OneDrive 上丢失数据太多次之后)。分享链接的便利可能也是像 Jupyter 这样的数据科学笔记本背后的成功的一部分。
然而,在 Excel 中,只需按一下[F11]键,就可以使用公司的视觉标识将您的表格变成图表(假设有人花时间设置了主题)。除此之外,内置的表格,过滤器,切片器,分组,窗口分割,单元格公式和其他功能,以及任何替代的表格或数据库编辑器都保持不变。也就是说,只要您对每张工作表的最大行数为 1,048,576,列数为 16,384 没有问题!对于大数据来说,这并不令人印象深刻,但对于实际编辑和查看数据来说,这通常就足够了。
高级分析平台
在一部关于人工智能视角的电影中,DARPA 使用电子表格来说明神经网络如何工作。
DARPA using spreadsheets to explain neural nets
事实上,Excel 有深度学习方法,但也许这不是你首选的工具。但是 Excel 附带了一个分析工具库,可以被激活以释放更多高级功能。前几天,我听到一位微软代表被问到“高级分析和普通分析的区别是什么?”。她回答“使用机器学习的能力”。由于分析工具库通过回归和其他复杂数据分析进行机器学习,我假设微软将 Excel 视为其高级分析平台之一。
无论如何,工具库感觉有点老派,因为在 SAS 或 SPSS 中使用硬编码的函数。现代数据科学是关于开放图书馆和透明度的。也许你出于某种原因想要调整你的高斯混合模型或者了解它是如何被优化的?在 Excel 中做这些或者在Visual Basic for Applications(VBA)中改编一些开源代码可能会很麻烦(在 VBA 你怎么能对一个矢量切片呢?).
编写 Excel 脚本——像数据科学家
当然,您会喜欢使用您最喜欢的数据科学脚本语言(Python、R、Scala、Julia、Java、JavaScript 等等)和可信库。这很好:你可以在 Excel 中使用 Python。至少如果你用的是 Windows 系统的机器(这是我推荐的,因为 Mac 上的 Excel 仍然不是很稳定)。
现在越来越专业了:Python 在 Excel 中的应用

Example data in “Table1” in Excel
要在 Excel 中演示 Python,只需创建一个新的电子表格,并输入一些类似于此处截图的数据。选择所有数据并制作表格[Ctrl+T 或 insert table]。如果您使用的是英文版的 Excel,该表默认为“Table1”。下面的 Python 代码使用包 win32com 与 Excel 的对象模型(一个程序员对 Excel 的接口)进行实时交互。请注意,您得到了一个与正在运行的程序交互的活动连接,我们不仅仅是读写磁盘上的文件。
实时连接到正在运行的 Excel 和活动工作表
import win32com.client
import pandas as pdapp = win32com.client.Dispatch("Excel.Application")
ws = app.ActiveSheet
获取表格内容和标题,放入 Pandas 数据框 注意,我们可以使用 Ranges 以及 ListObjects 等。
x = ws.Range("Table1").Value
headers = ws.ListObjects("Table1").HeaderRowRange.Value[0]df = pd.DataFrame(list(x), columns=headers)>>> df
Product Month Income
0 A January 7358.001583
1 A February 2218.386731
2 B January 5201.179032
3 C January 1765.453011
4 C February 6261.555208
计算每种产品的收入中值,并写回 Excel 中
注意,Excel 在分配范围时总是期望 2D 形状:
income_med = df.groupby('Product').Income.median()ws.Range("A10:A12").Value = (('A',), ('B',), ('C',))
ws.Range("C10:C12").Value = tuple((_,) for _ in income_med)
让我们演示一下 Python 与 Excel live 的交互
为表格设置一个过滤器并选择某个范围:
ws.ListObjects("Table1").Range.AutoFilter(
Field=2,
Criteria1="=January")ws.Range("C10:C12").Select()
上面的例子可以很容易地扩展到几十万行,而不会有性能问题。Python 可以直接访问 Excel 内部的数组存储。与运行 VBA 相比,Python 和 Pandas 在更高的抽象层次上提供了更强的数据操作能力。你也可以很容易地从 SciPy 和其他一些资源中获得科学工具——但是要保持 Excel 作为查看数据的“前端”。
更多可能性
使用 Excel 还有几种进一步分析的可能性。内置的数据库引擎可以对表和动态数据集执行 SQL 查询, Power 查询编辑器可以从各种数据源(包括 Azure cloud 或 Hadoop)获取数据。如果你还没有,还有很多东西值得探索。
数据唾手可得还是数据沿袭?
与数据科学工作流程相比,Excel 可以直接呈现数据。你可以随心所欲,想存多少版本就存多少版本,操纵自如。数据传承,从起点追踪数据的能力,通过操作到目的地或结论,因此很难。另一方面,在数据科学笔记本中,整个操作过程被列为脚本,其他人可以重复和验证。自然,自动化或投入生产的步骤要比笔记本小得多。更不用说处理版本控制和跟踪变更了。

Ad for Excel for Windows 3.0 (released 1990)
对于数据新手来说,Excel 的简单性降低了入门门槛,允许快速开始数据操作。重复任务的功能和宏可以在这个过程中学习。笔记本中的数据科学轨道最初看起来更艰难,但当涉及到更大的操作和更复杂和自由的分析时,它将会给你带来回报。
太早,还是领先?
我认为微软早在 90 年代就推出了 Office 套件。Excel 是一个很好的例子,它将数据仓库、图形用户界面、分析工具和 VBA 脚本环境都放在了一起。开放对象模型使得构建扩展、插件和直接与电子表格的核心交互变得相当容易。Microsoft Access 是另一个类似的、但更面向数据库的解决方案,它将所有这些结合在一起。你可以把它作为一个文件来分享,这不是很棒吗?微软显然是这种数据分析自助服务套件的领导者。在某种程度上,我认为他们甚至太早了。或者是 Excel、Access 和类似工具带来了我们最近看到的数据科学革命?
那些辉煌的日子
可悲的是,Excel 在脚本语言方面远远落后(VBA 是建立在 60 年代发明的 BASIC 之上的),更不用说脚本的版本控制或安全性了。数据容量并不令人印象深刻(即使数据模型可以在内部承载超过 1 百万行)并且 Excel 可能永远达不到大数据水平(不管那是什么)。图形是另一个 Excel 远远落后于开源库的主题,比如 ggplot 和 matplotlib 。显然,微软把所有的精力都放在了数据可视化的 Power BI 上。自从 Excel 成为唯一工具的辉煌时代以来,已经发生了很多事情。
数据科学家:向过去学习
许多超级大国依然存在。我认为 Excel 是几乎所有小规模 2D 数据的最佳编辑器,它被大量使用,有点像共享电子表格的默认编辑器。脚本和分析有很多种可能性,甚至像我们在 Python 中看到的交互方式。也许这就是为什么如此多的组织遭受“Excel 地狱”?绕过顽固的业务系统并构建自己的 Excel 解决方案实在是太容易了。(我知道,我已经贡献了不少了;-))

Depicting the “Excel Hell” (3xcorp)
现代数据科学平台可以从 Excel 中学到很多东西。数据科学就是从数据中学习,从数据中学习意味着从过去中学习。Excel 有很多过往的经验可以分享。也许 Jupyter 笔记本可以找到一种更好的方式来包含数据集以供共享?在线数据科学工作台能否提供更好的界面,以可视化方式快速编辑和格式化数据?有很多种可能。我认为优势在于允许智能存储、编辑、可视化、分析和共享。
对我来说,数据科学一直是关于组合最适合完成工作的工具。通常 Excel 就是其中之一。我不断尝试迁移到 Linux 上的 LibreOffice(享受开放软件,摆脱微软),但仍然经常发现自己启动了一个虚拟的 Windows 机器来访问 Excel 的超级功能。要么是我已经沉迷其中,要么是 Excel 的设计中隐藏了一些伟大之处。无论如何,我认为一个没有 Excel 经验的数据科学家和一个从来没有用过锤子的木匠是不相上下的。我可能会在很长一段时间内继续通过电子邮件向人们发送电子邮件。它仍然是数据交换的最佳格式,允许接收者立即进行自己的分析——每个人都知道这一点。
让你超越自我的工具
总而言之,Excel 已经存在了几十年,毫无疑问,它是编辑和分析表格数据最流行的工具。许多人在日常生活中离不开它。数据唾手可得,而且正如我们所展示的,可以从 Python 脚本和机器学习包中直接访问,您还能期望什么呢?我建议真正探索和学习 Excel,作为一名数据科学家,你将获得令人印象深刻的超能力。
你的体验是什么?
预计支付 215 美元来填写你的 2018 年世界杯贴纸相册

Photo from Emilio Garcia at Unsplash
加的夫大学的保罗·哈珀教授最近计算出如果收集者不与任何人交换她的任何复制品,填写 2018 年帕尼尼世界杯贴纸专辑将花费 773 英镑(1100 美元)。根据教授的计算,如果 10 个朋友互相交换,费用可能会下降到 247 英镑(352 美元)。贴纸专辑的制造商帕尼尼发布了一份官方声明,称哈珀教授假设收藏者生活在泡沫中,不与陌生人交易,从而高估了真实成本。
我最近开始填写我的贴纸相册,我想自己计算一下我应该支付多少来完成它。我写了一个程序来模拟各种交换场景下的贴纸收集,我认为真正的成本接近 290 美元。下面我将向您介绍我是如何设置模拟的以及我的发现。
该设置
自 1970 年墨西哥世界杯以来,帕尼尼世界杯贴纸专辑每四年发行一次。收藏家们成包地购买贴纸,并交换他们重复的贴纸,以便完成相册。今年,该专辑由 682 张贴纸组成。每包售价 1 美元,有 5 张贴纸。
我的模拟做了以下假设:
- 每个标签都同样有可能出现在任何包装中。
- 收藏者只能在互利的交易中交换重复的贴纸*
- 每位收集者从随机抽取的 25 张贴纸开始。
在我的模拟中,有 10 个朋友试图完成这张专辑。在每一个时间点,这 10 个朋友会互相交易。好友间的交易完成后,每个人都有机会和 k 个完全陌生的人进行交易。我对 k {0,2,5,10}的以下值进行了模拟。如果玩家不能和他的朋友或陌生人交易,他就买一包贴纸。当所有 10 个朋友完成相册时,模拟终止。
总而言之,以下是我的模拟所采用的参数和我使用的数值:
- 交易的朋友数量= 10
- 相册中的贴纸数量= 682
- 每包中的贴纸数量= 5
- 每位玩家每轮可以交易的陌生人数量=
- 陌生人在交易前购买的贴纸数量= 100
结果
对于所有的场景,我都进行了 100 次模拟,然后研究了这 10 个朋友花钱的分布情况。因此,每次分配都以 1000 点为基础。
场景 1:不与陌生人交易
在这种情况下,这 10 个朋友只能相互交易。对我来说,这就是哈珀教授计算出的 352 美元的成本。经过 100 次模拟,我发现平均成本是 326 美元,但有很多噪音。成本低至 199 美元,高至 1218 美元。我怀疑正在发生的事情是,一些不幸的朋友是唯一一个收集专辑的人,她需要求助于购买包,直到她完成。

场景二:与朋友交易后可以与 2 个陌生人交易
在这种情况下,结果噪音较小。收藏家们平均花费 215 美元,但也可能从 146 美元到 498 美元不等。

场景三:和朋友交易后可以和 5 个陌生人交易
这种情况下的平均成本是 181 美元。分布的范围正在接近平均值。

场景四:和朋友交易后可以和 10 个陌生人交易
在这种情况下,完成专辑的平均成本是 135 美元。

结论
与陌生人交易将有助于你以更低的成本更快地完成专辑,这是常识,但我的模拟通过量化成本预计会随着与你交易的陌生人数量的增加而减少,从而深入了解这种关系。我发现最令人信服的是,与只和同样的 9 个朋友交易相比,只和两个陌生人频繁交易可以减少 30%的成本。此外,随着陌生人数量的增加,与多一个陌生人频繁交易的额外好处也会减少。要点是,你只需要一点点打破你的泡沫,就能最大限度地降低成本。

最终,我认为哈珀教授和帕尼尼的观点都有道理。帕尼尼是对的,这张专辑的成本和你想要的一样高。如果你不想买很多包,你应该试着和尽可能多的陌生人交易。然而,哈珀是对的,他指出,随着帕尼尼增加专辑中贴纸的数量以及贴纸的价格,专辑的奖金会随着时间的推移而不断增加。考虑到帕尼尼故意提高专辑的价格,期望人们经常与 10 个以上的陌生人交易以保持价格低于 100 美元似乎有点不合理。
我希望这能让你对完成世界杯专辑的成本有一个更好的了解,但这一分析绝非详尽无遗。我邀请你看看我在这个模拟中使用的代码和修改你认为合适的假设。收集贴纸是一件非常有趣的事情,尤其是当你得到你渴望得到的贴纸时,所以我希望我没有阻止你开始收集。如果你在芝加哥,我很乐意和你交易!
附录:
*我还模拟了收藏家只进行一对一交易的场景。关键的要点是相同的,但分布的噪音更小。
“期望管理”或我如何学会不害怕商业演讲
我将写一些关于数据科学项目中的期望管理的内容。现在,这是我个性中学术方面发现的一点“商业用语”。然而,这在商业环境中很重要(可能在非商业环境中也是如此,比如非营利组织)。
值得分享一本呆伯特漫画。只是因为它总是与讨论“商业用语”相关。

版权所有:斯科特·亚当斯和呆伯特
所以下面是我学到的一些小技巧。我分享这些的原因是管理期望是数据科学过程中的一个困难部分。研究和开发类型的工作甚至软件工作都很难,它们很难管理,我们生活在一个期望相当膨胀的世界——许多评论(通常是似是而非和垃圾的)如“人工智能将窃取我们的工作”都于事无补。然而,这就是我们生活的世界。我在这方面并不完美,这是我仍在努力的一项技能,但我想写下我思考过的一些概念和框架。
首先关注简单的事情。即使是交付一个数据集或一些 KPI,在一个没有充分利用数据的环境中也是很重要的。这也有助于你搜索域名。一个好的策略是向人们发送更新——无论是电子邮件更新还是其他方式。我也喜欢把图表打印出来贴在墙上,这样人们就可以看到了。
其次,在你进行的过程中迭代地交付东西。你从一个 6 个月的研发项目中失去的政治资本通常是不值得的。例如,比较您从一些基于 SQL 的产品分析中获得的洞察(比如 6 个月内获得 20 个洞察)和从一个推荐引擎获得的洞察(可能需要超过一个季度才能看到 ROI)。
第三,也会产生负面结果。“我们发现这个功能不够强大”或者这里没有信号。Jonathan Nolis 在这个上写了一篇很棒的博文——这是我在一些雄心勃勃的项目上的经验,遗憾的是,这些项目就是行不通。实验包括接受积极的结果和消极的结果。
有时我们相信数据中的信号比实际的要多!这是可以的。
第四——与商业伙伴建立非常密切的工作关系,这样你就能站在他们的角度考虑问题,让他们成为旅程的一部分,这样即使是很小的决定也是共同的。这是我的朋友 Padraic 给我的,非常重要。向业务利益相关者展示 KPI(关键绩效指标)或分析—帮助他们理解流程,并真正帮助作为数据科学家的您了解什么是重要的以及每个领域的真正含义。
让我们分享一个具体的例子——在我做的一个项目中,结果是还款没有全部存储在同一个列中——所以需要一些时髦的 SQL 和业务流程理解来真正过滤所有的还款。如果你不这么做,很容易得到一个误导性的收入数字——比如收入加还款。我艰难地认识到,向商业利益相关者快速展示结果是非常重要的。
我有一些其他的想法,但这些是我目前的主要想法。对激动人心的研发项目说是非常容易的。然而,你的工作不是对此说“是”,而是为企业创造价值。专注于此,而不是$SHINY_TOOL
我要感谢与詹姆斯·斯坦尼尔、奥利·格拉斯、米克·库尼和罗布·霍顿的对话,这些对话形成了我对此的想法。
在生产中使用 R 和 Python 的经验
从 2016 年 5 月开始,重新分享我们伟大的经历,开始我的新媒体博客。

Python 和 R 是一些最好的数据科学开源工具。它们可以很容易地用于脚本和自定义分析,但作为在线软件的一部分自动运行它们需要更多的考虑。在 Smartly.io,我们已经广泛地使用了这两个工具。在这篇博文中,我将分享我们在生产中集成它们的一些经验。
作为背景,我们需要统计计算的第一个用例是预测预算分配。它自动在多个广告集之间重新分配预算,以优化营销活动中的每次行动总成本。它每天都会自动运行大量的活动。
为了将统计分析与我们在线平台的其余部分分开,我们创建了一个新的微服务。我们想把统计软件用在最合适的地方:做数学运算——并在其他地方做剩下的工作。基本上,服务获得它需要的所有输入数据并给出一个输出。在我们的例子中,输入数据包含所有必要的历史数据(印象、转化、花费、预算等。)并给出新的预算作为输出。下面是一个用 JSON 格式输入输出的简化例子。
Input: { "d": [ { "id": "a", "impressions": 100, "conversions": 5, "budget": 50, "spent": 50 }, { "id": "b", "impressions": 100, "conversions": 6, "budget": 50, "spent": 50 } ] }
Output: [ { "id": "a" "budget_prop": 46, }, { "id": "b" "budget_prop": 54, } ]
最初,我们通过使用 R 创建了微服务。有一些 R 包将自定义 R 库包装到 HTTP API 中,特别是至少有 DeployR 和 OpenCPU 。简而言之,这些服务允许您通过 HTTP 调用 R 函数。一年前,我们评估了备选方案,选择了 OpenCPU 作为我们的案例。我们自己没有尝试其他替代方案,所以我们的实际操作体验仅限于 OpenCPU。
在 Linux 上安装 OpenCPU 非常简单。要使用 OpenCPU,您必须创建一个自定义的 R 库。RStudio 有一个好的文档开始。在 R 中安装了库之后,它将连接到 OpenCPU 服务器,因此您可以通过 HTTP 调用开始调用 R 函数。
例如,在我们的例子中,我们有一个名为BudgetAllocation(d)的 R 函数,它在数据帧d中获取输入数据。该功能在我们的内部包smartlybuster中提供。使用 OpenCPU,我们能够通过 http://localhost:8080/ocpu/library/smartlybuster/R/BudgetAllocation/json 调用 BudgetAllocation 函数,将上述 JSON 作为输入,并获得函数的输出作为响应。
我们在 OpenCPU 上使用 R 大约半年,没有出现任何问题。我们的 R 代码库开始增长,最终我们意识到 Python 更适合我们的目的,因为它是一种更合适的编程语言。最初,我们从 R 代码到 Python 进行了几乎一对一的转换,并在大约一周内完成。对我们的 R 库进行适当的单元测试对转换帮助很大。
对于 Python,我们最终使用了 Flask ,因为它为 Python 提供了类似于 OpenCPU 为 r 提供的 HTTP API。由于我们的 BudgetAllocation 是一个独立的微服务,我们可以很容易地将旧的 R 服务切换到新的 Python 服务。在产品化阶段,我们同时运行这两个程序,以评估结果是否匹配。
从 R 到 Python 的过渡相当简单。通过使用 pandas 库,我们得到了与 r 中相似的数据帧。最大的惊喜之一来自 pandas 如何处理数据帧中的子集和索引。在 pandas 中,获取行的子集会返回一个数据帧,其中的行以它们原来的行号命名。这可以通过一个 reset_index()调用来解决,该调用允许您使用 d.loc[i,' budget']类型的访问权限再次访问数据。
Python,pandas 和 Flask 在迁移后对我们来说都很好用。有些部分将受益于以适当的 Python 方式重写。总而言之,我们认为 R 和 Python 都是非常适合的工具,在开发中很容易运行。Python 是一种更适合开发的编程语言,而 R 有更好的统计库。
在未来,我们看到我们可能会同时使用两者。Python 将作为处理大多数情况的主要工具。r 可用于某些特定的统计部分。为了进行这种集成,我们可以继续使用 OpenCPU 从 Python 调用 R,或者切换到特定的集成库,如 rpy2 。
体验数据科学中的“科学”

我从事软件行业已经很长时间了。我扮演过各种角色,但大多数时候我是一名开发人员,或者更正式地说,我是一名“软件工程师”。
今天,我是一名数据科学家。虽然我的工作并没有完全不同,我仍然坐在电脑前写代码,但工作性质不同了。在我开始数据科学之旅后不久,我开始经历沮丧的时刻。这并不是说我不喜欢我的工作,只是偶尔我会因为我当时从事的项目而感到沮丧。大多数时候,那些时刻是我认为我知道我在做什么,而意识到我不知道的结果。今天我已经意识到,这些时刻只是工程和科学之间的差异。
工程有很多定义,在维基百科中总结为:
工程是应用数学,以及科学、经济、社会、实用知识为了发明、创新、设计、建造维护、研究,改进结构、机器
或者在我的简短版本中:
工程是为了解决问题而应用的技术”
是的,也许这个定义太宽泛了,但我想说的是,在工程中,在大多数情况下,我们有一个明确定义的问题需要使用明确定义的资源和约束来解决。像“让我们建造一座支持许多汽车的桥梁”、“让我们铺设一条支持许多人的电线”或“让我们建造一个允许许多用户共享照片的应用程序”这样的问题。
许多人会同意软件开发就像工程一样。我们有一个问题,我们需要解决它。有时,这些是非常困难和重要的问题,在这种情况下,开发人员(或工程师)必须利用他最好的知识、经验和创造力。这就是开发的乐趣所在。你努力工作,你发明东西,最后你解决了问题。开发(工程)很有趣,我喜欢它!
这个过程的一个非常好的特性是能够知道你确实解决了问题,并且能够判断(在大多数情况下)一种方法可能有效而另一种方法无效。这正是工程和科学之间的主要区别(在我看来也是游戏规则的改变者)。
维基百科对科学的定义是:
“以可测试的解释和关于宇宙的预测的形式建立和组织知识的系统企业。”
或者在我的删节版中:
“一种描述现实的方式”
也许这是一个太深奥的定义,但最终科学是一个创造世界/宇宙如何运作的想法(模型)的过程。科学的一个重要属性是它必须是“可测试的”或“可测量的”一旦你有了一个假设,你必须能够测试,测量和重现你的结果,以证明这个理论/想法/模型描述的空间足够好。
在数据科学中,我们正是这样做的。我们有一些问题(如在工程中),我们试图创建一个模型,以尽可能最好的方式描述这个问题(世界),这样我们就可以对我们的问题做出预测/结论。我们用这个模型进行实验,测量我们的结果,确保我们可以重现我们的结果,并最终创建一个产品(或报告)。实验的一个不好的地方是它们可能会失败。此外,与工程不同,我们不能 100%确定我们解决了问题,也很难知道什么方法行得通,什么行不通(这就是实验的目的)。
数据科学家的工作很大一部分是运行实验,实验可能会失败。你可能对你的问题有一个很好的想法,直觉告诉你这个想法一定会大大提高你的模型的性能,你努力开发这个想法,你测试了几天,最后你发现你的想法..嗯,没用。它不起作用是因为你错过了一些东西,因为这个世界并不像你想象的那样工作,因为你没有足够的或不好的(嘈杂的)数据或其他原因。这令人沮丧,或者至少对初级数据科学家(或任何科学家)来说是令人沮丧的,尤其是对软件开发人员(或工程师)来说。
过了一段时间,我开始意识到这是这份工作的乐趣所在。你可能会失败,但当你成功时,那是一种很棒的感觉。数据科学很有趣,我喜欢它!
有一件事比实验失败更令人沮丧。当你实验失败的时候,你知道你在哪里,你知道你尝试过(和没有尝试过)什么,你知道它没有成功(或曾经成功)。经过几次实验后,你会知道什么可能有效,什么可能无效。为了实现这一点,你必须能够知道什么有效,什么无效,这意味着你必须能够衡量你的结果(并且相信你的衡量!).如果你没有一个合适的测量或者你不能重现你的结果,你就完全被蒙在鼓里,这真的很令人沮丧。
如果我有一个给初级数据科学家的建议,那就是你必须为你的问题/实验创建一个值得信赖的测量,无论是通过获得高质量的数据,自己标记还是任何其他方法,你都必须这样做。
基于扩展聚类质心的多数欠采样技术(E-CCMUT)对 CCMUT 的实验改进

在我之前的文章《 基于扩展聚类质心的多数欠采样技术(E-CCMUT) 》中,我提出了一种新的欠采样算法——基于扩展聚类质心的多数欠采样技术(E-CCMUT)。在本文中,我将演示一个实验,在这个实验中,我将证明 E-CCMUT 比 CCMUT 具有更好的统计结果,并且与 E-CCMUT 的直觉相符。
实验:
从人口普查数据中预测一个人的收入水平是否大于 5 万美元 。这与我以前的文章“ 欠采样:不平衡数据的性能助推器 ”中使用的实验相同,其中 CCMUT 被用作欠采样算法,以便通过实验证明欠采样可以提高模型性能。这里,将使用 E-CCMUT 而不是 CCMUT,并将使用在“ 欠采样:不平衡数据的性能助推器 ”中导出的结果进行直接性能比较。
数据集:
数据预处理:
标签编码、特征选择和一键编码按顺序完成,如“ 欠采样:不平衡数据的性能助推器 ”
数据不平衡消除:
这是使用 E-CCMUT 完成的,其中多数类(标签 0)是 68%的欠采样。E-CCMUT 的 Python 实现如下所示:
import numpy as np
from math import sqrtdef **ECCMUT**(X,f):
cluster_centroid = np.sum(X,axis=0)/X.shape[0]
euclidean = [None]*X.shape[0]
for i in range(0,X.shape[0]):
euclidean[i] = sqrt(sum((cluster_centroid-X[i])**2))
# finding the most important instance with label 1
imp_instance = X[euclidean.index(min(euclidean))]
# removing the instances (under-sampling...)
for i in range(0,X.shape[0]):
euclidean[i] = sqrt(sum((imp_instance-X[i])**2))
indices=list(reversed(sorted(range(len(euclidean)), key=lambda
j: euclidean[j])))
X_f = np.delete(X, indices[:int(f/100*X.shape[0])], axis=0)
return X_f
这里,X 是多数样本矩阵,f 是欠采样的百分比,X_f 是 E-CCMUT 对 X 的欠采样形式,它由 ECCMUT()返回
洗牌和拆分:
产生的数据集以一致的方式进行混洗,并且 80–20 分割(80%训练集和 20%验证集)。
学习算法:
梯度推进分类器用作训练集上的学习算法,并使用网格搜索进行调整。
网格搜索后得到 100 个估计量和最大深度为 4 的最优超参数。基于平均分数的模型的网格搜索调整的总结如图 1 所示。

Fig 1. Grid-Search Summary on Mean-Score
结果:
使用度量、训练准确度、验证准确度、召回率、精确度、F1 分数、受试者操作者特征曲线下面积(图 2 所示的 AUROC)和混淆矩阵(图 3 所示)来分析模型性能。

Fig 2. ROC Curve showing the Area Under the Curve

Fig 3. Normalized Confusion Matrix
表 1 中列出了训练准确度、验证准确度、召回率、精确度和 F1 分数。

Table 1
该模型与使用相同方法但使用 CCMUT 开发的模型的比较:
在某些情况下,用于开发机器学习/深度学习模型的数据集通常是…
towardsdatascience.com](/under-sampling-a-performance-booster-on-imbalanced-data-a79ff1559fab)
根据上述文章,CCMUT 所取得的结果被考虑在内。模型性能比较基于以下指标:
- 拟合度量:|训练准确性-验证准确性|
- 验证准确性
- 精确
- 回忆
- f1-分数
- 奥罗克
对照表如表 2 所示:

Table 2
- 在这里,E-CCMUT 在召回率、精确度、F1-Score 和 AUROC 方面的性能没有比 CCMUT 有所提高或下降。
- 在拟合方面,E-CCMUT 比 CCMUT 有了显著的提高,拟合度从 2.1 下降到 1.29。拟合度量越多,验证和训练精度的可比性就越小,因此要么过拟合,要么欠拟合,拟合度量越小,模型就越接近"完美拟合"
- 与 CCMUT 相比,E-CCMUT 的验证准确性有非常轻微的下降(0.24%),这可以忽略不计。
此外,还进行了许多其他实验,并观察到 E-CCMUT 产生了比 CCMUT 更适合的模型,而验证准确性没有显著下降。
因此,E-CCMUT 是对 CCMUT 模型的拟合性能指标的改进,并且证实了在构建算法时所采用的直觉。
[实验模型]实现用于 CIFAR 10 分类的树形深度神经网络[带有 TF 的手动后撑]

Gif from here
所以今天,我想做一个实验模型,昨天晚上我想到了这个网络架构。一种类似树的形状的架构,但是如果你知道任何支持这种创新或网络架构的知名学术论文,请在下面评论,以便我可以提供适当的参考。
更新 Peter Baylies 向我提供了一篇论文,该论文的网络架构与本文中的相似,请点击此处查看该论文。
请注意,这是一个实验模型,因此性能不是我的目标。
再一次,像往常一样让我们比较。手动反向传播方法与传统自动微分模型的比较。如果你不知道自动微分,请点击这里。
网络架构(基本构建模块/完整架构)


黑色矩形 →输入图像
→绿色/红色矩形 →卷积层(内核大小 3)→批量归一化
→黄色矩形 →瓶颈卷积层(内核大小 1)→批量归一化
蓝色圆圈 →加法运算(残差连接)
所以上面的剩余块是我们完整网络的基本块。现在,如果你看到完整的架构,你就会明白为什么我称这个网络为树状网络。(最主要是因为网络的形状像一棵树。)


圆圈 →我们上面覆盖的每个卷积残差块
浅棕色矩形 →全连通网络
橙色矩形 →软 Max 层
所以如果我们把我们的模型旋转 90 度,它看起来就像一棵树!(嗯有点……)

另外,请注意紫色箭头,我们也将做一些不同的事情。

Layer3_a →仅将红框圈和蓝框圈的结果相加。
Layer3_b →仅将蓝色方框和黄色方框的结果相加。
Layer3_c →只将红框圈和黄框圈的结果相加。
紫色箭头不同于粉红色箭头,因为我们没有把所有的变量加起来。
结果(自动微分)

在 100 epoch 上,我们可以看到模型明显过拟合,这可能是由于多种原因造成的。但众所周知,在深度学习模型中,Adam optimzers 并没有那么好地概括。如果您不知道 Adam optimizer,请单击此处的。
结果(破碎的散瞳反向传播)

对于这种情况,手动反向传播是可怕的。这个模型甚至不能达到 40%的准确率。
请注意,我们在前馈操作期间执行了批量标准化,但是,我没有在整个过程中反向传播,因此出现了中断的扩张反向传播。
透明度

为了让这个实验更加透明,我把所有的命令日志从我的窗口提示符上传到我的 Github。查看自动微分产生的输出请点击她的 e,对于手动反向传播请点击此处。
交互代码

对于 Google Colab,您需要一个 Google 帐户来查看代码,而且您不能在 Google Colab 中运行只读脚本,因此请在您的操场上创建一个副本。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!
要访问自动区分代码,请点击此处。
要访问手动 ba ck 繁殖模型,请点击此处。
最后的话
我真的很喜欢做实验模型,它们可能不能保证性能,但它们激发了我的创造力。
如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你希望看到我所有写作的列表,请在这里查看我的网站。
同时,在我的 twitter 上关注我这里,访问我的网站,或者我的 Youtube 频道了解更多内容。如果你感兴趣的话,我还做了解耦神经网络的比较。
参考
- 文件?,W. (2018)。解压一个. tar.gz 文件需要什么命令?。Askubuntu.com。检索于 2018 年 3 月 30 日,来自https://askubuntu . com/questions/25347/what-command-do-I-need-to-unzip-extract-a-tar-gz-file
- CIFAR-10 和 CIFAR-100 数据集。(2018).Cs.toronto.edu。检索于 2018 年 3 月 30 日,来自https://www.cs.toronto.edu/~kriz/cifar.html
- j . brown lee(2017 年)。深度学习的 Adam 优化算法的温和介绍-机器学习掌握。机器学习精通。检索于 2018 年 4 月 1 日,来自https://machine learning mastery . com/Adam-optimization-algorithm-for-deep-learning/
- JaeDukSeo/Only_Numpy_Basic。(2018).GitHub。2018 年 4 月 1 日检索,来自https://github . com/JaeDukSeo/Only _ Numpy _ Basic/blob/master/treenet/man 1 . txt
- 自动微分。(2018).En.wikipedia.org。于 2018 年 4 月 1 日检索,来自https://en.wikipedia.org/wiki/Automatic_differentiation
使用 Tensorflow 试验 twitter 数据

Credits — author : Diogo Palhais; illustrator : Tatuna Gverdtsiteli
机器学习和人工智能最吸引人的地方在于,通过使用它们,它让我们有可能开始重新思考一切——你可以从完全不同的角度看待一切,我认为,有时这种“重新思考”的事实是新发明的关键。
几天前我有过这样的时刻,这真的很有趣,我决定写下这个实验。
我大约在 7 年前创建了我的 twitter 账户,但我并没有经常使用它,几个月后,我将它与我的一个网站连接起来,并在上面安装了“自动转发”机器人。在这之后,很多事情都变了,我没有时间建立我的网站,我删除了这个机器人,因为我并不真正喜欢社交网络——我的 twitter 账户已经暂停了几年。
几个月前,我决定开始使用 Twitter。我想和其他人分享我的出版物,我的公开回购(或者不仅仅是我的)——所以这就是我决定重新加入 Twitter 的原因,但是当然,根据我的账户过去的活动,我有兴趣完全不同的追随者。所以,老实说,这对我的动力影响很大。
我决定寻找这样的用户——我也会对他们感兴趣。
起初,当你在 Twitter 上开始活动时,你没有太多的帖子(当然我删除了:D 的旧帖子)和关注者——你关注的人不会关注你的可能性很大,你需要长时间添加真正有趣的帖子,以尽可能最好地展示自己。
我们已经提到了“添加关注者”,所以在我开始写这个故事的主要部分之前,我想分享一下 Twitter 的规则和限制,因为在 Twitter 上对不道德行为的处罚是非常严重的。
以下是一些重要的链接:
要了解更多关于以下内容,请阅读以下常见问题。我们不限制您可以拥有的关注者数量…
help.twitter.com](https://help.twitter.com/en/rules-and-policies/twitter-following-rules) [## 自动化规则
此页面主要面向开发人员。对于 Twitter 用户:你最终要对所采取的行动负责…
help.twitter.com](https://help.twitter.com/en/rules-and-policies/twitter-automation)
S o,我们的目标是根据 Twitter 的用户数据(我们稍后会生成)建立分类模型,预测用户未来的行为——当我们向他/她发出追随请求时,这个用户是否会追随我们。所以,简而言之——这应该有助于我们找到未来会追随我们的人。
起初,我需要 Python 包,因为直接与 Twitter api 通信不是一个好主意,而且需要更多的时间,所以正如我们所知,Python 是“包含电池”的,我很容易就找到了一个很好的包,它具有我在这个项目中需要的所有功能,更重要的是,它还有很好的文档。
以下是链接:
[## 欢迎阅读 python-twitter 的文档!- python-twitter 3.4.2 文档
编辑描述
python-twitter.readthedocs.io](https://python-twitter.readthedocs.io/en/latest/index.html)
要使用这个包,首先我们需要使用 pip 安装它。
$ pip install python-twitter
在这之后,我们需要来自 Twitter 的 api 凭证,您可以很容易地从这里获得:
[## Twitter 开发者平台
Twitter 是世界上企业和个人联系的最佳场所。自从早期的 Twitter 人…
developer.twitter.com](https://developer.twitter.com/)
如果看起来有点混乱,您可以通过截图查看详细说明:
[## 入门- python-twitter 3.4.2 文档
如果那个页面上的信息有任何问题,Twitter 会投诉,你可以修复。(确保…
python-twitter.readthedocs.io](https://python-twitter.readthedocs.io/en/latest/getting_started.html)
好了,现在我们可以成功地连接 Twitter api 了:
现在是开始数据挖掘的时候了。我们需要收集足够的数据来训练我们的模型,这里有两个选项来获得它:第一个,这更难,我这样做是因为我没有任何选择——我们应该尝试关注有趣的人,并保存他们是否关注我们,以及第二个选项——对于那些已经有足够多朋友和追随者的人来说——你可以使用这些数据来训练你的模型。
在我的情况下,第二个选择行不通,我不得不选择更难的一个。因此,对于第一个场景,我需要在 Twitter 上找到受欢迎的人,他们大多发布关于编程/机器学习的帖子,因为他们的粉丝对我来说也非常好,所以我开始收集关于这类用户的数据。
首先,我选择“一个 Twitter 摇滚明星”用户,他总是发布关于编程或 ml 的帖子,然后获得他/她的追随者列表:
在那之后,我试着得到关于他们每一个人的详细信息。我正在使用的软件包会为每个用户返回这样的数据:

这里是非常有趣的信息,我可以用它来训练我的模型,但是我不想关注他们中的每一个人,我只想关注那些和我有相同兴趣并且有一些活动的人(见第 28 行)。
尽管事实上,Twitter api 和我们的软件包都让我们有可能非常容易地关注用户:
尽管如此,你必须小心,这样你的行为才不会看起来像垃圾邮件或者违反 Twitter 规则。
所以,如你所见,我用简单的“如果条件”来过滤那些不活跃或者没有足够多朋友的人。因为我想保存最大限度过滤的数据。
我决定在关系数据库中保存关于用户的信息,我使用 Sqlite 作为数据库,因为它对我们来说绝对足够了,我不想浪费时间在这种事情上。此外,在应用程序端,我只使用 sqlite3 包来连接数据库,没有任何orm,我希望它尽可能简单。
对于第二个场景,我们使用几乎相同的代码,但不是从其他用户的关注者那里获取数据,而是获取关于我们的关注者和关注者的数据,并将所有这些信息保存在我们的表中。
首先,我们获得关于我们的追随者和追随者的信息:
最后,我们将所有内容保存到表中,就像前面的例子一样。
所以,我已经有了我需要的信息。

我想开始训练我的模型,为此,我需要为它选择特征。我们已经看到了 Twitter api 的结果。我决定只用其中的几个来训练我的模型:created_at、favourites_count、friends_count、friends_count、statuses_count.
虽然,我对培训过程并不满意,但我认为很容易猜到原因:仅根据这些数据很难猜测一个用户是否仍然活跃地使用 Twitter 帐户,也许他/她有很多帖子,但都是 1 年前发布的,所以我决定从功能列表中删除列created_at和statuses_count,代之以添加关于最后发布日期的信息。
您可以通过以下方式获取相关信息:
我决定将这个字符串转换成整数格式,并保存这个用户上一次发 tweet 之后已经过了多少天。我为它写了一个小函数:
我已经可以在主循环中使用这个函数了:
为您的模型收集数据并不是一件容易的工作,它需要最少几天,有时超过几周,所以在那些日子里,用户发生了很多变化,他们的数据已经保存在我们的数据库中,所以我编写了代码,使我的数据总是最新的(例如:朋友列表、关注者列表等),我可以在开始创建我的模型之前运行这些代码。
最后,我的数据是这样的:

我不知道你使用哪个 ide 或编辑器,我几乎总是选择 Intellij 产品,在这种情况下我使用 Pycharm。我也使用相同的 ide 来连接 sqlitedb,它让我们可以很容易地将数据转换成 csv 格式。

I check that I want header as a first row.
训练、评估、预测
现在是最有趣的部分。最后一步,我们可以使用 Google Colab ,我认为这是最有用的 Google 产品之一。
首先,我正在导入必要的包。
接下来,我们需要上传我们的 csv 文件,当你使用 Colab 时,这真的很容易,你只需要 2 行代码,然后是验证码。
上传文件后,我们可以用 Panda 打开它,看看它是什么样子。

也许你已经知道,在 Twitter 上存在私人账户,这意味着,在他们允许之前,你不能看到用户的帖子。因此,在这种情况下,你看不到用户的最后一篇文章。在我看来,特性days_after_last_post真的很重要,我决定不使用用户进行训练,他们不会给出关于这些数据的信息。我们可以像这样在 sql 中添加这个过滤器:
select ud.* from users_data ud where ud.days_after_last_post is not null;
或者你可以在这里过滤,在 Colab。
我们还可以使用 panda 查看我们有多少关注者:

现在,我们可以为我们的特征和标签创建变量:
当我们已经有了我们的特性和目标时,为了方便起见,我们将使用 Scikit-learn 来拆分数据。Scikit-learn 有一个train_test_split函数,用于将熊猫的数据帧分割成一个训练和测试集。
我们给目标和特征作为参数给train_test_split函数,它返回随机打乱的数据。我们有 30%的数据用于测试集,70%的数据用于训练集。
现在,我将为每个特性调用函数numeric_column,因为幸运的是我所有的特性都是数值型的。接下来,我将为特性列创建列表,
现在我们可以为特性列创建列表。
输入功能、测试和评估
我们需要输入函数,它必须返回一个元组,包含两个元素:特征和标签列表,我们将此输入函数用于我们的模型,因为当我们训练它时,我们必须将特征和标签传递给模型。
但是,当然,我们并不一定要手写它,它已经有了一个名为‘pandas _ input _ fn’的函数,我们将使用它:
现在是实例化模型的时候了
我们准备训练我们的模型:
我们训练了它,现在,我们能够评估我们的模型。为了评估,我们将eval_fn作为参数传递给evaluat函数:

你可以在屏幕上看到,在我的例子中,准确率是 80%+,我认为,对于这种数据来说,这是正常的——我只有大约 1400 个用户的信息,只有 4 个功能。人们的决定有时并不依赖于这些特征,所以我们的准确性现在令我满意。现在我可以用这个模型对真实数据进行预测。
预言;预测;预告

最后,我们可以获得这些用户的列表,这些用户将根据我们的模型的预测回复我们的好友请求。
当然,您可以更好地训练您的模型以获得更高的准确性,您可以使用不同的功能或更改任何您想要的功能,因为这个实验只是为了好玩,为了花更多时间使用 Tensorflow 和其他库。
感谢您花时间阅读这个故事:
风格转换的不同损失配置实验
当我参加杰瑞米·霍华德的优秀的程序员前沿深度学习时,我对风格转移很感兴趣。我想探究改变损耗配置如何改变生成的图像。我想看看使用不同的损耗网络如何产生不同的图像。我用的不同损耗网络是 vgg-16 和 vgg-19。这是一篇关于我的发现的博文。
那些不熟悉风格转移的人可以阅读这篇介绍其工作原理的博客文章。
所有实验都是使用以下内容和样式图像完成的:


left (content image), right (style image) used in these experiments
这些实验中使用的所有预训练损耗网络都是从 tensorflow 瘦模型库下载的。除非特别说明,否则初始图像是内容图像,使用的预训练网络是 vgg-16。要找出 conv1_2、conv2_2 等指的是哪些层,请运行

在本次回购中。以下所有实验均使用本报告中给出的代码进行。
实验 1:一次从一层使用风格损失进行训练
我使用这 5 层的输出来计算样式损耗:conv1_2、conv2_2、conv3_3、conv4_1 和 conv5_1。作为一个开始实验,我将内容权重和电视权重设置为零,将图像初始化为“噪声”。并使用这些层中的每一层生成样式图像(每次使用一层来计算样式损失)。生成的风格图像应该与绘画的仿作相对应。
以下是产出:



image created using loss from conv1_2, conv2_2 and conv3_3 (left to right)


image created using loss from conv4_1 (left) and conv5_1 (right)
在早期层(conv1_2 和 conv2_2)的输出中,风格图像中需要较小感受野(如咖啡色背景)的图案是显著的。在后面的层(conv3_3 和 conv4_1)中,更大的图案更明显。conv5_1 的输出看起来更像垃圾。我认为这是因为在该层很少激活。所以对损失贡献不大。下面的初始损失也显示了同样的情况。
为了生成风格化的图像,我使用 conv3_3 来计算内容损失。
当我保持所有 5 层的权重等于 1 时,以下是图像初始化为“内容”时的层内容和样式损失值:

layer-wise style loss values for initial image ‘content’
当我保持所有 5 层的权重相等时,以下是图像初始化为“噪波”时的层内容和样式损失值:

layer-wise style loss values for initial image ‘noise’
显然,在这两种情况下,后面的层对样式损失的贡献都非常小。在大多数出版的关于风格转换的作品中,所有层的权重都是一样的,这没有意义。
接下来,我想看看如果我只使用其中一层来训练,会产生什么样的风格化图像。


Output image when trained with gram matrix from layer conv1_2 and conv2_2 (left to right)


Output image when trained with gram matrix from layer conv3_3 and conv4_1 (left to right)

Output image when trained with gram matrix from layer conv5_1
从上面生成的图像可以明显看出,当我们从 conv1_2 移动到 conv5_1 时,笔触的大小会增加。【conv5 _ 1 的输出中有一些奇怪的模式。很可能是因为 conv5_1 没有包含太多的信息(我不得不将这一层的损失缩放 1e6 来生成此图像)。所以这只是噪音。这 5 个中我最喜欢的输出?conv3_3 的输出。
实验 2:利用一次一层的内容损失进行训练
我使用 3 层的输出来逐一计算内容损失:conv2_2、conv3_3、conv4_1。
我首先尝试通过将样式权重和电视权重设置为 0 来查找生成的图像,并计算每个内容层的损失,即仅使用内容损失。

Image created using content loss from conv2_2

Image created using content loss from conv3_3

Image created using content loss from conv4_1
可以看出,当我们从 conv2_2 移至 conv4_1 时,仍能捕捉到窗口等高层信息,但边缘、拐角等低层信息越来越模糊。
接下来,我生成了风格化的图像(使用内容,风格和电视损失)。对于风格损失,我使用层 conv3_3。我想检查一下,如果我更改内容层,上一个实验中 conv3_3 层的图像输出会有什么变化。
以下是生成的图像:


Output image when trained with features from layer conv2_2 and conv3_3 (left to right)

Output image when trained with features from layer conv4_1
很明显。当我们从 conv2_2 移到 conv4_1 时,建筑的边缘变得更钝,颜色变得更淡。捕获的原始内容要少得多。
实验 3:使用损失网络中两个最大汇集层之间不同层的风格损失进行训练
接下来,我想看看在两个最大池层之间使用不同的层来计算样式损失是否会改变生成的风格化图像。为此,我使用了以下层“conv3_1”、“conv3_2”和“conv3_3”。



images generated by training using only the style loss: conv3_1, conv3_2, conv3_3 (left to right)
以上是仅使用风格损失进行训练时的输出。conv3_3 的输出与 conv3_1 和 conv3_2 的输出截然不同。
接下来,我尝试通过使用这些图层来计算风格损失,从而创建风格化的图像。用于内容丢失的层是 conv2_2。
以下是生成的图像:

image generated for loss calculated from layer conv3_1


image generated for loss calculated from layer conv3_2, conv3_3 (left, right)

magnified view of image generated using style loss from conv3_1

artifacts shown with black underlining (the image is the same as conv3_3 shown above)
在 conv3_1 和 conv3_3 之间,上图(conv3_3 输出)中带黑色下划线的伪像明显更高。有趣的是,conv3_3 的仿体不同于 conv3_1 和 conv3_2。生成的图像也是如此。
实验 4:使用不同大小的风格图像进行训练
我使用 conv2_2 层的输出来计算内容损失:conv2_2。对于风格损失,我使用权重为 1 的 conv2_2。我没有使用原始尺寸(928x514)的样式图像,而是调整了图像的大小,使短边等于特定的尺寸,并在中间裁剪了较大的尺寸,以提取一个正方形。我试的尺码是 128,256,384 和 512。
以下是生成的图像:


stylized images for style image sizes 128 (left) and 256 (right)


stylized images for style image sizes 384 (left) and 512 (right)

stylized image for default style image size : 514x928
使用较小尺寸的样式图像生成的图像不好看,甚至不能显示样式图像的笔触。
同样,很明显,随着风格图像尺寸的增加,生成的图像更好地捕捉了画家的笔触。
实验 5:使用不同的 vgg 网络(vgg16 和 vgg19)进行训练
接下来,我从 vgg16 和 vgg19 生成图像。内容损耗用 conv2_2 计算,风格损耗用 conv3_1 计算。
首先,我只生成了模仿作品(保持内容和电视权重为零)。生成了以下仿作:


pastiches generated left: vgg-16, right: vgg-19
生成的仿作几乎没有任何不同。因此,我期望程式化的图像几乎没有什么不同,但我完全错了。这些是生成的图像:


Output by training using vgg-16 (left) and vgg-19 (right) loss networks
使用 vgg-19 生成的图像看起来更好,捕捉内容更好。我对此很感兴趣,并决定绘制图像在训练过程中的内容损失、风格损失和总损失。



content loss, style loss and total loss of image as it gets trained
更重要的是,vgg-19 的起始风格损失值远低于 vgg-16。我的猜测是,生成的图像之所以不同,是因为网络对内容和风格损失赋予了不同的“隐含”权重。所谓“隐含”权重,我指的是网络本身赋予内容和风格损失的权重,而不是因为我指定的内容风格和电视权重。
注意,这里 vgg16 和 vgg19 表示不同的功能。因此,这种比较并不完全意味着“vgg-19”的绝对含量损失低于“vgg-16”。这只是表明,在优化图像的同时,vgg-16 的风格损失变得更加重要。
注:-对于后续实验,使用 conv2_2 计算(6,7,8)含量损失,conv3_1 计算风格损失。
实验 6:使用不同初始化(“噪声”/“内容”)的训练


image generated with initial ‘content’ (left) and initial ‘noise’ (right)



content loss, style loss and total loss of image for both these initial conditions as it gets trained
可以看出,内容和噪声图像都收敛到几乎相同的损失值。尽管生成的图像不同。使用“内容”初始化时,损耗收敛更快。
实验 7:使用不同类型的衬垫进行训练(相同/有效)


images generated using padding ‘SAME’ (left) and ‘VALID’ (right) in the loss network



content loss, style loss and total loss of image for both these types of padding as it gets trained
损失值相差不大。结果完全符合我的预期。
实验 8:使用不同类型的汇集(最大/平均)进行训练


image generated with pooling ‘avg’ (left) and pooling ‘max’ (right)



content loss, style loss and total loss of image for both these types of pooling as it gets trained
可以看到,使用“max”生成的图像有奇怪的点。使用“avg”生成的图像更加均匀。更重要的是,“平均值”的总损失收敛速度比“最大值”快得多。
实验 9:使用不同风格权重值进行训练
我想看看样式权重对生成的图像有什么影响。为此,我决定对内容层 conv2_2 和样式层 conv3_1 使用 vgg-19,样式权重设置为 200、400、800、1600 和 3200。生成了以下图像:


left image: style-weight 200, right image: style-weight 400


left image: style-weight 800, right image: style-weight 1600

style-weight 3200
可以看出,在使用风格权重 3200 生成的图像中,画家的笔触要突出得多。原始内容(颜色等)不太突出。
实验 10:使用不同的总变化损失值进行训练
我想看看总变差损失对生成的图像有什么影响。为此,我决定对内容层 conv2_2 和样式层 conv3_1 使用 vgg-19,总变差损失为零,下一个电视重量设置为 200。生成了以下图像:

Image created using default content and style weight and tv weight = 0. On careful observation, it becomes visible that image is quite rough.

Image created using default content and style weight and tv weight = 200. Roughness present in the previous image is gone
总变差损失有助于去除生成图像的粗糙纹理。从上面两幅图像中可以观察到,一幅有总变差损失,另一幅没有,总变差损失非零的图像非常平滑。
实验 11:使用风格图像的不同裁剪区域进行训练
我裁剪了样式图像的不同区域,以了解它如何影响生成的图像的质量。
以下是提取的样式图像部分:



style image portions used for training the image: left region, center region, right region of the style image (left to right)

complete style image
和以前一样,我首先为左侧区域、中间区域、右侧区域和完整的图像生成了仿制品。
使用了 vgg-16 网络。使用的样式层是 conv3_1。


left region (left), center region (right)


right region (left) and complete image (right)
右侧区域的仿作明显不同于左侧、中间区域和完整图像的仿作。这是预料之中的,因为样式图像的右边区域明显不同于所有其他区域,甚至不同于整个样式图像本身。
接下来生成风格化的图像,内容层是 conv2_2,样式层是 conv3_1。内容重量、风格重量和电视重量在规范中给出(分别为 8 和 200)。
生成了以下图像:


stylized image generated using left region (left) and center region (right)


stylized image generated using right region (left) and using whole style image (right)
如我们所见,从右侧区域生成的图像明显不同于从左侧、中间区域和完整图像生成的图像。
如果您喜欢这篇文章,请点击下面的小拍手图标帮助他人找到它。非常感谢!
一种新卷积的实验
警告:这篇文章假设读者对 CNN 有一定的了解
卷积有很多我不喜欢的地方。它们中最大的,特别是在后面的层中的大多数权重非常接近于零。这说明这些权重中的大多数没有学到任何东西,也没有帮助网络处理任何新信息。
所以我想修改卷积运算来解决这个问题。这篇博文强调了我在这个方向上做的实验和结果。
实验#1
本质上,每个 2D 卷积运算都是一个矩阵乘法运算。其中矩阵的维数为(内核大小 x 内核大小 x 输入通道,输出通道),假设卷积维数为(内核大小,内核大小,输入通道,输出通道)。为了简单起见,我在文章中称这个矩阵为维度为(m,n)的卷积矩阵。
如果我们能够保持卷积矩阵的列是正交的(以可微分的方式),我们可以确保输出特征图中的每个通道捕获任何其他特征图中不存在的信息。更重要的是,这可以帮助我们创建权重更容易解释的神经网络。
是的,使用线性代数中的一些技巧(一个是 householder 变换,另一个是 givens 旋转),有一些可微的方法来确定这一点。我使用户主转换,因为它在 GPU 上要快得多。
代码在这个文件里。
这个想法是这样的:
不是在卷积滤波器中保持所有 mxn 个可训练变量,在偏差中保持所有 n 个可训练变量,而是以可微分的方式从另一组可训练变量生成滤波器和偏差。
更具体地,对于维数为(m,n)的卷积矩阵,创建 n 个维数为 m 的向量。第一个向量(比如 v1)将有 m-n+1 个可训练变量(开头用 n-1 个零填充),第二个(比如 v2) m-n+2 个(用 n-2 个零填充),第三个(比如 v3),m-n+3 个(用 n-3 个零填充),等等。接下来归一化所有这些向量。使用这些向量创建 n 个 householder 矩阵,按照 v1v2v3…*vn 的顺序乘以向量。合成矩阵的维数为 m×m,并且是正交的。取这个矩阵的前 n 列。结果矩阵的大小为(m,n)。并将其用作卷积矩阵。
看起来这个操作非常耗时,但实际上对于一个 3×3×64×128 的卷积,意味着 576×576 大小的矩阵的 128 次矩阵乘法。考虑到这种卷积是在 256x256 大小的图像上执行的(这意味着(256x256)x(3x3x64x128) flops),这并不算什么。
如果您必须创建一个偏置和过滤器,用 m + 1 替换 m 进行上述过程,从大小为(m+1,n)的结果矩阵中提取最上面的行并将其用作偏置,使用剩余的(m,n)矩阵作为过滤器。
如果您使用批量规范化,这种想法将不起作用,因为列的正交性假设不成立。
对于这些实验,我使用了具有类似 vgg 架构的 cifar-10。代码是在相同的回购。
结果是非常非常令人失望。


plots of cross_entropy and accuracy on training data


plots of cross_entropy and accuracy on validation data
可以看出,基线和正交卷积之间的所有曲线的结果都很差。更重要的是,正交卷积的训练时间明显更长。这是时间单位的曲线图:

plot of training time per iter for baseline/orthoconv
从图中可以看出,时间平均高出 7 倍。有很多方法可以加速这段代码,但是由于结果不佳,我没有朝那个方向前进。
我的直觉是,它不起作用的原因是,由于所有列向量必须正交的约束,模型的优化前景受到严重限制。为了测试我的直觉,我做了下一个实验。
实验#2
在下一个实验中,我没有使用 householder 乘法产生的卷积权重和偏差,而是添加了另一个损失项,称为“正交性损失”。正交性损失计算如下:
设卷积矩阵的维数为(m,n),偏差向量的维数为(n),连接这两个向量形成一个维数为(m+1,n)的矩阵。称这个矩阵为 m。计算这个矩阵的列范数,称它为 N(它是一个维数为(1,N)的矩阵)。
计算转置(M)M .计算转置(N)N .并将两个矩阵相除。在结果矩阵中,a(i,j)包含矩阵 m 中索引 I 和 j 处的列向量之间角度的余弦值。通过平方此矩阵中的所有元素来创建新矩阵。求矩阵中所有元素的和(除了轨迹)。将所有卷积层的这个值相加,我们将结果值称为正交损失或正交损失。我将其乘以一个称为正交权重的超参数,并将其添加到总损耗中。
我使用不同的正交权重值做了实验:我尝试了 0.1、1、10、100,inf 对应于前面实验中描述的卷积。

orthogonality loss for all different experiments
初始正交性损失(没有乘以权重)约为 40。这远远大于交叉熵本身。然而,网络学会了在几次迭代内将它推到零。
从上图可以看出,网络很快学会了保持卷积矩阵中的所有列向量正交。当正交权重设置为零时,正交性损失不断增加,而对于其他情况(0.1、1、10、100),它稳定在接近零的值。这意味着如果我们增加加权正交性损失,卷积矩阵学习的权重确实是正交的。


cross entropy and accuracy on training data
从上图可以看出,随着正交权重的增加,网络变得难以训练。


cross entropy and accuracy on validation data
但是该网络实现的验证准确度/交叉熵非常接近正交权重为 0 的验证准确度/交叉熵。又一次失望,因为我希望它会给出更好的结果。但至少比以前的结果要好。
接下来,为了更仔细地检查,我决定只绘制正交权重 0 和正交权重 0.1。


cross entropy and accuracy on training data


cross entropy and accuracy on validation data
可以看出,两个网络收敛到相同的验证交叉熵和准确度。正交权重为 0 的网络训练交叉熵较高。这种方式表明,增加正交权重会使网络更好地泛化(更高的训练损失,但相同的验证损失)。
接下来,为了测试这是否适用于其他数据集,我决定用 CIFAR-100 进行同样的实验。



cross entropy, accuracy and ortho_loss on training data


cross entropy and accuracy on validation data
这些结果确实推广到 CIFAR-100。更重要的是,我们可以看到,正交性权重为 0.1 的网络表现出与正交性权重为 0 的网络相同的验证精度。如 ortho_loss 比较图所示,正交权重为 0.1 的网络学习卷积矩阵中的正交列。
实验#3
接下来,被这些结果激起了兴趣,我决定尝试将的相同想法用于递归神经网络。在这个 repo 中使用代码(除非特别说明,否则是默认架构),我决定通过给 LSTM 增加正交性损失来进行实验。注意,正交性损失= sum_square(I-transpose(M)*M)其中 M 是隐藏到隐藏状态矩阵。它不同于正交性损失,在正交性损失中,我们不关心所有列是否有范数 1。
以下是结果(我对正交性损失尝试了这些不同的权重:0.001、0.0001、0.00001、0.000001、0.000001、0):


cross entropy and orthonormality loss as network gets trained for 20 epochs
同样,当我们减小正交权重时,交叉熵减小得更快。接下来,为了更好地比较两个最佳模型的正交权重,我决定绘制权重为 0 和 0.0000001 的交叉熵和正交损失值。


cross entropy and orthonormality loss as network gets trained for 20 epochs for only two weights (0, 0.0000001)
同样没有太大的差别,但它设法匹配基线结果。
结论
我从这个小项目中学到的最重要的事情是神经网络非常复杂。即使看起来不错的想法也可能失败,因为大多数时候,当人们想到一个想法时,他们只是根据网络的最终训练状态来考虑它(就像我的情况一样,我希望矩阵的列是正交的)。但是,如果您考虑到网络必须遍历一条路径以进行优化的事实,大多数好的想法似乎马上就变得索然无味了(就像我的情况一样,很明显,我在实验#1 中严格限制了模型可以采用的路径)。
此外,我尝试了许多非标准(我自己的发明)的调整,使网络击败基线。没有一个管用。实际上,我很高兴我成功地重现了基线结果,尽管我添加了一个比交叉熵本身更大的损失项。
我也对图像分割做了同样的实验。得出了相似的结果。为了简洁起见,这里没有提到它们。
我也相信这项研究有助于更好地可视化卷积层的权重。我计划下一步探索这个问题。
本博客中给出的所有实验都可以使用这些回复进行复制:
正交卷积— Github repo 用于我的正交卷积思想的实验
github.com](https://github.com/singlasahil14/orthogonal-convolution) [## 新加坡 14/char-rnn
通过在 GitHub 上创建一个帐户来为 char-rnn 开发做贡献。
github.com](https://github.com/singlasahil14/char-rnn)
如果您喜欢这篇文章,请点击下面的小拍手图标帮助他人找到它。非常感谢!
Tensorflow 中合成模式生成网络/变分/普通自动编码器的实验

GIF from this website
我真的很想了解更多关于自动编码器(普通的和变化的)和组合模式生成网络的知识,这就是我写这篇文章的原因。所以我决定做一些实验,比如…..
情况 a) 合成模式产生网络 情况 b)使用自动编码器聚类数据
情况 c)使用变分自动编码器聚类数据
情况 d)使用自动编码器去表情图像
请注意,这篇文章是为我自己做的各种实验的存档结果。所以这篇文章没有任何具体的目标。另外,请注意,我不会在这篇文章中讨论这些架构背后的任何理论。
自动编码器简介
Video from Arxiv Insights
对于任何刚刚开始学习这个主题的人,我在上面链接了一个令人惊叹的 youtube 视频。它很好地描述了什么是自动编码器,以及它可以用在什么地方。
此外,如果您想要自动编码器的其他内容,请单击此处。
案例一) 组分产网

黑框 →比例因子输入(我设置为 1.0)
红框→X 坐标输入
蓝框→Y 坐标输入
天蓝框 →各坐标半径差输入
首先,让我们使用神经网络创建一些艺术品。O toro 在这里发表了一篇关于 CPPN 是什么的惊人博文,如果你感兴趣,请去阅读。(即使你不是,我也强烈推荐阅读这本书,它真的是一个令人惊叹的解释。).


Image created by Neural Network
如上所述,当我们将最终输出向量设置为 3 时,我们甚至可以创建彩色图像的颜色序列。(或者甚至是 RGBA,如果你愿意的话。).最后,请注意 CPPN 不一定要有类似于自动编码器的网络架构。
微型部分——通过对数损失函数进行反向传播

Image from this website
如果我们正在处理灰度图像,我们可以很容易地将该问题视为分类任务,因此我们可以使用 log Loss 函数来训练我们的网络。然而,由于我们正在执行手动反向传播,我们需要知道幕后的数学。

Image from this website
现在,我将向你展示这个等式是如何折叠的,就像上面看到的那样,但是如果你对数学的细节感兴趣的话。请点击这里,这里点击或者这里点击。另外,如果你对最大对数似然和交叉熵之间的差异感兴趣,点击这里。
情况 b)使用自动编码器对数据进行聚类

蓝色矩形 →我们网络的编码器部分
红色矩形 →我们网络的解码器部分
让我们首先做最简单的任务,我们将聚类 MNIST 数据集到一个三维潜在空间。看看我们能达到什么样的效果。首先让我们使用最大似然估计作为我们的成本函数。


左图 Gif →为 1000 个数据点创造潜在空间
右图 Gif →随时间重建图像
如上所述,当我们观察 1000 个数据点的潜在空间时,我们可以观察到具有相似属性(如曲线或边缘)的每个数字都聚集在一起。然而,这里需要注意的是,我们可以观察到范围相当大,仅 Y 轴的范围就从 0 到-70,这意味着数据更加分散。(如果我们想要生成新数据,这可能是一个问题。)
接下来让我们使用作为均方误差成本函数。


左 Gif →为 1000 个数据点创建潜在空间
右 Gif →随时间重建图像
即使我们使用均方误差作为我们的损失函数,网络在聚类数据点方面做得还不错,但是,再次注意每个轴的范围相当大。
情况 c)使用变分自动编码器聚类数据

蓝色矩形 →我们网络的编码器部分
红色矩形 →我们网络的解码器部分
现在,让我们使用变型自动编码器对我们的数据进行聚类,关于什么是变型自动编码器的详细解释,请点击此处、此处或此处。首先,让我们再次使用最大似然估计作为我们的损失函数。


左侧 Gif →为 1000 个数据点创建潜在空间
右侧 Gif →随时间重建图像
如上所述,网络在聚集每个数据点方面做得很好。然而,一个不同于普通自动编码器的是轴的范围。这是变型自动编码器与普通自动编码器相比的一个特性。再次理论解释请阅读链接。接下来,让我们看看如果使用均方误差函数会发生什么。


蓝色矩形 →我们网络的编码器部分
红色矩形 →我们网络的解码器部分
即使使用 MSE,我们也可以观察到集群看起来很棒,轴的范围不像普通的自动编码器那样大。最后,我想看看我们是否使用了 Kullback-Leibler 散度损失函数。


左侧 Gif →为 1000 个数据点创建潜在空间
右侧 Gif →随时间重建图像
因为我们不再有任何重建损失,所以网络没有任何动机来创建看起来像原始图像的图像。然而,观察一些点如何映射到更高的 z 轴是非常有趣的。
案例 d)使用自动编码器对图像进行去表情处理



左侧图像 →添加表情符号的图像
中间图像 →无表情符号的图像
右侧图像 →自动编码器去除表情符号的图像
这是一项非常简单的任务,因为去噪自动编码器是这类网络的标准用例。

图像顺序 →表情图像、原始图像、去表情图像
当我们看到自动编码器的进展时,我们可以观察到,随着网络的训练,它在消除图像中出现的表情符号方面做得更好。然而,我们可以清楚地看到一个问题,网络不知道如何填充表情符号占据的空间。现在我们可以让它保持原样,但将来我会计划解决这个问题。
交互代码

对于谷歌实验室,你需要一个谷歌帐户来查看代码,你也不能在谷歌实验室运行只读脚本,所以在你的操场上做一个副本。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!同样为了透明,我在 github 上上传了所有的训练日志。
要访问案例 a 的代码,请点击此处。
要访问案例 b 的代码,请点击此处,要查看日志,请点击此处。
要访问案例 c 的代码,请点击此处,日志的请点击此处。
要访问案例 d 的代码,请点击此处。
最后的话
很抱歉没有解释每个网络背后的理论,但这篇文章的目的实际上是为了实现我的一些实验。
如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你希望看到我所有写作的列表,请在这里查看我的网站。
同时,在我的 twitter 上关注我这里,访问我的网站,或者我的 Youtube 频道了解更多内容。我还实现了广残网,请点击这里查看博文 t。
参考
- 导数表。(2018).Math2.org。检索于 2018 年 6 月 23 日,来自http://math2.org/math/derivatives/tableof.htm
- tf.atan | TensorFlow。(2018).张量流。检索于 2018 年 6 月 23 日,来自https://www.tensorflow.org/api_docs/python/tf/atan
- 导数:普通神经网络激活函数的导数。(2014).聪明的机器。检索于 2018 年 6 月 23 日,来自https://theclevermachine . WordPress . com/2014/09/08/derivation-derivatives-for-common-neural-network-activation-functions/
- 导数表。(2018).Math.com。检索于 2018 年 6 月 23 日,来自http://www.math.com/tables/derivatives/tableof.htm
- 可变自动编码器。(2018).YouTube。检索于 2018 年 6 月 23 日,来自https://www.youtube.com/watch?v=9zKuYvjFFS8
- matplotlib,R. (2018 年)。在 matplotlib 中删除保存的图像周围的空白。堆栈溢出。检索于 2018 年 6 月 23 日,来自https://stack overflow . com/questions/11837979/remove-white-space-around-a-saved-image-in-matplotlib
- [复本],H. (2018)。如何在 Matplotlib (python)中隐藏轴和网格线?堆栈溢出。检索于 2018 年 6 月 23 日,来自https://stack overflow . com/questions/45148704/how-to-hide-axes-and-gridlines-in-matplotlib-python
- 合成模式生成网络。(2018).En.wikipedia.org。检索于 2018 年 6 月 23 日,来自https://en . Wikipedia . org/wiki/composition _ pattern-producing _ network
- 大トロ. (2018). Blog.otoro.net. Retrieved 23 June 2018, from http://blog.otoro.net/
- RGBA 颜色空间。(2018).En.wikipedia.org。检索于 2018 年 6 月 23 日,来自 https://en.wikipedia.org/wiki/RGBA_color_space
- 最大似然估计。(2018).En.wikipedia.org。检索于 2018 年 6 月 23 日,来自 https://en.wikipedia.org/wiki/Maximum_likelihood_estimation
- 均方差。(2018).En.wikipedia.org。检索于 2018 年 6 月 23 日,来自https://en.wikipedia.org/wiki/Mean_squared_error
- Mallya,A. (2018)。反向投影。arun mallya . github . io . 2018 年 6 月 23 日检索,来自http://arunmallya.github.io/writeups/nn/backprop.html
- (2018).Ttic.uchicago.edu。检索于 2018 年 6 月 23 日,来自http://ttic . uchicago . edu/~ shubhendu/Pages/Files/lecture 3 _ flat . pdf
- (2018).Ics.uci.edu。检索于 2018 年 6 月 23 日,来自https://www.ics.uci.edu/~pjsadows/notes.pdf
- (2018).[在线]可从以下网址获取:https://www . quora . com/What-is-the-differences-between-maximum-likelihood-and-cross-entropy-as-a-loss-function【2018 年 6 月 23 日获取】。
- 带图例的散点图— Matplotlib 2.2.2 文档。(2018).Matplotlib.org。检索于 2018 年 6 月 23 日,来自https://matplotlib . org/gallery/lines _ bars _ and _ markers/scatter _ with _ legend . html
- 颜色示例代码:colormaps _ reference . py—Matplotlib 2 . 0 . 2 文档。(2018).Matplotlib.org。检索于 2018 年 6 月 23 日,来自https://matplotlib . org/examples/color/colormaps _ reference . html
- 对抗性自动编码器的向导指南:第 1 部分,自动编码器?。(2017).走向数据科学。检索于 2018 年 6 月 23 日,来自https://towards data science . com/a-wizards-guide-to-adversarial-auto encoders-part-1-auto encoder-d9a5f 8795 af 4
- 教程-什么是可变自动编码器?—贾恩·阿尔托萨尔。(2018).贾恩·阿尔托萨尔。检索于 2018 年 6 月 23 日,来自https://jaan . io/what-is-variable-auto encoder-vae-tutorial/
CM1K 神经网络芯片的实验
2017 年 3 月,我获得了来自麻省理工学院沙盒项目的资金,利用 T2 的 CM1K 神经网络芯片 T3 开发了一款产品。CM1K 是一个集成电路,它在硬件中实现了 RBF 和 KNN 分类器,这应该比在软件中实现这些算法提供了更好的性能。我提议用这个芯片作为分线板的基础,可以与流行的业余爱好者电子平台(如 Raspberry Pi 或 Arduino )接口。所有代码和原理图都可以在这个项目的 Github 页面上找到。
先前的工作
在随机搜索谷歌以了解是否存在类似 CM1K 的芯片后,我受到启发开始了这个项目——我想知道是否有人开发出了在硬件中实现机器学习算法的 ASIC。我很快发现了 CM1K,但是项目例子很少。
我确实发现了 Braincard ,一个失败的 Indiegogo 整合 CM1K 的分线板活动。这与我打算开发的东西非常相似,声称可以将 CM1K 与 Pi、Arduino 和 Intel Edison 进行接口。尽管失败了,我并没有对我的想法失去信心——brain card 似乎缺乏成功所需的文档和业余爱好者社区中的可见性,这并不一定说 CM1K 本身有什么不好。

Sad reacts only 😦
一个有趣的注意事项是,Braincard 活动实际上隶属于 cogn mem。经过一番挖掘,我发现多家公司似乎都有关联:认知记忆、通用视觉和神经记忆等等。它们似乎都是由这种芯片技术的发明者 Guy Paillet 联系在一起的。如果你想去兔子洞,看看他的 LinkedIn 简介…无论如何,我最好的猜测是,Braincard 是 General Vision 试图增加业余爱好者市场对 CM1K 的需求。
我发现第三方使用 CM1K 的例子更少。我找到的几个参考资料是这个简单的分线板和这个研究论文。不幸的是,这两个来源都缺乏任何清晰的文档来证明 CM1K 的实际应用。
很难找到 CM1K 接受测试的例子。随着 Cognimem 宣称“无限可能”,我有动力建立一个分线板,并为自己评估 CM1K。
开发分线板
我最初计划在春天完成几个版本的分线板。第一个是一个相当简单的分组讨论板,由以下部分组成:
- CM1K 本身
- 为芯片供电的 3.3v 和 1.2v 稳压器
- 提供时钟信号的 27 MHz 振荡器
- 在需要的地方拉起电阻和滤波帽
- 电源指示灯
- 标题将 IC 上的每一行分开
然后,该板可以连接到我想要的任何平台上,一旦我开发了软件,并能够评估使用芯片的最佳方式,我就可以设计第二块板,它具有所需的额外功能,可以与我选择的平台很好地接口。
由于时间限制,我从未接近完成第二个设计。无论如何,在我运行的实验中,事实证明几乎不需要它:将第一个 rev 板与 I2C 上的 Raspberry Pi 连接起来非常简单。

Schematic!
我开始在高原设计分线板。绘制原理图相当简单,但布局花了我一段时间。我决定试着把所有东西都放进 2 平方英寸的空间里,这给了我太多的发挥空间。我在电路板边缘排列了接头,并将 IC 放在中央。我最初认为我可以把这块板分成两层,但是经过两次尝试后,我不能完全把它布置好。我最大的难点是试图将 1.2v 和 3.3v 线干净利落地分配给 IC 上所有分散的电源引脚。经过三次重新设计尝试,我选定了四层设计,第三层分为 1.2v 和 3.3v 电源层。1.2v 层直接位于 IC 下方,因此需要 1.2v 输入的所有引脚都向后走线,有一个过孔直接通向 1.2v 层。然后,3.3v 电源引脚可以向前走线,过孔向下到平面。由于所有外设都使用 3.3v 电压,因此很容易为电路板的其余部分提供 3.3v 电压。

Routing complete!
电路板设计完成后,我需要将它发送给 fab。我上一次这样做是在几年前,当时我在奥什公园为我的高中机器人团队做了一些东西。在这一点上,我需要的板比批处理服务提供的要快得多,所以我最终选择了 4pcb.com 的 T4,用 T6 的 66 each T7 交易以 66 美元的价格得到了我的两块板。作为一名学生,我可以免除最低订购量,这非常棒。

My breakout board straight from the fab in all its glory.
一旦我的主板和所有组件到达,这是组装的时间。我把它带到 MITERS 并开始用热风枪焊接所有东西。每一个组件都非常容易地关闭……除了集成电路,它需要一点工作来做好。我开始与此,并嗡嗡作响的所有突破引脚,以确保它被钉下来的权利。经过多次反复的嗡嗡声和毛细作用,并试图小心翼翼地应用更多的焊料,它似乎没问题。

All populated!
焊接完成后,我把电路板拿到电源前,插上电源。关键时刻平静地过去了:电源灯亮了,主板没有开始冒烟或发热。接下来,我决定第一次尝试使用示波器来检查振荡器的输出。起初,输出似乎真的很糟糕,但在无法找到我的板中的故障后,我意识到我对如何设置示波器没有任何线索。经过一些谷歌搜索和一些校准,我得到了一个输出,至少符合我要去的频率(即使它不是完全干净)。哦,好吧,不管怎样,事情似乎解决得很好。

The moment of truth!
随着这些初始测试的完成,是时候连接分线板并开始编码了!
开发软件
我首先将分线板连接到我身边的一个 3.3v Arduino Micro,选择它是因为它是我唯一一个具有 3.3v 逻辑电平的 Arduino。布线很简单:我只要接上两条 I2C 线,必要时在 GND 上绑几个配置引脚,就能让 I2C 正常工作。然后,我编写了一个函数,成功地从 CM1K 的 NCOUNT 寄存器中读取数据。在将其推广到可以读取/写入任何任意寄存器的功能后,我能够验证 CM1K 的硬件似乎按照数据手册中的规定工作。
硬件通过验证后,我和我的一个朋友聊了聊,他建议我试着根据 MNIST 数据集对芯片进行基准测试。我认为这是一个有价值的目标,并着手使用 CM1K 在 MNIST 上实现 KNN 分类。
我决定我不想担心将 MNIST 训练数据集安装到我的 Arduino 上,所以我拿起了一个 Raspberry Pi Zero W 以及一些外围设备,以使布线更容易。我像对 Arduino 一样连接好它,然后开始工作!

The Raspi Setup in all its glory.
我决定用 Python 编写我的所有代码,使用 smbus 模块通过 I2C 与 CM1K 对话。我首先根据 CM1K 硬件手册中的一些伪代码编写了一个简单的测试脚本。该脚本使用一个测试寄存器 TESTCAT,该寄存器写入与每个单个神经元的类别相同的值。然后,它遍历每个神经元,并检查以确保其存储的类别与写入 TESTCAT 的值相匹配。这个脚本起作用了,所以我决定是时候干脏活了。
第一步是对 MNIST 图像进行降采样。每个图像都是一个很小的 28x28 像素的图像,但是 CM1K 将每个神经元中的数据存储为一个长度为 256 的向量,存储字节值。因此,使用单个字节来表示每个像素的颜色值,我必须将每个图像压缩到 16x16 像素,这样我就可以将一个图像放入每个向量中。这很简单:我使用 python-mnist 作为一种简单的方式来获取训练数据,然后使用 Pillow 和 Numpy 来对图像进行重新采样。除了向下采样到 16x16,我的代码还将每个图像展平为一个长度为 256 的向量,该向量可以馈送到 CM1K。
由于单个 CM1K 只能容纳 1,024 个向量,所以我编写代码从训练集中随机选择 1,024 个图像来实际使用。鉴于完整的训练集总共使用了 60,000 张图像,我担心这会给芯片的性能带来巨大的限制。
训练过程只是将这些图像中的每一个都写入 CM1K。我使用了芯片的保存和恢复模式,这种模式可以让你将一个向量直接写入每个神经元的内存,而无需调整它们的激活功能(当芯片运行在 RBF 模式下时,这是相关的,但不是 KNN),从而加快了这个过程。
然后,测试过程对 CM1K 运行可配置数量的测试图像。我开始简单地选择最近的邻居(k=1),但这样得到了可怕的结果(不幸的是,我做的是糟糕的科学,没有记录这些结果)。然而……在最近的邻居之间快速实现多数投票(所以我可以任意 k≥1)后,我的运气变了!事不宜迟——
结果
—结果证明,我最终还是能获得相当好的结果!总的来说,我最好的成绩(图中没有)是在 k=5 的情况下,对 100 个样本进行 89%的准确率测试。

Results! Sexy progress bar courtesy of tqdm.
这种精确度让我非常高兴。根据 Yann Le-Cun 的网站,这不是最先进的,但却是可靠的 B+(如果你四舍五入的话,是 A-)。然而,让我有些沮丧的是脚本有多慢,特别是考虑到使用这种神经网络硬件的一个大承诺是它会相对较快。然而,它以不到 5 个样本/秒的速度进行训练和测试,我觉得这有点令人失望。
我可以通过将 Pi 上的 I2C 时钟速度更改为 400 kbps(CM1K 的理论极限)来稍微解决这个问题。这给了我稍微好一点的结果,整体提升速度达到每秒 7 个样本。
结论
在 CM1K 上运行 KNN,我能够成功地对 MNIST 数据集中随机选择的 100 幅图像进行分类,准确率为 89%,测试和训练速度约为每秒 7 个样本。这看起来并不太糟糕,但一个重要的问题是,这是否真的比在软件中运行 KNN 算法更好。
我最接近回答这个问题的方式是在 GitHub 上找到的一个 CM1K 模拟器上运行我自己代码的修改版本。考虑到仿真 CM1K 显然不是在 Raspberry Pi 上实现 KNN 算法的最快方式,这个测试并没有真正演示那么多。但是,我很好奇比较性能。

如您所见,与在实际芯片上运行我的代码相比,准确性和速度都受到了影响。从某些方面来看,这有点奇怪,尽管看起来很振奋人心。然而,我对此持保留态度,因为我真的不能指望模拟器代码。
我的直觉是,举例来说,如果用写得很好的 C 代码实现,软件 KNN 会比 CM1K 有更好的性能。也就是说,我也可以用 CM1K 优化很多方法。我相信这是真的,特别是考虑到 CM1K 理论上应该能够在大约 10 微秒内加载一个完整的矢量,这是根据数据手册中给出的时钟速度和周期数计算的。以这个理论上的最大值运行,它应该能够每秒训练 1000 个样本,这意味着在我目前的方法中有很多开销。
优化思路包括:
- 用 C 重写代码,以消除 Python 解释中的开销
- 在 CM1K 上使用并行数据总线,而不是 I2C,考虑到 Raspberry Pi GPIO 的限制,这可能涉及一些硬件重新设计(可能使用移位寄存器)
即使 CM1K 在软件中运行 KNN 的速度比 Pi 运行 KNN 的速度快,接下来出现的问题是,无论如何,是否有必要离线运行机器学习算法。在大多数应用程序中,将这类计算交给服务器似乎更可行。随着越来越多的嵌入式设备连接到互联网(这已经是一种趋势了,它现在有自己的流行语了!),嵌入式离线模式识别好像会变得越来越没用。然而,这仍然是一件有趣的事情。
我打算暂时搁置这个项目,去做其他事情。然而,对于如何继续前进,我确实有很多想法:
- 将另一个分线板和两个 CM1K 菊花链连接在一起:这将允许我在不牺牲速度的情况下获得更好的性能
- 执行上面描述的优化来提高我当前设置的速度
- 尝试 CM1K 的 RBF 模式(相对于 KNN 模式)
- 为 Pi 编写/找到一个合适的 KNN 实现,以便在 CM1K 上与 KNN 并行比较
- 使用 Arduino 作为主设备,使用 SD 卡模块存储训练数据
- 使用 CM1K 开发一些示例应用程序。在这一点上,我的首要想法是开发一个基于语音命令或脑电波导航的移动机器人
最后一点需要注意的是,General Vision/Cognimem 的技术现已内置于 Arduino 101 芯片的处理器中。这可能有助于将他们的技术引入主流爱好者市场,尽管我从未发现许多人使用芯片这一功能的例子。
伙计们,现在就到这里吧!对 CM1K 进行实验,并尝试开发一款几乎不为广大业余爱好者所知的芯片,是一件非常有趣的事情。希望这篇博文能给这个神秘的小家伙一点启发!如果您有任何意见或问题,请随时通过电子邮件与我联系。
专家观点:“用户与虚拟现实互动的方式允许极其普遍的信息收集
我们采访了 DreamSail Games 的商业分析师兼虚拟现实游戏开发者辛迪·马洛里
《创新企业》的高级编辑詹姆斯·奥文登采访了纽约商业分析师辛迪·马洛里,期待她在下个月举行的 2017 年游戏分析峰会上的 VR 演讲。
辛迪·马洛里(Cindy Mallory)是一名商业分析师,也是梦之帆游戏公司(DreamSail Games)的虚拟现实游戏开发者,该公司制作了包括《刀锋芭蕾》(Blade Ballet)在内的获奖游戏。她在 DreamSail 的重点是分析管理,她通过定义、分析和记录使用新兴技术进行游戏创作的要求来协助虚拟现实开发。她还创建并维护了一个公司数据库,用于记录 KPI 和归档相关审计。
在她于今年 4 月 26 日至 27 日在旧金山举行的游戏分析峰会上发表演讲之前,我们采访了她。
你是如何开始你的职业生涯的?
我学习生物化学,重点是数学和物理。实验室研究的方法使我为数据分析做好了准备;当我计算酶反应速率、进行动力学分析、读取紫外线波长和修改实验以便更好地运行时,我已经在做这些了。这是我第一次接触趋势分析和预测建模。我的项目是分离和纯化用于生物燃料应用的重组克隆酶。在我在一个交友网站上发表个人简介之前,我一直在做实验,目的是纯化大肠杆菌中生长的蛋白质…
一个纽约的游戏设计师把我研究项目的 3D 模型扔进了游戏引擎。我被迷住了。我开始涉猎一些编码语言、商业策略和数据驱动营销。我接受了中城虚拟现实创意工作室 DreamSail Games 的一个职位,担任他们的商业分析师。每当我能把我的方法从生物化学转移到商业领域时,我就拼命工作。
为什么在视频游戏开发中跟踪 KPI 很重要,你认为哪些是最重要的?
基于规模、资金、方法和行业标准,每个工作室都有不同的分析文档需求。我认为重要的是首先分解你工作室的需求,并创建一个利益相关者一致目标的列表。您可以用度量标准将目标分解成不同的维度,然后找出哪些测量数据的工具最适合您。
我为 DreamSail Games 创建了一个 KPI 数据库,将指标分为营销、财务和游戏内指标。在发展过程中,KPI 可以作为衡量兴趣的温度计。Alexa、Google Analytics、脸书洞察、SteamWorks Financial、GameAnalytics 和 StreamHatchet 都提供了可用于监控社交提及和营销活动功效的数据。
您在跟踪 KPI 时面临哪些挑战,您对那些希望克服这些挑战的人有什么建议?
我创建了一个系统来记录和归档我的 KPI 的每周快照,使我能够以一致和全面的方式与网站管理员和分析套件进行交互。记录信息并不困难。最大的障碍在于有效的报告生成和数据可视化。
我是一个熟悉有条不紊地倾倒数据集的女孩。列出和计算价值很容易,真正的挑战在于评估。整理信息宝藏、挑选趋势以战略性地支持营销提案的能力……这是我不断磨练的技能。能够将电子表格格式的信息转换成清晰、直观的报告,让您的团队做出明智的决策,这一点非常重要。
与游戏的其他领域相比,你认为虚拟现实领域特有的分析挑战是什么?
为 VR 游戏收集数据的新技术的出现已经令人兴奋。cognitiveVR 和 Ghostline 等平台是分析解决方案,可以绘制用户交互、可视化会话、收集硬件数据,并鼓励 A/B 测试和反馈驱动的设计。有如此多的 SDK 正在开发,以协助游戏分析,挑战不在于创新;这是个伦理问题。许多新技术依赖于实时处理玩家的生理和行为信息。
用户与虚拟现实交互的方式允许极其普遍的信息收集。生物触觉和位置跟踪将随着虚拟现实硬件的每一次迭代而显著改善。随着技术的进步,沉浸感也会提高,但访问个人数据不应该成为代价。我加入 VR/AR 协会娱乐行业委员会的一个原因是帮助建立 VR 空间关于数据收集、同意、存储和个人信息传输的标准。
你认为虚拟现实领域最激动人心的发展是什么?你认为这个行业将走向何方?
我试图通过跟踪初创企业收购和风险资本融资来描绘出该行业的进展。值得关注的一家新浪潮外围虚拟现实公司 Ultrahaptics 正在通过超声波传感器阵列提供触觉虚拟按钮技术的开发套件。除了体积捕捉,内外跟踪也是 VR 和 AR 的热门技术。我正在密切关注 8i(高保真立体视频)和 Fove(低延迟眼睛跟踪和有凹渲染)。我也为 OEM 生态系统的爆发感到兴奋。随着价格在 300-500 美元之间的个人电脑驱动的头盔显示器向消费者提供,高端虚拟现实将变得更加容易获得。戴尔(Dell)和联想(Lenovo)等制造商正忙着为一系列 Windows 10 VR 就绪型电脑推出 HMD 套件。
就个人而言,我对混合现实感到非常兴奋。通过照片或视频等传统 2d 媒体分享空间体验是一项挑战。对玩家视角的不稳定、扁平的记录不能传达虚拟现实的存在。混合现实是向观众介绍虚拟现实的一种奇妙方式…它看起来真的很酷。告诉我你从来没有盯着一个电子游戏,并希望自己在环境中。传统的绿屏设置需要将物理相机与虚拟世界中的相机对准,以合成捕捉混合现实游戏。这种方法既费时又繁琐。我对原型丽芙魔方太着迷了。这是一个便携式绿色屏幕房间,将彻底改变内容创作者处理 VR 流媒体的方式。我很高兴地宣布,DreamSail Games 与 LIV 合作,将首批 50 个 LIV 立方体中的一个带到纽约市(以及游戏分析峰会!).
你认为性别仍然是游戏中的一个问题吗?你认为公司在改善这个问题上做得足够多了吗?你认为还可以做些什么?
我们都记得 Gamergate。女性和非独联体个人融入游戏文化的斗争仍在激烈进行。白皮书展示了在访问虚拟现实方面的差距,并强调了从事虚拟现实开发的女性在工资和雇佣方面的差距。作为一个习惯于在我的领域中成为少数派的女性,收集受众细分报告表明“聪明”的做法是设计一款旨在安抚男性千禧一代的游戏是毁灭性的。话虽如此,VR 是一个平等的时机已经成熟的空间。围绕支持虚拟现实领域女性的运动,形成了令人惊叹的开发者和布道者社区。
一个必须解决的问题是虚拟空间中的骚扰。传统的游戏平台一直局限于语音、信息和 2D 屏幕上的虚拟角色动作。随着社交 VR 的出现,空间骚扰的案例早已如雨后春笋。开发者需要主动解决对虚拟现实礼仪的担忧,并努力杜绝有害行为。我觉得公司已经意识到了不平等的问题,只要社区积极主动地要求安全的游戏空间,开发者就会非常乐意去遵守。
游戏工作室能够分享数据和分析见解来开发更好的虚拟现实吗?或者竞争太大了?
当然,这已经发生了。在 GDC、Twitchcon 和 PAX 这样的大会上展出时,我很幸运地遇到了一些了不起的游戏开发者,他们很友好地回复了我荒谬的电子邮件。我发出请求(带笑脸),询问关于他们游戏的活跃会话统计数据、营销活动的功效以及开发系统查询的私密开发问题,从生产持续时间到团队规模,再到敏捷软件偏好。我为我的团队培养的行业指导和支持系统展示了在虚拟现实领域为了更大的利益而分享的意愿。我们正处于一个未知的领域,拥有颠覆性的技术。在线社区提供支持,同时开发人员创建教程、举办讲座和发布开发博客。
巧合的是,我的演讲将是关于我在虚拟现实领域的智力合作。合作竞争,也称为合作竞争,是博弈论中记载的一个主要内容。竞争与合作并存的机制发生在利益一致的行业。相互竞争的公司的集体贡献创造了一种鼓励的现象,促进了研究和知识共享。这反过来又加速了内容创建、VR 开发可访问性和消费者采用率。随着 DreamSail 越过 R&D 和前期制作进入垂直切片开发,我有了一些为争夺相同的小群体的 VR 工作室工作的导师和朋友。在生产的早期阶段,先锋开发人员提供的见解和合作伙伴关系,他们支持我们取得成功,使一切都变得不同。
在游戏分析峰会上,您可以听到辛迪以及该领域其他行业领先的演讲人的更多内容。点击 查看完整议程 。
原刊此处。
可解释性:最后一英里

为了让你的用户理解你的模型,仅仅“可解释”是不够的——你需要提供最终的解释
可解释或可解释的模型已经从近乎空想变成了日益普遍的业务需求。然而,尽管有越来越多的方法可用于解释模型,但这些仍然是技术工具,针对的是需要理解他们创建的模型的统计和数据科学实践者。对于创建最终用户可以理解的模型来说,它们是必要的,但还不够。
创建一个最终用户可以理解的模型,一方面意味着确保他们基本理解模型中的输入和输出变量是什么,另一方面意味着他们理解这些变量在模型中如何操作。
在每一种情况下,最终的演示对于确保实现无缝用户体验的最终目标至关重要。虽然相对明显的是,输入变量本身是复杂模型的输出,或者变量具有不透明的名称,如“Var1 ”,会增加用户的困惑,而不是帮助他们理解,但有时不清楚需要多少解释。
部分问题在于,从建模者的角度来看,重要的是变量中包含了什么——模型的比率输入的名称很可能指的是构成比率的变量。显然,这对变量的用户来说意义不大。想想会计比率的名称——“速动比率”、“酸性测试”,或者物理和工程中的无量纲常数,如雷诺数(在简单的水平上,它表示流体中的湍流程度)。
雷诺数虽然没有一个完美的交流名称(从这个角度来看,“湍流数”可能是一个改进),但它确实说明了以不同的方式将模型输入的计算与其在模型中的意义分离的概念——在不同的背景下,不同的工程模型中使用多个雷诺数,但基本上以相同的方式使用雷诺数——来量化流体的湍流。对于管道和通道中的流动,对于穿过流体下落的颗粒,对于搅拌槽中的叶轮以及对于填充床中流动的流体,都有一个雷诺数——所有这些都有不同的计算,都至少在基本层面上表达了相同的概念。
在数据科学模型中,这有两种方式。一个是,如果你想在尽可能多的地方重用你的模型,为了可移植性,用一种独立于它们的成分的方式来标记你的变量是很方便的。例如,在信贷风险模型中,由于当地税收或其他监管原因,收入或资产可能有不同的计算方法。
第二点更为重要——如果其他人要使用模型,您的界面将需要标记,而在模型中引用变量含义的标记比解释其成分的标记更能向用户解释输入。在雷诺数的情况下,解释“表示湍流趋势的常数,其中较高的数更倾向于湍流”更有用,并且比“直径、速度和流体密度与流体粘度之比”更能解释其在模型中的用途。
当然,这个变量定义必须易于用户访问。如果它足够短,悬停或工具提示是一个很好的方法。否则,一个易于访问的定义屏幕将确保您的用户理解您的模型的输入。
很明显,解释变量是什么是不够的——你需要确保你的用户理解他们如何一起工作以确保最终的结果。最大的障碍可以说是机器学习算法通过考虑非线性关系和相互作用来实现准确性,而这些特别难以可视化。
现有的模型解释器(如 LIME)通过假设在靠近模型表面上任意点的区域中,相互作用效应和非线性效应可以忽略不计来简化这些方面。如果你的模型需要理解的重要方面是你的模型如何对单个案例进行评级,那么这就是正确的方法。
如果对你的用户来说,理解整个模型的趋势更重要,创建可视化,可能基于附加模型,梳理出非线性的方面,可能是更用户友好的方法。
罗伯特·德格拉夫是《进行中的书’【懒惰的数据科学家】 的作者,可通过 LeanPub 获得。他最近为 Medium 撰写的文章是 保持用户的信任。
可解释人工智能:数据科学家的新挑战

在我们开始之前,让我提一下,在这篇文章中,我将使用可解释性和可解释性这两个词来描述同一个概念。
也就是说,让我们想象一下这样一种情况,有人要求银行贷款,而由信贷风险评估中专门的机器学习算法驱动的计算机拒绝了这一要求。雇员无法解释这样一个明确的答案的原因,肯定会被留在一个非常尴尬的位置。
在机器学习的进步正在到达医学、刑事司法系统和金融市场等关键领域的背景下,这种情况肯定会更加频繁。事实上,人们越来越担心人工智能代理的可接受性和信任问题,因为它们缺乏可解释性。多年来,性能优先于可解释性,导致了包括计算机视觉、自然语言处理和序列建模在内的几个领域的巨大进步。然而,由不愿接受基于人工智能的决策所驱动的关键问题可能会导致一种全新的动态,其中可解释性可能是评估模型的关键措施之一。在本文中,我将讨论一些具体的原因,为什么它会是一个主要的区别。还将提出一些方法来开发强大的算法,同时保持良好的可解释性。
"有一个精确的模型是好的,但是解释导致更好的产品. "
数据科学的进步一直是由寻找解决任何问题的最佳性能模型推动的。从数学的角度来看,模型的搜索集中于成本函数的最小化或似然函数的最大化。因此,模型的性能几乎完全是根据我们根据一些正确选择的度量标准得到的结果来衡量的。这种趋势导致了越来越复杂的算法,以牺牲可解释性为代价。事实上,一些数据科学家甚至可能断言 “让机器学习算法难以理解的东西也是让它们成为优秀预测者的东西” 。它们很复杂,这就是为什么对大多数领域从业者来说,它们看起来像【黑盒】 。

Interpretability vs performance seen through machine learning techniques (non exhaustive)
上图描绘了机器学习算法的两个可解释性级别:
- 高解释性:这一层包括传统的回归算法(例如线性模型)、决策树以及分类规则。基本上它们近似单调线性函数。
- 可解释性低:这个级别包括高级机器学习技术,如支持向量机、高级集成方法和深度学习。他们复杂的谎言
在这两者之间,你可以找到一些方法,根据学习过程中应用的约束,这些方法可以被归入任何一类(单调性约束可以应用于集成方法,并且一些实现已经可用)。
可解释性是对人类观察者理解模型所做预测背后的原因的程度的衡量,在准确性之间找到正确的平衡变得越来越有必要。这可能是让算法对日常用户尽可能透明的关键。这种对 【以用户为中心】 的关注点的改变,可能会对该技术在各种领域的应用和接受产生影响,使他们能够更舒适地适应以更现实的方式执行任务。
尽管应用机器学习的许多核心方面在不同领域都是相同的,但它们不能应用于每个行业。机器学习方法非常不同,特别是在银行、保险公司、医疗保健提供商和其他受监管的行业。原因主要是他们倾向于法律甚至伦理要求,这些要求倾向于越来越多地限制黑盒模型的使用。作为一个例子,我可以列举公平信用报告法案第 609(f)(1)条
应向消费者提供在所用模型中对消费者信用评分产生不利影响的所有关键因素,其总数不得超过 4 个
最重要的是,这显然意味着人们应该提供关于如何获得模型响应的见解。直接后果是将可能方法的范围缩小到最简单的方法,因为它们易于解释,除非我们找到方法将上下文添加到最先进算法的预测中。
更不用说,这种趋势更多的是加强监管约束,而不是减缓监管约束。

An ever growing list of legal and ethical considerations surrounding businesses
所有这些因素都在很大程度上导致了行业普遍不愿意采用和部署由机器学习系统驱动的高级数据产品。面对这样的限制,研究越来越多地集中于确定处理模型可解释性的方法。
据我所知,实现模型可解释性的途径主要有两种:和 局部可解释 。前者旨在使整个决策过程完全透明和全面,而后者侧重于为每个决策提供解释。
“当我们开始一个数据科学项目时,现在的最佳做法可能是首先确定我们希望达到的可解释性程度。”
事实上,首先决定可解释性的程度将指导我们选择可能实现的算法和技术。具体来说,这意味着是选择一个简单的模型并使其更加强大(以实现全局可解释性),还是使用一个我们可以使其更加可解释的复杂模型(以至少实现局部可解释性)。下表呈现了一个**-的详尽列表 的技巧处理模型的可解释性。**

也许你已经注意到局部可解释性比全局可解释性有更多的细节。这主要是由于在解释复杂模型方面所做的巨大努力,但是采用了局部边界方法。
最后,当我们用正确的方法实现我们的算法时,最后的问题在于如何评估模型的可解释性。有两种方法可以更好地表示最终模型所赋予的理解程度:
- ****模拟具有已知特征和内在含义的数据,以对抗模型对我们在该上下文中已有先验知识的解释。
- ****测试数据扰动下的稳定性在显式变量中加入少量噪声。可信的解释可能不会因为微小的变化而发生剧烈的变化。
希望您在这个非常重要的“最近”关注点的旅途中过得愉快。如果您有任何问题或意见,我将很高兴欢迎进一步讨论。在我的下一篇文章中,我将通过一个真实世界的用例来直接解决这个问题,以便更好地理解上面的所有含义。
如果需要进一步的阅读资料,请不要犹豫参考下面的链接。
我还要感谢对本文做出贡献的同事们何塞·桑切斯、纳尔逊·费尔南德斯、西蒙·帕尔马。
https://arxiv.org/pdf/1606.03490.pdf
**【https://distill.pub/2018/building-blocks/ **
Navdeep Gill 和 Patrick Hall 的《机器学习可解释性简介》
可解释的人工智能与解释人工智能——第一部分
深度学习够深吗?

Framework of Explainable Deep Learning, source Society of Mind (Marvin Minskey)
尽管最近深度学习(DL)取得了显著的成果,但由于欠拟合、过拟合或不完整的训练数据等几个原因,它总是存在产生妄想和不切实际的结果的风险。例如,职业围棋选手 Lee Sedol 的著名棋步 78 导致了 Alpha Go 的妄想行为、对抗性攻击以及 DeepXplore 在 Nvidia DAVE-2 自动驾驶汽车平台中发现的错误行为,其中系统决定对同一输入图像做出两种不同的决定,唯一的区别是亮度级别。这些例子推动人工智能研究人员更加专注于打开深度学习的黑匣子,避免只依赖模型的准确性。
前一段时间,我在为非人工智能职业准备一个关于人工智能状态的研讨会。由于人工智能目前是一个流行词,并且流行词通常有很多定义,我不得不选择一个。人工的定义很清楚,但是智能呢?我搜索并找到了马文·明斯基对人工智能最合理和相关的定义:
我们的模型包含过程,使我们能够解决我们认为困难的问题。
“黑盒”是那些我们还不了解的过程的名称。
实际上,这是这个定义的修改版本,我用“黑盒”代替了“智能”,用“模型”代替了“头脑”虽然我已经改变了它,但定义仍然成立。
这些论点告诉我们这些事情:a)黑盒和智能是一样的,b)复杂的问题需要复杂的解决方案,c)简单、可理解的过程很可能不适合复杂的问题,如自动驾驶汽车和机器翻译,以及 d)盒子越暗,它就越智能。
因此,当我们要求深度学习科学家打开黑盒时,这可能意味着限制模型能力。
但是真的吗?
人类大脑中的大多数过程都是模糊的,我们不理解它们,这是正确的,但我们仍然可以解释我们的决定和想法。我们的解释通常由陈述和理由组成。我们的讲解不涉及统计推断分析(除非和题目有关)。
所以问题是:我们如何解释或决定?
人类的大脑由两个不同的系统组成,大脑用这两个系统来形成思想。这两个系统是:
系统 1: 是一种快速、直观、无意识和情绪化的、刻板的、自动的,并利用与过去经验的相似性来做出决定
系统 2: 是一个缓慢的、有意识的、有逻辑的、努力的系统,使用高级推理来做出决策

Two systems of thinking
系统 1 做出不需要太多注意力和常识的自动决定,比如走路、拿着物体、理解简单的句子或者在高速公路上开车。系统 2 进行高级推理,这需要常识,比如理解法律条款或在拥挤的城市中驾驶汽车,这不仅需要车道间驾驶的知识,还需要城市内交通规则和人为因素的知识。
那么接下来的问题是:系统 1 和系统 2 在 AI 中代表什么?
1988 年,马文·明斯基出版了他的书《心智的社会》。这本书最有趣的部分之一是在人脑中表现知识的框架。

Framework for representing knowledge, source Society of Mind (Marvin Minskey)
大脑中的知识由七层组成(忽略小词,输入层)。考虑到最近的人工智能技术,我将对它们的功能解释如下:
- 神经网络:代表 ANN/DL。这一层的主要目标是避免维数灾难,并构建一个高层次的分布式/非纠缠表示。这一层代表大脑最直观的部分(系统 1)。这是刻板和自动的。学习缓慢而艰难,解释困难
- K 线和 k 线树:马文·明斯基把 k 线看做记忆线。但我提出 k 线层代表的是所谓的归纳编程。为解决某些问题而学习的一系列程序。这一层是系统 1 和系统 2 之间的第一个桥梁。它比 NN 层更有逻辑性,使用的推理更多。更容易学习和解释。
- 语义网络:表示知识图、语义网或本体。它再次更接近系统 2 的方向。通过断开或连接两个事实(节点),一次性学习变得更加容易。
- 框架:框架是一种数据结构,具有关于特定对象或概念的典型知识。它和第三层一样,但是有更多的解释和更容易学习
- 常识台词:这里我把最后三层都合并成了一层。这些层的目标是将不同的领域连接在一起,形成常识和常识,例如,在城市中驾驶汽车。它和第四层一样,但是有更多的解释和更容易学习
考虑到以上几点,我们得出以下结论:

Framework of Explanation Deep Learning, source Society of Mind (Marvin Minskey)
- 我们所谓的深度学习实际上还没有深到可以解释的程度
- 我们所说的深度学习实际上还不足以执行一次性学习
- 实现可解释人工智能的关键是缩小四层知识之间的差距
- 通过弥合这些差距,我们实现了一个可以使用系统 2 解释自己的人工智能,同时它在直观的系统 1 中保持复杂的解决方案
- 通过弥合这些差距,我们实现了一个可以使用系统 1 解决直观体验问题,并可以使用系统 2 概括和解决推理问题的人工智能
- 解释人工智能的目标不仅是建立信任,而且是提高性能和实现人工智能的一般智能
在本系列文章的下一部分中,我将深入研究旨在弥补上述框架缺陷的最新技术。从使用时间或形状来解释系统 1 的决策开始,通过最近的神经符号研究和归纳逻辑编程,由 Yoshua Bengio 解决意识先验,最后如何建立一个解释 AI 模型而不是解释 AI 模型。
敬请期待!
模型解释策略
可解释的人工智能(第二部分)
了解模型解释技术、局限性和进步

Source: Pixabay
介绍
本文是我针对 【可解释的人工智能(XAI)系列文章的延续。如果你还没有阅读第一篇文章,我肯定会建议你快速浏览一下 【第一部分——人类可解释机器学习的重要性】 ,它涵盖了人类可解释机器学习的内容和原因,以及模型解释的必要性和重要性及其范围和标准。在本文中,我们将从我们停下来的地方开始,进一步扩展到机器学习模型解释方法的标准,并探索基于范围的解释技术。本文的目的是让您很好地理解现有的、传统的模型解释方法,以及它们的局限性和挑战。我们还将讨论经典的模型准确性与模型可解释性之间的权衡,最后看看模型解释的主要策略。
简而言之,我们将在本文中讨论以下几个方面。
- 模型解释的传统技术
- 传统技术的挑战和局限
- 准确性与可解释性的权衡
- 模型解释技术
这应该让我们为第 3 部分中模型解释的详细实践指南做好准备,所以请继续关注!
模型解释的传统技术
模型解释的核心是找到更好地理解模型决策政策的方法。这是为了实现公平、问责和透明,这将使人类有足够的信心在现实世界的问题中使用这些模型,这些问题对商业和社会有很大影响。因此,现在有一些已经存在很长时间的技术,可以用来以更好的方式理解和解释模型。这些可以分为以下两大类。
- 探索性分析和可视化技术,如聚类和降维。
- 模型性能评价指标如 精度、 、 ROC 曲线、AUC (用于分类模型)和(R-square)、 均方根误差、平均绝对误差 (用于回归模型)
让我们简单地更详细地看一下这些技术。
探索性分析和可视化
探索性分析的想法并不是全新的。多年来,数据可视化一直是从数据中获取潜在洞察力的最有效工具之一。这些技术中的一些可以帮助我们从我们的数据中识别关键特征和有意义的表示,这些数据可以给出可能影响模型以人类可解释的形式做出决策的指示。
降维技术在这里非常有用,因为我们经常处理非常大的特征空间(维数灾难),降维有助于我们可视化并了解什么可能影响模型做出特定决策。其中一些技术如下。
现实世界问题中的一个例子是,通过使用单词嵌入检查它们的语义相似性,并使用 t-SNE 对其进行可视化,来尝试可视化哪些文本特征可能对模型有影响,如下所述。

Visualizing word embeddings using t-SNE (Source: Understanding Feature Engineering (Part 4) — Deep Learning Methods for Text Data — Towards Data Science)
您还可以使用 t-SNE 来可视化著名的 MNIST 手写数字数据集,如下图所示。

Visualizing MNIST data using t-SNE using sklearn. Image courtesy of Pramit Choudhary and the Datascience.com team.
另一个例子是通过利用 PCA 进行降维来可视化著名的 IRIS 数据集,如下图所示。

Principal Component Analysis on the IRIS dataset
除了可视化数据和特征之外,某些更直观、更易理解的模型,如决策树,有助于我们直观地了解做出某个决策的确切方式。下面描述了一个示例树,它帮助我们以人类可理解的方式可视化确切的规则。

Visualizing human-interpretable rules for a decision tree model (Source: Practical Machine Learning with Python, Apress 2018)
然而,正如我们所讨论的,我们可能无法为其他模型获得这些规则,这些模型不像基于树的模型那样可解释。此外,巨大的决策树总是变得非常难以想象和解释。
模型性能评估指标
模型性能评估 是任何数据科学生命周期中选择最佳模型的关键步骤。这使我们能够看到我们的模型表现如何,比较不同模型的各种性能指标,并选择最佳模型。这也使我们能够 调整和优化模型中的超参数 ,以获得对我们正在处理的数据给出最佳性能的模型。典型地,基于我们正在处理的问题的类型,存在某些标准的评估度量。
- 监督学习—分类:对于分类问题,我们的主要目标是预测离散的分类响应变量。混淆矩阵在这里非常有用,我们可以从中获得一系列有用的指标,包括准确度、精确度、召回率和 F1 分数,如下例所示。

Classification Model Performance Metrics (Source: Practical Machine Learning with Python, Apress 2018)
除了这些指标,我们还可以使用其他一些技术,如 ROC 曲线和 AUC 分数,如下图中葡萄酒质量预测系统所示。

ROC Curve and AUC scores (Source: Practical Machine Learning with Python, Apress 2018)
ROC 曲线下的面积是客观评估分类器性能的一种非常流行的技术。在这里,我们通常试图平衡真阳性率(TPR)和假阳性率(FPR)。上图告诉我们,**‘high’**级葡萄酒的 AUC 分数是**0.9**,这意味着模型给**‘high’**(正级)级葡萄酒分配的分数比给**NOT ‘high’** (或**‘low’**(负级)级葡萄酒分配的分数高的概率是 90%。有时,如果 ROC 曲线交叉,结果可能会产生误导并难以解释(来源: 测量分类器性能:ROC 曲线下面积的连贯替代方法 )。
- 监督学习—回归:对于回归问题,我们可以使用标准指标,如决定系数(R 平方)、均方根误差(RMSE) 和平均绝对误差(MAE) 。
- 无监督学习—聚类:对于基于聚类的无监督学习问题,我们可以使用类似于剪影系数、同质性、完整性、V-measure 和卡林斯基-哈拉巴兹指数的度量。
传统技术的局限性和更好模型解释的动机
我们在前面的技术中讨论的技术肯定有助于理解更多关于我们的数据、特征以及哪些模型可能是有效的。然而,在试图辨别模型如何工作的人类可解释的方式方面,它们相当有限。在任何数据科学问题中,我们通常在静态数据集上构建模型,并获得我们的目标函数(优化损失函数),该函数通常在满足基于模型性能和业务需求的特定标准时部署。通常,我们利用上述探索性分析和评估指标的技术来决定我们数据的整体模型性能。然而,在现实世界中,由于数据特征的可变性、增加的约束和噪声,模型的性能在部署后通常会随着时间的推移而降低并停滞不前。这可能包括环境的变化、功能的变化以及增加的约束。因此,简单地在相同的特征集上重新训练模型是不够的,我们需要不断检查特征在决定模型预测中的重要性,以及它们在新数据点上的工作情况。
例如,入侵检测系统 (IDS),一个网络安全应用程序,容易受到规避攻击,攻击者可能会使用对抗性输入来击败安全系统(注意:对抗性输入是攻击者故意设计的例子,以欺骗机器学习模型做出错误的预测)。在这种情况下,模型的目标函数可能充当现实世界目标的弱代理。可能需要更好的解释来识别算法中的盲点,以通过修复易于受到敌对攻击的训练数据集来建立安全的模型(有关进一步的阅读,请参见 Moosavi-Dezfooli 等人,2016 年, DeepFool 和 Goodfellow 等人,2015 年, 解释和利用敌对示例 )。

此外,由于我们正在处理的数据的性质,模型中经常存在偏差,就像在罕见的预测问题(欺诈或入侵检测)中一样。度量不能帮助我们证明模型预测决策的真实情况。此外,这些传统形式的模型解释对于数据科学家来说可能很容易理解,但由于它们本质上是理论性的,并且通常是数学性的,因此在尝试向(非技术)业务利益相关者解释这些内容以及尝试仅基于这些指标来决定项目的成功标准时,存在很大的差距。仅仅告诉业务部门,“我有一个准确率为 90%的模型”还不足以让他们在现实世界中开始信任该模型。我们需要对模型的决策策略进行人类可解释的解释(HII ),这些决策策略可以用适当和直观的输入和输出来解释。这将使有洞察力的信息能够容易地与同行(分析师、经理、数据科学家、数据工程师)共享。使用这种形式的解释,可以根据投入和产出进行解释,可能有助于促进更好的沟通和合作,使企业能够做出更有信心的决定(例如,金融机构的风险评估/审计风险分析)。
重申一下,我们将模型解释(新方法)定义为能够解释预测模型的 公平性 (无偏性/非歧视性) 责任性 (可靠的结果),以及(能够查询和验证预测决策)——目前是关于监督学习问题。
准确性与可解释性的权衡
在模型性能和可解释性之间存在一种典型的权衡,就像我们在机器学习中有标准偏差和方差的权衡一样。在行业中,您经常会听到业务利益相关者倾向于更易于解释的模型,如线性模型(线性\逻辑回归)和树,这些模型直观、易于验证,并易于向非数据科学专家解释。这增加了人们对这些模型的信任,因为它的决策策略更容易理解。然而,如果您与解决行业中真实世界问题的数据科学家交谈,他们会告诉您,由于真实世界数据集固有的高维性和复杂性,他们通常不得不利用机器学习模型,这些模型可能是非线性的,本质上更加复杂,通常无法使用传统方法(集成、神经网络)进行解释。因此,数据科学家花费大量时间试图改善模型性能,但在这个过程中,他们试图在模型性能和可解释性之间取得平衡。

Model performance vs. interpretability (Source: https://www.datascience.com))
上图显示了一个客户贷款批准问题的模型决策边界。我们可以清楚地看到,具有单调决策边界的简单、易于解释的模型在某些场景中可能工作良好,但通常在现实世界的场景和数据集中,我们最终会使用具有非单调决策边界的更复杂、更难以解释的模型。因此,为了加强我们的动机,我们需要模型解释,以便我们能够说明预测模型的公平性(无偏性/非歧视性)责任性(可靠的结果)和透明性(能够查询和验证预测决策)。有兴趣的读者可以查阅文章, 【迈向机器学习的喷射时代】 。除此之外,我肯定会推荐读者查看我个人最喜欢的一篇文章,我在这个系列中改编了很多内容, “用 Skater 解释预测模型:拆箱模型不透明度” 其中更详细地谈到了这一点。
* [## 用 Skater 解释预测模型:打开模型不透明度
深入探究作为理论概念的模型解释,以及对滑手的高层次概述。
www.oreilly.com](https://www.oreilly.com/ideas/interpreting-predictive-models-with-skater-unboxing-model-opacity)
模型解释技术
有各种各样的新模型解释技术试图解决传统模型解释技术的局限性和挑战,并试图对抗经典的可解释性与模型性能之间的权衡。在这一节中,我们将看看其中的一些技术和策略。请记住,我们的重点将是涵盖模型不可知的解释技术,因为这些技术将真正帮助我们走向可解释的人工智能(XAI) 。
使用可解释的模型
开始模型解释的最简单的方法是使用开箱即可解释的模型!这通常包括您的常规参数模型,如线性回归、逻辑回归、基于树的模型、规则拟合,甚至像 k-最近邻和朴素贝叶斯这样的模型!根据主要功能对这些模型进行分类的方法是:
- 线性:通常,如果特征和目标之间的关联是线性建模的,那么我们有一个线性模型。
- 单调性:单调模型确保特性和目标结果之间的关系在特性上(在其值的整个范围内)总是在一个一致的方向上(增加或减少)。
- 交互:您可以随时使用手动特征工程向模型添加交互特征、非线性。有些型号还会自动创建它。
Christoph Molnar 的优秀著作, 【可解释机器学习】 有一个很好的表格总结了以上几个方面。

Source: Interpretable Machine Learning, Christoph Molnar
需要记住的一点是,其中一些模型可能过于简单,因此我们可能需要考虑更好的方法来构建和解释更复杂、性能更好的模型。
特征重要性
特征重要性是预测模型依赖特定特征的程度的通用术语。通常,一个特征的重要性是在我们改变了该特征的值之后模型预测误差的增加。像 Skater 这样的框架基于一个信息论标准来计算,在给定一个给定特征的扰动的情况下,测量预测变化的熵。直觉告诉我们,一个模型的决策标准越依赖于一个特征,我们就越会看到预测随着对一个特征的扰动而变化。然而,像 SHAP 这样的框架,使用特征贡献和博弈论的组合来得出 SHAP 值。然后,它通过对整个数据集的 SHAP 值进行平均来计算全局要素重要性。以下是人口普查数据集中溜冰者要素重要性图的标准示例。

看起来Age和Education-Num是最重要的两个特征,其中Age负责模型预测在扰动/置换Age特征时平均变化 14.5%。因此,总而言之,模型不可知特性重要性的全局解释背后的概念非常简单。
- 我们通过计算扰动特征后模型预测误差的增加来衡量特征的重要性。
- 如果扰动某个要素的值会增加模型误差,则该要素是“重要的”,因为模型依赖于该要素进行预测。
- 如果扰动某个特征的值使模型误差保持不变,则该特征是“不重要的”,因为模型基本上忽略了该特征的预测。
Breiman (2001) 为随机森林引入了排列特征重要性度量。基于这一想法, Fisher、Rudin 和 Dominici (2018) 提出了特征重要性的模型不可知版本——他们称之为模型依赖。
部分相关图
部分相关性描述了某个功能对模型预测的边际影响,使模型中的其他功能保持不变。部分相关的导数描述了特征的影响(类似于回归模型中的特征系数)。部分相关性图(PDP 或 PD 图)显示了某个特性对先前拟合模型的预测结果的边际影响。PDP 可以显示目标和特征之间的关系是线性的、单调的还是更复杂的。部分相关图是一种全局方法:该方法考虑了所有实例,并陈述了某个特征与预测结果的全局关系。下图显示了一些 PDP 示例。

PDP for 1 feature
我们用溜冰者和 SHAP 来说明教育水平对挣更多钱的影响。这是一个单向 PDP,显示了一个特征对模型预测的影响。我们还可以构建双向 PDP,显示两个特征对模型预测的影响。下图显示了一个示例。

PDP for 2 features
在上述 PDP 中,您可以清楚地看到影响模型预测的特性的效果和相互作用。受教育程度更高、每周工作时间更长的显著中年人挣钱更多!
全球代理模型
我们已经看到了用特征重要性、依赖图、不太复杂的模型来解释机器学习模型的各种方法。但是有没有一种方法可以建立真正复杂模型的可解释的近似值呢?谢天谢地,我们有全球代理模型,正是为了这个目的!全局代理模型是一种可解释的模型,它被训练成近似黑盒模型的预测,而黑盒模型本质上可以是任何模型,不管其复杂性或训练算法如何,这是模型不可知的!

通常,我们基于被视为黑盒模型的基本模型,近似一个更易解释的代理模型。然后,我们可以通过解释代理模型得出关于黑盒模型的结论。用更多的机器学习来解决机器学习的可解释性!
(可解释的)替代模型的目的是在可解释的同时尽可能接近基础模型的预测。拟合代理模型是一种模型不可知的方法,因为它不需要关于黑盒模型内部工作的信息,只使用输入和预测输出的关系。基本黑盒模型类型和代理模型类型的选择是分离的。基于树的模型不是太简单,而是可解释的,是构建代理模型的好选择。
Skater 介绍了使用**TreeSurrogates**作为解释模型的学习决策策略(用于归纳学习任务)的手段的新颖想法,这是受 Mark W. Craven 的工作(称为特雷潘算法)的启发。我们将在本系列的第 3 部分中用例子介绍特雷普恩模型。目前,Christoph Molnar 在他的一书中出色地讲述了构建代理模型的主要步骤。
- 选择数据集这可以是用于训练黑盒模型的同一数据集,也可以是来自同一分布的新数据集。根据您的应用程序,您甚至可以选择数据的子集或点的网格。
- 对于所选数据集,获取基础黑盒模型的预测。
- 选择一个可解释的替代模型(线性模型、决策树等等)。
- 对数据集及其预测训练可解释的模型。
- 恭喜你!你现在有了一个代理模型。
- 衡量代理模型复制黑盒模型预测的能力。
- 解释/可视化代理模型。
当然,这是一个高层次的说明,TREPAN 等算法在内部做得更多,但整体工作流程仍然保持不变。

Sample illustration of a surrogate tree model
上图是从复杂的 XGBoost 黑盒模型近似而来的代理树模型。我们将在第 3 部分从头开始构建它,敬请关注!有趣的是,与 XGBoost 模型的 87%的准确度相比,这个模型具有 83%的总准确度。还不错!
局部可解释的模型不可知解释(LIME)
LIME 是由 Riberio Marco、Singh Sameer 和 Guestrin Carlos 设计的一种新算法,用于使用本地可解释替代模型(如线性分类器/回归器)来评估任何基础估计量(模型)的行为。这种形式的综合评估有助于产生局部忠实的解释,但可能不符合全局行为。基本上,石灰解释是基于本地代理模型。这些替代模型是可解释的模型(如线性模型或决策树),是根据原始黑盒模型的预测学习的。但是,LIME 没有试图拟合一个全球代理模型,而是专注于拟合局部代理模型,以解释为什么会做出单一预测。事实上,也可以作为 GitHub 上的一个 开源框架,并且是基于本文 中 介绍的工作。**
这个想法非常直观。首先,试着忘掉你已经做过的事情!忘记训练数据,忘记你的模型是如何工作的!认为你的模型是一个黑盒模型,里面有一些神奇的事情发生,你可以输入数据点,并得到模型预测的结果。你可以随时探测这个神奇的黑箱,得到输入和输出预测。现在,你的主要目标是理解为什么你作为一个神奇的黑盒子对待的机器学习模型,给出了它产生的结果。LIME 试着为你做这件事!它测试当你把数据集的变化或扰动输入黑盒模型时,黑盒模型的预测会发生什么。通常,LIME 会生成一个由扰动样本和相关黑盒模型预测组成的新数据集。在这个数据集上,LIME 然后训练可解释的模型,该模型通过采样实例与感兴趣实例的接近度来加权。以下是标准的高级工作流程。
- 选择您感兴趣的实例,您希望对其黑盒模型的预测进行解释。
- 扰动数据集,获得这些新点的黑盒预测。
- 根据与感兴趣的实例的接近程度对新样本进行加权。
- 将加权的、可解释的(替代)模型拟合到有变化的数据集上。
- 通过解释本地模型来解释预测。
下面是一个在 Skater 框架中使用 LIME 的示例,它解释了为什么该模型预测一个人将赚超过 50K 美元。

Explaining predictions with LIME
我们将使用人口普查数据集来构建模型,并在下一篇文章中用 LIME 更详细地探索它们。
沙普利值和沙普利加法解释(SHAP)
****SHAP(SHapley Additive exPlanations)是解释任何机器学习模型输出的统一方法。SHAP 将博弈论与局部解释相结合,结合了以前的几种方法,并基于他们所声称的,代表了唯一可能一致且局部精确的附加特征归因方法!(详情请查看 SHAP 夹纸)。SHAP 是一个优秀的模型解释框架,它基于对 Shapley 值的调整和增强,我们将在本节中深入探讨。再次感谢 Christoph Molnar 的 惊人的模型解释书 ,我将无耻地将它改编到本教程中,因为在我看来,这可能是理解这个概念的最佳方式!
通常,模型预测可以通过假设每个特征是游戏中的【玩家】来解释,其中预测是支出。Shapley 值——一种来自联合博弈论的方法——告诉我们如何在特性之间公平地分配‘支付’。让我们举一个说明性的例子。

假设你训练了一个机器学习模型来预测公寓价格。对于某个公寓,它预测 300,000 €,你需要解释这个预测。公寓面积50 平米,位于二楼,附近有公园和禁止养猫。所有公寓的平均预测价格是 31 万€。与平均预测相比,每个特征值对预测的贡献有多大?
线性回归模型的答案很简单:每个特征的影响是特征的权重乘以特征值减去所有公寓的平均影响:这只是因为模型的线性。对于更复杂的模型,我们该怎么做?一种选择是我们刚刚讨论过的石灰。另一个不同的解决方案来自合作博弈理论: 由 Shapley 创造的 Shapley 值 ,是一种根据玩家对总支出的贡献将支出分配给玩家的方法。玩家在联盟中合作,并从合作中获得一定的收益。
- “游戏”是数据集的单个实例的预测任务。
- ‘增益’是该实例的实际预测减去所有实例的平均预测。
- ‘玩家’是实例的特征值,协同接收增益(=预测某个值)。
因此,在我们的公寓示例中,特征值**‘park-allowed’**、**‘cat-forbidden’**、**‘area-50m-sq’**和**‘floor-2nd’**共同实现了 300,000€的预测。我们的目标是解释实际预测(300,000€)和平均预测(310,000€)的差异:差异为-10,000€。答案可能是:**‘park-nearby’**号贡献了 3 万€;**‘size-50m-sq’**贡献了一万€;**‘floor-2nd’**贡献了 0€;**‘cat-forbidden’**出资 5 万€。捐款加起来是-10,000€:最终预测减去平均预测公寓价格。
Shapley 值是一个特征值在所有可能的联合中的平均边际贡献。联盟基本上是用于估计特定特征的 shapley 值的特征的组合。通常情况下,要素越多,它就开始呈指数增长,因此可能需要花费大量时间来计算大数据集或宽数据集的这些值。下图显示了评估**‘cat-forbidden’**的 Shapley 值所需的所有特征值组合。

第一行显示了没有任何特征值的联盟。第二、第三和第四行显示不同的联盟——由**‘|’** 分隔——联盟规模逐渐增大。对于这些联盟中的每一个,我们计算有和没有**‘cat-forbidden’**特征值的预测公寓价格,并取其差值以获得边际贡献。Shapley 值是边际贡献的(加权)平均值。我们用来自公寓数据集的随机特征值替换不在联盟中的特征的特征值,以从机器学习模型获得预测。当我们对所有特征值重复 Shapley 值时,我们得到特征值之间预测的完整分布(减去平均值)。SHAP 是沙普利值的增强。
SHAP (SHapley 附加解释)为每个特征分配一个特定预测的重要性值。其新颖的组成部分包括:识别一类新的加性特征重要性度量,理论结果表明在这一类中有一个唯一的解决方案,具有一组理想的性质。通常,SHAP 值试图将模型(函数)的输出解释为引入条件期望的每个特征的效果的总和。重要的是,对于非线性函数,引入特征的顺序很重要。SHAP 值由所有可能的排序的平均值产生。博弈论的证据表明这是唯一可能的一致方法。下面的图来自 KDD 18 论文, 一致的个性化特征归属为树系综 很好地概括了这一点!

Understanding SHAP value
下面是一个使用 SHAP 来解释模型在预测一个人的收入是否大于 5 万美元时的决策的例子

Explaining model predictions with SHAP
看到模型背后的关键驱动因素(特性)做出这样的决定是很有趣的!我们还将在本系列的第 3 部分中用实际操作的例子来介绍这一点。
结论
这篇文章将帮助你在通往可解释人工智能(XAI)的道路上迈出更明确的步伐。您现在知道了模型解释的必要性和重要性。第一篇文章中关于偏见和公平的问题。在这里,我们研究了模型解释的传统技术,讨论了它们的挑战和局限性,还介绍了模型可解释性和预测性能之间的经典权衡。最后,我们研究了当前最先进的模型解释技术和策略,包括特征重要性、PDP、全局代理、局部代理和 LIME、shapley 值和 SHAP。就像我之前提到的,让我们努力实现人类可解释的机器学习和 XAI,为每个人揭开机器学习的神秘面纱,并帮助增加对模型决策的信任。*
下一步是什么?
在本系列的第 3 部分中,我们将会看到一个使用我们在本文中学到的所有新技术来构建和解释机器学习模型的综合指南。为此,我们将使用几个最先进的模型解释框架。
- 关于使用最新的模型解释框架的实践指南
- 使用 ELI5、Skater 和 SHAP 等框架的特点、概念和示例
- 探索概念并观察它们的实际应用——特征重要性、部分相关图、替代模型、用石灰的解释和说明、SHAP 值
- 基于监督学习示例的机器学习模型解释
敬请期待,这肯定会变得更加有趣和令人兴奋!
请查看 “第一部分——人类可解释机器学习的重要性” ,其中涵盖了人类可解释机器学习的内容和原因,以及模型解释的必要性和重要性及其范围和标准(如果您还没有了解的话)!
我在我的书中覆盖了很多机器学习模型解释的例子, 【用 Python 实现实用的机器学习】 。为了您的利益,代码是开源的!
有反馈给我吗?或者有兴趣与我一起从事研究、数据科学、人工智能甚至发表一篇关于TDS的文章?可以在LinkedIn上联系我。****
** [## Dipanjan Sarkar -数据科学家-英特尔公司| LinkedIn
查看 Dipanjan Sarkar 在世界最大的职业社区 LinkedIn 上的个人资料。Dipanjan 有 6 份工作列在…
www.linkedin.com](https://www.linkedin.com/in/dipanzan/)**
动手机器学习模型解释
可解释的人工智能(第三部分)
解释机器学习模型的综合指南

介绍
鉴于人工智能在行业中的快速采用,解释机器学习模型不再是一种奢侈品,而是一种必需品。本文是我针对 【可解释人工智能(XAI)系列文章的延续。这里的想法是通过炒作,使您拥有开始解释任何黑盒机器学习模型所需的工具和技术。如果您想快速浏览一下,下面是本系列的前几篇文章(但不是本文的强制要求)。
- 第 1 部分——人类可解释机器学习的重要性’:涵盖了人类可解释机器学习的内容和原因,以及模型解释的需求和重要性及其范围和标准
- 第二部分——模型解释策略’它涵盖了人类可解释的机器学习的方式,我们在其中查看了与模型解释的主要策略相关的基本概念。
在本文中,我们将为您提供实践指南,展示以模型不可知的方式解释潜在黑盒机器学习模型的各种方法。我们将致力于一个真实世界的人口普查收入数据集,也称为成人数据集,可在 UCI ML 知识库中获得,在那里我们将预测人们的潜在收入是否超过 5 万美元/年。
这篇文章的目的是多方面的。第一个主要目标是让我们自己熟悉主要的最新模型解释框架(它们中的许多都是 LIME 的扩展——我们已经在本系列的 第 2 部分 中详细介绍的为模型解释提出的原始框架和方法)。
我们将在教程中介绍以下模型解释框架的使用。
我们将在本教程中讨论的主要模型解释技术包括以下内容。
- 特征重要性
- 部分相关图
- 模型预测解释结合局部解释
- 用基于代理树的模型构建可解释模型
- 用 SHAP 值进行模型预测解释
- 依赖&与 SHAP 的互动剧情
事不宜迟,让我们开始吧!
正在加载必要的依赖项
鉴于这是一个模型解释的实践指南,我们将在本文中使用大量的框架和工具。我们建议您加载以下依赖项,以充分利用本指南!

记住调用**shap.initjs()**函数,因为**shap**中的很多图都需要 JavaScript。
加载并查看人口普查收入数据集
你其实可以从 UCI ML 资源库 中获取 人口普查收入 数据集(俗称 成人数据集 )。幸运的是**shap**为我们提供了这个数据集的一个已经清理过的版本,我们将在这里使用它,因为这篇文章的目的是模型解释。
查看数据属性
让我们看看数据集的主要特征或属性。
***((32561, 12), (32561,))***

Census Dataset Features
我们将很快解释这些特性。
查看类别标签
让我们来看一下 < = $50K ( **False**)和>【50K】(**True**)收入的人的分布,这是我们要预测的阶级标签。
***In [6]: Counter(labels)****Out[6]: Counter({0: 24720, 1: 7841})***
鉴于我们应该让更少的人拥有更高的收入,肯定会出现一些阶级失衡。
了解人口普查收入数据集
现在让我们来看看我们的数据集属性,并理解它们的含义和重要性。
我们总共有 12 个特征,我们的目标是预测一个人的收入是超过 5 万美元 ( **True**)还是低于 5 万美元 ( **False**)。因此,我们将建立和解释一个分类模型。
基础特征工程
这里,我们将带有字符串值的分类列转换为数字表示。通常,XGBoost 模型本身是一个基于树的模型,可以处理分类数据,所以我们在这里不对这些特性进行一次性编码。

在我们建立分类模型之前,是时候建立我们训练和测试数据集了。
构建训练和测试数据集
对于任何机器学习模型,我们总是需要训练和测试数据集。我们将在训练数据集上构建模型,并在测试数据集上测试性能。我们维护两个数据集(一个具有编码的分类值,一个具有原始值),因此我们可以使用编码的数据集进行训练,但在以后需要时使用原始数据集进行模型解释。
***((22792, 12), (9769, 12))***

Our encoded dataset
我们还在一个单独的数据帧中用实际(未编码的)值维护我们的基本数据集(对以后的模型解释有用)。
***((22792, 12), (9769, 12))***

Our actual dataset
训练分类模型
现在,我们将使用流行的 XGBoost 框架在我们的训练数据上训练和构建基本的 boosting 分类模型,这是一个优化的分布式梯度 boosting 库,旨在实现高效、灵活和可移植性。
***Wall time: 8.16 s***
根据测试数据进行预测
在这里,我们像往常一样,使用训练好的模型对测试数据集进行预测。
***array([0, 0, 1, 0, 0, 1, 1, 0, 0, 1])***
模型性能评估
是时候对模型进行测试了!让我们评估一下我们的模型在测试数据上的预测表现如何。为此,我们使用我的漂亮的**model_evaluation_utils**模块,它在内部利用**scikit-learn**为我们提供标准的分类模型评估指标。

默认模型解释方法
默认情况下,很难评估开箱即用的机器学习模型的特定模型解释方法。逻辑回归等参数模型更容易解释,因为模型的参数总数是固定的,与数据量无关,并且可以利用参数系数对模型的预测决策进行一些解释。
非参数模型更难解释,因为参数总数保持无界,并且随着数据量的增加而增加。一些非参数模型,如基于树的模型,确实有一些现成的模型解释方法,如特征重要性,这有助于我们了解哪些特征可能对模型做出预测决策有影响。
来自 XGBoost 的经典特性重要性
在这里,我们尝试 XGBoost 附带的全局特性重要性计算。该模型使我们能够根据以下内容来查看特性的重要性。
- 特征权重:这是基于一个特征在所有树中出现的次数
- 增益:这是基于使用该功能的拆分的平均增益
- 覆盖率:这是基于使用该特性的分割的平均覆盖率(受影响的样本数)
请注意,它们都是相互矛盾的,这激发了模型解释框架的使用,如 SHAP,它使用了被称为 SHAP 值的东西,声称具有一致性保证(意味着它们通常会正确地排列特性)。

Feature Importance Plots from XGBoost
使用 ELI5 进行模型解释
ELI5 是一个 Python 包,帮助调试机器学习分类器,并以一种易于理解的直观方式解释它们的预测。这可能是三个机器学习框架中最容易开始的,因为它只需要阅读最少的文档!然而,它不支持真正的模型不可知的解释,对模型的支持大多局限于基于树的和其他参数\线性模型。让我们看看在我们的分类模型上使用 ELI5 进行模型解释的一些直观方式。
安装说明
我们建议使用**pip install eli5**安装这个框架,因为**conda**版本似乎有点过时。也可以根据需要随意查看 文档 。
ELI5 的特性重要性
通常,对于基于树的模型,ELI5 不做任何特殊处理,而是使用我们在上一节中讨论的现成的特性重要性计算方法。默认情况下,使用‘gain’,这是该特性在树中使用时的平均增益。
***eli5.show_weights(xgc.get_booster())***

用 ELI5 解释模型预测决策
向技术人员或更面向业务的人员解释模型预测决策的最佳方式之一是检查各个数据点的预测。通常,ELI5 通过显示每个特征的权重来实现这一点,这些权重描述了该特征对所有树的最终预测决策的影响程度。这里的 描述了 计算重量的思路;ELI5 为 XGBoost 和大多数 scikit-learn 树集成提供了该算法的独立实现,这无疑是朝着模型不可知解释的方向发展,但不像 LIME 那样纯粹是模型不可知的。
通常,预测可以被定义为特征贡献的总和+偏差(即,由覆盖整个训练集的最顶端区域给出的平均值)
预测一个人什么时候的收入<= $50K
Here we can see the most influential features being the 【 、、**Hours per week**、、**Marital Status**、、、**Occupation**、、、**Relationship**

预测一个人的收入何时超过 5 万美元
这里我们可以看到最有影响力的特征是**Education** 、 **Relationship** 、 **Occupation** 、 **Hours per week** & **Marital Status**

看到相似的特征如何在解释这两个类的模型预测决策中发挥有影响的作用,肯定是有趣的!
用溜冰者解释模型
Skater 是一个统一的框架,能够对所有形式的模型进行模型解释,以帮助人们使用模型不可知的方法构建现实世界用例经常需要的可解释的机器学习系统。它是一个开源的 python 库,旨在从全局(基于完整数据集的推理)和局部(关于单个预测的推理)两个方面揭开黑盒模型的已知结构。

Skater 最初以一个酸橙叉开始,但后来发展成为一个独立框架,具有各种各样的特性和能力,可以对任何黑盒模型进行模型不可知的解释。该项目最初是一个研究想法,旨在为研究人员和实践者找到更好的可解释性(最好是人类的可解释性)来预测【黑盒】。
安装滑冰者
你通常可以使用一个简单的**pip install skater**来安装 Skater。有关依赖关系和安装说明的详细信息,请查看安装滑板。
📖证明文件
我们建议你去查阅溜冰者的详细资料。
算法
溜冰者有一套模型解释技术,其中一些在下面提到。

用法和示例
由于该项目正在积极开发中,了解用法的最佳方式是遵循交互式笔记本的图库中提到的示例。但是我们将使用在我们的人口普查数据集上训练的模型来展示它的主要能力。
溜冰者的全球诠释
预测模型是从输入空间到输出空间的映射。解释算法分为提供领域区域统计数据和度量标准的算法,如要素的边缘分布或整个训练集的联合分布。在一个理想的世界中,将存在一些允许人类在任意数量的维度中解释决策函数的表示。鉴于我们通常一次只能直观地看到几个维度的可视化,全局解释算法要么聚集特征空间,要么划分特征空间的子集。
目前,skater 支持的模型不可知的全局解释算法包括部分依赖和特征重要性,以及一个非常新的树代理版本。我们将在这里讨论特性重要性和部分依赖图。
创建解释对象
skater 包中的一般工作流是创建解释、创建模型和运行解释算法。通常情况下,**Interpretation**会消耗一个数据集,以及可选的一些元数据,比如特性名称和行 id。在内部,**Interpretation**将生成一个**DataManager**来处理数据请求和采样。
- 局部模型(
**InMemoryModel**): 要创建一个基于局部函数或方法的溜冰者模型,将预测函数传递给一个**InMemoryModel**。用户可以选择将数据样本传递给 examples 关键字参数。这仅用于推断输出类型和格式。开箱即用,skater 允许模型返回**numpy**数组和**pandas**数据帧。 - 可操作模型(
**DeployedModel**): 如果您的模型可以通过 API 访问,那么使用一个**DeployedModel**,它包装了请求库。**DeployedModels**需要两个函数,一个输入格式化程序和一个输出格式化程序,它们对请求库进行发布和解析。输入格式化程序接受一个**pandas**DataFrame 或一个**numpy**ndarray,并返回一个可以转换成 JSON 的对象(比如 dict)来发布。输出格式化程序将 requests.response 作为输入,并返回一个**numpy**ndarray 或**pandas**DataFrame。
我们将使用以下工作流程:
- 构建一个解释对象
- 构建内存模型
- 执行解释
对溜冰者的重要性
特征重要性是预测模型依赖特定特征的程度的通用术语。给定给定特征的扰动,溜冰者特征重要性实现基于信息理论标准,测量预测变化的熵。直觉告诉我们,一个模型的决策标准越依赖于一个特征,我们就越会看到预测随着对一个特征的扰动而变化。使用的默认方法是**prediction-variance**,它是给定数据扰动时预测变化的平均绝对值。

Feature Importances from Skater
部分依赖
部分相关性描述了某个功能对模型预测的边际影响,使模型中的其他功能保持不变。部分相关的导数描述了特征的影响(类似于回归模型中的特征系数)。本文改编自 T. Hastie、R. Tibshirani 和 J. Friedman 的《统计学习要素》。2、斯普林格。2009.
部分相关性图(PDP 或 PD 图)显示了某个特性对先前拟合模型的预测结果的边际影响。PDP 可以显示目标和特征之间的关系是线性的、单调的还是更复杂的。滑冰者可以显示一维和二维等离子体显示器
影响模型预测的“年龄”的 PDP
让我们看看**Age**特性是如何影响模型预测的。

PDP for the Age feature
看起来,与年轻人或老年人相比,中年人赚更多钱的机会稍高一些。
“教育程度”的 PDP 影响模型预测
让我们看看**Education-Num**特性是如何影响模型预测的。

PDP for the Education-Num feature
看起来受教育程度越高,赚更多钱的机会就越大。不奇怪!
影响模型预测的“资本收益”的 PDP
让我们看看**Capital Gain**特性是如何影响模型预测的。

PDP for the Capital Gain feature
不出所料,资本收益越高,赚钱的机会就越多,大约在 $5K 到$8K 之间急剧上升。
影响模型预测的“关系”的 PDP
记住,关系是用数字表示的分类变量编码的。我们先来看看它是如何表示的。

Label Encoding for Relationship
现在让我们看看**Relationship**特性是如何影响模型预测的。

PDP for the Relationship feature
有趣的是,已婚人士(夫妻)比其他人更有可能赚更多的钱!
双向 PDP 显示特征“年龄”和“教育程度”之间的相互作用,以及它们对超过 50K 美元收入的影响
我们在这里对所有数据样本进行了更深入的模型解释,试图在双向部分依赖图的帮助下,看到**Age**和**Education-Num**之间的相互作用,以及它们对模型预测此人是否会赚更多钱的概率的影响。

Two-way PDP showing effects of the Age and Education-Num features
有趣的是,教育水平越高,中年人(30-50 岁)赚更多钱的机会越大!
双向 PDP 显示了“教育-数字”和“资本收益”功能之间的相互作用,以及它们对获得超过 50K 美元收入的影响
我们在这里对所有数据样本进行了更深入的模型解释,试图在双向部分依赖图的帮助下,看到**Education-Num**和**Capital Gain**之间的相互作用,以及它们对模型预测此人是否会赚更多钱的概率的影响。

Two-way PDP showing effects of the Education-Num and Capital Gain features
基本上,更好的教育和更多的资本收益会让你赚更多的钱!
滑冰者的地方诠释
有可能通过两种方式实现本地解释。首先,可以使用简单的可解释辅助或替代模型(如线性回归器)在单个输入附近近似复杂预测模型的行为。第二,可以使用基本估计量来理解单个预测的行为,使用基于输入和输出的直观近似函数。
局部可解释的模型不可知解释(LIME)
LIME 是由 Riberio Marco、Singh Sameer 和 Guestrin Carlos 设计的一种新算法,用于使用可解释的替代模型(如线性分类器/回归器)来评估任何基础估计量(模型)的行为。这种形式的综合评估有助于产生局部忠实的解释,但可能不符合全局行为。基本上,石灰解释是基于本地代理模型。这些替代模型是可解释的模型(如线性模型或决策树),是根据原始黑盒模型的预测学习的。但是,LIME 没有试图拟合一个全球代理模型,而是专注于拟合局部代理模型,以解释为什么会做出单一预测。
这个想法非常直观。首先,试着忘掉你已经做过的事情!忘记训练数据,忘记你的模型是如何工作的!认为你的模型是一个黑盒模型,里面有一些神奇的事情发生,你可以输入数据点,并得到模型预测的结果。你可以随时探测这个神奇的黑箱,得到输入和输出预测。
现在,你的主要目标是理解为什么你作为一个神奇的黑盒子对待的机器学习模型,给出了它产生的结果。LIME 试着为你做这件事!它测试当你把数据集的变化或扰动输入黑盒模型时,黑盒模型的预测会发生什么。通常,LIME 会生成一个由扰动样本和相关黑盒模型预测组成的新数据集。在这个数据集上,LIME 然后训练可解释的模型,该模型通过采样实例与感兴趣实例的接近度来加权。以下是标准的高级工作流程。
- 选择您感兴趣的实例,您希望对其黑盒模型的预测进行解释。
- 扰动数据集,获得这些新点的黑盒预测。
- 根据与感兴趣的实例的接近程度对新样本进行加权。
- 将加权的、可解释的(替代)模型拟合到有变化的数据集上。
- 通过解释本地模型来解释预测。
我们推荐你阅读 Christoph Molnar 关于模型解释的优秀著作中的第章,其中详细讨论了这一点。
用石灰解释溜冰者的模型预测
溜冰者可以利用石灰来解释模型预测。通常,它的**LimeTabularExplainer**类有助于解释对表格(即矩阵)数据的预测。对于数值特征,它会根据训练数据中的平均值和标准差,通过从正态(0,1)采样并执行平均值居中和缩放的逆操作来扰动它们。对于分类特征,它通过根据训练分布进行采样来进行扰动,并在值与被解释的实例相同时生成为 1 的二元特征。**explain_instance()**函数为预测生成解释。首先,我们通过随机扰动实例中的特征来生成邻域数据。然后,我们学习这个邻域数据上的局部加权线性(代理)模型,以可解释的方式解释每个类。
由于 XGBoost 在使用数据帧构建模型时在特性名称排序方面有一些问题,我们将使用**numpy**数组构建相同的模型,以使 LIME 工作起来,而没有特性重新排序的额外麻烦。请记住,正在建立的模型与我们视为黑盒机器学习模型的集合模型是相同的。
***XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1,
colsample_bytree=1, gamma=0, learning_rate=0.1,
max_delta_step=0, max_depth=5, min_child_weight=1,
missing=None, n_estimators=500, n_jobs=1,
nthread=None, objective='binary:logistic',
random_state=42, reg_alpha=0, reg_lambda=1,
scale_pos_weight=1, seed=None, silent=True,
subsample=1)***
预测一个人的收入<= $50K
Skater gives a nice reasoning below showing which features were the most influential in the model taking the correct decision of predicting the person’s income as 何时低于 5 万美元。

Local interpretations with LIME in Skater
预测一个人的收入何时超过 5 万美元
Skater 在下面给出了一个很好的推理,显示了在模型中哪些特征是最有影响力的,并做出了正确的决定,预测此人的收入为 超过 5 万美元。

Local interpretations with LIME in Skater
使用 Skater 通过树代理获得更多可解释模型的途径
我们已经看到了用特征、依赖图甚至时间来解释机器学习模型的各种方法。但是,我们能从一个真正复杂的黑盒模型中建立一个更容易解释的近似模型或代理模型吗?比如我们的 XGBoost 模型,它有数百个决策树。
在这里,我们介绍了使用**TreeSurrogates**作为解释模型的学习决策策略(用于归纳学习任务)的手段的新想法,这是受 Mark W. Craven 的工作(称为特雷潘算法)的启发。
我们推荐查看以下关于 TREPAN 算法构建代理树的优秀论文。
简而言之,Trepan 以最佳优先的方式构建决策树。它维护一个树叶队列,当从队列中移除树叶时,树叶被扩展成子树。对于队列中的每个节点,Trepan 存储,
- 训练示例的子集,
- 另一组实例(查询实例),
- 一组约束。
存储的训练样本子集仅由到达该节点的那些样本组成。如果节点是内部节点,则使用查询实例和训练示例来选择分裂测试,如果节点是叶节点,则确定类标签。约束集描述了实例为了到达节点而必须满足的条件;在为新创建的节点绘制一组查询实例时,会用到这些信息。Trepan 中扩展节点的过程与传统的决策树算法非常相似:为节点选择一个分裂测试,并为测试的每个结果创建一个子节点。每个孩子要么成为树的一片叶子,要么被放入队列中等待将来的扩展。
对于 Skater 的实现,为了构建可解释的代理模型,基本估计器(Oracle)可以是任何形式的监督学习预测模型——我们的黑盒模型。通过学习类似于 Oracle 所学习的决策边界(来自基础模型的预测用于学习决策树表示),使用决策树(用于分类/回归)来近似解释。该实现还生成保真度分数,以量化基于树的代理模型对 Oracle 的近似。理想情况下,全球和局部的真实解释得分应为 0。让我们来看看实际情况吧!
注:该实现目前处于试验阶段,将来可能会有所改变。
使用解释器实例调用 TreeSurrogate
我们可以使用前面实例化的解释对象来调用 TreeSurrogate 功能。
使用代理模型来学习由基本估计器学习的决策边界
现在,我们可以在数据集上拟合这个代理模型,以了解我们的基本估计量的决策边界。
- 报告与基本估计值相比的保真度值(越接近 0 越好)
- 学员使用 F1 分数作为分类的默认选择指标。
***0.009***
查看每个特征的位置
我们这样做是因为代理树中的特征名称不显示(但存在于模型中)

可视化代理树
我们现在可以使用下面的代码来可视化我们的代理树模型。

Our surrogate tree model
来自代理树的有趣规则
从上面的树中你可以观察到一些有趣的规则。
- 如果
**Relationship**< 0.5(表示 0)**Education-num**<= 9.5 并且**Capital Gain**<= 4225→***70%的机会使人< = $50K*** - 如果
**Relationship**< 0.5(表示 0)**Education-num**<= 9.5 并且**Capital Gain**>= 4225→***94.5%的几率中人>【50K】*** - 如果
**Relationship**< 0.5(表示 0)**Education-num**>= 9.5 并且**Education-num**也是>= 12.5→***94.7%的几率人做成> $50K***
请随意从中导出更多有趣的规则以及您自己的模型!现在让我们看看代理模型在测试数据集上的表现。
代理模型性能评估
现在让我们根据测试数据来检查代理模型的性能。

正如预期的那样,该模型的性能下降了不少,但我们仍然获得了总的 F1 分83%,相比之下,我们的提升模型的分数 87% 相当不错!
SHAP 的模型解释
SHAP(SHapley Additive exPlanations)是解释任何机器学习模型输出的统一方法。SHAP 将博弈论与局部解释相结合,结合了以前的几种方法,并基于他们所声称的,代表了唯一可能一致且局部精确的附加特征归因方法!(请务必检查 SHAP 夹纸了解详情)。我们在本系列的第二部分 中也详细介绍了这一点。
装置
SHAP 可以从 PyPI 安装
***pip install shap***
或者康达锻造
***conda install -c conda-forge shap***
这个框架真正令人敬畏的方面是,虽然 SHAP 值可以解释任何机器学习模型的输出,但对于真正复杂的集成模型来说,它可能会很慢。但是他们开发了一种用于树集成方法的高速精确算法(树 SHAP arXiv 论文)。快速 C++实现支持 XGBoost 、 LightGBM 、 CatBoost 和 scikit-learn 树模型!
SHAP (SHapley 附加解释)为每个特征分配一个特定预测的重要性值。其新颖的组成部分包括:识别一类新的加性特征重要性度量,理论结果表明在这一类中有一个唯一的解决方案,具有一组理想的性质。通常,SHAP 值试图将模型(函数)的输出解释为引入条件期望的每个特征的效果的总和。重要的是,对于非线性函数,引入特征的顺序很重要。SHAP 值由所有可能的排序的平均值产生。博弈论的证据表明这是唯一可能的一致方法。
理解 Shapley 值的直观方式如下:特征值以随机顺序进入一个房间。房间里的所有特征值都参与了游戏。沙普利值 ϕᵢⱼ 是特征值 xᵢⱼ 通过加入之前已经进入房间的任何特征的平均边际贡献,即

下面的图来自 KDD 18 号论文, 一致个性化特征归属为树系综 很好地概括了这一点!

现在让我们深入 SHAP,并利用它来解释我们的模型!
用 SHAP 解释预测
这里我们使用集成到 XGBoost 中的树 SHAP 实现来解释测试数据集!请记住,基于您正在构建的模型类型,有多种解释器方法。我们估计一组样本(测试数据)的 SHAP 值
***Expected Value: -1.3625857***

这将返回 SHAP 值的矩阵(**# samples**,**# features**)。每一行加起来就是该样本的模型输出和模型输出的期望值之间的差值(该值存储为解释器的**expected_value**属性)。通常,这种差异有助于我们解释为什么模型倾向于预测特定的班级结果。
预测一个人的收入何时< = 5 万美元
SHAP 在下面给出了一个很好的推理,显示了哪些特征在模型中最有影响力,正确的决定是预测个人的收入为 低于 5 万美元 。以下说明显示了将模型输出从基础值(我们传递的训练数据集的平均模型输出)推至实际模型输出的各种功能。将预测值推高的要素显示为红色,将预测值推低的要素显示为蓝色。

预测一个人的收入何时超过 5 万美元
同样,SHAP 在下面给出了一个很好的推理,显示了在模型中哪些特征是最有影响力的,正确的决定是预测这个人的收入 大于 50K 。

可视化和解释多重预测
SHAP 的一个关键优势是它可以构建美丽的互动情节,可以同时可视化和解释多种预测。在这里,我们将前 1000 个测试数据样本的模型预测决策可视化。

上述可视化可以以多种方式进行交互。默认的可视化显示了一些有趣的模型预测模式决策。
- 前 100 个测试样本都可能收入超过 5 万美元并且他们已婚或\有良好的资本收益或\并且有更高的教育水平!
- 接下来的 170 多个测试样本可能都收入少于或等于 5 万美元而且他们大多未婚和\或年龄很小或离婚!
- 接下来的 310 多个测试样本大多倾向于收入超过 5 万美元的人,他们有不同的背景,包括已婚人士、不同年龄、教育水平和职业的人。推动模型预测更高收入的最主要特征是结婚的人,即关系:丈夫还是妻子!
- 剩余的 400 多个测试样本大多倾向于收入少于 5 万美元,他们的情况各不相同,但主要模式包括关系:未婚或离婚和年龄非常小!
非常有趣的是,我们如何找出导致模型做出特定决策的模式,并能够为这些决策提供解释。
SHAP 的重要特征
这基本上是取整个数据集的 SHAP 值的平均值,并将其绘制成一个简单的条形图。

SHAP feature importance plot
SHAP 汇总图
除了典型的要素重要性条形图,SHAP 还使我们能够使用每个要素的 SHAP 值的密度散点图来确定每个要素对验证数据集中个体的模型输出的影响程度。要素按所有样本的 SHAP 量值总和排序。请注意,当散点不在一条线上时,它们会堆积起来以显示密度,每个点的颜色代表该个体的特征值。

SHAP summary plot
有趣的是, 年龄 和 婚姻状况 特征比 资本收益 特征具有更大的总模型影响,但是对于那些 资本收益 重要的样本,它具有比 年龄 或 婚姻状况 更大的影响。换句话说, 资本收益 对少数预测影响较大,而 年龄 或 婚姻状况 对所有预测影响较小。
SHAP 依赖图
SHAP 相关图显示了单个(或两个)要素对整个数据集的影响。他们绘制了许多样本中某个特性的值与该特性的 SHAP 值。SHAP 相关图类似于部分相关图,但是考虑了特征中存在的交互作用,并且仅在由数据支持的输入空间的区域中定义。单个特征值处 SHAP 值的垂直离差由交互作用影响决定,可以选择另一个要素进行着色,以突出显示可能的交互作用。
你也会注意到它和溜冰者的部分依赖情节的相似性!
影响模型预测的“年龄”的 PDP
让我们看看**Age**特性是如何影响模型预测的。

PDP for the Age feature
就像我们之前观察到的一样。中年人的 shap 值略高,这推动了模型的预测决策,即与年轻人或老年人相比,这些人赚的钱更多
“教育人数”影响模型预测的 PDP
让我们看看**Education-Num**特性是如何影响模型预测的。

PDP for the Education-Num feature
教育程度越高,shap 值越高,推动模型的预测决策说,与教育程度较低的人相比,这些人赚的钱更多。
影响模型预测的“关系”的 PDP
让我们看看**Relationship**特性是如何影响模型预测的。

PDP for the Relationship feature
正如我们在模型预测解释中观察到的,已婚人士(丈夫或妻子)的 shap 值略高,推动模型的预测决策,认为这些人比其他人赚得更多!
影响模型预测的“资本收益”的 PDP
让我们看看**Capital Gain**特性是如何影响模型预测的。

PDP for the Capital Gain feature
双向 PDP 显示了特征“年龄”和“资本收益”之间的相互作用,以及它们对获得超过 50K 美元收入的影响
单个特征值处 SHAP 值的垂直离差由交互作用影响决定,选择另一个特征进行着色以突出可能的交互作用。在这里,我们试图看到Age和Capital Gain之间的相互作用,以及它们对 SHAP 值的影响,这导致模型在双向部分依赖图的帮助下预测这个人是否会赚更多的钱。

Two-way PDP showing effects of the Age and Capital Gain features
有趣的是,资本收益越高,中年人(30-50 岁)赚更多钱的机会越大!
双向 PDP 显示了“教育-数量”和“关系”特征之间的相互作用,以及它们对创造超过 50K 美元收入的影响
在这里,我们试图看到**Education-Num**和**Relationship**之间的相互作用,以及它们对 SHAP 值的影响,这导致模型在双向部分依赖图的帮助下预测这个人是否会赚更多的钱。

Two-way PDP showing effects of the Education-Num and Relationship features
这很有趣,因为在某些情况下两者的特征是相似的,我们可以看到典型的已婚人士,无论是丈夫还是妻子,都有最高的机会赚更多的钱!
双向 PDP 显示了特征“婚姻状况”和“关系”之间的相互作用,以及它们对获得超过 5 万美元收入的影响
在这里,我们试图看到**Marital Status**和**Relationship**之间的相互作用,以及它们对 SHAP 值的影响,这导致模型在双向部分依赖图的帮助下预测这个人是否会赚更多的钱。

Two-way PDP showing effects of the Marital Status and Relationship features
有趣的是,受教育程度越高,丈夫或妻子(已婚)挣更多钱的机会越大!
双向 PDP 显示特征“年龄”和“每周小时数”之间的相互作用,以及它们对创造超过 50K 美元收入的影响
在这里,我们试图看到**Age**和**Hours per week**之间的相互作用,以及它们对 SHAP 值的影响,这导致模型在双向部分依赖图的帮助下预测这个人是否会赚更多的钱。

Two-way PDP showing effects of the Age and Hours per week features
这里没什么特别的,工作最多的中年人赚的钱最多!
结论
如果你正在阅读这篇文章,我真的想称赞你在阅读这本关于机器学习模型解释的庞大而全面的教程上所做的努力。这篇文章应该帮助你利用最先进的工具和技术,这将有助于你在通往可解释的人工智能(XAI)的道路上。基于我们在 第二部分 中学到的概念和技术,在本文中,我们实际上在一个在真实世界数据集上训练的复杂机器学习集成模型上实现了它们。我鼓励您用自己的模型和数据集来尝试这些框架,探索模型解释的世界!
下一步是什么?
在本系列的第 4 部分中,我们将会看到一个在非结构化数据(如文本,甚至深度学习模型)上构建解释模型的综合指南!
- 非结构化数据集上的动手模型解释
- 深度学习模型的高级模型解释
敬请关注一些有趣的内容!
注意:随着时间的推移,这一领域出现了许多快速发展,包括许多新工具和框架的发布。如果您希望我介绍任何其他流行的框架,请随时联系我。我对此非常感兴趣,并将在未来的某个时候开始研究 H2O 的模型解释能力。
本文使用的代码可以在 my GitHub 上获得,也可以作为交互式 Jupyter 笔记本 。
请查看 “第一部分——人类可解释机器学习的重要性” ,其中涵盖了人类可解释机器学习的内容和原因,以及模型解释的必要性和重要性及其范围和标准(如果您还没有了解的话)!
还有 第 2 部分——模型解释策略’,它涵盖了人类可解释的机器学习的方式,我们在其中看到了与模型解释的主要策略相关的基本概念。**
有反馈给我吗?或者有兴趣与我一起从事研究、数据科学、人工智能甚至发表一篇关于TDS的文章?可以在LinkedIn上联系我。****
** [## 人工智能顾问&数据科学导师-跳板| LinkedIn
查看 Dipanjan Sarkar 在世界最大的职业社区 LinkedIn 上的个人资料。Dipanjan 有 2 份工作列在…
www.linkedin.com](https://www.linkedin.com/in/dipanzan)**
解释:一个基于风格的 GANs 生成器架构——生成和调整真实的人造脸
NVIDIA 针对生成式对抗网络的新型架构
生成对抗网络(GAN)是机器学习中一个相对较新的概念,于 2014 年首次引入。他们的目标是合成人工样本,如图像,这些样本与真实图像无法区分。GAN 应用程序的一个常见示例是通过从名人人脸数据集学习来生成人工人脸图像。随着时间的推移,GAN 图像变得越来越逼真,但其主要挑战之一是控制其输出,即改变面部图像中的特定特征,如姿势、脸型和发型。
NVIDIA 的一篇新论文,一个为 GANs ( StyleGAN )设计的基于风格的生成器架构,提出了一个解决这个挑战的新模型。StyleGAN 逐渐生成人工图像,从非常低的分辨率开始,一直到高分辨率(1024×1024)。通过单独修改每个级别的输入,它控制在该级别中表达的视觉特征,从粗略特征(姿势、脸型)到精细细节(头发颜色),而不影响其他级别。
这种技术不仅可以更好地理解生成的输出,还可以产生最先进的结果——比以前生成的图像看起来更真实的高分辨率图像。

Source: StyleGAN
背景
每个 GAN 的基本组件是两个神经网络——一个从头合成新样本的生成器,一个从训练数据和生成器输出中提取样本并预测它们是“真”还是“假”的鉴别器。
发电机输入是随机向量(噪声),因此其初始输出也是噪声。随着时间的推移,当它收到来自鉴别器的反馈时,它学会了合成更“真实”的图像。通过将生成的样本与真实样本进行比较,鉴别器也会随着时间的推移而改进,使生成器更难欺骗它。

GANs overview
直到 2018 年,研究人员一直难以生成高质量的大图像(如 1024×1024),当时英伟达首次用 ProGAN 解决了这一挑战。ProGAN 的关键创新是渐进式训练——它从用非常低分辨率的图像(例如 4×4)训练生成器和鉴别器开始,每次都添加更高分辨率的层。
这种技术首先通过学习甚至在低分辨率图像中出现的基本特征来创建图像的基础,并且随着时间的推移随着分辨率的增加学习越来越多的细节。训练低分辨率图像不仅更容易和更快,它也有助于训练更高的水平,因此,总的训练也更快。

ProGAN overview
ProGAN 可以生成高质量的图像,但与大多数模型一样,它控制所生成图像的特定功能的能力非常有限。换句话说,这些特征是纠缠在一起的,因此试图调整输入,即使是一点点,通常也会同时影响多个特征。一个很好的类比是基因,改变一个基因可能会影响多个特征。

ProGAN progressive training from low to high res layers. Source: (Sarah Wolf’s great blog post on ProGAN).
StyleGAN 的工作原理
StyleGAN 论文提供了 ProGAN 图像生成器的升级版本,重点是生成器网络。作者观察到,如果使用得当,ProGAN 渐进层的潜在好处是它们能够控制图像的不同视觉特征。图层(和分辨率)越低,其影响的要素就越粗糙。本文将这些特征分为三种类型:
- 高达 82 的粗分辨率-影响姿势、一般发型、脸型等
- 162 到 322 的中等分辨率-影响更精细的面部特征、发型、眼睛睁开/闭上等。
- 642 到 10242 的精细分辨率-影响配色方案(眼睛、头发和皮肤)和微观特征。
新的发电机包括对 ProGAN 发电机的几个补充:
映射网络
映射网络的目标是将输入向量编码成中间向量,中间向量的不同元素控制不同的视觉特征。这是一个重要的过程,因为用输入向量控制视觉特征的能力是有限的,因为它必须遵循训练数据的概率密度。例如,如果黑头发的人的图像在数据集中更常见,则更多的输入值将被映射到该要素。因此,该模型无法将部分输入(向量中的元素)映射到特征,这种现象称为特征纠缠。然而,通过使用另一个神经网络,该模型可以生成不必遵循训练数据分布的向量,并且可以降低特征之间的相关性。映射网络由 8 个完全连接的层组成,其输出ⱳ与输入层的大小相同(512×1)。

The generator with the Mapping Network (in addition to the ProGAN synthesis network)
样式模块(AdaIN)
AdaIN (自适应实例标准化)模块将映射网络创建的编码信息ⱳ转换为生成的图像。该模块被添加到合成网络的每个分辨率级别,并定义该级别中的特征的视觉表达:
- 卷积层输出的每个通道首先被归一化,以确保步骤 3 的缩放和移动具有预期的效果。
- 使用另一个全连接层(标记为 a)将中间矢量ⱳ变换为每个通道的比例和偏差。
- 比例和偏移向量移动卷积输出的每个通道,从而定义卷积中每个滤波器的重要性。这种调谐将来自ⱳ的信息翻译成视觉表示。

The generator’s Adaptive Instance Normalization (AdaIN)
移除传统输入
大多数模型以及其中的 ProGAN 使用随机输入来创建发生器的初始图像(即 4×4 级别的输入)。StyleGAN 团队发现,图像特征是由ⱳ和阿丹控制的,因此初始输入可以被省略,并用常数值代替。虽然这篇论文没有解释为什么它提高了性能,但一个安全的假设是它减少了特征纠缠——网络只使用ⱳ学习更容易,而不依赖于纠缠的输入向量。

The Synthesis Network input is replaced with a constant input
随机变化
在人的面部中有许多方面是小的并且可以被看作是随机的,例如雀斑、头发的精确位置、皱纹,这些特征使得图像更加真实并且增加了输出的多样性。将这些小特征插入 GAN 图像的常用方法是向输入向量添加随机噪声。然而,在许多情况下,由于上面描述的特征纠缠现象,很难控制噪声效果,这会导致图像的其他特征受到影响。
StyleGAN 中的噪声添加方式与 AdaIN 机制类似,即在 AdaIN 模块之前的每个通道中添加一个缩放后的噪声,并稍微改变它所操作的分辨率级别特性的视觉表达。

Adding scaled noise to each resolution level of the synthesis network
风格混合
StyleGAN 发生器在合成网络的每个级别中使用中间向量,这可能会使网络了解到级别是相关的。为了降低相关性,该模型随机选择两个输入向量,并为它们生成中间向量ⱳ。然后,它用第一个级别训练一些级别,并(在随机点)切换到另一个级别来训练其余的级别。随机开关确保网络不会学习和依赖级别之间的相关性。
虽然它没有提高所有数据集的模型性能,但这个概念有一个非常有趣的副作用-它能够以连贯的方式组合多个图像(如下面的视频所示)。该模型生成两幅图像 A 和 B,然后通过从 A 获取低级特征并从 B 获取其余特征来组合它们。
W 中的截断技巧
生成模型的挑战之一是处理训练数据中表现不佳的区域。生成器无法学习它们,也无法创建类似的图像(反而会创建难看的图像)。为了避免生成差的图像,StyleGAN 截断中间向量ⱳ,迫使它接近“平均”中间向量。
在训练模型之后,通过选择许多随机输入来产生“平均”ⱳavg;用映射网络生成它们的中间向量;并计算这些向量的平均值。在生成新图像时,不直接使用映射网络输出,而是将ⱳ转换为ⱳ_new=ⱳ_avg+𝞧(ⱳ -ⱳ_avg),其中𝞧的值定义了图像与“平均”图像的距离(以及输出的多样性)。有趣的是,在仿射变换块之前,通过对每个级别使用不同的𝞧,该模型可以控制每组特征与平均值的距离,如下面的视频所示。
Tweaking the generated image by changing the value of 𝞧 in different levels
微调
StyleGAN 在 ProGAN 基础上的其他改进是更新几个网络超参数,如训练持续时间和损失函数,并替换从最近邻到双线性采样的向上/向下缩放。虽然这一步对模型性能很重要,但它没有什么创新性,因此这里不做详细描述(本文的附录 C)。

An overview of StyleGAN
结果
该论文展示了两个数据集的最新成果——由名人图像组成的 CelebA-HQ,以及由“普通”人图像组成的更加多样化的新数据集 Flickr-Faces-HQ (FFHQ)。下图显示了模型不同配置的 Frèchet 初始距离( FID )得分。

The performance (FID score) of the model in different configurations compared to ProGAN. The lower score the better the model (Source: StyleGAN)
除了这些结果之外,该论文通过在卧室图像和汽车图像的其他两个数据集上展示其结果,表明该模型不仅仅适用于人脸。
特征解开
为了使关于特征分离的讨论更加量化,本文提出了两种新颖的方法来测量特征解缠:
- 感知路径长度—在两个随机输入之间进行插值时,测量连续图像(其 VGG16 嵌入)之间的差异。剧烈的变化意味着多个特征一起改变,并且它们可能纠缠在一起。
- 线性可分性-将输入分类为二元类的能力,例如男性和女性。分类越好,特征的可分性越强。
通过比较输入向量 z 和中间向量ⱳ的这些度量,作者表明ⱳ的特征明显更加可分。这些指标还显示了与 1 或 2 层相比,在映射网络中选择 8 层的优势。
实施细节
StyleGAN 使用 8 Tesla V100 GPUs 在 CelebA-HQ 和 FFHQ 数据集上训练了一周。它在 TensorFlow 中实现,并将是开源的。
结论
StyleGAN 是一种突破性的论文,不仅可以生成高质量和逼真的图像,还可以对生成的图像进行高级控制和理解,使生成可信的假图像变得比以前更加容易。StyleGAN 中介绍的技术,尤其是映射网络和自适应标准化(AdaIN),将可能成为 GANs 中许多未来创新的基础。
要了解最新的深度学习研究,请订阅我在 LyrnAI 上的简讯
解释:RL 中的好奇心驱动学习
随机网络蒸馏探索
近年来,强化学习已经被证明是一种强大的技术,可以解决有持续回报的封闭任务,最常见的是游戏。该领域的一个主要挑战仍然是在行动的外部反馈(奖励)稀少或不存在的情况下训练模型。最近的模型试图通过创建一种内在的奖励机制来克服这一挑战,这种机制主要被称为好奇心,奖励发现新领土和州的模型。
OpenAI 的一篇新的论文通过随机网络蒸馏探索(RND)提出了一种内在奖励的新方法。该模型试图预测一个给定的状态以前是否被见过,并对不熟悉的状态给予更大的奖励。
该模型显示了几个雅达利游戏的最先进的结果,包括蒙特祖马的复仇,这是众所周知的 RL 算法很难。它也相对简单,并且已经证明在包括分散注意力的背景噪声的环境中是有效的。
背景
强化学习(RL)是一组以奖励为导向的算法,这意味着它们通过最大化从环境中获得的奖励来学习如何在不同状态下采取行动。对他们来说,一个具有挑战性的测试平台是 30 多年前开发的 Atari 游戏,因为它们提供了丰富的视觉输入(每帧 210X160X3)和一系列对人类来说很难的任务。
这些游戏在复杂性和外部奖励的频率上有所不同。在《越狱》中,每次击中砖块都会有奖励,而在《蒙特祖马的复仇》和《其他》中,一个关卡只有少量奖励。例如,蒙特祖马的复仇是众所周知的挑战,因为它需要长时间(数百步)和复杂的动作组合来通过致命的障碍并找到奖励。下面的动画说明了游戏之间的区别。

Breakout — The agent receives external rewards frequently, one for each brick

Montezuma’s Revenge — The only external reward is received when picking up the key
为了在没有频繁外部奖励的游戏中取得成功,代理人必须探索环境,希望发现稀疏的奖励。这些场景在现实生活中很常见,从在房子里找到丢失的钥匙到发现新的癌症药物。在这种情况下,代理人被要求使用内在奖励,同时主要独立于外在奖励。有两种常见的带内在奖励的 RL 方法:
- 基于计数的方法,对以前访问过的州进行计数,并对新的州给予更大的奖励。这种方法的缺点是,随着可能状态数量的增加,它往往变得不那么有效。
- 另一种方法是“下一状态预测”,在这种方法中,模型试图预测下一状态,采取行动转移到下一状态,然后将与预测状态相比的误差降至最低。通过探索,更多的状态变得已知,误差下降。
这些方法比只基于外在奖励的模型(如著名的 DQN 和 A3C 模型)表现得更好,但仍然比普通人差。
一般来说,当使用内在奖励时,对未来状态的评估有三个可能的错误来源:
- 不熟悉的状态错误-模型无法从以前访问过的状态归纳到新的状态,导致未来状态预测中的高错误。通过反复发现新的状态并从中学习,模型逐渐减少了这种错误。
- 随机噪声——这也称为电视噪声问题,其中环境的一部分会产生随机噪声(就像房间里有一台呈现白噪声的电视)。这导致许多状态对于代理来说是新的,下一个状态通常是不可预测的,并且与代理的动作无关。
- 模型约束—模型的架构是有限的,不能足够准确地概括环境以预测下一个状态。例如,预测下一个状态所需的神经网络的层数和大小是未知的。
RND 是如何工作的?
具有内在奖励的 RL 系统使用不熟悉状态误差(误差#1)进行探索,并且旨在消除随机噪声(误差#2)和模型约束(误差#3)的影响。为此,该模型需要 3 个神经网络:一个为给定状态生成恒定输出的固定目标网络,,一个试图预测目标网络输出的预测网络,以及一个决定代理下一步行动的策略网络。
目标和预测网络
通过计算两个网络输出之间的差异,目标和预测网络被用来为不熟悉的状态产生更大的内在奖励。网络具有相同的大小和架构——卷积编码器(CNN ),后面是全连接层,用于将状态嵌入特征向量 f 。然而,它们之间有一个重要的区别:
- 目标网络是一个具有固定随机权重的神经网络,从未被训练过。因此,对于给定状态(输入),其输出是恒定的,但在不同状态之间是可变的:对于任何时间步长 I,fi(x)=fj(x ),对于任何两个不同的输入,fi(x)fi(y)。
- 预测网络被训练来预测目标网络的输出。每个状态被输入到两个网络中,预测网络被训练以最小化它们的输出(ri)之间的差异(MSE)。

The target and prediction networks
随着越来越多的状态被输入到系统中,当预测网络接收到已知状态时,它在预测目标网络输出方面变得更好。当到达以前访问过的州时,代理会收到一点奖励(因为目标输出是可预测的),并且代理没有动力再次到达这些州。换句话说,与普通模型不同,智能体不是试图根据当前状态和动作来预测下一个状态,而是试图预测未来状态的新颖性。
目标预测架构有几个好处:
- 在用随机噪声(来自固定的稳定分布)对状态进行足够的训练之后,预测网络能够更好地预测目标网络的输出。随着预测误差的减小,智能体对噪声状态的吸引力会比其他未探测的状态小。这减少了电视噪音错误(#2)。
- 在下一步预测模型中,事先不知道需要哪种体系结构(层数、层大小等)来模拟动作的结果。然而,预测器网络只需要预测目标网络的结果。通过具有与目标网络相同的架构,它应该能够正确地学习熟悉状态的输出。这“解决”了模型约束错误(#3)。
- 它让代理人倾向于在游戏中存活,因为死亡迫使它回到熟悉的状态。其他“基于好奇心”的 RL 方法也有这种优势。
该模型的一个挑战是,随着更多的状态变得熟悉,内在奖励会减少,并且可能在不同的环境中变化,这使得选择超参数变得困难。为了克服这一点,内在奖励在每个更新周期中被标准化。
政策网络
策略网络的作用是根据当前状态及其内部模型决定下一步行动,该模型是根据以前的状态训练的。为了做出这个决定,它使用了一个输入嵌入器和一个策略优化器:
输入嵌入器
输入嵌入器将环境状态编码成特征。本文比较了两种体系结构——CNN 或 CNN 与循环层(GRU 细胞)的混合。重现层被认为有助于通过捕捉游戏的更长上下文来预测下一个动作,例如,在当前状态之前发生的事件,并且在大多数情况下确实被发现比只有 CNN 的层表现得更好。
PPO
训练策略模型的一个主要问题是收敛性,因为策略往往会因为奖励的一次更新而发生剧烈变化。例如,在一些架构中,一个糟糕的插曲(游戏)可以完全改变你的策略。因此,在嵌入层之上,网络有一个邻近策略优化器 ( PPO ),它根据嵌入状态预测下一个动作。PPO 的主要贡献是通过限制连续策略更新之间的差异,在没有激进更新的情况下安全地优化策略。
为了更新政策,PPO 首先需要估计给定状态的未来内在和外在报酬(“价值头”)。单独处理每种类型的奖励可以更灵活地确定每种类型对政策的影响以及每种类型的计算方式:
- 内在奖励是在固定的一批时间步长上计算的,例如 128 个时间步长,而不管代理是否已经在游戏中“死亡”。研究发现,这种独特的方法(非情节性的)能够实现更好的探索,因为它鼓励代理采取可能揭示新状态的冒险行动。如果内在奖励是偶发的,这些行为可能会结束游戏,从而结束奖励。
- 外在奖励会在整个剧集中计算,直到特工死亡。使用非偶发性奖励可能会导致代理“黑”游戏。比如通过寻找轻松快捷的奖励,然后自杀。
下图显示了策略网络和整个架构:

The policy network

The RND architecture
注意事项:
- 本文中的 PPO 是使用行动者-批评家模型(A3C)实现的。然而,它可以与任何优势功能一起使用。
- PPO 的另一个好处是,它允许多个时期的训练,每个时期都有小批量的输入,从而提高了训练效率。限制策略更新可以确保即使有多个时期,总的变化也不会太大。
结果
本文将 RND 模型与最先进的(SOTA)算法进行了比较,并将两个相似的模型作为消融试验:
- 没有内在探索奖励的标准 PPO。
- 基于前向动力学误差的内含报酬 PPO 模型。这种模型根据当前状态和动作预测下一个状态,并使预测误差最小化,这就是内在报酬。
这位 RND 特工在 6 场比赛中的 3 场比赛中取得了最先进的成绩,并在蒙特祖马的《复仇》中取得了比“普通人”更好的成绩。然而,与其他 SOTA 算法相比,它在另外两个游戏中的性能明显较低。这篇论文没有解释这种技术不太有用的游戏的本质。

Scores comparison of various RL algorithms (source: OpenAI’s blog)
结论
RND 模式体现了近年来在艰苦探索游戏中取得的进步。该模型的创新部分,即固定和目标网络,由于其简单性(实现和计算)及其与各种策略算法一起工作的能力,是有前途的。
另一方面,还有很长的路要走——没有一个模型可以统治所有人,不同游戏之间的表现也各不相同。此外,虽然 RNN 可能有助于保持更长的背景,但全球勘探仍然是一个挑战。需要长期关系的场景,例如使用在第一个房间找到的钥匙打开最后一扇门,仍然无法实现。
要了解最新的机器学习研究,请订阅我在 LyrnAI 上的简讯
解释:GPipe——使用流水线并行技术训练巨型神经网络
近年来,机器学习数据集和模型的规模一直在不断增加,允许在广泛的任务中改善结果。与此同时,硬件加速(GPU、TPU)也在改进,但速度明显较慢。模型增长和硬件改进之间的差距增加了并行性的重要性,即在多个硬件设备上训练单个机器学习模型。一些 ML 架构,尤其是小型模型,有助于并行性,可以在硬件设备之间轻松划分,但在大型模型中,同步成本会导致性能下降,从而妨碍它们的使用。
Google Brain 的一篇新论文 GPipe 提出了一种模型并行性的新技术,允许在多个硬件设备上训练大型模型,性能提高近 1:1(论文显示在 4x 硬件上有 3.5 倍的处理能力)。GPipe 库将是开源的,它自动分析 TensorFlow 神经网络模型的结构,并将训练数据和模型委托给多个硬件设备,同时应用独特的反向传播优化技术。
GPipe 帮助 ML 模型包含更多的参数,从而在训练中获得更好的结果。为了证明该技术的有效性,谷歌团队创建了一个更大版本的 AmoebaNet,即 2017 年 ImageNet 获奖者,以更大的图像(480×480)作为输入,并在 ImageNet,CIFAR-10,CIFAR-100 和其他计算机视觉指标上取得了最先进的(SOTA)结果。
背景
机器学习中的并行通常分为两类:
- 模型并行性-当在训练中使用模型并行性时,机器学习模型被划分到 K 个硬件设备上,每个设备持有模型的一部分。一种模拟并行性的简单方法是通过在每个设备上简单地托管 N/K 层(“级”)来将 N 层神经网络分成 K 个设备。更复杂的方法通过分析每一层的计算复杂度来确保每个设备处理相似的计算复杂度。标准模型并行性允许训练更大的神经网络,但是由于设备不断地相互等待,并且在给定时间只有一个设备可以执行计算,因此性能受到很大影响。
- 数据并行性-在数据并行性中,机器学习模型在 K 个硬件设备上复制,一个小批量的训练样本被分成 K 个微批量。每个设备执行微批次的向前和向后传递,并且当它完成该过程时,它与其他设备同步更新的模型权重,然后计算整个微批次的更新权重。在每次小批量计算结束时,K 个模型的重量都是同步的(相同值)。
虽然微批处理允许并行,但在使用模型并行时,每个阶段自然仍需要等待前一阶段的结果,从而导致闲置的“泡沫”,如随附的图像所示。在图中,F0,i-F3,I 是跨越四个阶段的单个微批处理的成员,而 Fi,0-Fi,3 是在单个阶段中执行的四个微批处理计算。

Model + Data Parallelism (GPipe: Huang et al. 2018)
尽管存在气泡问题,但数据并行可能是有效的,但它还会遇到一个额外的问题——通信开销。随着模型的增长和硬件变得更快,在设备之间同步整个模型的要求成为训练过程中的瓶颈,大大降低了训练速度。随附的图像举例说明了在大型神经网络中,通信开销如何占据了大部分训练时间。通信开销的现象鼓励创建非常大的小批量,但是这些对于训练网络来说通常是错误的选择,并且可能在生产中呈现较差的结果。

PipeDream: Fast and Efficient Pipeline Parallel DNN Training
GPipe 的工作原理
GPipe 同时使用模型和数据并行,这种组合通常被称为“流水线”。它为以前的流水线技术提供了两个关键贡献——自动并行和设备内存优化。
自动并行
该软件接收神经网络的结构、小批量和可用于计算的硬件设备的数量作为输入。然后,它会自动将网络层划分为阶段,将小批量划分为微批量,并将它们分布在各个设备上。为了将模型分成 K 个阶段,GPipe 在给定其激活函数和训练数据内容的情况下估计每一层的成本。虽然这篇论文没有详细说明如何在 GPipe 中实现这一点,但一个常见技术是通过神经网络运行数据样本,测量每一层的计算时间,并相应地进行划分。GPipe 接收每一层的可选成本估计函数作为输入,允许更复杂的技术来改进其内部机制。
设备内存优化
当在神经网络中计算反向传递时,需要网络的正向传递激活来执行计算。通常,这意味着对于神经网络中 N 层和 L 层大小的微批次,O(N×L)个激活在正向传递之后被保存在设备存储器中,为反向传递做准备。
GPipe 使用了一种不同的方法,应用了一种有趣的计算-内存权衡——它不是将 NxL 激活保存在内存中,而是只将 N 个激活保存在 stage 的最后一层(stage =层组)。在这种情况下,每次反向过程开始时(从最后一层开始),都会重新计算正向过程激活并保存在内存中。当单个样本的反向通过结束时,存储器中的激活被丢弃,并为下一个样本的反向通过重新计算。使用这种方法,设备内存一次只保存一组激活,以进行 O(N)次转发为代价获得了宝贵的内存。因为一般的硬件趋势是设备速度比设备内存增长得更快,所以这种权衡通常是有用的。
GPipe 应用
在论文中,研究人员将 AmoebaNet 从 1.553 亿个参数扩展到 5.57 亿个参数,并插入 480×480 ImageNet 图像作为输入,而不是标准 AmoebaNet 模型使用的降采样 331×331 图像。结果是 ImageNet 前 1 名的准确率(84.3%对 83.5%)和前 5 名的准确率(97.0%对 96.5%)有所提高,标志着一个新的最先进水平。
使用扩展的 AmoebaNet 模型进行迁移学习,研究人员在 CIFAR-10、CIFAR-100、牛津-IIIT Pets、Stanford Cars 和 Food-101 数据集上取得了最先进的(SOTA)结果。该模型在两个数据集(FGVC Aircraft 和 Birdsnap)中取得的结果不如最先进的结果,这可能是因为这些数据集中最先进的模型利用了除 ImageNet 数据之外来自 Google Image Search 的 980 万张预训练图像。

实施细节
GPipe 是用 TensorFlow 写的,会开源。该技术并不是 TensorFlow 独有的,也可以在其他平台上实现。
结论
作为一个开源库,GPipe 将允许机器学习从业者以相对较低的成本训练大得多的模型。可以肯定的是,结果将是新的大量大型机器学习模型,它们将获得优于现有模型的结果,以及与缩小图像相反的全尺寸图像数据的使用增加。
虽然对每个人都有用,但数据并行性的这一突破自然会为拥有大量计算和数据的大型组织提供特殊优势。
保持最新机器学习研究的更新,订阅我们的简讯在LyrnAI
特别感谢本文主要作者黄阳平对 GPipe 工作的宝贵见解。
向小学生解释人工智能
最近,我被邀请给五六年级的小学生(9-11 岁)讲计算机和人工智能。我花了很多时间向一系列不同的人解释 AI 和 ML,但从来没有向这么年轻的观众解释过!我在网上找不到太多的灵感,所以想出了自己的素材。这是我的课程计划大纲,每节课我都要花 30 分钟。
1。简介
我的日常工作包括语音识别,所以我先介绍自己,然后问全班有多少人曾经对着电脑或设备说话来完成某件事——通常我会让全班大多数人举手。
对于一些背景,我包括一点历史。小学生是在智能手机和语音计算的环境中长大的,他们通常不知道技术发展有多快。在撰写本文时,Y5 类诞生于 2008/2009 年。相比之下,iPhone 于 2008 年推出,Siri 于 2011 年在其上发布。
2。计算机编程
第一个讨论的话题是计算机如何通过编写规则(或程序)被编程去做事。用这种方法可以编写非常复杂和看似智能的计算机程序。到了 Y5、6 岁,这个学校的孩子已经上了用 scratch 编程的课。他们知道如何根据指令编写计算机程序,以及如何容易将这些指令弄错,从而使计算机无法按照您的意图运行。
3。识别猫咪的规则
人们喜欢在网上分享照片,他们分享了很多猫咪的照片!有一件事可能会让计算机变得人工智能,那就是能够判断一张照片是不是一只猫。我和全班一起头脑风暴,想出一些规则写在黑板上,我们可以用它们来识别照片中的猫。我们在之前的课程中提出了一些规则:
我们不能在计算机中直接实现这些规则,但它们能让人们理解这个想法。

接下来我们来看一组播放“猫不猫”的幻灯片。我的幻灯片有一系列图片——有些很容易识别是不是猫,有些是模糊不清或姿势滑稽的猫,还有一些是和猫有一些相同特征的其他动物。他们让孩子们思考如何定义这个任务(大猫算不算猫?),edge cases(一只猫的画法呢?)以及你真正需要的那种规则(你到底怎么区分小熊猫和猫?).
4。智能计算机
在这之后,我问孩子们是否认为我们的规则是好的还是坏的。大多数人承认,我们的规定并未涵盖所有图片,因此本可以更好。
有些任务,如视觉和听觉,是不可能写出计算机可以遵循的规则的。我们需要一种不同的方法。我们让计算机学习如何从数据中完成任务,而不是编写规则。为此,我们采集了大量数据(图像、音频、视频等)。)并让人们给它贴上标签。对于图像,人们可能会给每幅图像贴上什么物体被描绘的标签。从这个“标签数据”的数据库中,我们可以训练一台机器来学习构成猫的图片的模式。一旦计算机从这些训练数据中学习,我们就可以利用计算机建立的模型,用它来识别图片中从未见过的猫。
识别图片中的猫或其他物体可能看起来很无聊,但是有很多方法可以在现实世界中使用这项技术。很多人正在研究的一个例子是在自动驾驶汽车中识别出你面前的是什么。另一个是帮助拯救濒危野生动物,通过识别动物并在野外计数。
5 .讨论和问题
我最后讨论了这个班将来会制造什么样的智能机器人。如果我对他们的建议有所了解,我会谈谈那个地区已经在建的项目。
我听到的想法包括:
- 帮助盲人的计算机:例子包括微软的视觉人工智能或文本到语音技术,它可以大声朗读文本
- 太空旅行:我们已经将人类送上了月球,并将火星车送上了火星,但是人工智能可以帮助我们进行更进一步的探索,比如火星车导航或者识别太空中的物体,
- 照顾住院病人:计算机可以通过多种方式帮助医院从手术到诊断再到管理,从而节省医生和护士与病人相处的时间。
- 会烹饪的机器人:这种处理原料的机器人很难制造,但是有一些例子
- 做作业的电脑。我通常不会指出像阿列克谢这样的语音助理已经可以回答很多问题了
当我问班主任时,他们通常只想要一台智能电脑来帮助他们批改作业!
在讨论中,我还加入了其他几点讨论:
- 电脑并不总是对的。当计算机从数据中学习时,我们总是知道它们会犯一些错误。
- 有些事情是电脑做不到的,例如,判断某人是否在说谎。一般来说,如果一个人很难做到,那么机器也很难学习。
- 技术有好的一面,也有坏的一面。有时,班上的人会想出别人觉得令人毛骨悚然的想法,这有助于说明问题。
额外背景
对于那些有兴趣了解更多的人来说,图像识别有着悠久的历史,并且在最近几年得到了很好的研究。一个名为 ImageNet 的图像数据库已经成为许多物体识别学术研究的基础。该数据库有超过 20,000 个类别的数百万张图片。
2012 年,花了 16000 台电脑才学会如何识别一只猫。近年来,研究人员也在研究更困难的任务,如区分 5000 种动物、识别和跟踪视频中的物体或自动对照片中发生的事情进行深入描述。
原为 2018 年 12 月 17 日在http://mycomputerdoesntlisten.wordpress.com发表。
用通俗易懂的语言解释机器学习

在最近的演讲活动中,我遇到了一个两难的问题,即试图从概念上解释机器学习,而不牺牲对我试图推销的应用程序的关注,无论是创业风险还是研究项目。由于比赛时间的限制以及在进行推销时简洁的普遍需要,机器学习是一个特别棘手的短语,因为其过程背后的复杂性。
随着“机器学习”作为一个流行词获得关注,这种解释变得越来越重要。观众很少会假装知道机器学习算法将如何工作,但他们经常会期望一个普通人可以理解和理解的解释。这使得能够将机器学习作为一个概念和单个算法分解为可消化的部分变得至关重要。传递这些易于管理的信息的最简单的方式通常是通过相关的类比和轶事。
因此,让我们从一个最相关的轶事开始对机器学习的简单解释:数学课。数学教学的一般框架是给学生许多练习题和答案。是的,老师可能会事先教授这个概念,但是为了举例,我们假设这个概念没有被教授。每个练习题都对学生(机器学习算法)在答案(标签)旁边观察到的信息片段(有点像输入特征)进行编码。我们可以称这个学习过程为算法的训练。
在大量的练习题之后,我们假设的学生应该能够找到某种模式来解决问题。因此,我们对学生进行测试,给他们一份试题,并将生成的答案与实际答案进行比较(类似于对算法的测试)。评估学生的准确性给了我们一个衡量学生和给他们的练习题的有效性的方法。
我们也知道,每个学生往往有不同的学习风格。同样,每个机器学习算法都有不同的方式来尝试在输入数据中找到模式。这些不同的风格使得不同的学生在特定的科目上特别精通,就像一些 ML 算法对于特定的数据类型更加有用和健壮一样。
总结一下类比,机器学习算法就像数学学生,他们被给予大量的实践问题,并被指示通过找到这些问题中的信息及其相关答案之间的模式来找到解决这些问题的方法。能够找到最有效的数据(练习题)以反馈给最有效的算法(学习风格)是很重要的,因为这是产生最佳性能的地方。
显然,这种解释避免了算法开发和课堂教学的细微差别,但对于不熟悉这个概念的人来说,这是一种快速解释机器学习的便捷方式。为什么这很重要?能够清楚地解释一个非常复杂的主题(一个普通人可以识别为复杂的主题)可以让观众更容易相信你的可信度。事实证明,复杂概念的简化与大多数人的预期相反。这种简化并没有让机器学习策略看起来更强大,而是向观众传达了这样一种信息:你不仅仅是引擎盖下的一名工程师,你也是一个不仅仅能够理解代码的人。
可能存在更合适的类比来解释机器学习,这肯定是演讲者和演示者应该考虑的事情。你的听众的经历将永远是决定他们是否理解你的解释的主要因素,因此理解该场合的共同主题并根据听众的共性调整类比是至关重要的。总的来说,记住这些考虑因素,并不难做出解释,将概念及其应用传递给受众,帮助他们接受主题。无论是数学学生还是企业高管,机器学习都是一个值得分享的想法,只要它对所有参与者都有意义。
解释数据中的矛盾趋势

在我的工作中,我帮助普通人理解复杂的数据。偶尔有人会完全不知所措:他们会观察一段时间的变化,看到总值下降了。但是当他们仔细观察时,他们发现他们使用的每个类别都增加了。他们问,他们的数据有什么问题?
实际上没什么不对。
他们刚刚无意中发现了一个极其普遍的统计悖论;但它可能会一直令人困惑。以下是我如何试图解释正在发生的事情,这样他们就可以继续他们的生活(并向他们的老板汇报结果)。
从一个例子开始:

Median values in two different years, for two groups, and overall.
我们可以清楚地看到这个悖论:
- A 组下降
- B 组拒绝
- 总的来说,整个系统增加
这个例子很普通,这些数据可以在任何地方出现:公司的薪水,网络流量,病人对治疗的反应。你可能会问,我们怎么能同时看到这两种趋势呢?
这是怎么回事?
首先让我们看一下数据集(我已经把它保持得很小了):

The data, split by years, with groups shown by color.
这很容易地证实了柱状图中的汇总趋势:绿色组下降,红色组也下降。但是其他的事情也在发生。
各组的大小不同
在第 1 年,数据以红色数据为主(B 组),但这在第 2 年发生了变化,因此绿色数据更常见。中间数据点是红色的,然后变成绿色。我们可以看到绿色比红色高。这意味着整体中位数必须上移(这同样适用于平均值或其他集中趋势的衡量标准)。

悖论就这样解决了。两种变化同时发生:
- 个别测量的实际值增加。由于通货膨胀,工资上涨了。交通速度加快。病人会好起来。
- 我们没有仔细控制我们测量的内容,并且样品的成分发生了变化。
在一个理想的、科学严谨的世界里,我们不会让第二种情况发生。相反,我们会设计一个实验,在所有类别中有相同数量的受试者(“控制”这些差异)。但是在观察研究中,以及在混乱的现实世界中,我们经常做不到这一点。即使在科学领域,你也可以在事实发生后意识到,主题并不像你想象的那样相似。所以我们使用现有的数据——但是我们在解释这些数据时必须更加老练。
所以看似矛盾的模式实际上是两种变化同时出现:

群体平均水平确实下降了,全球平均水平确实上升了。“悖论”是我们天真的假设,即这些必须以同样的方式进行。
解决办法?
您可以通过在未来更多地控制您的组来避免这种情况,确保您每次都有相同的数量。
在报告您的结果时,您可能希望坚持总体平均值或组平均值,这取决于您试图从数据中了解什么。如果问题是,“这些病人治疗有效吗?”答案是肯定的,因为两组都有进步。如果问题是,“我所有的病人有多健康?”你要说“更差”是因为整体平均水平。
当向他人报告这些结果时,你可以试图隐藏一种效果,而强调另一种效果。但是你可能也需要变得更复杂一点——给出一个和这个很像的解释。
(这种效应有时被称为逆转悖论或辛普森悖论。)
下面的样本数据集:
year group value
1 A 7
1 A 8.5
1 A 10
1 A 11.5
1 A 13
1 B 32
1 B 34
2 A 5.5
2 A 7
2 A 8.5
2 B 27
2 B 28.5
2 B 29.5
2 B 33
解释强化学习:主动还是被动

这篇文章假设你熟悉强化学习(RL)和马尔可夫决策过程的基础知识,如果没有,请先参考这篇前一篇文章。
在这篇文章中,我们将探究,
- 解决一个 RL 问题需要哪些要素?
- 什么是被动和主动强化学习,我们如何比较这两者?
- 常见的主动和被动 RL 技术有哪些,适用的场景有哪些?
解决 RL 问题需要哪些要素?
让我们考虑一个问题,代理可以处于各种状态,并且可以从一组动作中选择一个动作。这类问题称为 序贯决策问题 。一个的数学框架就是捕捉这样一个完全可观测的、非确定性的环境,具有马尔科夫转移模型和加性报酬的主体在其中行动。MDP 的解是一个 最优策略 ,它指的是最大化总累积报酬的每个状态的行动选择。因此,代表代理环境的 转换模型 (当环境已知时)和决定代理在每个状态下需要执行什么动作的 最优策略 是训练代理学习特定行为的必需元素。****

Fig 1: Markov Decision Process (source: wikipedia)
什么是被动和主动强化学习,我们如何比较这两者?
主动强化学习和被动强化学习都是强化学习的类型。在被动 RL 的情况下,代理的策略是固定的,这意味着它被 告知做什么 。与此相反,在主动 RL 中,代理 需要决定做什么 ,因为没有固定的策略可供其操作。因此,被动 RL 代理的目标是执行固定的策略(动作序列)并对其进行评估,而主动 RL 代理的目标是采取行动并学习最优策略。
有哪些常见的主动和被动 RL 技术?
被动学习
由于代理的目标是评估最优策略有多好,代理需要学习每个状态 s 的期望效用 Uπ(s) 。这可以通过三种方式实现。
直接效用估算
在这个方法中,代理执行一个试验序列或运行(状态-动作转换序列,一直持续到代理到达终端状态)。每个试验给出一个样本值,代理根据样本值估计效用。可以计算为样本值的**移动平均值。主要缺点是这种方法错误地假设 状态效用是独立的 ,而实际上它们是 马尔科夫 。还有,收敛慢。****
假设我们有一个 4x3 的网格作为环境,代理可以在其中向左、向右、向上或向下移动(一组可用的操作)。跑步的例子

总奖励从 (1,1) = 0.72 开始
**2。自适应动态规划
ADP 是一种比直接效用估计更智能的方法,因为它通过将状态的效用估计为处于该状态的奖励和处于下一状态的预期折扣奖励之和来运行试验以学习环境模型。

其中 R(s) =处于状态的报酬 s , P(s'|s,π(s)) =过渡模型, γ =贴现因子, Uπ(s) =处于状态的效用 s' 。
可以使用值迭代算法来解决。该算法收敛很快,但是对于大的状态空间来说,计算可能变得相当昂贵。ADP 是一种基于模型的方法,需要环境的转换模型。无模型方法是时间差异学习。
Fig 2: AI playing Super Mario using Deep RL
**3。时间差分学习(TD)
TD 学习不要求代理学习过渡模型。更新发生在连续的状态之间,代理仅更新直接受影响的状态。

其中 α =学习率,它决定了向真实效用的收敛。
ADP 用所有后继状态来调整 s 的效用,而 TD learning 用单个后继状态 s’的效用来调整。TD 的收敛速度较慢,但在计算方面要简单得多。
主动学习
具有探测功能的 ADP
由于主动代理的目标是学习最优策略,代理需要学习每个状态的期望效用并更新其策略。可以使用被动 ADP 代理完成,然后使用值或策略迭代,它可以学习最佳操作。但是这种方法导致了一个贪婪的代理。 因此,我们使用一种方法,对未探索的动作给予较高的权重,对具有较低效用的动作给予较低的权重。

其中 f(u,n) 是随着期望值 u 增加并且随着尝试次数 n 减少的探索函数

R+ 是一个乐观的奖励,Ne 是我们希望代理在每个状态下被迫选择一个动作的次数。 探索功能将被动代理转化为主动代理。
②。问学**
Q-learning 是一种 TD 学习方法,它不需要代理学习过渡模型,而是学习 Q 值函数 Q(s,a) 。

q 值可以使用下面的等式来更新,

可以使用以下策略选择下一个操作,

同样,这比 ADP 计算简单,但速度较慢。

Table 1: Comparison of active and passive RL methods
我推荐以下资源来更深入地理解这些概念,
向孩子(或你的老板)解释监督学习
既然知道了机器学习是什么,那就来认识一下最简单的那种。我在这里的目标是让所有人和(几乎)所有年龄的人都熟悉它的基本术语:实例、标签、特征、模型、算法和监督学习。
例子
请看:四个实例!

实例也被称为“实例”或“数据点”或“观察值”
数据表
当我们把这些例子放到表格中时,它们看起来像什么?遵循惯例(因为礼貌是好的),每一行都是一个实例。

数据不好看吗?但是我们到底在看什么?让我们从两个特殊的列开始:一个惟一的 ID 和一个每个实例的标签,因为这次我们很幸运。
标签
标签是正确答案。当我们向计算机展示这样一张照片时,我们希望它能学会输出什么,这就是为什么有些人更喜欢用“目标”、“输出”或“反应”这样的术语。
特征
其他栏里有什么?像素颜色。不像你,电脑把图像看成数字,而不是漂亮的灯光。你看到的是像素的红-绿-蓝值,从图像的左上角开始向下。不相信我?尝试将我的数据表中的值输入到这个 RGB 色轮中,看看它会给出什么颜色。想知道如何从照片中获取像素值?回头看看我的代码这里。

你知道什么很酷吗?每次你看一张数码照片,你都在分析数据,理解以一串数字形式存储的东西。不管你是谁,你已经是一名数据分析师了。你这个摇滚明星,你!
你已经是数据分析师了!
这些像素值是计算机将要学习的输入。我不太喜欢机器学习的名称(“特征”),因为这个词意味着各种学科中的各种事物。你可能会看到人们用其他词来代替:“输入”、“变量”或“预测”。
模型和算法
我们的特征将形成模型的基础(这是食谱的一个花哨的词),计算机将使用它从像素颜色到标签。
模型只是“配方”的一个花哨的词
但是怎么做呢?这是机器学习算法的工作。你可以在我的另一篇文章中看到它是如何在幕后工作的,但现在,让我们使用一个现有的令人敬畏的算法:你的大脑!
监督学习

我希望你成为我的机器学习系统。再次浏览实例并做一些学习!这是什么?

Classify this image using what you’ve learned from the examples above.
"布洛克尔"吗?没错。你能行的!你刚才做的是监督学习,牛逼!你现在已经体验到了最简单的学习方式。如果你能把你的问题框定为监督学习,那是个好主意。其他的更难…所以让我们来认识一个:无监督学习(本系列文章的第 2 部分)。
总结:如果算法对每个实例都有正确的标签,你就在处理监督学习。稍后,它将使用模型或配方来标记新的实例,就像您所做的那样。

In this video, your author gives you a quick refresher on how supervised learning (the topic of this article) differs from unsupervised learning.
感谢阅读!YouTube 课程怎么样?
如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:
Enjoy the entire course playlist here: bit.ly/machinefriend
与凯西·科兹尔科夫联系
让我们做朋友吧!你可以在 Twitter 、 YouTube 和 LinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用表格取得联系。
解释这个笑话:“当公司说他们需要‘人工智能’的时候,他们真正需要的是一个带有 GROUP BY 的 SELECT 子句。”
Mat Vellosso 最近发推文:

它像病毒一样传播开来。嗯,就像一个无聊的笑话一样,奥巴马的不痛不痒的母亲节推特被十倍于奥巴马的人喜欢。尽管如此,将近一半喜欢 Mat Velloso 的推文的人也转发了它。
像所有好的笑话一样,这里有几个层次和一个巨大的真理内核。所以,让我成为那个家伙,那个解释笑话并从中获取所有乐趣的家伙。
长话短说:如果你只有几个独立的输入特征,SELECT + GROUP BY 可能和一个奇特的机器学习模型一样好。只有当特征数量增加,因素变得依赖时,你才需要机器学习。
大数据分析
假设您想预测在伦敦租了一辆自行车的人是否会在 10 分钟内归还自行车。你认为人们会在周末进行更长时间的骑行,所以在工作日进行短距离快速骑行的概率更高。你可以用一个 SELECT GROUP BY 来完成:
#standardsql
CREATE TEMPORARY FUNCTION dayOfWeek(ts TIMESTAMP) AS
(
['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'][ORDINAL(EXTRACT(DAYOFWEEK FROM ts))]
);WITH bikeshare AS (
SELECT
IF(duration < 600, 1, 0) AS short_ride,
dayOfWeek(start_date) AS dayofweek
FROM `bigquery-public-data.london_bicycles.cycle_hire`
)SELECT
dayofweek,
SUM(short_ride)/COUNT(1) AS frac_short_rides,
COUNT(1) AS num_all_rides
FROM
bikeshare
GROUP BY
dayofweek
ORDER BY num_all_rides DESC
运行这个,我们对< 10 min rides will be 33% on weekdays and 24% on weekends:

We wanted to find the likelihood that bicycles are returned in less than 10 minutes and we just computed it in brute force over the entire historical dataset. The reason this works is that there were 2.9 million rentals on Sunday and 23.6% of them were returned. Once you have Big Data, it is super-easy to make statistically significant inferences.
Sparse input features
What if you add one more factor though? In addition to day of the week, we would like to use the station that the bicycle is being rented from as an input feature. Perhaps rentals in the city center are likely to be short. We can simply 的预测通过在我们的组中添加第二个字段:
SELECT
dayofweek, start_station_name,
SUM(short_ride)/COUNT(1) AS frac_short_rides,
COUNT(1) AS num_all_rides
FROM
bikeshare
GROUP BY
dayofweek, start_station_name
ORDER BY num_all_rides DESC
桌面很好:

你需要考虑到在海德公园租自行车的人会长期保管它们。但是最底层…你在莫尼耶路有严重的问题:

你愿意根据 1、2 个历史数据点来做预测吗?这就是机器学习的用武之地——以智能的方式处理像车站这样的稀疏输入。一个好的 ML 算法不是使用由 GROUP BY 指定的硬阈值,而是“借用”其他站的可能性,并在 Monier Road 使用它们。也许您会添加一个指示车站附近人口密度的要素,然后 ML 模型将借用具有相似人口密度的车站的可能性。
我还没毁了这个笑话吗?
.
.
.
.
.
.
.
好吧,那么,让我来为你毁了它——就像所有好笑话一样,这个笑话在仔细检查后会崩溃。Mat 到底在说什么?一半关注人工智能的公司有如此多的数据行,他们可以简单地进行分组?这样的公司也没有足够的列,他们需要一个 ML 模型?
探索性分析:美国数据科学家的薪水
在我之前的帖子中,我谈到了在全美国征集 Indeed.com 的数据科学家职位。虽然我能找到 10,500 多份清单,但其中很少包含工资数据,许多工资是按小时、月或周计算的。在对数据进行大规模清理后,我只剩下 493 份工资用于建模。薪酬中位数为 10 万美元,其中 236 家高于中位数,257 家低于中位数。我很兴奋能去做模特。然而,在进入大结局之前,我想看看我还能从这些数据中获得什么样的见解。这个任务要求我从我的数据科学家工具箱中拿出我最喜欢的数据探索工具之一——Tableau!
当我将数据加载到 Tableau 时,我最感兴趣的是了解数据科学家的工资如何因地点而异,以及哪些地点的独特工作列表数量最多。

这里我们有一张各州平均工资的热图,深色代表高工资,浅色代表低工资。正如我们从地图上看到的,弗吉尼亚州的数据科学家工资似乎最高,平均为 182,000 美元。最差的是佛罗里达州,平均工资为 57253 美元。

通过观察各个城市的平均工资情况,我可以进一步细分这些数字。在收入最高的弗吉尼亚州,麦克林、莱斯顿和安布勒的平均工资最高,分别为 19.6 万美元、19 万美元和 17.5 万美元。在西海岸,旧金山以 171,245 美元的平均工资紧随其后。从较低的范围来看,佛罗里达州的 Dania Beach 以 30k 美元排名垫底。然而,来自佛罗里达州的其他人成功地将他们的数字拉高了一点,珊瑚墙和迈阿密分别为 51,311 美元和 91,000 美元。
在如此大的工资范围内,我想看看我实际上是在做什么样的工作。毕竟,弗吉尼亚在顶端,但是我的样本实际上处理了多少独特的工作列表。当你考虑到其他地方有更多的空缺职位需要填补时,少量的列表并不算多。

上图中,我们有一张地图,按照各州独特工作列表的数量来划分大小,并按照平均工资来着色。颜色从暗红色到暗绿色不等,最暗的绿色代表最高工资,最暗的红色代表最低工资。在这里,我们对之前的数据进行了分析。虽然弗吉尼亚的工资可能是最高的,但我们只看了 3 个独特的工作列表,这实际上将弗吉尼亚排在了机会的最后。加州似乎保持了它以前的记录,有来自 24 家不同公司的 33 个不同的职位,平均工资为 12.5 万美元。此外,虽然纽约州和伊利诺伊州可能不是薪酬最高的州(11.5 万英镑不是我抱怨的数字),但它们的机会数量确实最多,分别有 55 个和 37 个独特的职位空缺。
探索性分析和回归模型帮助抗击寨卡
Alerta Zika!是一项合作活动,旨在探索数据和技术改善寨卡病毒应对措施的潜力。美洲开发银行在包括里约热内卢市政厅和该市一些主要大学在内的几个合作伙伴的支持下组织了这次活动。从 2016 年 12 月 2 日到 3 日,大约 10 个注册团队探索了流行病学、环境和社会因素,以了解和解释这种疾病的进展。总结里约热内卢抗击寨卡疾病的努力,是一天半的辛苦工作。我们获得了里约热内卢市 2015 年和 2016 年期间登记的所有寨卡、登革热和基孔肯雅病病例的数据集。为了了解数据,我们的团队开始“玩”数据集并检查变量。在这样做的过程中,我们对寨卡的进化模式及其在 2016 年前几个月爆发期间的作用产生了幻想。
我们的假设是,疾病传播模式及其在时间、城市地区和天气方面的相关性可以用作一个指标,以显示疾病在何时何地传播,并帮助城市官员决定分配资源的最佳方式。我们当时设定的目标是,绘制一幅里约热内卢地图,展示寨卡病毒在不同时间和温度下的历史演变。在与市卫生秘书代表的几次交谈中,我们想知道一个社会发展指标是否可以提供关于传播模式的见解。我们决定将人类发展指数(HDI)——在巴西被称为 IDH——作为一个社会参数。
然后,我们将坐标(纬度和经度)、案件发生的日期、四季温度以及里约关于收入、教育水平和寿命的社会发展指标确定为目标变量。我们的初步任务是创建一个由里约热内卢城市地图和数据框组成的网格,以聚集来自不同数据集的变量子集。我们执行探索性分析的第一个目标是探索分布的形状。网格帮助我们检查箱子的位置;探索约 400 米的区域,这是蚊子的活动范围,并在更广阔的区域聚集患者病例。这也使我们能够检查疾病在整个城市的传播范围,并确定大多数病例发生的地区。
通过进行时间序列分析,我们能够确定温度和病例数之间的相关性。在这一点上,了解蚊子的生命周期是有价值的。埃及伊蚊在从 23 摄氏度到 28 摄氏度(大约 73 到 82 华氏度)的温度变化中茁壮成长。低于或高于这一阈值几度并不一定会杀死蚊子,但会使环境对其发展更不舒适,从而延缓其进化。从卵中的病毒接种到一个个体中,有 20 到 25 天的时间,所以前一个月的蚊子负责本月的病人。从下面的曲线图可以看出,通过逐月比较全市的疾病病例和前一个月每天的温度变化,3 月和 4 月期间的疫情(曲线图 3 和 4)遵循了整个 2 月和 3 月观察到的最佳条件,在这两个月的大部分时间里观察到了 23 至 28 摄氏度的阈值。红圈对应的是病例最多的地区。
剧情一

剧情二

剧情三

剧情四

剧情五

剧情 6

剧情 7

这让我们获得了第一个有意义的发现:上个月的气温似乎会影响本月的病例数量。
当我们将注意力转移到手头的社会指标数据时,我们能够识别出一种奇怪的行为。暴发期间的一些关键地区具有低 IDH 系数的相似性。下面的情节提供了直观的支持。橙色圆圈的大小与 IDH、较小的圆圈/下 IDH 的等级相关,反之亦然。
剧情 8

上图中突出显示的区域对应马雷(一个社区),城市的远北区和远西区。与该市其他地区相比,这些地区的社会指标水平较低。
尽管收入似乎不是影响疫情爆发的社会影响因素——从下面的图表中可以看出——但将该市最富裕的南区行为与 3 月和 4 月的情况进行比较,可以看出一个特点。在这个特殊的领域,存在着巨大的经济差异。最高档的地址位于一些贫民窟的步行距离内(贫民窟通常位于该地区周围的山上),那里的 IDH 与之前地块上的相似)。
剧情 9

从这一观察中,我们得出了第二个有意义的见解:在疫情爆发期间,社会指标(IDH)似乎在病例数量最多的地区起到了影响作用。
随着我们进一步分析,其他奇怪的行为引起了我们的注意。即使气温从 23 至 28 摄氏度的阈值下降,一些地区仍然出现在最高得分病例中(从下面 5 月至 7 月的比较中可以看出)。
剧情 10

这些地区的共同点是都被树林和森林包围着。这一共同因素提供了我们提供的第三个有意义的见解:一些复发疾病的病灶区似乎生长在树林和森林地区的周围或附近。
探索性分析通常是预测建模的良好开端,因为它有助于进一步理解数据集并总结其主要特征。探索数据和制定可能导致新的数据收集和实验的假设是从数据中提取有用信息的主要组成部分;提出假设;并支持选择适当的统计工具和技术。我们在数据考察中的主要目标是设定有助于理解过去行为的第一步,以便为未来的“作物”准备“种子”。我们的第三名是我们的骄傲,似乎表明这个目标已经实现。
数据远征后
我们继续探索数据,并汇总其他变量。我们的目标是获得一些可以添加到初始探索性分析中的预测模型。这些新的变量是每个街区的人口和降雨量。我们还添加了更多关于 2016 年最后几个月和 2017 年 1 月初的温度数据。
第一种选择是简单的线性回归,使用每个邻域的可变人口来预测基于人口的病例。下面是 R 和统计读数中的一些代码块(我们打算在 markdown 文件中显示更多信息,这是一种可以一起显示文本、代码和图表的文件)。
型号:

数据集的快速视图:

“bairro”代表邻里;针对寨卡病例的“casos _ Zika”;“populacao”代表人口。
来自 Rstudio 控制台的一些统计数据:

诊断图
在图 1(残差与拟合值)中,在某一点上,残差沿水平线均匀分布,但也有异常值。在图 2(正态 Q-Q)中,残差似乎正态分布,至少在某种程度上是这样。
情节 1

剧情二

在补充图 1 的图 3(标度-位置)中,一些残差沿预测值范围平均分布,显示出一些同质性。图 4(残差对杠杆)将有影响的观察结果确定为#120 和#23。
剧情三

剧情四

基于当温度阈值在 23 到 28 摄氏度之间时,蚊子的周期更快的理论,我们试图检查降雨是否也有助于繁殖。然后,我们试图确定这两个变量与寨卡病例数量之间的关系。我们的第二个选择是使用多元回归模型来达到这个目标。这种分析是在 Phython 进行的。
下图显示了温度阈值发生率最高的月份是 2015 年 12 月至 2016 年 4 月之间的月份。我们还可以注意到,这一趋势在 2016 年 12 月和 2017 年 1 月初再次出现。

绿线和红线:温度阈值
粉色和灰色线条:最低和最高温度
接下来的一系列图显示,在显示每周病例数、温度和降雨量的曲线之间存在类似的正趋势。该分析是基于 2016 年疫情爆发期间受到严重影响的 Campo Grande (1)、Santa Cruz (2)和 Guaratiba(3)社区进行的。
蓝线:每周病例数
红线:温度低于阈值
黄线:降雨量
(1)

(2)

(3)

我们决定使用多元回归模型来构建一个预测应用程序。我们通过将实际数据与用于拟合模型的测试数据集中应用的预测数据进行比较的一系列图来测试该模型。
里约热内卢的测试值与预测值

绿点:测试值
灰点:预测值
里约热内卢的真实案例与预测案例

绿线:真实案例
灰色线条:预测案例
里约热内卢真实案例与预测案例对比2015 年 12 月& 2016 年

格林:真实案例
灰色:预测病例
在这个特殊的案例中(上图),我们没有 2016 年 12 月实际寨卡病例的数量,所以我们只预测了病例的数量。
每个街区的分析 : Campo Grande。
Jupyter 笔记本电脑控制台的统计读数:

绿线:真实案例
灰色线:预测病例

每个街区的分析:圣克鲁斯。
统计读数

绿线:真实案例
灰色线:预测病例

每街坊分析:瓜拉蒂巴。
统计读数

绿线:测试值
灰色线:预测值

我们创建了一个原型来应用这个模型。这是一个网站,上面有每月寨卡病例数量的信息,以及显示每个社区实际病例和预测病例的图表。
对于那些想了解它的人来说,这里有和。
利用 R 对 FIFA 18 数据集的探索性分析

[Image [1] (Image courtesy: https://www.easports.com/fifa)]
随着 2018 年 FIFA 世界杯的临近,我结合了我对足球和数据科学的热爱,使用 r 对 FIFA 18 数据集进行了一次简短的探索性分析。我使用了非身体球员属性,如Name, Age, Nationality, Overall, Club, Value, Wage, Preferred.Positions.
我使用了在 Kaggle 上可用的数据集,其中包含 17,000 多名 FIFA18 中的球员,每个人都有超过 70 个属性。是从网站 SoFiFa 上刮下来的。
如果你对数据可视化感兴趣,你可以看看我的另一篇文章gg plot ' Em All | Pokemon on R。如果你对大数据感兴趣,可以看看我的文章开始使用 Hive 。
在开始分析之前,让我们导入库并读入数据集。
library(ggplot2)
library(dplyr)
library(gridExtra)df = read.csv(file = "CompleteDataset.csv", stringsAsFactors = FALSE)df = tbl_df(df)df <- select(df, ID, X, Name, Age, Nationality, Overall, Club, Value, Wage, Preferred.Positions)
head(df, 10)

First 10 rows of the dataset [Image [2]]
读取数据后,我做的第一件事是将Value和Wage列转换为实际的货币值。我编写了一个函数,将一个向量作为输入,并从列中删除“€”符号,然后乘以适当的数字,将其转换为千(K)和百万(M)。
toNumberCurrency <- function(vector) {
vector <- as.character(vector)
vector <- gsub("(€|,)","", vector)
result <- as.numeric(vector)
k_positions <- grep("K", vector)
result[k_positions] <- as.numeric(gsub("K","", vector[k_positions])) * 1000
m_positions <- grep("M", vector)
result[m_positions] <- as.numeric(gsub("M","",
vector[m_positions])) * 1000000
return(result)
}df$Wage <- toNumberCurrency(df$Wage)
df$Value <- toNumberCurrency(df$Value)
然后,我从Preferred.Positions列的空格分隔值中选取第一个位置值。数据集中的不同位置是:CAM CB CDM CF CM GK LB LM LW LWB RB RM RW RWB ST。
df$Preferred.Positions <- gsub(" ", "", substr(df$Preferred.Positions, 1, 3))
基于上面的Preferred.Positions,我创建了另一个专栏,将这些Preferred.Positions分类为更一般的职位,即GK DEF MID FWD。清理后的数据集如下所示:
x <- as.factor(df$Preferred.Positions)levels(x) <- list(GK = c("GK"),
DEF = c("LWB", "LB", "CB", "RB", "RWB"),
MID = c("LW","LM","CDM","CM","CAM","RM","RW"),
FWD = c("CF", "ST"))df <- mutate(df, Position = x)head(df)
选择Preferred.Position栏中的第一个职位,并创建一个表格,将这些职位分类为更一般的职位,即GK DEF MID FWD。

Cleaned data set [Image [3]]
首先,球员的年龄分布。我们看到有很多 25 岁左右的球员。
g_age <- ggplot(data = df, aes(Age))g_age +
geom_histogram(col="orange", aes(fill = ..count..)) + ggtitle("Distribution based on Age")

Distribution of players based on their age [Image [4]]
下面的图表显示了运动员的年龄和他们的一般比赛位置之间的关系。
g_age +
geom_density(col="orange", aes(fill = Position), alpha=0.5) + facet_grid(.~Position) +
ggtitle("Distribution based on Age and Position")

Distribution based on Age and Position [Image [5]]
根据玩家的总体评分来分配玩家。我们看到大多数玩家的总体评分在 65 分左右。
g_overall <- ggplot(data = df, aes(Overall))g_overall +
geom_histogram(col="orange", aes(fill = ..count..)) + ggtitle("Distribution based on Overall Rating")

Distribution based on overall rating [Image [6]]
来自不同(前 10 名)国家的玩家数量。
countries_count <- count(df, Nationality)top_10_countries <- top_n(countries_count, 10, n)top_10_country_names <- top_10_countries$Nationality
country <- filter(df, Nationality == top_10_country_names)ggplot(country, aes(x = Nationality)) +
geom_bar(col = "orange", aes(fill = ..count..)) + ggtitle("Distribution based on Nationality of Players (Top 10 Countries)")

Number of players from different countries [Image[7]]
我使用 R 中的分位数函数来获得玩家Value和Wage的前 1 %的计数。许多球员的周薪为 10 万€。
top_1_percent_wage <- quantile(df$Wage, probs=0.99)filtered_wage <- filter(df, Wage > top_1_percent_wage)
g_value <- ggplot(filtered_wage, aes(Wage))g_value +
geom_histogram(aes(fill=..count..)) +
ggtitle("Distribution of top 1% value")

Top 1% wage [Image [8]]
大量的球员价值 2500 万€,随着价格的上涨,人数急剧减少。
top_1_percent_value <- quantile(df$Value, probs=0.99)filtered_value <- filter(df, Value > top_1_percent_value)
g_wage <- ggplot(filtered_value, aes(Value))g_wage +
geom_histogram(aes(fill=..count..)) +
ggtitle("Distribution of top 1% Value")

Top 1% player valuation [Image [9]]
为了进一步分析wage和value,我创建了wage_brackets和value_brackets。
wage_brackets是:0–100k 100k-200k 200k-300k 300k-400k 400k-500k 500k+。value_brackets是:0–10M 10–20M 20–30M 30–40M 40–50M 50–60M 60–70M 70–80M 80–90M 90–100M 100M+。
# Create wage bracketswage_breaks <- c(0, 100000, 200000, 300000, 400000, 500000, Inf)wage_labels <- c("0-100k", "100k-200k", "200k-300k", "300k-400k", "400k-500k", "500k+")wage_brackets <- cut(x=df$Wage, breaks=wage_breaks,
labels=wage_labels, include.lowest = TRUE)df <- mutate(df, wage_brackets)# Create value brackets
value_breaks <- c(0, 10000000, 20000000, 30000000, 40000000, 50000000, 60000000, 70000000, 80000000, 90000000, 100000000, Inf)
value_labels <- c("0-10M", "10-20M", "20-30M", "30-40M", "40-50M","50-60M", "60-70M", "70-80M", "80-90M","90-100M","100M+")value_brackets <- cut(x=df$Value, breaks=value_breaks, labels=value_labels, include.lowest = TRUE)df <-mutate(df, value_brackets)head(df)

Dataset [Image [10]]
很多球员的工资在 0-10 万英镑之间,估值在 0-5000 万英镑之间。绘制这些值会使图形发生很大的倾斜,因为与其他值相比,它们的幅度很大,因此我没有在这里展示它们。
not0To100K <- filter(df, wage_brackets != "0-100k") ggplot(not0To100K, aes(x = wage_brackets)) +
geom_bar(aes(fill = ..count..)) +
ggtitle("Distribution of top Wage between 100K-500K+")

Wage between 100k and 500k+ [Image [11]]
moreThan50M <- filter(df, Value>50000000)ggplot(moreThan50M, aes(x = value_brackets)) +
geom_bar(aes(fill = ..count..)) +
ggtitle("Distribution of value between 50M-100M+")

Player valuation between 50M-100M+ [Image [12]]
不同工资等级的球员的年龄和总体情况。工资最高的是年龄在 30 岁左右的 85 岁以上的球员。克里斯蒂亚诺罗纳尔多是上面三个紫色点之一。在下面的评论区猜另外两个。😛
g_age_overall <- ggplot(df, aes(Age, Overall))g_age_overall +
geom_point(aes(color=wage_brackets)) + geom_smooth(color="darkblue") +
ggtitle("Distribution between Age and Overall of players based on Wage bracket")

Overall vs Age (Wage) [Image [13]]
玩家的年龄与整体价值的关系图与上面的趋势非常相似。
g_age_overall <- ggplot(df, aes(Age, Overall))g_age_overall + geom_point(aes(color=value_brackets)) + geom_smooth(color="darkblue") +
ggtitle("Distribution between Age and Overall of players based on Value bracket")

Age vs Overall (Value) [Image [14]]
根据运动员的一般比赛位置确定运动员人数。中场人数最多,其次是后卫,前锋,最后是守门员。
ggplot(df, aes(Position)) +
geom_bar(aes(fill = ..count..)) +
ggtitle("Distribution based on General Playing Position")

Number of players per playing position [Image [15]]
根据玩家偏好的游戏位置确定玩家数量。基于上面的图表,我们期望一些特定的中场位置有最高的数量,但是这里中后卫的数量是最高的,其次是前锋的数量。
ggplot(df, aes(Preferred.Positions)) + geom_bar(aes(fill=..count..)) +
ggtitle("Distribution of players based on preferred position")

Number of players per Preferred Position [Image [16]]
让我们看看球员的工资是多少,以及他们基于首选位置的估值。
gf1 <- filter(df, Value<30000000)g1 <- ggplot(gf1, aes(Preferred.Positions)) + geom_bar(aes(fill=value_brackets)) +
ggtitle("Position based on Value (0-50M)")gf2 <- filter(df,Value>30000000)g2 <- ggplot(gf2, aes(Preferred.Positions)) + geom_bar(aes(fill=value_brackets)) +
ggtitle("Position based on Value (50M +)")grid.arrange(g1, g2, ncol=1)

Wage based on Preferred position [Image [17]]
gw1 <- filter(df, Wage > 100000, Wage<300000)g1 <- ggplot(gw1, aes(Preferred.Positions)) + geom_bar(aes(fill=wage_brackets)) +
ggtitle("Position based on Wage (0-100k)") gw2 <- filter(df,Wage>300000) g2 <- ggplot(gw2, aes(Preferred.Positions)) + geom_bar(aes(fill=wage_brackets)) +
ggtitle("Position based on Wage (100k+)")
grid.arrange(g1, g2, ncol=1)

Valuation based on preferred position [Image [18]]
最后,
十大最有价值俱乐部。俱乐部价值通过合计每个俱乐部的球员估价来计算。
group_clubs <- group_by(df, Club)club_value <- summarise(group_clubs, total_val = sum(Value))top_10_valuable_clubs <- top_n(club_value, 10, total_val)
top_10_valuable_clubs$Club <-as.factor(top_10_valuable_clubs$Club)
ggplot(top_10_valuable_clubs, aes(x = Club, y = total_val)) + geom_bar(stat = "identity", aes(fill=total_val)) + coord_flip() + ggtitle("Top 10 valuable clubs")

Top-10 valuable clubs [Image [19]]
感谢您的阅读。你可以在 RPubs 和 GitHub 找到源代码(R-notebook)。你可以在 LinkedIn 和 Twitter 上找到我。
点击查看我的其他博客。
gg plot ' All |口袋妖怪

Pokemon [Image [0] Image courtesy: https://bdfjade.com/pokemon-pictures.html]
这篇博文致力于使用口袋妖怪数据集的数据可视化进行分析。第一部分是探索性分析。第二部分有一个机器学习的方面——将口袋妖怪归类为传奇。两篇博文都在 r。

Pokemon Image [1] [Image courtesy]
让我们开始吃吧。😄
导入库。
library(dplyr)
library(ggplot2)
library(gridExtra)
library(tidyr)
library(reshape2)
library(RColorBrewer)
library(ggrepel)
请阅读。csv 文件。
df = read.csv(file="/home/akshaj/projects_R/Pokemon/pokemon.csv")
df = tbl_df(df)
colnames(df)[25] <- "classification"
df$capture_rate <- as.numeric(df$capture_rate)
head(df)

First 5 rows of the dataset [Image [2]]
现在,我们将从整个数据框中选择并使用一些列进行探索性分析。
df = select(df, name, classification, hp, weight_kg,
height_m, speed, attack, defense,
sp_attack, sp_defense, type1, type2,
abilities, generation,is_legendary,
capture_rate)head(df)

Subset of the original dataset [Image [3]]
密度图
各种口袋妖怪属性的密度图。密度图显示了连续时间间隔内的数据分布。这个图表是一个直方图的变体,它使用内核平滑来绘制值,通过平滑噪声来实现更平滑的分布。密度图的峰值有助于显示值在间隔内的集中位置。
density_hp <- ggplot(data=df, aes(hp)) + geom_density(col="white",fill="pink", alpha=0.8) + ggtitle("Density Plot of HP")density_speed <- ggplot(data=df, aes(speed)) + geom_density(col="white", fill="darkorchid", alpha=0.8) + ggtitle("Density Plot of Speed Characterstics")density_attack <- ggplot(data=df, aes(attack)) + geom_density(col="white", fill="orange", alpha=0.7) + ggtitle("Density Plot of Attack Characterstics")density_defense <- ggplot(data=df, aes(defense)) + geom_density(col="white", fill="firebrick", alpha=0.7) + ggtitle("Density Plot of Defense Characterstics")density_height <- ggplot(data=df, aes(height_m)) + geom_density(col="white", fill="slateblue1", alpha=0.8) + ggtitle("Density Plot of Height (m) ")density_weight <- ggplot(data=df, aes(weight_kg)) + geom_density(col="white", fill="mediumturquoise", alpha=0.8) + ggtitle("Density Plot of Weight (kg)")grid.arrange(density_hp, density_speed, density_attack, density_defense, density_height, density_weight, ncol=2)

Density plot of various attributes [Image [4]]
条形图
条形图可能是媒体最常用的统计数据显示方式。条形图将分类数据(因子)按组细分,并用不同长度的条形表示这些数量。我们将绘制每组中的个体数量(也称为频率)。
基于主要和次要类型的口袋妖怪数量
我们观察到最常见的口袋妖怪类型有水、普通和 Bug 。而最常见的二次元口袋妖怪类型是飞。请注意,大量的口袋妖怪没有第二类型。
type_1_poke <- ggplot(data=df, aes(type1)) + geom_bar(aes(fill=..count..), alpha=0.8) + theme(axis.text.x = element_text(angle = 90, hjust = 0)) + ggtitle("Distribution Based on Type-1") + coord_flip()type_2_poke <- ggplot(data=df, aes(type2)) + geom_bar(aes(fill=..count..), alpha=0.8) + theme(axis.text.x = element_text(angle = 90, hjust = 0)) + ggtitle("Distribution Based on Type-2") + coord_flip()grid.arrange(type_1_poke, type_2_poke, ncol=2)

Distribution of Pokemon based on Primary and Secondary type [Image [5]]
基于主要类型的传奇口袋妖怪数量
我们观察到有超过 15 个 Pyschic 类型的传奇口袋妖怪。仙、飞、鬼类型的传说口袋妖怪数量最少。这可能是因为灵媒口袋妖怪很“神秘”。
df %>%
filter(is_legendary==1) %>%
ggplot(aes(type1)) + geom_bar(aes(fill= ..count..)) + theme(axis.text.x = element_text(angle=90, hjust=0)) + ggtitle("Number of Legendary Pokemon Based on Type-1")

Distribution of Legendary Pokemon based on primary type [Image [6]]
每一代引入的初级口袋妖怪数量
该数据集中有 7 代。例如,在第 5 代中引入了大量 Bug 类型的口袋妖怪,而在第 7 代中引入了极少数黑暗类型的口袋妖怪。
这个图表的代码有点长,所以我在这里展示了这个图表。你可以查看完整的代码在这里。

Distribution of primary type per generation [Image [7]]
散点图
散点图是一种二维数据可视化,使用点来表示两个不同变量的值,一个沿 x 轴绘制,另一个沿 y 轴绘制。散点图对于解释统计数据的趋势很有用,并且在您想要显示两个变量之间的关系时使用。散点图有时被称为相关图,因为它们显示了两个变量如何相关
防御 vs 攻击口袋妖怪的特点
这里,传说中的口袋妖怪是红色的,而非传说中的口袋妖怪是蓝色的。对于非传奇的口袋妖怪,攻击和防御属性之间似乎存在正线性关系。这意味着拥有更高攻击属性的口袋妖怪也倾向于拥有更高的防御属性。而传说中的口袋妖怪却没有这种关系。
虽然有一些异常,传说中的口袋妖怪,总的来说有更大的防御和攻击属性。像 Groudon 和 Gyarados(右上)这样的口袋妖怪似乎在攻击和防御方面都很平衡,而像鲤鱼王和凯西这样的口袋妖怪则具有低防御和攻击的特点。你可能会选择格鲁登而不是鲤鱼王来赢得决斗。
ggplot(data=df, aes(attack, defense)) + geom_point(aes(color=is_legendary), alpha=0.8) + scale_color_gradient(low="darkblue", high="red") + ggtitle("Defense vs Attack Characterstics") +
geom_label_repel(data=subset(df,attack > 150 | defense >150 | attack < 25), aes(label=name),
box.padding = 0.35, point.padding = 0.5,
segment.color = 'grey50')

Defense vs Attack attributes [Image [8]]
速度、身高、体重、 Hp V.S .攻击属性
我们在所有 4 个图中观察到的一个共同趋势是,口袋妖怪的速度、身高、体重和 Hp 特性相对于攻击属性增加。
速度与攻击属性之间存在微弱的正相关关系,而身高、体重、血量与攻击属性之间存在较强的正线性关系。
我已经在散点图上标注了传说中的口袋妖怪。《宇宙》和《科斯莫姆》是传奇口袋妖怪的例外。与其他口袋妖怪相比,它们的速度、、高度和血量更低。然而,就重量而言,科斯莫姆是一个异数。与其他传奇口袋妖怪相比,它拥有异常高的重量和较少的攻击。
speed_attack_legendary <- ggplot(na.omit(df), aes(attack, speed)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (attack > 170 | attack < 50 & speed >150 | speed < 50) & is_legendary == 1 | speed > 145), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")weight_attack_legendary <- ggplot(na.omit(df), aes(attack, weight_kg)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (attack > 170 | attack < 50 | weight_kg > 650) & (is_legendary == 1)), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")height_attack_legendary <- ggplot(na.omit(df), aes(attack, height_m)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, ((attack > 170 | attack < 50 | height_m > 7.5) & is_legendary == 1) | height_m > 5 & is_legendary == 0), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")hp_attack_legendary <- ggplot(na.omit(df), aes(attack, hp)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, ((attack > 170 | hp > 190 | attack < 50) & is_legendary == 1) | hp >160), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")grid.arrange(speed_attack_legendary, weight_attack_legendary, height_attack_legendary, hp_attack_legendary, ncol = 2)

Height, Weight, Speed, Hp vs Attack [Image [9]]
速度、身高、体重和 Hp V.S .防御属性
我们绘制了与上面相同的图表,但这次是防御属性。我们在这里观察到趋势的不同。速度和防守有一种微弱的负线性关系。速度随着防御的增加而降低。这意味着防守型口袋妖怪通常比进攻型口袋妖怪要慢。
对于一个传奇的口袋妖怪来说,Cosmog 在拥有超级弱属性方面是非常一致的。为什么 Cosmog 这么没用?我在网上查了一下 Cosmog。这是我发现的。
Cosmog 从 43 级开始进化成科斯莫姆,它从 53 级开始进化成 Solgaleo 或 Lunala 取决于它进化的游戏。

Evolution of Cosmog [Image [10]]
speed_defense_legendary <- ggplot(na.omit(df), aes(defense, speed)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (defense > 130 | defense < 50| speed > 140 | speed < 50) & is_legendary == 1), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")weight_defense_legendary <- ggplot(na.omit(df), aes(defense, weight_kg)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (defense > 160 | defense < 50 | weight_kg > 600) & is_legendary == 1), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")height_defense_legendary <- ggplot(na.omit(df), aes(defense, height_m)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (defense > 150 | defense < 50 | height_m > 6) & is_legendary == 1 | height_m >5 & is_legendary ==0), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")hp_defense_legendary <- ggplot(na.omit(df), aes(defense, hp)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (defense > 150 | defense < 50 | hp > 150) & is_legendary == 1 | hp > 200), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")grid.arrange(speed_defense_legendary, weight_defense_legendary, height_defense_legendary, hp_defense_legendary, ncol = 2)

Height, Weight, Speed, Hp vs Attack [Image [11]]
箱线图
箱线图是显示数据集的分布和中心的一种方式。传播的测量包括数据组的四分位数范围和平均值。中心的度量包括平均值和中值(数据集的中间)。
黑线表示中间值。彩色框表示代表中间 50%数据的四分位数范围。胡须从盒子的两边延伸出来。晶须代表数据值的底部 25%和顶部 25%的范围,不包括异常值。
口袋妖怪属性的方框图
我们观察到,传奇口袋妖怪的所有特征的中位数都高于非传奇口袋妖怪。
与其他属性相比,非传奇口袋妖怪的 Hp 属性有更多的异常值。但是另一方面,相同的 Hp 属性与其他属性相比变化最小。
与传说中的口袋妖怪相比,非传说中的口袋妖怪有更多的离群值。
box_plot_attr <- select(df, type1, is_legendary, hp, defense, attack, sp_attack, sp_defense, speed)box_plot_attr_leg <- filter(box_plot_attr, is_legendary == 1)box_plot_attr_nor <- filter(box_plot_attr, is_legendary == 0)box_plot_attr_leg_long <- gather(box_plot_attr_leg, attribute, value, -c(type1, is_legendary))box_plot_attr_nor_long <- gather(box_plot_attr_nor, attribute, value, -c(type1, is_legendary))bp_leg <- ggplot(data = box_plot_attr_leg_long, aes(attribute, value)) + geom_boxplot(fill="green4") + ggtitle("Legendary Pokemon")bp_nor <- ggplot(data = box_plot_attr_nor_long, aes(attribute, value)) + geom_boxplot(fill = "yellow2") + ggtitle("Normal Pokemon")grid.arrange(bp_leg, bp_nor,ncol=2)

Boxplot of Pokemon attributes’ [Image [12]]
热图
热图基本上是用颜色代替数字的表格。热点图中的最低值设置为深蓝色,最高值设置为红色,中间值设置为白色,在这些极端值之间有相应的过渡(或渐变)。热图非常适合可视化大量多维数据,并可用于识别具有相似值的行的聚类,因为这些行显示为相似颜色的区域。
接下来,我们将看到各种类型的口袋妖怪的属性如何相互叠加。为此,我们将计算这些属性的中位数,并绘制传奇和非传奇口袋妖怪的热图。
初级类型 vs 属性热图|传奇口袋妖怪
冰型传奇口袋妖怪的 sp_ 防御值很高,而速度值很低。地传奇口袋妖怪有非常高的攻击属性。 Bug 型传奇口袋妖怪 sp_defense 很低。
相反, bug 型和黑暗型口袋妖怪有着相似的速度属性。
hmap_attr <- select(df, type1, is_legendary, hp, defense, attack, sp_attack, sp_defense, speed)hmap_attr_leg <- filter(hmap_attr, is_legendary == 1)
hmap_attr_nor <- filter(hmap_attr, is_legendary == 0)hmap_attr_leg <- group_by(hmap_attr_leg, type1)
hmap_attr_nor <- group_by(hmap_attr_nor, type1)hmap_attr_leg <- summarise(hmap_attr_leg, hp=median(hp), attack=median(attack), defense=median(defense), sp_attack=median(sp_attack), sp_defense=median(sp_defense), speed=median(speed))hmap_attr_leg_m <- melt(hmap_attr_leg)hmap_attr_nor <- summarise(hmap_attr_nor, hp=median(hp), attack=median(attack), defense=median(defense), sp_attack=median(sp_attack), sp_defense=median(sp_defense), speed=median(speed))hmap_attr_nor_m <- melt(hmap_attr_nor)hm.palette <- colorRampPalette(rev(brewer.pal(5, 'RdYlBu')), space='Lab')ggplot(data=hmap_attr_leg_m, aes(type1, variable)) + geom_tile(aes(fill=value)) + ggtitle("Legendary Pokemon: Type1 - Attribute") + scale_fill_gradientn(colours = hm.palette(100)) + theme(axis.text.x = element_text(angle=90, hjust=0)) + coord_equal()

Heat map of legendary attributes vs primary type [Image [13]]
初级型 vs 属性热图|非传奇口袋妖怪
钢铁型口袋妖怪防御数值高但是速度很低。战斗型口袋妖怪攻击值很高而 sp_attack 值很低。地、冰、普通口袋妖怪都有类似的 Hp 水平,毒药、和摇滚型口袋妖怪也是如此。
hm.palette <- colorRampPalette(rev(brewer.pal(5, 'RdYlBu')), space='Lab')ggplot(data=hmap_attr_nor_m, aes(type1, variable)) + geom_tile(aes(fill=value)) + ggtitle("Non-Legendary Pokemon: Type1 - Attribute") + scale_fill_gradientn(colours = hm.palette(100)) + theme(axis.text.x = element_text(angle=90, hjust=0)) + coord_equal()

Heatmap of non-legendary attributes vs type1 [Image [14]]
相关矩阵
相关矩阵是一个显示变量集之间相关系数(皮尔逊系数)的表格,它允许您查看哪些变量对具有最高的相关性。相关系数的取值范围为 1 至+1。系数的绝对值越大,变量之间的关系越强。
对于皮尔逊相关,绝对值为 1 表示完美的线性关系。
传奇口袋妖怪属性关联热图
我已经把相关矩阵转换成了热图。热点图中的最低值设置为深蓝色,最高值设置为白色,中间值设置为绿色,在这些极端值之间有相应的过渡(或渐变)。
现在,在绘图之前,让我们制定一个假设,看看它是否是真的。人们会认为防御性口袋妖怪会有更高的 Hp(也许这样它可以承受很多攻击?)和攻击值高到 sp_defense 值高但防御值低的口袋妖怪。
对角线上的元素都是白色的,因为属性与其自身具有线性关系。矩阵是其自身在白色对角线上的镜像。
基于以下传奇口袋妖怪的相关矩阵,在攻击和防御之间似乎存在某种线性关系,但在攻击和sp _ 防御之间并没有那么大的关系。此外,在防御和生命属性之间存在某种关联。
hmap_attr <- select(df, type1, is_legendary, hp, defense, attack, sp_attack, sp_defense, speed)hmap_attr_leg <- filter(hmap_attr, is_legendary == 1)
hmap_attr_nor <- filter(hmap_attr, is_legendary == 0)hmap_attr_leg <- group_by(hmap_attr_leg, type1)
hmap_attr_nor <- group_by(hmap_attr_nor, type1)hmap_attr_leg <- summarise(hmap_attr_leg, hp=median(hp), attack=median(attack), defense=median(defense), sp_attack=median(sp_attack), sp_defense=median(sp_defense), speed=median(speed))hmap_attr_nor <- summarise(hmap_attr_nor, hp=median(hp), attack=median(attack), defense=median(defense), sp_attack=median(sp_attack), sp_defense=median(sp_defense), speed=median(speed))row.names(hmap_attr_leg) <- hmap_attr_leg$type1
hmap_attr_leg$type1 <- NULL
hmap_attr_leg$is_legendary <- NULLrow.names(hmap_attr_nor) <- hmap_attr_nor$type1
hmap_attr_nor$type1 <- NULL
hmap_attr_nor$is_legendary <- NULLhmap_attr_leg_cor <- cor(hmap_attr_leg)
hmap_attr_leg_cor_m <- melt(hmap_attr_leg_cor)hm.palette <- colorRampPalette(rev(brewer.pal(5, 'GnBu')), space='Lab')ggplot(data=hmap_attr_leg_cor_m, aes(Var1, Var2)) + geom_tile(aes(fill=value)) + ggtitle("Attribute Correlation - Legendary") + scale_fill_gradientn(colours = hm.palette(100)) + coord_equal()

Correlation matrix of legendary Pokemon [Image [15]]
非传奇口袋妖怪属性的关联热图
对于非传说中的口袋妖怪来说, sp_attack 和 sp_defense 之间似乎有关联,而 attack 和 sp_attack 或 defense 和 speed 等等之间则没有这样的关系。
例如,具有高值 sp_attack 的口袋妖怪往往具有高值 sp_defense。
hmap_attr_nor_cor <- cor(hmap_attr_nor)
hmap_attr_nor_cor_m <- melt(hmap_attr_nor_cor)hm.palette <- colorRampPalette(rev(brewer.pal(5, 'GnBu')), space='Lab')ggplot(data=hmap_attr_nor_cor_m, aes(Var1, Var2)) + geom_tile(aes(fill=value)) + ggtitle("Attribute Correlation - Normal") + scale_fill_gradientn(colours = hm.palette(100)) + coord_equal()

Correlation matrix of non-legendary Pokemon [Image [16]]
基于初级类型的口袋妖怪的有效性
为此图选择数据框的一部分。
df_fight_against <- select(df, type1, against_bug:against_water)
head(df_fight_against)

Fight_against data frame [Image [17]]
求所有对 _type 列的中值。
df_fight_against_g <- group_by(df_fight_against, type1)df_fight_against_summ <- summarise(df_fight_against_g,
against_bug = median(against_bug),
against_dark = median(against_dark),
against_dragon = median(against_dragon),
against_electric = median(against_electric),
against_fairy = median(against_fairy),
against_fight = median(against_fight),
against_fire = median(against_fire),
against_flying = median(against_flying),
against_ghost = median(against_ghost),
against_grass = median(against_grass),
against_ground = median(against_ground),
against_ice = median(against_ice),
against_normal = median(against_normal),
against_poison = median(against_poison),
against_psychic = median(against_psychic),
against_rock = median(against_rock),
against_steel = median(against_steel),
against_water = median(against_water))
绘制热图。
df_fight_against_long <- melt(df_fight_against_summ)hm.palette <- colorRampPalette(rev(brewer.pal(9, 'RdYlBu')), space='Lab')ggplot(data=df_fight_against_long, aes(type1, variable)) + geom_tile(aes(fill=value)) + scale_fill_gradientn(colours = hm.palette(100)) + coord_equal() + theme(axis.text.x=element_text(angle=90, hjust=0)) + ggtitle("Effectiveness of different types of Pokemon")
热点图中的最低值设置为深蓝色,最高值设置为红色,中间值设置为白色,在这些极端值之间有相应的过渡(或渐变)。
热图显示会飞的型口袋妖怪对冰型口袋妖怪高效,而火型口袋妖怪则不然,等等。

Effectiveness of Pokemon in a duel based on fight [Image [18]]
感谢您的阅读。欢迎提出建议和建设性的批评。:)你可以在 LinkedIn 和 Twitter 上找到我。你可以点击查看的完整代码。
你也可以在这里查看我的其他博客文章。
什么是探索性数据分析?



当我在考虑我应该开始写博客的第一个话题是什么时,EDA 立刻出现在我的脑海中。逻辑上很贴切,不是吗?!为什么?你很快就会知道了!
直觉
想象一下你的狼群决定去看一部你没听过的电影。这是绝对没有争议的,它会导致你发现自己被许多问题所困扰,而这些问题需要得到回答才能做出决定。做一个好酋长你会问的第一个问题是,这部电影的演员和工作人员是什么?作为惯例,你还会在 YouTube 上观看这部电影的预告片。此外,你还可以找到观众对这部电影的评价和评论。
无论你最终在影院为你的家族购买爆米花之前会采取什么样的调查措施,都只不过是数据科学家的行话所说的“探索性数据分析”。
探索性数据分析是指对数据进行初步调查的关键过程,以便发现模式,发现异常,测试假设,并借助汇总统计数据和图表检查假设。
首先理解数据并尝试从中收集尽可能多的见解是一个很好的做法。EDA 就是在数据被弄脏之前,理解手头的数据。
EDA 用样本数据集解释:
为了分享我对我所知道的概念和技术的理解,我将以 UCI 机器学习知识库上的葡萄酒质量数据集的白色变体为例,并尝试使用 EDA 从数据集中获取尽可能多的见解。
首先,我导入了必要的库(在本例中是 pandas、numpy、matplotlib 和 seaborn)并加载了数据集。
注意:无论我能得出什么样的推论,我都提到了要点。

- 原始数据由分隔符“;”分隔在给定的数据集中。
- 为了仔细查看这些数据“帮了大忙了。head()" pandas 库的函数,它返回数据集的前五个观察值。同样”。tail()"返回数据集的最后五个观察值。
我用“.”找出了数据集中的行和列的总数。形”。

- 数据集由 4898 个观察值和 12 个特征组成。
- 其中一个是因变量,其余 11 个是自变量——物理化学特性。
了解列及其对应的数据类型,以及发现它们是否包含空值,也是一个很好的做法。

- 数据只有浮点值和整数值。
- 没有变量列具有空值/缺失值。
pandas 中的 describe()函数在获取各种汇总统计数据时非常方便。该函数返回数据的计数、平均值、标准差、最小值和最大值以及分位数。

- 在这里,您可以注意到平均值小于每列的中间值,中间值由索引列中的 50%(第 50 个百分位)表示。
- 预测值“残余糖”、“游离二氧化硫”、“总二氧化硫”的最大值与 75%之间存在显著差异。
- 因此,观察 1 和 2 表明,在我们的数据集中存在极端值-异常值。
仅通过观察因变量得出的一些关键见解如下:

- 目标变量/因变量本质上是离散的和分类的。
- “质量”评分范围为 1 至 10 分;其中 1 表示差,10 表示最好。
- 1、2 和 10 质量等级不是由任何观察给出的。只有获得的分数在 3 到 9 之间。

- 这告诉我们按降序排列的每个质量分数的投票数。
- “质量”的大多数值集中在类别 5、6 和 7 中。
- 对于第 3 类和第 9 类,只做了一些观察。
我很好地浏览了一下数据。但这就是数据科学,你参与的越多,就越难停止探索。现在让我们用漂亮的图表来探索数据。Python 有一个可视化库, Seaborn ,它构建在 matplotlib 之上。它提供了非常有吸引力的统计图,以便执行单变量和多变量分析。
要使用线性回归建模,必须移除相关变量以改进模型。人们可以用熊猫来寻找相关性。corr()"函数,并可以使用 seaborn 中的热图来可视化相关矩阵。

Heatmap
- 深色代表正相关,而浅色代表负相关。
- 如果设置 annot=True,您将获得格网单元中要素相互关联的值。
在特征选择过程中移除相关变量是一个很好的做法。

Correlation Matrix
- 这里我们可以推断“密度”与“残糖”有很强的正相关性,而与“酒精”有很强的负相关性。
- “游离二氧化硫”和“柠檬酸”与“品质”几乎没有相关性。
- 由于相关性为零,我们可以推断这两个预测值之间没有线性关系。但是,在对数据集应用线性回归模型的情况下,删除这些要素是安全的。
箱线图(或盒须图)以一种便于变量间比较的方式显示定量数据的分布。该框显示数据集的四分位数,而触须延伸以显示分布的其余部分。
盒状图(也称为盒须图)是一种基于五个数字摘要显示数据分布的标准化方法:
- 最低限度
- 第一四分位数
- 中位数
- 第三个四分位数
- 最大值。
在最简单的箱线图中,中间的矩形跨越第一个四分位数到第三个四分位数(四分位数间距或 IQR)。
矩形内的一段显示了中间值,方框上下的“胡须”显示了最小值和最大值的位置。

Boxplot
异常值要么高于第三个四分位数 1.5 倍 IQR,要么低于第一个四分位数 1.5 倍 IQR。
- 在我们的数据集中,除了“酒精”之外,所有其他特性列都显示异常值。
现在,要检查变量的线性度,绘制分布图并寻找特征的偏斜度是一个很好的做法。核密度估计(kde)是绘制分布形状的一个非常有用的工具。

Distribution Plot
- “pH”列似乎呈正态分布
- 剩余的所有独立变量都是右偏/正偏的。
最后,总结所有的探索性数据分析是一种哲学和艺术的方法来衡量早期接触的数据的每一个细微差别。
你可以浏览我的 jupyter 笔记本 这里 并且尝试用不同的方法进行测试,例如,尝试一个 pairplot 并且分享你可以从中获得的所有推论,或者如果我在我自己的方法中没有捕捉到任何有用的信息,也请在评论中分享。
阅读我发表的其他文章—
Kaggle 竞赛初学者的探索性数据分析(EDA)技术
EDA 和数据科学竞赛初学者实践指南

Photo by Andrew Neel on Unsplash
E 探索性数据分析 ( EDA )是一种分析数据集以总结其主要特征的方法,通常采用可视化方法。以下是 EDA 中涉及的不同步骤:
- 数据收集
- 数据清理
- 数据预处理
- 数据可视化
数据收集
数据收集是以一种既定的系统方式收集信息的过程,这种方式使人们能够轻松地检验假设和评估结果。

获得数据后,我们需要检查要素的数据类型。
有以下类型的功能:
- 数字的
- 绝对的
- 序数
- 日期时间
- 协调
为了了解数据的数据类型/特征,我们需要运行以下命令:
train_data.dtypes

或者
train_data.info()

让我们看一下关于我们数据集的统计摘要。
train_data.describe()

数据清理
数据清理是通过识别数据中的任何错误或通过更正或删除丢失的数据来确保您的数据正确可用的过程。参考此链接进行数据清理。
一旦数据是干净的,我们可以进一步进行数据预处理。
数据预处理
数据预处理是一种数据挖掘技术,涉及将原始数据转换成可理解的格式。它包括标准化和规范化、变换、特征提取和选择等。数据预处理的产品是最终的训练数据集。
数据可视化
数据可视化是信息和数据的图形表示。它使用统计图、曲线图、信息图和其他工具清晰高效地传达信息。
在这里,我们将重点放在常用的 Seaborn 可视化。Seaborn 是一个基于 matplotlib 的 Python 数据可视化库。它提供了一个高层次的界面来绘制有吸引力的和信息丰富的统计图形。
以下是常用的 seaborn 可视化
- 散点图
- 箱形图
- 柱状图
- 猫图
- 小提琴情节
- 配对图
- 联合地块
- 热图
导入 seaborn 库
import seaborn as sns
散点图
散点图是绘制在水平轴和垂直轴上的一组点。
下面的散点图显示了乘客年龄和乘客票价之间的关系,基于从泰坦尼克号数据集获取的数据的 pclass(客票等级)
sns.scatterplot(x="Age", y="Fare", hue = 'Pclass', data=train_data)

箱形图
箱形图是在图上表示统计数据的一种简单方法,在图上画一个矩形来表示第二个和第三个四分位数,通常用一条垂直线来表示中间值。上下四分位数显示为矩形两侧的水平线。

下图显示了乘客票价如何根据机票等级而变化。
sns.boxplot(x="Pclass", y="Fare",data= train_data)

柱状图
直方图是数字数据分布的精确表示。它是对连续变量的概率分布的估计
sns.distplot( train_data['Pclass'], kde=False)

猫图
Cat plot 提供了对几个轴级函数的访问,这些函数使用几个可视化表示中的一个来显示数值变量与一个或多个分类变量之间的关系。我们可以使用不同种类的绘图来绘制(对应于分类绘图函数的名称)选项有:“点”、“条”、“带”、“群”、“框”或“小提琴”。更多关于猫情节的细节在这里
下面我们用条形做一个猫图
sns.catplot(x="Embarked", y="Survived", hue="Sex",col="Pclass", kind = 'bar',data=train_data, palette = "rainbow")

让我们看看同样的猫情节与小提琴类
sns.catplot(x="Embarked", y="Survived", hue="Sex",col="Pclass", kind = 'violin',data=train_data, palette = "rainbow")

小提琴情节
小提琴图与盒须图的作用相似。它显示了数量数据在一个(或多个)分类变量的几个级别上的分布,以便对这些分布进行比较。关于小提琴剧情的更多细节是这里
sns.violinplot(x='Sex', y='Survived',data=train_data)

配对图
seaborn 中的 Pair plot 仅绘制数字列,尽管稍后我们将使用分类变量进行着色。更多关于双人剧情的是这里。
sns.pairplot(train_data, hue="Sex")

联合地块
Jointplot 是 seaborn 库特定的,可用于快速可视化和分析两个变量之间的关系,并描述它们在同一图上的单独分布。
更多关于联合剧情的是这里。
sns.jointplot(x="Age", y="Fare", data=train_data, color ='green')

热图
热图是以地图或图表的形式表示数据,其中数据值用颜色表示。
sns.heatmap(train_data.corr(), fmt = ".2f")

这篇文章到此为止,希望对你有所帮助。干杯!
原载于 2018 年 11 月 25 日confusedcoders.com。
探索性数据分析、特征工程和使用超市销售数据的建模。第一部分。
通过处理真实世界的数据集,学习数据分析和见解生成的基础知识。

source: pixabay
在这一系列的文章中,我们将深入并全面探索数据探索、特征工程和建模的神奇世界。如果您是机器学习和数据科学的初学者,并且需要对这些概念进行实用和直观的解释,那么本系列适合您。
这个系列分为三个部分,我将在接下来的几周内撰写。
第 1 部分:学习如何探索数据集并从中获得洞察力。
第二部分:通过数据探索 学到特征工程的基础知识。
第三部分: 造型与特征重要性 。
在我们开始这个旅程之前,我们需要定义一些我们将在这篇文章和后续文章中使用的重要术语。
一、 EDA (探索性数据分析)什么是 it ?

source: dsguide
探索性数据分析(EDA)是一种对 数据集**进行分析以总结其主要特征的方法,往往带有直观性。一个 统计模型 可以用,也可以不用,但主要是 EDA 是为了看看数据能告诉我们什么,超越正式的建模或假设检验任务。(来源: 维基百科 )**
总之, EDA 可以向我们展示数据中隐藏的关系和属性,甚至在我们将数据扔给机器学习模型之前。
接下来, F.E (特征工程)你是谁?

Source: Data Science Central
特征工程 是利用数据的领域知识来创建使机器学习算法工作的特征的过程。特征工程是机器学习应用的基础,既困难又昂贵。(来源:维基百科)
总之,FE 只是使用您现有的数据集知识来创建新的功能,这些功能可以帮助机器学习模型更好地执行。让我们看一个例子。假设我有一个不同汽车类型的数据集,如下所示;

sample car dataset
现在,假设我想根据数据集中的信息预测汽车的价格,我可以使用我在汽车领域的知识来创建额外的功能,帮助机器学习模型更好地完成这项任务。像车速或引擎类型这样的特征。我甚至可以进一步添加布尔特性,比如:

1.这辆车有信息娱乐系统吗?
2.车上有后座娱乐吗?
3.这辆车是四轮驱动还是四轮驱动?电子贸易公司
你掌握了窍门。
我也可以通过我们所谓的 特征交叉 (下一篇文章中会有更多关于这个的)从现有的特征中创建特征。****
现在我们已经熟悉了术语 EDA 和 FE,让我们获取数据并开始探索。
我们将使用由尼日利亚 数据科学 提供的超市销售数据集。这里有一个 链接 到数据。
我们将使用流行的原型开发工具 Jupyter Notebooks 和抱歉" R "各位,我将使用 Python 进行这次探索。
下载数据后,将其放在与笔记本相同的文件夹中,以便可以访问。启动您的笔记本并导入以下库,如下所示。

- 这里,我们导入 NumPy、pandas 和 matplotlib,它们分别用于数组操作、CSV 文件处理和绘图可视化。
- 这里,我们导入 stats 模块,它包含一些统计函数,比如 norm 和 skew,我们将使用它们来计算一些统计数据。
- 我们进口海博。基于 matplotlib 构建的强大绘图库。我们将用它来创造一些有见地的情节。
- Python 可能会抛出一些烦人的警告,我们使用 ignore_warns 函数来阻止这种情况。
- 我们导入了操作系统,一个可以轻松访问文件和文件夹的软件包。我们使用 os.listdir 来显示我们当前目录(当前工作目录)的内容
接下来,让我们读入数据。

first five rows of our data
- 我们使用 pandas read_csv() 命令读入数据
- 我们打印出数据的前五行。
****注意:我调换了 train.head() 命令,因为我想在一个页面上看到所有的行和列,而不需要水平滚动。
现在我们可以看到我们的数据和它包含的特征。让我们言归正传。

source: pixabay.com
首先,我们需要知道我们的目标变量。
我们可以选择任何特征作为我们的目标,这反过来会告诉我们我们将构建什么样的模型。
例如,如果我们选择 Product_Fat_Content 作为我们的目标变量,那么我们将有一个分类问题,如果我们决定选择 PProduct _ Price,那么它将变成一个回归问题。
但是因为我们在这篇文章中不关心构建模型,我们就假设我们正在尝试预测产品 _ 超市 _ 销售额(超市的总销售额)。****
接下来,我们来了解一下我们的特点。由于特征的数量很少,我们可以手动查看它们,并立即删除那些不值得研究或放入模型的特征。为此,我们将使用我们在超市领域的知识。
我通常拿出笔和纸,画出如下所示的五列,并手动填充所有功能:
特征重要介于==不重要= =原因
不过,你也可以用其他方式来做这件事。让我们来看看这些特征。
- ****产品标识:这是每个特定产品的唯一标识。判决:介于两者之间。
原因:有时最好删除任何唯一的 ID 列,因为我们的模型可能会超出这个范围,但有时它可能会有所帮助。我们可以用这个做实验。 - ****超市标识符:这是每个超市的唯一 ID。
判决:介于两者之间。
原因:同上 - ****产品超市标识符:这是产品和超市标识符的串联。 判断:中间
原因:该特性可以用来代替产品和超市标识符。这可能是两种特征的结合。这可能很重要,但在编码时可能会大大增加我们的维度空间。(稍后会有更多相关内容) - ****产品 _ 重量:产品的重量。
判决:重要
理由:一件商品的重量可能会影响其价格,而价格又会影响超市的总销售额。 - ****产品 _ 脂肪 _ 含量:产品中所含的脂肪量。
判决:重要
理由:脂肪含量也会影响价格,进而对超市总销售额有贡献。 - Product _ Shelf _ Visibility:**根据数据描述,这是分配给一组产品的百分比中的总展示面积。
结论:重要
原因:产品的知名度很可能决定了该产品是否会被顾客看到。这会影响该产品的销售。 - ****产品类型:产品所属的类别。
结论:重要
原因:某种类型的产品一般会比其他产品卖得多。 - ****产品 _ 价格:产品的价格。
判决:重要
原因:这当然是一个重要的特征因为产品的价格肯定会影响我们的目标变量 产品 _ 超市 _ 销售 。 - ****超市 _ 开业 _ 年份:超市开业的年份。
判决:重要
原因:开业年份可能影响产品销量。 - ****超市 _ 大小:这是超市的大小。它被分为小型、中型和高级。
判决:重要
理由:超市的规模可以意味着超市的销售额更多。 - ****超市 _ 位置 _ 类型:该特征是对超市位置的描述。根据数据,有 3 个集群(集群 1、2 和 3)。我们不知道哪个更高,但是我们想保留这个特性。
结论:重要
原因:位置类型可能包含超市所在位置的信息,无论它们是在城市、农村、繁忙还是偏僻的地方。 - ****超市 _ 类型:超市的类型分为杂货店、超市类型 1、超市类型 2、超市类型 3。
结论:重要
原因:它给了我们关于超市的有用信息,这些信息在预测总销售额时可能很重要。 - ****产品 _ 超市 _ 销售:这是我们这个岗位的 目标 变量。它是超市的销售总额。
判决:对,重要!
原因:是我们的目标变量。
现在我们已经手动检查了我们的数据,发现几乎所有的特性都很重要(尽管有些还在检查中),我们可以开始我们的 EDA 了。
当对一个有合理数量的数字列的数据集进行 EDA 时,我喜欢做的第一件事是检查我的目标变量和这些数字特征之间的关系。一个快速的方法是使用 seaborn 热图 图。此 seaborn 热图 采用根据我们的数据集中的数字特征计算的相关矩阵,并对其进行加热绘图。输入下面的代码制作一个热图。

seaborn heatmap plot of correlations
- 首先,我们使用熊猫 计算数据的相关性。corr( ) 函数,然后我们将它存储在变量 corrmat 中
- 这里,我们简单地设置我们的图的图形大小。
- 在这里,我们将 corrmat 传递给seabornfunctionheat map()来制作美丽的剧情。
现在我们来解读一下上面的剧情。看一看它,看看你能从中得到什么启示。
如果你不知道如何解读一个 热图 剧情,下面几段给你。如果有,请跳过。

Heatmap plot of Supermarket dataset
解读热图
热图中的每个方块显示了任意两个特征与的相关程度(它们之间是否存在某种关系)。一个特性的增加会导致另一个特性的增加吗?(正相关)还是一个的增加导致另一个的减少?(负相关)。
- 从 0.0 到 1.0 的垂直范围显示了任意两个要素之间相关性的相对大小,其中较热的值较高,意味着相关性较高。
- 矩阵的几乎发白的对角线部分表示所有特征都与自身高度相关。(当然,他们应该是。)
现在,让我们来解释正方形内的标签。
向左水平追踪 标签 3 引出 产品 _ 重量 垂直向下追踪引出 产品 _ 价格 。这意味着方形的框(3)** 向我们展示了产品 _ 重量和产品 _ 价格的相关程度。我们可以看到它们实际上并不相关,因为正方形几乎是冷的。**
标签 4 显示产品 _ 价格和**产品 _ 超市 _ 销售之间的关联。我们清楚地看到该区域很热,这意味着相关性很高。**
这就是你解读热图的方式。
好了,你已经获得了热图阅读的学位。现在,你开始了你的第一份工作,下面的热图就摆在你面前。

heatmap of dataset

你的老板满怀信心地看着你,认为他雇对了人,并要求你给出答案。
你站起来,看一眼热图,笑着说:

这个图显示了产品价格是与我们感兴趣的目标 【产品 _ 超市 _ 销售】 最相关的特征,根据我们的直觉,如果销售更贵的产品,那么总的产品 _ 超市 _ 销售可能会增加,反之亦然。
你的老板点点头,让你继续。你现在充满了自信,而且还在继续。
我能看到的另一个关联——通过 small——是 产品 _ 价格 和 超市 _ 开业 _ 年份。
你的老板问这是什么意思?
嗯,综上所述,这是在告诉我们,超市开业的年份似乎是影响着产品的价格。它可能是积极的(新超市卖得更多),也可能是消极的(旧超市有更多忠诚的顾客,卖得更多)。我必须对此进行调查并找到更多的信息。
除此之外,这个图没有其他有趣的关联,先生。但这些只是数字特征。我还是要检查分类特征。

source: pixabay.com
你的老板很高兴,他给你一个坚定的握手,并要求你调查进一步向他报告第二天。
你走吧,去做更多的探索。
首先,您决定调查数据集中所有要素之间的关系。因此,您希望根据其他特性来绘制每个特性,但是您希望只绘制一次,而不编写多个 for 循环。
还好, Seaborn 的pair plot()前来救援。

seaborn pairplot on supermarket dataset
如果你以前没有见过 seaborn pairplot,这就是它的样子。基本上就是一个 的单线奇观。我们还可以指定一个分类特征,用于着色。
注意:Seabornpair plot只绘制数字特征,但是我们可以根据所选的分类列为我们的图着色。此外,如果传递给 pairplot 的数据集包含缺失值,它将引发错误。
首先,让我们检查有缺失值的列,这样我们就不会将它们添加到 pairplot 中。

Check for missing values
嗯,我们有两个缺少值的列,Supermarket_size 是一个分类特征,Product_Weight 是一个数值特征。我们将在下一篇文章中讨论这些缺失的特性,现在,让我们将它们从我们的 pairplot( ) 专栏中排除。

code block to pairplot features
- 这里我们列出了数据集中所有的分类特征。(我们将用它们来着色。这意味着每个分类特征都有一组配对图。
- 在 for 循环中,我们列出了所有没有缺失值的列。
- 每次创建一个新的图形
- 调用单行奇迹 pairplot( ) 并传递我们的数据“火车”和我们想要的列。我们指定尺寸为 3.0 ,这样我们就可以看到完整的 pairplot 而无需滚动。
- hue 变量从我们的分类列中提取一列,并使用它们为我们的配对图着色。
运行上面的代码后,我们总共会有四个图。让我们一个接一个地看它们,并试着从中解读或得出见解。
情节一:类别(产品 _ 脂肪 _ 含量)

Plot one: Category (Product_Fat_Content)
释义:
- 我们可以看到绝大多数产品都含有正常脂肪。那么,我们能用这些知识做些什么呢?** 嗯,我们可以创建一个布尔特征列 is_normal_fat 并将正常脂肪(多数类)与另外两个低脂肪和超低脂肪(少数类**)分开。这只是一个建议。****
- 产品价格和超市销售额之间呈正相关趋势。这证实了热图图所示的相关性(正相关)。那么,我们能用这些知识做些什么呢?
- 嗯,这个功能肯定很重要。我们可以从中创造更多的功能。
- 我们还注意到我们的目标变量(产品 _ 超市 _ 销售)和变量产品 _ 货架 _ 可见性是 右偏 。我们可以使用对数函数对它们进行转换,使它们正常偏斜。我们以后再做这个。
- 我们也可以看到 低脂 和 超低脂 的价格相对高于 正常脂 的产品。那么,我们能用这些知识做些什么呢?
嗯,我们可以创建一个分类功能,将 正常脂肪 产品的价格设置为低,将 低/超低脂肪 产品的价格设置为高。 - 我注意到的另一件事是 Supermarket _ Opening _ Year之间似乎有差距。注意 90 年代的超市集群和 2000 年代的另一个集群。我们能用这些知识做些什么?嗯,我们可以创建一个新的特性列来捕获这两个集群。
- 在这一对情节中,我没有注意到任何其他有趣的关系,所以我们继续下一个。
如果你注意到任何其他关系,请在下面留言通知我。
地块二:类别(产品 _ 类型)

Plot two: Category (Product_Type)
释义:
- 从Product _ typecategory家居、健康卫生、** 和 其他 主导剧情。那么,我们能用这些知识做些什么呢?
我们可以创建一个特征列,将数据分为两组,一组捕获 家庭、健康卫生 和 其他 ,另一组捕获其余产品。谁知道呢?这可能是一个很好的功能。** - 其他的似乎都没什么意思。所以我就暂时停在这里,进入下一个情节。
地块三:(超市 _ 位置 _ 类型)

Plot three: (Supermarket_Location_Type)
释义:
- 似乎集群 2 是最昂贵的位置。是产品 _ 价格和产品 _ 超市 _ 销售看起来更高。
- 我们还注意到,集群 2 中的超市较新(2010 年以后)。
- 集群 1 的产品价格较低,集群 2 介于两者之间。那么,我们能用这些知识做些什么呢?
好了,现在我们知道了超市 _ 位置 _ 类型是一个非常重要的特性,它似乎有一些 平凡性 。如果我们要标记编码这个变量,我们应该尽量保持这个顺序结构。
请记住,如果你注意到我错过了任何解释,请使用下面的评论框。
地块四(超市 _ 类型):

Plot four (Supermarket_Type)
释义:
看着这个图,我们可以立即看到不同的超市几乎被精细地分开。我们可以从中获得很多启示:
- 首先,我们可以看到超市类型 3** 的商品价格一般从 350 左右开始,超市类型 1 的商品价格大约在 0-250 之间,而超市类型 2 的商品价格大约在 250-350 之间,最后,杂货店接受所有范围的价格。我们能用这种洞察力做什么?
我们可以创建分类列来捕获这些范围,或者我们可以创建箱并根据价格范围对每个超市进行分组。** - 查看超市 _ 开业 _ 年份,我们立即注意到属于超市类型 3** 的超市都是在 90 年代开业的;这意味着我们之前提议创建的功能——将开放年份划分为两个集群——将非常重要。**
一如既往,如果你注意到我可能错过了任何好的解释,请在下面的评论框中通知我。
哇哦!这是一个漫长的第一个帖子。希望你学到了很多。
在我的下一篇帖子中,我们将谈论 特征工程和创作 。在那里,我们将把我们在做这个 EDA 时收集的所有直觉带入生活。
我给你的临别建议是,你得到一个数据集,戳它,撕开它,找到隐藏的宝石并从中获得洞察力,并从中获得乐趣。

source: pixabay.com
但是请记住,EDA 是一门艺术,它可以用许多不同的方式来完成;上面列出的步骤绝不是你必须严格遵循的大纲。做对你有用的事。

Source: Pixabay.com
所以,去享受探险的乐趣吧。再见了。
本帖的笔记本和资料可以在 这里 找到
欢迎提问、评论和投稿。
在 twitter 上跟我连线。
在insta gram上跟我连线。****
R 中的探索性数据分析-使用伪脸书数据集探索一个变量
根据维基百科,“ 探索性数据分析(EDA)是一种分析 data 集合以总结其主要特征的方法,通常采用可视化方法。可以使用或不使用统计模型,但 EDA 主要是为了查看数据可以告诉我们什么,而不仅仅是正式的建模或假设测试任务。
EDA 是一个让数据给你惊喜的机会。回想调查的目标,重新思考我们试图回答什么问题。识别可能导致意外结果的数据特征。
作为一个实际的例子,我们将使用由 Udacity 整理的 facebook 数据集。该数据集有近 99,000 个观察值和 15 个变量,即对于每个观察值,我们都有用户的不同信息,如姓名、年龄、出生日期。
我们的目标是了解用户的行为和他们的人口统计数据。因此,我们有诸如 friend_count、likes_received 等变量。
使用 ggplot
ggplot 是一个用于统计编程语言 r 的数据可视化包。它是为了用最少的代码行为数据分析设计优雅的可视化而构建的。您可以使用以下功能下载并安装 ggplot 库
install.packages('ggplot2')
qplot — qplot 代表快速绘图,可用于绘制直方图。
1。生日等级分析
为伪 facebook 数据集中出现的所有用户的生日绘制直方图。

Histogram using qplot
在上面的图中,假设我们需要为一个月中的每一天绘制一个清晰的图形,那么我们需要添加scale_x_continuous,这是连续 x 美学的默认比例。

Histogram using qplot with continuous x axis scale
绘制直方图的另一种方法是使用 ggplot()

Use of binwidth in ggplot2()
这里的线条是等间距的,因为我们还指定了 binwidth。同样在上面的图中,我们观察到大多数人在每个月的第一天出生,这看起来很奇怪。让我们使用刻面来深入研究这个问题。
刻面
在某些情况下,我们希望绘制多个数据子集中的集合变量之间的关系,结果显示为面板。这是 ggplot2 的一个漂亮的特性。分面由分类变量定义。facet_wrap 和facet_grid用于 r 中的刻面

Faceting in R
从上面可以推断,只有第一个月,即一月,由出生于第一天的大多数用户组成。这可以是数据集中的默认值,也可以是异常值。
极端值
远离数据集中其他值的值称为异常值。异常值会影响均值和标准差等测量值。异常值可能是关于极端情况的准确数据,或者是由于数据集中的一些变量被顶部编码或底部编码,即一些变量被设置了最大或最小限制。
2.朋友级别分析
画出用户的生日后,让我们画出每组观察的朋友数量。

Long tail graph for number of friends of each observation
这种类型的图叫做长尾图。该图是这样的,因为许多人在 500 范围内有脸书朋友,因此我们在左边得到高的箱子。但是有些用户有很多朋友,可能多达 5000 个,这是一个用户可以拥有的最大朋友数量。为了进一步研究这个尾巴中的一些其他观察结果,我们将不得不检查朋友数低于 1000 的用户。
为了避免看到这种长尾数据,我们可以使用以下方法之一:
- qplot 内的 xlim 参数。这个参数取一个向量,我们有轴的开始位置和结束位置。
qplot(x=friend_count,data=pf,xlim=c(0,1000))
2.添加一个层并在scale_x_continuous内使用限制
qplot(x=friend_count,data=pf) +
scale_x_continuous(limits=c(0,1000))
这两个步骤都会产生下图

现在让我们添加一些更好的标签和一些宁滨。要调整 binwidth,我们可以传递 binwidth 参数 25,我们也将每隔 50 个单位断开 x 轴,这可以通过将 breaks 参数传递给 scale_x_continuous 层来实现。

从上面的图表我们可以知道,许多用户的朋友少于 25 个。因此,他们可以被认为是新用户。
3.性别水平分析

Gender Level Analysis
当我们绘制朋友的性别等级数量时,我们发现很多性别被归入 NA 类别。去掉 NA 后,我们得到下图。
qplot(x = friend_count, data = subset(pf,!is.na(gender)), binwidth = 10) +
scale_x_continuous(limits = c(0, 1000),
breaks = seq(0, 1000, 100)) +
facet_wrap(gender ~ .)

Gender Level Analysis — Removing NA
4.任期水平分析
用户的天级任期是下面给出的数据集。请注意,参数 color 决定图中对象的颜色轮廓,而参数 fill 决定图中对象内部区域的颜色。
qplot(x=tenure,data=pf,
color=I('black'),fill=I('#632b6c'))

Daily Tenure Level Analysis
如果我们希望看到年级别的任期,那么使用下面的代码, xlab 和 ylab 是为图分配标签的参数。
qplot(x=tenure/365,data=pf,binwidth=0.25,
xlab="Number of years using facebook",
ylab="Number of users in sample",
color=I('black'),
fill=I('#632b6c')) +
scale_x_continuous(breaks = seq(1, 7, 1),limits=c(0,7))

Yearly Tenure Level Analysis
github 上共享了使用权图的等效 ggplot 语法。
5.年龄层次分析
绘制年龄水平直方图显示,对于某些特定的年龄,存在某些峰值,并且存在一些一百岁的用户,这在此刻看起来相当奇怪。
qplot(x=age,data=pf,xlim=c(0,200),binwidth=1,
xlab="Number of years using facebook",
ylab="Number of users in sample",
color=I('black')
,fill=I('#95ada5')) +
scale_x_continuous(breaks=seq(10,130,5))

Age Level Analysis
转换数据
在生成汇总统计数据时,我们经常会发现一些情况,例如,一些值比中间值大 10 或 100 倍。乍一看,这可能被认为是异常值,但当深入研究时,会发现这是正确的数据。在我们的伪脸书数据集的情况下,可能一些用户比大多数用户具有更高的喜欢和评论量。在统计学中,我们说数据过于分散。通常它有助于转换这些值,所以我们可以看到标准差,所以简单地说,我们只是缩短了尾巴。
从用户级别的好友计数直方图,我们知道我们的直方图有一个长尾。我们可以通过取对数(以 2 为底或以 10 为底)或平方根来转换这个变量,这将帮助我们更清楚地找到一个模式,而不会被尾部所偏离。
统计技术,如线性回归,是基于假设变量具有正态分布。因此,通过取对数,我们可以将数据转换成更接近正态分布的形式,这对于建模来说是有效的。虽然本文的范围仅限于探索性的数据分析,但是让我们看看变量转换后的情况。

Data transformation
从上图中可以推断出,变量 friend count 下所有观察值的对数是正态分布的,可以用于线性回归。
频数多边形
正如在线统计手册、中所定义的,频率多边形是一种用于理解分布形状的图形设备。它们的作用与直方图相同,但在比较数据集时尤其有用。”
频率多边形类似于直方图,但它们绘制了一条连接直方图中计数的曲线,从而使我们能够更详细地观察分布的形状和峰值。
qplot(x = friend_count,
data = subset(pf,!is.na(gender)),
xlab="Number of users using facebook",
ylab="Number of friends per user",
binwidth = 10
, geom="freqpoly",color=gender) +
scale_x_continuous(limits = c(0, 1000),
breaks = seq(0, 1000, 100))

箱形图
我们将生成一个按性别划分的好友数量的箱线图
qplot(x=gender
,y=friend_count
,data= subset(pf,!is.na(gender))
,geom='boxplot')

BoxPlot 1 — Gender Level Total Friends
上面方框图中的黑色水平线是中间值,这意味着上面图中的大多数小点都是异常值。我们认为异常值是中位数的四分位数范围的一倍半。按照这种逻辑,这个数据集中有很多离群值。
为了解决这个问题,我们调整了代码,将重点放在好友数量在 0 到 1000 之间的用户上。
qplot(x=gender
,y=friend_count
,data= subset(pf,!is.na(gender))
,geom='boxplot')+
coord_cartesian(ylim=c(0,1000))

BoxPlot 2— Gender Level Total Friends
在上图中,我们将scale _ y _ continuous(limits = c(0,1000)) 替换为 coord_cartesian(ylim=c(0,1000)) 。我们这样做是为了让表格摘要与我们的方框图相匹配(查看 github 了解更多细节)。
结论
在一个变量的探索性数据分析中,我们知道每个变量都是重要的,它们可能有一些隐藏的特征,直到我们绘制它们时才显现出来。接下来,我们将通过探索两个变量来讨论 EDA。
GapMinder 全球数据的探索性数据分析

Hans Rosling/GapMinder
在这篇文章中,我对来自 GapMinder 的两个数据集进行了探索性的数据分析( EDA )。这个帖子包括使用的 R 代码(也可以在这个 GitHub repo 中找到)。总而言之:
- 方法:探索性数据分析、相关、线性回归
- 程序/平台:R/RStudio
- 资料来源:世界卫生组织、世界银行
数据
在这个数据分析中,我使用了 GapMinder 的数据网页上的数据。具体来说,我专注于:
这个问题
我在这个分析中提出的问题是:
在 15-49 岁年龄段中,人均国内生产总值和艾滋病毒感染率之间是否存在关联?如果是,这种相关性有多强?
我的预期是,人均 GDP 和艾滋病毒流行率之间存在负相关关系;这意味着越穷的国家艾滋病毒感染率越高。
数据争论
让我们在 R 中对从 GapMinder 下载的 CSV 文件进行一些初始数据辩论,为我们的数据分析做准备。
人均国内生产总值数据
来自 GapMinder 的数据是 CSV 文件的形式,需要根据原始 CSV 表中的键值对进行重新组织。我使用了惊人的' tidyr '库中的函数 gather() 。
让我们来看看生成的数据帧结构,并确定该数据集涵盖的时间范围:
**## 'data.frame': 14300 obs. of 3 variables:
## $ Income per person (fixed 2000 US$):
Factor w/ 275 levels "Abkhazia","Afghanistan",..: 1 2 3 5 6 7 8 9 10 12 ...
## $ Year : int 1960 1960 1960 1960 1960 1960 1960 1960 1960 1960 ...
## $ GDP : num NA NA NA NA 1280 ...**
**## [1] 1960 2011**
产生的数据框架包含 3 个变量(国家、年份、GDP)的 14,300 个观察值。“国家”一栏列出了 275 个国家。提供了 275 个国家从 1960 年至 2011 年的人均国内生产总值。
艾滋病毒流行率数据
让我们对艾滋病毒流行率数据进行类似的数据整理。同样,我将使用来自“ tidyr ”库中的函数 gather() 。
同样,让我们来看看生成的数据帧的结构:
**## 'data.frame': 9075 obs. of 3 variables:
## $ Estimated HIV Prevalence% - (Ages 15-49):
Factor w/ 275 levels "Abkhazia","Afghanistan",..: 1 2 3 5 6 7 8 9 10 12 ...
## $ Year : int 1979 1979 1979 1979 1979 1979 1979 1979 1979 1979 ...
## $ HIV_prev : num NA NA NA NA NA ...**
由此产生的数据框架包括 3 个变量(国家、年份、估计的艾滋病毒流行率)的 9075 个观察值。“国家”一栏列出了 275 个国家。提供了 275 个国家从 1979 年至 2011 年的人均国内生产总值。
组合数据帧
让我们结合这两个数据框架来比较人均 GDP 和艾滋病流行率。我正在使用 【合并() 功能。接下来,让我们来看看结果数据帧的结构。
**## 'data.frame': 9075 obs. of 4 variables:
## $ Country : Factor w/ 275 levels "Abkhazia","Afghanistan",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ Year : int 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 ...
## $ GDP : num NA NA NA NA NA NA NA NA NA NA ...
## $ HIV_prev: num NA NA NA NA NA NA NA NA NA NA ...**
我们现在有了一个用于后续数据探索的数据框架。该数据框架分为四栏:(一)国家,(二)年份,(三)该国该年的人均国内生产总值,(四)该国该年的艾滋病毒流行率。
探索数据
数据集通常以缺失数据为特征。我怀疑这个数据集也是如此,即使它来自一个官方组织。让我们来看看缺失的 GDP 数据在综合数据框架中所占的百分比。
**## [1] 35.30579**
综合数据框架中约 35.3%的人均国内生产总值列有缺失数据。这是相当可观的,很可能是因为持续的 GDP 测量成本很高,而且只是在过去几十年才开始(注意:世界银行成立于二战后的 1945 年)。
在随后的分析中,缺失的数据将被排除(即不绘制),而不是用平均值或估计值代替缺失的数据。
让我们来看看艾滋病毒流行率方面缺失数据的百分比。
**## [1] 63.62534**
在综合数据框架中,艾滋病毒流行缺失数据的比例甚至更高,达到 63.6%。这当然是因为世界卫生组织的初始数据框架包括了始于 1979 年的时间框架,而我们的综合数据框架始于 1960 年。
自 20 世纪 80 年代初,HIV/Aids 成为公认的重大健康危机后,HIV 相关指标的一致性测量才真正大规模开展。
让我们从两组数据中初步了解一下分布的类型。对于人均国内生产总值:
**## Min. - 1st Qu. - Median - Mean - 3rd Qu. - Max. - NA's
## 54.51 - 590.26 - 2038.88 - 7315.07 - 9239.73 - 108111.21 - 3204**
关于艾滋病毒流行率:
**## Min. - 1st Qu. - Median - Mean - 3rd Qu. - Max. - NA's
## 0.010 - 0.100 - 0.300 - 1.743 - 1.200 - 26.500 - 5774**
快速浏览清楚地显示,在我们的数据框架中,一些国家显著提高了分布的平均值(与中位数相比)。艾滋病毒流行率数据尤其如此。
情节
在本节中,我生成了各种图(使用 ggplot )来获得分布的概况,并试图确定趋势和模式。
首先,我们查看整个数据集,并生成一个散点图,显示 1960 年至 2011 年数据集中所列的 275 个国家的人均 GDP。
我们还覆盖了平均值和上下限(5%;95%)的 GDP。这将使我们更好地理解我们的大部分分布在哪里。

该图显示了 1960 年至 2011 年间全球 GDP 的总体增长趋势。大部分数据属于最高人均国内生产总值 30,000 美元(2,000 先令)。
让我们通过生成我们的数据集中所列的 275 个国家从 1960 年到 2011 年的艾滋病毒流行率散点图来查看艾滋病毒流行率的数据集。
与人均 GPD 类似,我们也叠加了平均值和上下限(5%;95%)的艾滋病毒感染率。我们将关注 1985 年至 2011 年的数据。

根据我们的数据,艾滋病毒感染率在 1985 年至 2011 年期间有所上升,平均水平从 2000 年代初开始停滞,自 2005 年以来略有下降。这将对应于预防措施的进步,以减少感染艾滋病毒的发生率和可能性。
相关和线性回归
现在,让我们将重点放在我们之前创建的组合数据框架上,以研究两个感兴趣的变量之间的相关性。为了先看一下相关性,让我们画出 HIV 感染率与人均 GDP 的关系图。

散点图清楚地表明,与人均国内生产总值较高的国家相比,人均国内生产总值较低的数据点(即国家)的艾滋病毒流行率要高得多。
让我们通过创建一个将平方根标度应用于 x 轴的图来进一步强调人均 GDP 较低的国家。我们还将使用 R 函数 geom_smooth() 来执行简单的线性回归,以更好地显示两个变量之间的关系。

上面的散点图进一步表明,人均国内生产总值较高的国家平均艾滋病毒感染率较高。
让我们使用皮尔逊方法计算两个变量之间的相关系数。
**## ## Pearson's product-moment correlation
## ## data: gdp.HIV$HIV_prev and gdp.HIV$GDP
## t = -10.938, df = 3183, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## -0.2235800 -0.1566303
## sample estimates:
## **cor**
## **-0.1903264****
得到的相关系数是-0.19,这是一个负的但微弱的相关性。这与上面绘制的线性回归相匹配。
这种负相关但很弱的负相关与其他发表的结果相匹配,这些结果发现个人的财富(而不是个人居住国家的人均 GDP)是个人特定社区内艾滋病毒流行率的更强指标。
结束语
在这个项目中,我们从公共来源(GapMinder,世卫组织,世行)收集数据。我们进行了数据辩论和初步的探索性数据分析。然后,我们推导出一个相关因子,并应用线性回归来评估两个感兴趣的变量(人均国内生产总值、艾滋病毒流行率)之间的线性关系。
对伦敦不同类型犯罪之间关系的探索性数据分析
最近,我制作了一张地图,标出了伦敦警察局记录的 14 种不同类型的犯罪地点。这让我思考是否有某些类型的犯罪更有可能一起发生(例如,犯罪之间是否存在关系)。
我最初的假设是,因为我们正在处理犯罪问题,如果一个地区的犯罪率较高,那么该地区的所有类型的犯罪率通常都会较高,反之亦然。然而,我想更深入地探讨各种类型的犯罪之间的关系以及犯罪发生的地点。
大量的数据使得简单地使用我创建的互动图来直观地查看一些犯罪是否倾向于一起发生变得有点困难。
数据概述
本次分析中使用的数据与我在之前的帖子中使用的数据相同,只是这次我用纬度和经度变量替换了 LSOA(低层超级输出区域)名称定义的犯罪发生区域。这是因为我对每个犯罪事件的确切位置不感兴趣,而是对各种犯罪发生的区域感兴趣。不涉及太多细节,LSOA 是对较小地区的人口普查测量,基于从 1000 到 3000 的人口规模和从 400 到 1200 的家庭。更多信息可以在国家档案馆网站和伦敦数据商店网站上找到。
根据数据集定义,总共有 5149 个 LSOA 地区在 2016 年经历了 14 种不同类型的犯罪中的至少一种。
方法
首先,我需要使用基本的描述性统计和可视化进行一些探索性分析,以提供对数据的总结和理解,并识别任何模式和特征。为了观察哪些犯罪可能一起发生,我设想使用 k-means 聚类来将这些特定的犯罪分组在一起。在进行聚类之前,我需要将数据的维度从 14 个变量(犯罪类型)减少到一个更容易解释和可视化的数量,同时仍然考虑所有类型的犯罪。为此,我选择使用主成分分析。
用于此分析的代码可以在 Github 上找到。
第 1 部分:探索性数据分析
从对数据的基本总结开始,很明显,每种类型的犯罪都经历了非常广泛的发生率。14 种犯罪中有 5 种的第一个四分位数为 0,所有犯罪类型的最大值都显著高于各自的第三个四分位数。这可以通过创建 14 种不同类型犯罪的方框图来看出(图 1)。同样清楚的是,每项犯罪都有大量的异常值。因此,这个箱线图对于可视化每个犯罪的分布不是很有用,所以我为此创建了另一个没有异常值的箱线图(图 2)。

Figure 1: Box plot of the 14 different types of crime including all the data

Figure 2: Box plot of the 14 types of crime without the outliers
通过查看图 1,很难理解每种犯罪的大量异常值和零值,因此我计算了每种犯罪的内部上限值,然后确定有多少区域记录的发生率高于每种犯罪的内部上限值(即外部上限值)。这一点可以在表 1 中看到,其中有一栏列出了每种类型的犯罪都没有发生的地区的数量。

Table 1: List of the 14 types of crime and their respective upper inner fence value, the number of areas that recorded outliers and the number of areas that recorded zero incidences for any particular type of crime.
这现在开始提供数据的一些特征以及 14 种犯罪类型之间分布的差异。我们也越来越了解每起犯罪可以解释多少差异。我计算了每项犯罪的方差,其中“反社会行为”的方差最大,为 3437.2,而“持有武器”的方差最小,仅为 4.3。为这两个变量创建直方图可以更详细地解释它们的分布。

Figure 3: Histogram for anti social behaviour

Figure 4: Histogram for possession of weapons
可以看出,在 5149 个地区中,有 4000 多个地区的“拥有武器”发生率为零或为零。上表也证实了这一点,我们可以看出,这些值中的大多数实际上为零,因为“拥有武器”有 3022 个地区的发生率为零。
“反社会行为”在每个地区记录的事件数量中有更广泛的分布。从上表可以看出,“反社会行为”有 279 个零发生率区域,这少于上异常值的数量(345)。
第二部分:犯罪类型的关系
在对数据和数据中的某些特征有了更详细的理解之后,下一步是探索不同类型犯罪之间的关系。
人们可以从制作 14 种犯罪的相关矩阵开始。即使相关矩阵确定了某些类型的犯罪比其他类型的犯罪具有更高的相关性,也很难理解所有 14 种犯罪之间的这些关系。制作所有 14 种犯罪的散点图也很难解释。
在不涉及太多细节的情况下,主成分分析(PCA)因此可以用于将数据的维度减少到更少的成分,这将尽可能多地保留原始数据所表达的可变性。更少的组成部分将有助于描述原始变量之间的关系,方法是将它们投影到二维网格上,以便更容易地进行可视化,从中可以将相似类型的犯罪分组在一起。
PCA 结果提供了 14 个分量(等于变量的数量),分量的重要性可以通过每个分量所占方差的比例来确定。在该分析中,前两个成分分别占方差的 60%和 7%。第一个分量明显高于其余分量,总方差的 80%归因于前 4 个分量。这可以通过每个成分的累积方差比例的折线图来可视化(图 5)。

Figure 5: Proportion of variance explained by each component displayed showing the cumulative proportion of variance.
该图有助于确定保留用于分析的成分数量。很明显,第一个分量是最重要的分量,其后的分量所解释的差异量变化很小,因此在分析中只需要保留前两个分量。
最后,为了确定不同类型的犯罪之间的关系,可以使用前两个主要部分,使用双标图(图 6)进行直观解释。双标图显示代表每个变量的向量,这些向量远离原点,指向由前两个主成分分配给每个变量的值。它还包括分配给数据集中每个区域(5149)的两个组件的值,但是,此分析的重点更多地是变量(犯罪类型)的向量之间的关系。

Figure 6: Biplot representing the values assigned to the variables (crime types) and data points (areas) by the first two principal components.
解释该图时需要考虑的两个因素是矢量的长度和它们之间的角度。较长的向量意味着变量被图很好地表示,反之亦然。向量之间的角度大小决定了变量的相关性,这是实现此分析目标的理想指标。小角度表示强正相关,90 度表示不相关,180 度表示负相关。
由于拥挤,很难解释这一情节,但是,很明显,在比较“其他犯罪”与其他类型犯罪的关系时,“其他犯罪”似乎有点离群。可以生成分配给 14 种犯罪类型的前两个分量值的散点图,以便从双标图中更好地显示其他犯罪类型之间的关系。没有显示两个非常相似的图,一个单独显示散点图,另一个只添加了 K-means 聚类输出,我只是包含了后者(图 7)。

Figure 7: Scatter plot displaying the 14 different types of crime along with their respective clusters.
通过这个情节,各种类型的犯罪之间的关系开始变得更加明显。除了已经被确定为异常值并在此重申的“其他犯罪”之外,还有其他两个变量分组(1 和 3)。在群组 1 和群组 3 中,可以确定某些类型的犯罪比其他类型的犯罪具有更强的关联性。例如,在第一组中,“刑事破坏和纵火”、“反社会行为”、“毒品”、“公共秩序”和“暴力和性犯罪”被认为是密切相关的。而在群组 3 中,“自行车盗窃”、“入室盗窃”、“抢劫”和“偷窃他人”密切相关。
我没有深入分析这些犯罪发生的具体区域,因为我将违反这一分析的范围,所以我将把这一点留给另一篇文章,我制作了一个表格来查看每个犯罪发生率最高的区域。从表 2 中可以看出这一点,表中列出了各地区每种犯罪的发生率,突出显示的单元格代表该特定类型犯罪记录的最高数字。

Table 2: List of areas that had recorded the highest figure for each type of crime.
有趣的观察结果是,有两个地区(威斯敏斯特 018A 和威斯敏斯特 013E)记录了 4 种不同类型犯罪的最高发生率:
威斯敏斯特 018A -“反社会行为”、“刑事破坏和纵火”、“公共秩序”和“暴力和性犯罪”。
威斯敏斯特 013E -“入室盗窃”、“其他盗窃”、“入店行窃”和“偷窃他人财物”。
这些犯罪非常类似于前一情节中产生的集群中被确定为彼此相关的两组明显不同的犯罪类型。
结论
这篇文章开头列出的目标是深入挖掘 2016 年伦敦记录的不同类型的犯罪事件,并确定某些类型的犯罪之间是否存在任何关系。
这是通过一些探索性的数据分析方法进行分析的,以确定数据的特征,然后使用主成分分析来降低数据的维度,从而可以使用 K-均值聚类来可视化某些类型的犯罪之间的关系。
进行这一分析是因为我在以前的帖子中获得了一些好奇心,在那里我绘制了不同犯罪的地理位置。我已经开始考虑的下一步是探索不同地区的犯罪概况,并确定某些地区是否可能经历类似的犯罪,以及这些犯罪彼此之间的关系。
探索性数据分析(JHU 课程,课程 4)

数据科学专业的第四门课程“探索性数据分析”还不错。没有开始任何建模有点令人沮丧,但课程的很大一部分是绘图,这是一项基本技能。一如既往,测验和作业的代码位于我的 github 上。
第一周回顾:分析图形和基本绘图系统的基础有点令人失望。测验看起来不太实用,但我希望第二周更实用。任务本身并不太糟糕。
Exploratory Data Analysis Quiz 1
Exploratory Data Analysis John Hopkins Project 1
第二周回顾:第二周远比第一周实用,因为它涉及到了 ggplot,这是 R 中主要的绘图库,在工业中广泛使用。小测验其实是让人理解 ggplot 的。
Exploratory Data Analysis Quiz 2 JHU Coursera
第三周回顾:终于!令人高兴的是,这种专门化正在进入广泛使用的层次聚类和 K-Means 聚类。不幸的是,没有测验来测试知识,也没有在课程的其他地方涉及。本周没有作业到期,所以这是一个很好的喘息机会。
第 4 周回顾:空气污染案例研究是一个非常好的项目,因为它让人们下载解压文件,对数据进行清理和聚合,绘制并导出 png 文件。
Exploratory Data Analysis Project 2 John Hopkins Coursera
请让我知道你是否有任何问题,或者如果你有任何关于我如何改进我的编码技巧!这个约翰·霍普斯金专业甚至帮助了我的工作。下一门课程“可重复研究”的复习已上线。
电子商务数据的探索性数据分析
发现不同客户和国家的有趣交易模式

(Source)
一般的解释,数据科学无非是利用先进的统计和机器学习技术,利用数据解决各种问题。然而,更容易的是直接应用一些奇特的机器学习算法——瞧!你得到了预测——没有首先理解数据。
这正是探索性数据分析(EDA) (由贾迪普·哈雷定义)的重要性所在,不幸的是,这是作为数据科学过程的一部分通常被低估的步骤。
EDA 如此重要(至少)有以下三个原因:
- 确保业务利益相关者提出正确的问题——通常通过探索和可视化数据——并通过彻底的调查验证他们的业务假设
- 发现数据中的任何潜在异常,以避免向机器学习模型输入错误的数据
- 解释模型输出并测试其假设
这就是了。现在我们已经了解了 EDA 的“什么和为什么”方面,让我们一起检查一个数据集,并浏览“如何”,这将最终引导我们发现一些有趣的模式,我们将在下一节中看到。
我们将关注 EDA 的整体工作流程、可视化及其结果。关于技术参考,如果您想对代码有更详细的了解,请随时查阅 Kaggle 上的 我的笔记本。
为了给出一个简要的概述,这篇文章分为以下 5 个部分:
- 数据的上下文
- 数据清理(又称数据预处理)
- 探索性数据分析
- 结果
- 结论
让我们开始玩吧!
数据的上下文

在本帖中,我们将调查从 Kaggle 获得的电子商务数据集。在处理数据集之前,让我们试着理解它是什么,以便更好地理解它的上下文。
简而言之,数据集由来自不同国家的客户的交易数据组成,这些客户从一家总部位于英国的在线零售公司购买独特的全场合礼品。信息概述如下:
- 公司——总部位于英国并注册的无店铺在线零售
- 销售产品—主要是各种场合的礼品
- 客户—大多数是批发商(本地或国际)
- 交易期—2010 年 12 月 1 日至 2011 年 12 月 9 日(一年)
数据清理

我们都知道现实世界中的数据是混乱的(包括 Kaggle!)因此,让我们花一些时间将数据整理成我们需要的格式。下面是将数据集加载到 dataframe 后原始数据的快照。

虽然变量(列名)听起来很直观,但让我们更进一步,理解每个变量的含义:
invoice no(invoice _ num):分配给每笔交易的编号
stock code(stock _ code):产品代码
描述 (description) :产品名称
数量(数量) :每笔交易购买的产品数量
invoice date(invoice _ date
注释→在我们的整个分析中,假设单位产品价格遵循相同的货币

Check missing values
到目前为止,一切顺利。我们发现客户 ID 和描述中缺少一些值。因此,具有任何这些缺失值的行将被删除。

Descriptive statistic of data
通过以更具描述性的方式理解数据,我们注意到两件事:
- 数量有负值
- 单价有零值(自由项?)
有意思…
在这一阶段,我们将只删除具有负值的数量— 本笔记本解释了负值的含义—具有零值的单价将在后面的部分解释。
要计算每次购买的总花费,我们只需将数量乘以单价:
花费金额=数量*单价
最后,我们为每个事务添加几列,包括年、月、日和小时,供以后分析。最终的数据帧将如下所示:

Final dataframe
探索性数据分析

订单数量和购买金额最高

Top 5 customers with most number of orders

Top 5 customers with highest money spent
在电子商务世界中,我们经常想知道哪些客户——他们来自哪里——下的订单最多,花的钱最多,因为他们推动了公司的销售。
从结果中我们观察到,大多数订单都是在英国完成的,而荷兰顾客的购物金额最高。
(每月)有多少订单?

Number of orders for different months
总体而言,我们认为该公司在 2011 年 11 月收到的订单数量最多,因为我们没有 2011 年 12 月整月的数据。
(每天)有多少订单?

Number of orders for different days
令人惊讶的是,在整个期间(2010 年 12 月 1 日至 2011 年 12 月 9 日),星期六没有任何交易。由于数据集及其上下文有限,后面的原因留待讨论。
我们还发现了一个趋势,即公司收到的订单数量从周一到周四趋于增加,之后减少。
多少订单(每小时)?

Number of orders for different hours
就时间而言,晚上 8:00 之后直到第二天早上 6:00 都没有交易。
此外,我们注意到该公司在中午 12:00 收到的订单数量最多。原因之一可能是因为大多数顾客在中午 12:00-2:00 的午餐时间购物。
发现单价的交易模式

Descriptive statistics of Unit Price

Boxplot for Unit Price
在我们将注意力转移到单价的零值(自由项)之前,我们制作一个箱线图来检查所有产品的单价分布。
我们观察到 75%的数据单价低于 3.75 美元,这表明大多数产品相对便宜。只有少数单位价格高(同样,我们假设每个单位价格遵循相同的货币)。
嗯……购买免费物品?是的,也许…

Frequency of giving out FREE items for different months
从剧情来看,公司倾向于每个月不定期的免费发放购物品(2011 年 6 月除外)。
然而,不清楚是什么因素促成了向特定顾客发放免费物品。可以做更深入的分析来进一步解释。如果你发现了背后的原因,请告诉我!😏
发现每个国家的交易模式
订单数量最多的前 5 个国家

Number of orders in each country (with UK)

Number of orders in each country (without UK)
不出所料,该公司在英国获得的订单数量最多(因为它是一家总部位于英国的公司)。
为了更好地辨别趋势,为了更清楚地比较其他国家,英国被删除。因此,订单数量最多的前 5 个国家(包括英国)如下:
- 联合王国
- 德国
- 法国
- 爱尔兰
- 西班牙
花钱最多的前 5 个国家

Total money spent by each country (with UK)

Total money spent by each country (without UK)
由于该公司从英国客户那里收到的订单数量最多,因此很自然地会看到英国客户的购物支出最多。
和以前一样,为了更清楚地比较其他国家,英国被删除。花钱最多的前 5 个国家(包括英国)如下:
- 联合王国
- 荷兰
- 爱尔兰
- 德国
- 法国
来自 EDA 的结果
- 订单数量最多的客户来自英国
- 购买金额最高的客户来自荷兰
- 该公司从英国客户那里收到的订单数量最多(因为它是一家总部位于英国的公司)。因此,下单数量最多的前 5 名国家(包括英国)如下→ 英国、德国、法国、爱尔兰(EIRE)、西班牙
- 由于该公司从英国客户处收到的订单数量最多(因为它是一家总部位于英国的公司),英国客户的采购支出最多。因此,在购买上花费最多的前 5 个国家(包括英国)如下→ 英国、荷兰、爱尔兰(EIRE)、德国、法国
- 2011 年 11 月销量最高。销售额最低的月份尚未确定,因为数据集包含截至 2011 年 12 月 9 日的交易
- 从 2010 年 12 月 1 日到 2011 年 12 月 9 日,星期六没有交易
- 公司收到的订单数量从周一到周四呈上升趋势,之后呈下降趋势
- 公司在中午 12:00 收到的订单数量最多。可能大多数顾客都是在中午 12:00 到下午 2:00 的午餐时间购买的
- 该公司倾向于每月不定期地发放免费购物品(2011 年 6 月除外)。然而,不清楚是什么因素促成了向特定顾客发放免费物品
结论

厉害!
通过对数据集执行 EDA,我们发现了一些有趣的结果。当然,结果不止于此。它们总是可以用来验证业务假设(如果有的话),并解释机器学习模型的输出等等!
记住。做 EDA 的时候创意是你的极限。这真的取决于你对商业的理解,提出有趣问题来挑战和验证假设的好奇心,以及你的直觉。
感谢您的阅读。希望通过展示 EDA 的整体工作流程、可视化及其结果,EDA 将变得不那么让你害怕,并且你将更有兴趣在下一次弄脏你的手。
一如既往,如果您有任何问题或意见,请随时在下面留下您的反馈,或者您可以随时通过 LinkedIn 联系我。在那之前,下一篇文章再见!😄
关于作者
Admond Lee 目前是东南亚排名第一的商业银行 API 平台 Staq — 的联合创始人/首席技术官。
想要获得免费的每周数据科学和创业见解吗?
你可以在 LinkedIn 、 Medium 、 Twitter 、脸书上和他联系。
让每个人都能接触到数据科学。Admond 正在通过先进的社交分析和机器学习,利用可操作的见解帮助公司和数字营销机构实现营销投资回报。
www.admondlee.com](https://www.admondlee.com/)
使用 Python 对日本旅舍进行探索性数据分析

Photo by Andre Benz on Unsplash
作为一个热爱旅行却又未能再次赢得破纪录的彩票的人(我正瞪着你这个南卡罗来纳州的中奖者),在旅行中找到省钱的方法是至关重要的。对于预算有限或只想体验传统酒店之外的不同体验的旅行者来说,招待所是一个令人惊叹的、负担得起的住宿选择。在与几个人交谈后,令我惊讶的是,有这么多资金有限的人没有住旅馆,甚至没有考虑过。
受到这些对话和我自己最近旅行的启发,我为我的第一篇媒体博客文章进行了一项关于日本旅馆的简单研究。我使用的数据集是 Koki Ando 从 Hostelworld 网站上搜集的,可以在 Kaggle 上找到。
数据清理和基本可视化
今年早些时候,我参加了一个编码训练营课程,以将我的职业生涯过渡到数据分析,我的导师说,几乎总结了我所有未来数据项目的一件事是,数据科学是 80%的数据清理和 20%的分析。这个项目就是如此。让我们从导入我们的依赖项并读取 CSV 文件作为 pandas 数据帧开始。
# Dependencies
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
import seaborn as sns
from wordcloud import WordCloud# Read CSV file
hostels_df = pd.read_csv("../raw_data/Hostel.csv", index_col=0)
hostels_df.head()

在处理新数据集时,我喜欢做的第一件事就是检查缺失值并查看列名。
# Check for missing values and column names
hostels_df.count()

Number of existing values for each column
为了可读性,我们将继续重命名这些列,这对我们的第一对可视化来说应该足够了。
# Rename column names
hostels_df.columns = ["Hostel Name", "City", "Min. Price for One Night (yen)", "Distance from City Center", "Summary Score", "Rating", "Atmosphere", "Cleaniness", "Facilities", "Location", "Security", "Staff", "Value for Money", "Longitude", "Latitude"]
让我们用柱状图和饼状图来看看每个城市有多少旅舍。
# Get hostel count for each city
city_group = hostels_df.groupby("City").count()# Reset index
city_group = city_group.reset_index()# Create new dataframe for city name and hostel count
city_group = city_group[["City", "Hostel Name"]]# Rename columns
city_group.rename(columns={"Hostel Name": "Hostel Count"}, inplace=True)# Create bar chart for hostel count by city
city_bar = city_group.plot.bar(x="City", y="Hostel Count", rot=90, legend=None, color="teal", zorder=3)
plt.grid(which="major", axis="y", zorder=0)
plt.xticks(rotation=45)
plt.title("Hostel Count by City in Japan")
plt.ylabel("# of Hostels")

# Create pie chart for hostel count by city
hostel_count = city_group["Hostel Count"]
colors = ["aqua", "lightblue", "gold", "olive", "turquoise"]
city_labels = city_group["City"]
plt.figure(figsize=(8,6))
plt.pie(hostel_count, labels=city_labels, colors=colors, startangle=115, autopct="%1.1f%%")plt.title("Hostel Count Percentage by City in Japan")

大多数旅馆位于东京、大阪和京都,这并不奇怪,因为这些城市是日本的顶级旅游目的地。超过三分之一的旅舍位于东京,大约三分之二的旅舍位于东京和大阪。
人们普遍认为,越靠近市中心的酒店和 Airbnb 房源越贵,尤其是在热门旅游目的地。让我们通过创建一个散点图来看看这是否也适用于这些旅馆。需要进一步清理数据,因为我们只需要距离列中的数值,然后数据集中的所有数值都必须转换为浮点数。
# Use split to obtain numeric value from distance column
hostels_df["Distance from City Center (km)"] = hostels_df["Distance from City Center"].str.split("km").str[0]# Change all numeric values to integer/float data types
hostels_df.apply(pd.to_numeric, errors="ignore")hostels_df[["Distance from City Center (km)"]] = hostels_df[["Distance from City Center (km)"]].apply(pd.to_numeric)
如果我们现在使用数据集绘制散点图,图表的尺寸将非常大...关了。让我们调查一下这里发生了什么。
# Check value count for each unique value for minimum price column
hostels_df.groupby(["Min. Price for One Night (yen)"]).count()["City"]

两家旅馆的最低价格是 1003200 日元(8965.40 美元)一个晚上…让我想一想。这些值是偏离旅馆价格分布的异常值。由于这两个异常值具有相同的值,而且值高得令人怀疑,因此有理由假设某个数字是无意中刮出来的价格值。去除这些异常值是合适的。
# Remove outlier
hostels_reduced = hostels_df[hostels_df["Min. Price for One Night (yen)"] < 8000]
我们现在可以继续创建散点图。
# Create scatter plot
hostels_reduced.plot.scatter("Distance from City Center (km)", "Min. Price for One Night (yen)", alpha=0.6)
plt.tight_layout()
plt.title("Minimum Price for One Night vs. Distance from City Center")
plt.grid()

令人惊讶的是,在靠近市中心的地方,有很多价格较低的旅馆。似乎离市中心的距离并不是影响旅馆价格的重要因素。现在,让我们快速看一下每个城市的平均成本和价格分布。
# Obtain the mean and standard deviation (STD)
price_mean = hostels_reduced.groupby(["City"]).mean()["Min. Price for One Night (yen)"]
price_std = hostels_reduced.groupby(["City"]).std()["Min. Price for One Night (yen)"]# Create new dataframe for mean values
mean_df = pd.DataFrame({"City":price_mean.index, "Price Mean (yen)":price_mean.values})
mean_df = mean_df.set_index("City")# Create bar chart with y error bar
mean_df.plot(kind="bar", yerr=price_std.values, color="teal", legend=None)
plt.xticks(rotation=45)
plt.grid()
plt.title("Average Minimum Hostel Cost for One Night")
plt.ylabel("Minimum Hostel Cost (yen)")

正如我们在这里看到的,在所有列出的日本城市中,旅馆每晚的平均最低费用约为 2500 日元(22.43 美元),其中东京的价格分布差距最大。
缺失数据和宿舍评级分析
很明显,这些旅馆并不贵,但我们现在必须问问自己,即使价格合理,它们是否真的值得入住。幸运的是,这个数据集包括入住过的顾客对每家旅馆不同类别的平均评分。
为了进行这种额外的分析,我们必须克服每个数据分析师、数据科学家、数据工程师等的障碍。面,那就是缺失的数据。有几种方法来处理丢失的数据,有许多博客文章和文章涉及这个主题(我最近读了一篇我喜欢的文章,是这个的一篇)。当我们之前检查缺失值时,我们可以看到所有具有评级分数的列都缺失相同数量的值。根据这一观察,我们可以假设当一家旅馆缺少一个评级分数时,那么它就缺少所有的分数。但是,我们仍然应该仔细检查,看看丢失的值在哪里。
# Create new data frame for hostel rating analysis and view # of missing data
score_df = hostels_df.loc[:, "Summary Score":"Value for Money"]
score_df = score_df.drop(["Rating"], axis=1)# Create new data frame that only returns rows with missing values
null_df = score_df[score_df.isnull().any(axis=1)]

正如这里看到的,我们最初的假设是正确的。我们知道丢失的值在哪里,现在我们需要决定如何处理它们。为了帮助确定如何处理丢失的数据,我们可以使用 pandas 的 describe 函数为我们提供数据框的基本统计数据的快照。
# Generate descriptive statistics for data frame to help determine what to do with missing data
score_df.describe()

由于分布变化不大,只有一小部分数据集丢失数据,因此删除丢失数据的行不会对后续分析产生太大影响。
# Drop missing values
score_df = score_df.dropna().reset_index(drop=True)
现在我们可以继续我们的可视化和分析。要查看不同评级类别之间的关系,我们可以使用从 Seaborn pairplot 模块生成的 Pearsons R 分数。
# Use seaborn package to find pairwise relationships in dataset
def corrfunc(x, y, **kws):
r, _ = stats.pearsonr(x, y)
ax = plt.gca()
ax.annotate("R = {:.2f} ".format(r),
xy=(0.1, 0.9), xycoords=ax.transAxes)
g = sns.pairplot(score_df)
g.map_lower(corrfunc)
g.map_upper(corrfunc)

氛围、清洁度、设施和性价比是与汇总分数正相关度最高的类别,对汇总分数的正面影响最大。接下来,让我们创建箱线图,按城市分析旅舍评级。
# Create Seaborn boxplots
fig = plt.figure(figsize=(12,18))
fig.subplots_adjust(hspace=1.4, wspace=0.3)
for idx, col in enumerate(city_analysis.columns[3:11]):
fig.add_subplot(3, 3, idx+1)
sns.boxplot(x=city_analysis["City"], y=city_analysis[col], data=city_analysis)
plt.xticks(rotation=90)

广岛旅馆的评分紧密分布在平均值附近,这意味着这些旅馆具有最一致的分数。这一数据表明,广岛的旅舍为旅行者提供了最一致的服务和体验。
结论
很明显,日本的旅馆是一个不容忽视的旅游住宿选择。他们离市中心很近,成本低,物有所值,顾客满意,这些都是任何旅行者值得考虑的理由,无论他们是否在预算之内。为了完成这一数据探索,我使用旅行者给出的评价旅馆的形容词生成了一个词云。
# Create list from column values
rating_list = hostels_df["Rating"].tolist()# Convert list to one big string
rating_list = " ".join(rating_list)# Create word cloud
wordcloud = WordCloud().generate(rating_list)
wordcloud = WordCloud(background_color="white", max_words=len(rating_list), max_font_size=100, relative_scaling=0.5).generate(rating_list)
plt.figure()
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis("off")

请随时通过我的联系人留下您的意见和反馈。旅行愉快。
参考资料:
探索性数据分析:2015 年美国警察杀人可视化。
简要描述:
该数据共包含 1146 个观察值——2015 年美国警察杀人事件的受害者——以及每个受害者的共 14 个特征——属性。**
每个受害者的特征记录如下…
- id :给每个受害者的唯一号码
- 姓名:受害者姓名
- 年龄:受害者的年龄
- 性别:受害者的性别
- 种族/民族:受害者的种族/民族
- 武装:受害者有武装吗?如果是,什么类型的手臂?
- 月:事件发生的月份
- 日:事件发生的当天。
- 年:事件发生的年份(2015 年)
- 街道地址:发生杀人事件的街道
- 城市:杀戮之城
- 状态:事件发生的状态
- 经度:杀戮的经度(坐标)
- 纬度:杀戮的纬度(坐标)
- 分类:受害者的死因,即枪击/车辆
- 执法机构:负责攻击的办公室
可视化:
性别:毫不夸张地说,在美国,大多数被警察杀害的受害者都是男性,因为这占了所有记录数据的 95%以上。

年龄分布:年龄呈长尾正态分布,25-35 岁年龄组出现次数最多。

0-10 之间的小酒吧是杰里米·马迪斯,一个 6 岁的男孩,他没有武装,在 2015 年 11 月被枪杀。他是“白人”,负责谋杀的执法机构是洛杉矶第二区执法官。
种族/民族:被杀的‘白人’比所有其他民族/种族加起来还多。2015 年,超过 50%被美国警察部队杀害的人是白人,阿拉伯裔美国人记录的受害者人数最少,不到记录的总数据的 1%。

嫌犯持有武器?:超过 50%的受害者持有枪支或刀具。超过 30%的记录数据没有使用火器,或者使用了非致命火器,或者不知道他们是否携带武器。

死亡性质:几乎 90%的受害者都是被枪杀的,死因和死亡性质都很清楚。其他形式有:羁押期间死亡,被车辆、泰瑟枪和其他物体击中(不到 1%)。

每月杀戮:杀戮在 7 月份达到顶峰,有超过 125 名受害者,在 6 月份达到最低点,有 80 名受害者。

各州的杀人事件:在记录在案的 51 个州中,有 10 个州的杀人事件超过 50%,其中加利福尼亚州以 211 起记录在案的事件高居榜首,占总数据的 18.4%。

基于武器的种族/民族:这显示了基于武器杀死每个民族的比率。

几乎 50%被杀的“白人”携带枪支,而阿拉伯裔美国人携带枪支的受害者比例最低。此外,不到 30%的阿拉伯裔美国人被枪杀。
基于种族/民族的死亡性质:正如我之前所说,几乎 90%的受害者是被枪杀的。所有记录在案的阿拉伯裔美国人都是被枪击致死的,这是唯一一个 100%死亡的群体。美洲原住民在羁押中死亡的比例最高,亚太裔被泰瑟枪致死的比例最高。请注意,这些比率是相对于每组记录的总数而言的。

2015 年美国警察杀人的探索性数据分析到此结束。
数据和代码可以从github.com下载。
留下你的评论、问题和你想让我添加到帖子中的内容,别忘了推荐。
干杯
Ede
使用 Jupyter 笔记本对熊猫进行探索性数据分析

A beautiful red panda doing his thing. If you look close enough at that bamboo, you can see the commas. Source: pixabay
作为一名数据科学家,我花了大约三分之一的时间查看数据,并试图获得有意义的见解。这些是我最常用的工具。
你是数据科学闪亮世界的新人吗?探索性分析之类的花哨词汇会吓到你吗?别担心,我是来帮你在这个疯狂的世界里导航的。
今天我们将看看两个很棒的工具,紧跟我在 github 项目上上传的代码。一个是 Jupyter 笔记本,一个是 Python 框架叫 Pandas。
如果你是 Python 的新手,我建议你在阅读这篇文章之前先阅读一篇语言教程。我不会用太晦涩的东西,但也不会停下来解释列表理解。我推荐 O'Reilly 的书“用 Python 从零开始的数据科学”,但是任何其他教程都可以。
首先来说说 Jupyter 笔记本。如果您曾经使用过 Python 控制台,您可能已经意识到它是多么有用。通过检查输出是否符合您的预期来轻松调试功能(我不是说这是测试的良好替代品,但是谁没有这样做过呢?),运行一次昂贵的进程,这样就可以将它们加载到内存中,然后就可以开始在它们的输出上测试其他东西,拥有一个交互式环境有很多好处。

Just picture this but, like, less round, and a bit more squarish. Rectanglish? Is that a word? Source: Pixabay
Jupyter 笔记本也是同样的环境,使用类固醇。这就像运行 Python 控制台工具进行读取-评估-打印循环,但是界面很可爱,并且能够记录和保存您测试的内容。这非常方便,例如,如果你正在写一篇关于 Python 工具的中型文章!
要安装 Jupyter,您只需运行以下 pip 命令:
python -m pip install jupyter
如果您在 Linux 上,您应该使用这个命令:
pip3 install --user jupyter
(注意:本文之前的版本推荐使用 sudo 进行安装。一位 善良的读者 告诉我这是 不安全的,实际上是非常糟糕的做法 ,因为它给了 setup.py 程序 sudo 特权,这通常是不好的,会允许恶意代码运行。你知道的越多!)
然后要运行程序,打开你的终端,在你想要存储笔记本的文件夹中,然后运行
jupyter notebook
是的,就这么简单。该命令将初始化您计算机中的服务器,并将您最喜欢的浏览器重定向到该服务器。从那里,只需使用 GUI 创建一个新的笔记本,并打开它。使用 + 按钮创建一个新的代码块,使用“剪切”按钮删除一个代码块。通过将光标放入代码块并点击“Shift+Enter”,每个代码块都可以独立运行(尽管不是并发的)。
既然你已经知道了如何运行 Jupyter 笔记本,那么克隆并拉动我刚刚链接的项目将是明智的。你所要做的就是点击克隆绿色按钮,获得链接,然后开始
git clone *link*
现在有趣的部分,让我们来谈谈熊猫。Pandas 是一个开源 Python 框架,由 PyData 社区维护。它主要用于数据分析和处理,主要用于操作 CSV 文件。

They keep making them cuter and cuter. It’s like each hair is a commit. Source: pixabay
如果您不知道,CSV 只是一种将数据编码为序列(列)的文件格式,其中每个对象(行)都有一个值。文件中的每一行都是一行,每一个值都用逗号与前一个值隔开,这样就形成了逗号分隔值文件。第一行是为标题保留的,包含每一列的名称。
在本教程中,我们将首先生成一个“员工数据”的模拟数据集,该数据集来自一家非常冷的公司,它只存储每个员工的姓名和工资。数据集将被生成为 CSV 文件,如 generate_people.py 程序所示。
我们首先要做的是使用一些常规的 Python 来生成字典,每个字典代表一个人。如果你更熟悉 JavaScript,每个字典只是一个 JSON,有“名字”、“姓氏”和“薪水”字段。
然后,我们生成一个 Pandas Dataframe:它们在 CSV 文件上的抽象,其中每一列都是 Pandas 系列(可通过一些矢量化运算进行迭代)。
就是这样。如您所见,Dataframe 是作为字典列表和列名的(可选)参数生成的。将它导出到 CSV 文件就像调用 to_csv 方法一样简单,只需将文件名作为唯一的参数。
现在,对于读取和处理部分,让我们运行“分析数据集”笔记本,它也在存储库中。我建议你打开它,把它放在边上阅读这篇文章,但我会添加相关的片段,以防你在手机上或只是觉得有点懒。
我们首先将 CSV 文件作为数据帧导入,其中包含以下行:
**import** **pandas** **as** **pd**
df = pd.read_csv("random_people.csv")
对一些 k 使用 df.head( k )会让我们看到数据帧的第一个 k 行,由于 Jupyter 的魔力,这些行看起来会非常漂亮。这是了解数据的一种简单方法(也是开始处理数据时的主要调试工具)。
为了只看到系列中的一个,我们所要做的就是将其作为字典字段进行索引:
df[“*series name*”]
您可以调用在任何其他数据分析工具(如 SQL)中使用的任何常用聚合作为方法。如果我想直观地了解一个系列,我最喜欢的方法是 value_counts 方法,它显示每个值,以及它在系列中出现的次数,按照幽灵数量的降序排列。其他选项包括平均值、总和、计数和中位数。
使用这些方法而不是手动打开 CSV 并自己运行这些函数的实现的一个优点是,其中大多数都是矢量化的(它们使用 SIMD 指令和其他黑魔法),这意味着它们将快大约 10 倍。这也适用于加法、减法、除法和乘积,它们可以很容易地通过一个系列进行广播。
然而,有时你会想把一个功能应用到一个不那么琐碎的系列中,也许制作熊猫的人没有真正考虑过你的用例。在这种情况下,您可以定义自己的函数,并对您想要修改的系列使用 apply 方法。这将是一个有点慢,但仍然运行简单的功能顺利。它相当于 Python 的原生地图,将为你的处理增加大量的灵活性。
如果您想过滤数据帧,只保留保持某个属性的行,您可以这样做:
df_high = df[df["salary"]>=6000]
其中" df[" salary "]>= 6000 "可以用任何返回一系列布尔值的东西来切换,或者" df["any series name"]。应用(f)"使得 f 为布尔函数。但是,请确定该系列与您要过滤的系列具有相同数量的元素。
最后,请记住,这些过滤后的数据帧在默认情况下是只读的,因为它们是通过引用生成的。如果你想改变它们,只需添加。loc" 在数据帧名称之后,第一个括号之前,如下所示:
df_low= df.loc[df["salary"]<6000]
您也可以将列名作为第二个参数添加到 loc 中,以保留单个过滤序列,而不是整个数据帧。这是一个直接来自笔记本的例子。
df_low= df.loc[df["salary"]<6000,"salary"]
请注意,后者是通过引用制作的切片,因此您对它们所做的任何更改也将在原始数据帧上进行。为了避免这种情况,只需在行尾调用 copy 方法。
就是这样,这是一些关于熊猫和笔记本的初步速成课程。我希望你会觉得它很有用,如果你觉得还有什么我应该介绍的,或者有什么你想问我的,你知道在哪里可以找到我。我也欢迎任何批评,不管是好是坏,因为这是我第一篇关于媒体的文章,我还在适应。
如果你想在这方面展开,这里有一篇我写的关于如何在并行上做数据分析的文章。
有一本 O'Reilly 的书我很喜欢,当我开始我的数据科学之旅时,我发现它非常有用。用 Python 从零开始叫 数据科学,大概也是我得到这份工作的一半原因。如果你读到这里,你可能会喜欢它!
附:关注我以获得更多的 Python 教程、技巧和诀窍,如果您发现本文有用,请 支持我的写作 。
使用熊猫的真实数据集的探索性统计数据分析

Your Data Science journey has just begun. source: Pixabay
有时候,当面临一个数据问题时,我们必须首先深入数据集并了解它。它的属性,它的分布——我们需要沉浸在这个领域中。
今天我们将利用 Python 的 Pandas 框架进行数据分析,利用 Seaborn 进行数据可视化。
作为一个审美感很差的极客程序员,我发现每当我需要理解某个观点时,Seaborn 都是一个非常棒的可视化工具。
它在幕后使用 Matplotlib,但用默认的样式值设置图形,使它们看起来比我能做的漂亮得多。我们将查看一个数据集,我将尝试让您直观地了解如何查看不同的要素。谁知道呢,也许我们真的会从中得到一些启示!
没有鸡蛋就做不成煎蛋卷:数据集。
在这个分析中,我使用了 120 年奥运数据集,你可以点击链接下载或阅读更多信息。
我从 Kaggle 免费下载了它,如果你需要一个数据集来尝试一些新的机器学习算法,温习一些框架的 API,或者只是找点乐子,这是一个很棒的网站。
我将只使用“运动员事件”CSV 文件,该文件包含自 1900 年以来每届奥运会上的每名参赛者,以及他们的出生国、是否获得奖牌等。
一个有趣的事实是,奖牌栏有 85%是空的,所以平均来说只有大约 15%的奥运会运动员真正拿到了奖牌。除此之外,一些运动员还获得了不止一枚奖牌,这表明,在已经很少的奥运级别运动员中,有更少的人真正获得了奖牌。更值得称赞的是他们!
开始分析:数据集是什么样的?
首先,在我试图收集任何见解之前,我想对数据集有一个更好的直觉。有多少数据丢失了?有多少不同的列?我喜欢从这些问题开始。
我使用 Jupyter 笔记本进行分析,但是我将为我运行的每一行相关代码添加代码片段,以便您能够理解。
尽管如此,我还是在这个库中提供了这个笔记本,以防你自己想看一眼,想有一个起点。
我首先要做的是加载熊猫的数据,并检查它的大小。
在本例中,数据集有 15 个不同的列,总共 271116 行!超过 27 万运动员!不过,我想知道实际上有多少不同的运动员。还有,他们中有多少人真的获得了奖牌?
为了检查这一点,我将首先列出对数据集调用“list”函数的数据集的行。我看到我们有许多有趣的特点。
我能想到的一些事情是,我们可以看看奥运会运动员的平均身高和体重,或者按照运动项目来划分。我们也可以看到这两个变量的分布取决于性别。我们甚至可以看到每个国家获得了多少奖牌,以及整个二十世纪文明的兴衰。
可能性是无限的!但首先让我们解决一些难题:我们的数据集有多完整?
对一个序列使用 Pandas 的计数方法,我可以得到非空行的数量。但是查看 shape 属性,我实际上可以看到行的总数,不管它们是否为空。
之后就是减法和除法的问题了。我们看到只有四栏是不完整的:身高、体重、年龄和奖牌。
任何时候运动员没有真正赢得奖牌,奖牌都是不完整的,所以它不会太满。然而,在体重、身高和年龄方面,我们面临着相当大的挑战。
我试图按不同年份过滤这些数据,但随着时间的推移,不完整性似乎是一致的,这使我认为可能有几个国家不提供这些关于他们运动员的数据。
开始我们的实际分析:奖牌是怎么回事?
关于这个领域,我们问的第一个问题是,自 1900 年以来,有多少人真正获得了奖牌?以下片段回答了这个问题:
正如你所看到的,在过去的 120 年里,几乎有 135,000 名不同的人参加了奥运会的比赛,但是只有 28,000 多一点的人至少获得了一枚奖牌。
这大约是五分之一,还不算太糟。然而,一旦你考虑到许多人实际上在不止一个类别中竞争,这就不那么乐观了。
现在我们来看看,在这 120 年中,我们实际上获得了多少枚奖牌?
不出所料,奖牌分布几乎是一致的:获得的金牌、银牌和铜牌数量几乎相同。
然而,总共颁发了近 39,000 枚奖牌,这意味着如果你属于获得任何奖牌的前 20%的运动员,你平均应该获得不止一枚奖牌。
按国家分配呢?为此,我们将运行以下代码片段:
使用该函数,我们可以获得某个国家获得的每种类型的奖牌数量,而通过获取熊猫头像数据帧,我们可以看到获得奖牌最多的国家。
有趣的是,第二个获得更多奖牌的国家仍然是苏联,尽管它已经不存在近 20 年了。
在所有类别中,第一名是美国,第三名是德国。我还调查了我的两个国家阿根廷和克罗地亚,惊讶地发现克罗地亚已经获得了 58 枚金牌,尽管它从 1991 年才出现(奥运会年份是 1992 年)。
找到一个脚本来获取一个国家参加奥运会的不同年份将作为读者的一个练习——我打赌你可以做到这一点!
女性参与
我想到的另一件有趣的事情是,在整个世纪的奥运会中,女性代表是什么样的?这个片段回答了这个问题:
我很惊讶地看到女性早在 1900 年就开始参加奥运会了。然而,从历史上看,奥运会上每有一名女性,就有三名男性。对 1900 年女性参加奥运会感到惊讶,我决定随时核查她们的人数。我终于用了 Seaborn!

我们可以看到,在过去的几十年里,女性的参与率一直在快速上升,从几乎为零开始,到数千人。然而,她们的参与率真的比男性增长得快吗?或者这仅仅是世界人口的问题?为了解决这个问题,我制作了第二张图表:

Female participation (Orange) vs male (Blue) over time.
这一次我们可以清楚地看到一种模式是如何出现的:女性实际上正在以绝对的数量接近男性!另一件有趣的事情出现了:看到下面右边的那些小点了吗?我想那是冬季奥运会!无论如何,女性代表的情况看起来相当乐观,尽管还没有哪一年女性参与者多于男性。
杂集分析:身高和体重
我花了很长时间查看身高和体重图表,但没有收集到任何有趣的结论。
- 对于大多数运动来说,两者都是明显的正态分布
- 在我检查过的所有运动项目中,男性总是比女性更重更高
- 唯一有趣的变化似乎是一种性别与另一种性别的差距有多大,这取决于运动。
如果你有任何有趣的想法可以用体重和身高来分析,请告诉我!我还没有足够深入地按每项运动进行分组,因此可能会有一些见解。今天就到这里,我希望你对这个分析感兴趣,或者至少你了解了一些关于熊猫或数据分析的知识。
我在 GitHub 上提供了这个笔记本,这样你就可以分叉这个项目,做你自己的分析,然后做一个拉取请求。
你当然可以把所有的功劳都拿走!希望你在图表和视觉效果方面比我强。
第二部关于体育的真知灼见 已经有了。
有一本 O'Reilly 的书我很喜欢,当我开始我的数据科学之旅时,我发现它非常有用。用 Python 从零开始叫 数据科学,大概也是我得到这份工作的一半原因。如果你读到这里,你可能会喜欢它!
请考虑 用一点点捐款支持我的写作习惯 。
如果您还没有,请关注我的 Medium 和Twitter以获取更多针对软件开发人员和数据科学家的教程、提示和技巧。
如果你真的喜欢这篇文章,就和朋友分享吧!
探索原始数据并从中获取价值:Splunk 简介
您刚刚接触了一些原始数据文件(json、csv 等)。现在会发生什么?你如何理解它?
你打开一个控制台,开始使用 less、grep、jq 等工具。开始的时候很棒,但是…除了基本的,很难做更多的事情。
这听起来熟悉吗?太好了!请继续阅读,了解 Splunk 如何帮助您。
安装 Splunk 企业版
让我们从在您的计算机中安装 Splunk Enterprise 开始。安装 Splunk 非常简单,安装包几乎适用于所有平台:OSX/Linux/Windows。在此下载软件包,并按照安装说明进行操作。
Splunk 企业?但是...它有免费许可证吗?是啊!
指标 500 MB/天。(…)60 天后,您可以转换为永久免费许可证或购买 Splunk 企业许可证,以继续使用专为企业级部署设计的扩展功能。”
https://www . splunk . com/en _ us/download/splunk-enterprise . html
虽然在介绍和个人使用的范围内,在您的机器上进行本地安装是很好的,但我强烈建议您在开始更广泛地使用 Splunk 时,尽快转移到正确的 Splunk 部署(内部部署或云中部署)。

Splunk Enterprise 7.1.3 Web Interface
如果您的本地安装进展顺利,您将会看到一个类似于上面截图的 web 界面。耶!
导入原始数据
本文适用于任何类型的原始数据- Splunk 与其生成一些无意义的虚拟测试数据集,我决定搜索一个有趣的真实世界数据集,作为开放数据。
赫尔辛基公共交通(HSL)—2016 年 10 月期间每个车站的客运量
我从赫尔辛基地区交通局(HSL)找到了一个有趣的数据集,其中包含赫尔辛基地区每个车站的乘客量。数据集(此处可用)包含 2016 年 11 月期间每天的平均乘客人数,从乘客旅行卡系统中收集。虽然我对这个特定的数据集只有可用的旧数据(2016 年 11 月)感到有点失望,但我非常惊讶地发现 HSL (以及芬兰公共当局总体而言)有相当大的公开可用的数据目录(【https://www.opendata.fi/en】)。不错!
通过下载这个特定的 HSL 数据集——我选择了 GeoJSON APIJSON 数据格式——您将获得一个名为HSL % 3 an _ nousijam rt . geo JSON的原始数据文件

Raw data from HSL
正如你所看到的,在顶层我们有一个单一的 FeatureCollection ,其中包含了所有的 Feature 事件。
由于我们只关心事件(不需要高级 FeatureCollection 数组部分),我们可以通过删除 JSON 数组并把所有的特性事件放到一个新文件(HSLvolumes.json)中来清理数据。

将数据添加到 Splunk
从本地硬盘中的文件向 Splunk 添加新数据非常简单。让我们前往 Splunk 并使用 UI 选项来实现这一目的。


Splunk > Add data
单击添加数据选项,然后选择上传(从我电脑中的文件)

Splunk > Add data: Select Source
将出现一个逐步指南。让我们从选择原始数据文件开始。在我的例子中,我将使用包含特性事件的 HSLvolumes.json 文件。

Splunk > Add data: Set Source Type
在获得您的数据后,Splunk 将尝试自动"理解""您的数据,并允许您调整和提供有关数据格式的更多细节。
在这个特殊的例子中,您可以看到它自动将我的数据识别为 JSON (Source type: _json),总体来说事件看起来不错。但是,有一些警告说它无法解析每个事件的时间戳。
为什么?Splunk 的核心是事件处理,时间至关重要。基于您正在索引的事件,Splunk 将自动尝试查找时间戳。由于我们的数据没有时间戳字段,Splunk 将使用每个事件被编入索引时的当前时间作为事件时间戳。
有关 Splunk 时间戳分配如何工作的深入解释,请查看此 Splunk 文档页面。

Splunk > Add data: Save Source Type
因此,在时间戳部分,我们将通过选择当前来实施这一点,因为我们修改了 _json 源类型,所以让我们点击“另存为”并根据我们的数据源对其进行命名(例如 hslvolumesjson)。

Splunk > Add data: Input Settings
在此部分中,我们需要选择要在哪个 Splunk 索引中存储此数据。为不同类型的数据创建单独的索引是一个好习惯,所以让我们创建一个新的索引。

Splunk > Add data: New Index
选择您的索引名称,然后单击保存。我们可以保留其他字段的默认值。

仔细检查是否选择了新索引。点击审核,提交 & 开始搜索即可。
有关在 Splunk 中获取数据的更深入的解释,请查看 Splunk 文档:http://dev.splunk.com/view/dev-guide/SP-CAAAE3A
第一眼看你的数据:探索
单击开始搜索按钮后,您将被引导至 Splunk 搜索面板。

这个观点里有很多有趣的东西。如果你以前从未使用过 Splunk,你可能会感到有点不知所措。请允许我重点介绍一些领域,并为您拆分视图。
在左上角,你会找到你当前所在的 Splunk 应用(默认:搜索&报告)和面板(默认:搜索)。
在它的正下方,您会发现 Splunk 搜索栏,其中有一个查询(乍一看)可能有点复杂。给定我们的简单用例,完全相同的搜索结果将出现在查询中: index="hslnov2016 "。我们将在下面探索查询语言。
在右上角,你会发现时间选择器(默认:所有时间)。这允许您选择搜索的时间范围。因为我们的时间戳被设置为索引当前时间,这在这里没有用。
在左下角,你会发现有趣的字段。这些是 Splunk 能够从您的数据中自动提取的字段。
最后,剩下的下半部分将显示您的搜索查询结果事件。在这种情况下,所有的索引结果都会出现。
酷,现在怎么办?
在 Splunk 中浏览数据时,我最喜欢首先使用的选项之一是“有趣的字段”面板。通过点击任何一个领域,你都可以很快获得有价值的见解。

在这种情况下,通过选择字段 properties.nimi_s ,我们能够快速了解什么是字段顶值,即在大多数事件中出现的 HSL 站名称。[对任何赫尔辛基地区的居民来说都不奇怪的是,劳塔廷托里(中央火车站)和坎皮在最上面:]
获得答案:统计和数据整理
Splunk 搜索和查询语言既强大又庞大,但是通过一些简单的命令和少量经验,您可以快速获得一些有价值的答案。

如果您从: index=yourindex | command, Splunk 将为您提供关于每个命令的自动完成、指导和解释。
由于每个事件都包含单个车站的日平均乘客量,假设我们想知道每个车站的总乘客量是多少。我们如何做到这一点?

轻松点。我们可以快速使用 stats 命令,将所有的日平均值(properties.nousijat)相加,并按电台名称(properties.nimi_s)汇总这些结果。
额外收获:通过获得 5071 个结果,我们还知道了数据集中的电台总数。不错!
想知道前几名或者后几名的 X 站怎么办?

通过追加到我们之前的查询: | sort -volume | head 20 ,我们立即得到了这个问题的答案。
我们使用排序来获得较高音量的结果,即降序(对于较低,即升序,将是排序+音量)和头来仅过滤出前 X 个结果
通过不同的 Splunk 查询探索您的数据并获得有价值的答案。
仪表板和可视化
一旦您开始掌握 Splunk 搜索的诀窍并保存了几个最有趣的查询,您就可以创建您的第一个仪表板并以不同的方式可视化您的数据。

转到仪表板部分,点击创建新仪表板。为您的仪表板命名,并添加您的第一个面板。

使用与前面相同的查询,我添加了一个简单的柱形图面板。
很快,我们的前 20 个车站在客流量方面变得非常非常不同。Kamppi 和 Rautatientori 的客流量是排名前五的其他三个车站的两倍。当我们看剩下的 15 个站(前 20!)我们得到 3 倍的体积。
在这一点上,我决定添加两个额外的新面板…

左边是每站旅客量前 50 名(与|头 50 查询相同)和一个简单的可视化表格。
右边是每个车站的乘客量(最下面一排,不到 30 名乘客)。带饼图和查询:index = " HSL nov 2016 " | stats sum(properties . nousijat)as volume by " properties . nimi _ s " | sort+volume | search volume<30 | stats count by volume
我决定只包括客流量少于 30 人的车站。而且我很惊讶的看到有这么多车站(1827)0 乘客。
最后一个面板…
由于我的数据集包括每个站点的地理坐标(纬度和经度),我决定再添加一个面板(类型地图)。为此,我扩展了我的 Splunk 并安装了一个名为 Maps+ for Splunk 的第三方可视化工具。

您可以通过浏览现有的可视化类型并转到“查找更多可视化”来完成同样的操作
Splunk 具有内置的地图可视化功能。为什么不用它呢?
我一开始确实使用了内置地图,但我发现了一些局限性:你不能在城市级别缩放,而且我的 Splunk 查询更复杂。Splunk 的 Maps+对我来说是一个明显的赢家。

面板 Splunk 搜索查询为:index = " hslnov 2016 " | spath path = " geometry . coordinates { 0 } " output = longitude | spath path = " geometry . coordinates { 1 } " output = latitude | stats first(latitude)为纬度,first(longitude)为经度,first(properties.nimi_s)为描述,sum(properties.nousijat)为标题 by " properties . nimi _ s " | sort-title |搜索标题> 0
需要使用 spath 进行初始转换,因为纬度和经度在同一个字段中(多值 json 类型),因此我必须将它们“分割”到不同的字段中。
这种可视化(Maps+ for Splunk)只要求您在一个表中有一些带有特定标签名称的字段。更多详细信息,请查看位于https://github.com/sghaskell/maps-plus的项目文件。
base_search | table latitude, longitude [ description| title | (...)

我发现这张地图真的很好,很有帮助。我可以通过悬停在某个车站上来快速查看该车站的乘客量。
我希望这篇文章对你有用!请分享您的反馈和想法。
布鲁诺
探索机器学习模型,无需编写代码或安装软件包
利用 scikit-learn 的模型并通过 API 公开它们的行为

“forced perspective photography of bus on road” by Muneeb Syed on Unsplash
机器学习|人工智能|深度学习——它们是下一件大事,我知道,我们都知道。那为什么要等?当机会就在我们面前时,是什么阻止我们抓住它?也许是因为从日常琐事中抽身出来,做一些新的事情需要一点努力。
早在我开始探索机器学习及其应用的时候,我的很大一部分时间都浪费在猜猜是什么上了。—搞清楚和研究 1。要使用的语言,请按 2。框架选择,3。安装(以正确的方式安装)和设置开发环境。在所有的戏剧之后,我开始实际的发展。
然后出现了构建基于云的应用程序的想法,任何人都可以开始利用机器学习的力量,它会处理其余的事情。当然有很多可用的服务——其中一个是 BigML ,但是为了我自己的实践和满足,我开始发展这个想法。
一夜之间成了我梦寐以求的项目;一个独立的 web 应用程序,可以通过 API 学习和测试机器学习模型。没有更多的编码专业知识,安装问题,兼容性问题,需要一个强大的钻机。甚至邮递员也能跑。
示例用法
获取当前用户的 JWT
POST /api/login/
Content-Type: application/json
{
"username": "username",
"password": "password"
}
Response
{
"token": "abcd12345"
}
考虑下面的问题陈述
你是一名物理系学生,参加了期末考试,迫不及待地想知道你的最终分数。但是给你打分的老师非常严格。他有一个计算总分的公式但是没人知道(就是 0.5 * Paper_1 + 2 * Paper_2 + Paper_3)。你有一份你朋友的考试成绩和期末成绩的清单,并想计算你的分数。
用给定的输入启动线性回归器
POST /api/model/
Content-Type: application/json
Accept: application/json
Authorization: JWT abcd12345
{
"model_path": "sklearn.linear_model.LinearRegression",
"action": "new_model",
"name": "Compute Final Score",
"input_x": [[95, 87, 69], [99, 48, 54], [85, 57, 98], [90, 95, 91]],
"input_y": [291, 200, 254, 326]
}
Response
{
"status": "Trained",
"model_id": "randommodelid"
}
使用这个训练好的模型来预测你的分数
POST /api/model/
Content-Type: application/json
Accept: application/json
Authorization: JWT abcd12345
{
"action": "predict",
"model_id": "randommodelid",
"input_x": [[90, 95, 91]]
}
Response
{
"status": "OK",
"prediction": [
326
]
}
这是一个正在开发的活动项目。目前服务于线性回归,SVM 和 KNN。更复杂的型号即将推出…
更新(2018 . 9 . 30):重构代码,动态获取用户在 API 中提到的模型类。理论上,scikit learn 中的所有模型现在都可以测试。
model_path参数决定调用哪个模型。您可以尝试各种其他方法,包括但不限于:
sklearn.svm.SVRsklearn.svm.SVCsklearn.linear_model.BayesianRidge
还有很多很多…
我期待着志同道合的人,就像我一样,谁愿意帮助或有助于该项目。该项目托管在 Github 上,我很乐意接受一些拉请求。😃
使用 R 探究两个变量
本文是 R-One Variable 中的探索性数据分析的继续,其中我们讨论了伪 facebook 数据集的 EDA。
在本文中,我们将基于 Udacity 策划的伪 facebook 数据集,了解数据聚合、条件均值和散点图。
现在我们将同时考察两个连续变量。散点图是检验两个变量之间关系的最佳图之一。让我们在所有用户的年龄和朋友数量之间画一个散点图。
qplot(age,friend_count,data=pf)
运筹学
ggplot(aes(x=age,y=friend_count),data=pf)+
geom_point()
当我们使用 geom_point()时,散点图是默认图。

Plot 1 Scatter Plot — Friend Count Vs Age
从上面的图中,以下两个观察结果是相当明显的:
- 年龄不到 30 岁的人有成千上万的朋友
- 69 岁接近 100 岁有一条垂直线,似乎不正确。
我们知道持有脸书帐户的最低年龄要求是 13 岁,90 岁似乎是一个相当大的年龄,所以让我们将 x 轴限制在 13 到 90 岁之间。
ggplot(aes(x=age,y=friend_count),data=pf)+
geom_point()+
xlim(13,90)

Plot 2 Scatter Plot — Age Vs Friend Count (x axis restricted)
上面的地块比地块 1 好,但是下部人满为患,很难统计那个区域的点数。
geom_point 的 Alpha 美学可用于设置地块过度拥挤区域中点的透明度级别。
对于我们的场景,让我们设置 alpha 值为 1/20,这意味着需要 20 个点来完成一个黑点。
ggplot(aes(x=age,y=friend_count),data=pf)+
geom_point(alpha=1/20)+
xlim(13,90)

Plot 3 Scatter Plot — Age Vs Friend Count — Alpha Aesthetics
此外,将抖动添加到我们的绘图中,以分散过度绘制的点。
抖动是指向数据中添加少量随机噪声。
ggplot(aes(x=age,y=friend_count),data=pf)+
geom_jitter(alpha=1/20)+
xlim(13,90)

Plot 4 Scatter Plot — Age Vs Friend Count — Jittering
从上面的情节可以推断,25 岁以下的用户绝大多数朋友都在 1000 以下。这个推论与我们从情节 1 的第一个观察相矛盾,象征着 EDA 的重要性。
更进一步,让我们使用 coord_trans 进行可视化。
ggplot(aes(x=age,y=friend_count),data=pf)+
geom_point(alpha=1/20)+
xlim(13,90)+
coord_trans(y = "sqrt")
运筹学
ggplot(aes(x=age,y=friend_count),data=pf)+
geom_point(alpha=1/20,position=position_jitter(h=0))+
xlim(13,90)+
coord_trans(y = "sqrt")

Plot 5 Scatter Plot — Age Vs Friend Count — Use coord_trans
有了这个剧情,看好友数,条件,年龄就容易多了。
从数据可视化到现在,我们可以观察数据集中的每一个点。尽管如此,从这样的显示中还是无法确定重要的量,如平均值和中间值。有时我们想了解均值或中值如何随其他变量而变化。让我们创建一个表格,为我们提供所有年龄的平均值和中间值。为此我们将使用D Plyr。【Dplyr 的基础教程可以在这里和这里找到。同样可以使用 lapply、tapply 和 split 等函数创建。
age_groups<-group_by(pf,age)
pf.fc_by_age<-summarise(age_groups,
friend_count_mean=mean(friend_count),
friend_count_median=median(friend_count),
n=n())
pf.fc_by_age<-arrange(pf.fc_by_age,age)
head(pf.fc_by_age)
上面的代码产生一个tible,输出如下所示:
A tibble: 6 x 4
age friend_count_mean friend_count_median n
<int> <dbl> <dbl> <int>
1 13 165\. 74 484
2 14 251\. 132 1925
3 15 348\. 161 2618
4 16 352\. 172\. 3086
5 17 350\. 156 3283
6 18 331\. 162 5196
Tibbles 是数据帧的现代版本。他们保留了经受住时间考验的功能,放弃了过去方便但现在令人沮丧的功能。更多信息可以在找到。
使用上面的表格,我们将绘制年龄与朋友数量平均值的散点图。
ggplot(aes(age,friend_count_mean),data=pf.fc_by_age) +
geom_point()

Plot 6 Scatter Plot — Age Vs Friend Count Mean
用线将分散的点连接起来。请遵守几何线。
ggplot(aes(age,friend_count_mean),data=pf.fc_by_age) +
geom_line()

Plot 7 Line Plot — Age Vs Friend Count Mean
酷!让我们在图 5 中绘制之前的散点图。
ggplot(aes(x=age,y=friend_count),data=pf)+
geom_point(alpha=1/20,
position=position_jitter(h=0),
color='red')+
xlim(13,90)+
coord_trans(y = "sqrt")+
geom_line(stat='summary',fun.y=mean)+
geom_line(stat='summary',fun.y=median,linetype=2,color='blue')+
geom_line(stat='summary',fun.y=quantile,fun.args=list(probs=0.9),color='blue')

Plot 8 — Overlaying summaries with raw data
从上面我们可以推断,超过 1000 个朋友是很少发生的。要进一步缩放,我们可以使用 coord_cartesian。
ggplot(aes(x=age,y=friend_count),data=pf)+
coord_cartesian(xlim=c(13,70),ylim=c(0,1000))+
geom_point(alpha=1/20,
position=position_jitter(h=0),
color='orange')+
geom_line(stat='summary',fun.y=mean)+
geom_line(stat='summary',fun.y=median,linetype=2,color='blue')+
geom_line(stat='summary',fun.y=quantile,fun.args=list(probs=0.9),color='brown')

Plot 9— Overlaying summaries with raw data — Zoomed
接下来,作为探索性数据分析系列的一部分,我们将通过 R 探索多个变量。
探索神经网络的激活函数
在这篇文章中,我想更多地关注我们在神经网络中使用的激活函数。为此,我将使用具有不同激活函数的简单全连接神经网络来解决 MNIST 问题。
MNIST 数据是一组大约 70000 张手写数字的照片,每张照片的尺寸是 28x28,并且是黑白的。这意味着我们的输入数据形状是(70000,784),我们的输出是(70000,10)。
我将使用一个基本的全连接神经网络,只有一个隐藏层。它看起来像这样:

输入层有 784 个神经元,照片中的每个像素一个,隐藏层有 512 个神经元,输出层有 10 个神经元,每个数字一个。
在keras中,我们可以为每一层使用不同的激活功能。这意味着,在我们的情况下,我们必须决定在隐藏层和输出层使用什么激活函数,在这篇文章中,我将只在隐藏层进行实验,但它也应该与最终层相关。
有许多激活函数,我将只讨论基本的:Sigmoid,Tanh 和 Relu。
首先,让我们尽量不要使用任何激活功能。你认为会发生什么?下面是代码(我跳过了数据加载部分,你可以在这个笔记本里找到完整的代码):
model = Sequential()
model.add(Dense(512, input_shape=(784,)))
model.add(Dense(10, activation='softmax'))
我说过,784 个输入,512 个在隐藏层,10 个神经元在输出层。在培训之前,我们可以使用model.summary and model.layers查看网络架构和参数:
Layers (input ==> output)
--------------------------
dense_1 (None, 784) ==> (None, 512)
dense_2 (None, 512) ==> (None, 10)Summary
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 512) 401920
_________________________________________________________________
output (Dense) (None, 10) 5130
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________
None
好了,现在我们确定了网络的架构,让我们针对 5 个时期进行培训:
Train on 60000 samples, validate on 10000 samples
Epoch 1/5
60000/60000 [==============================] - 3s - loss: 0.3813 - acc: 0.8901 - val_loss: 0.2985 - val_acc: 0.9178
Epoch 2/5
60000/60000 [==============================] - 3s - loss: 0.3100 - acc: 0.9132 - val_loss: 0.2977 - val_acc: 0.9196
Epoch 3/5
60000/60000 [==============================] - 3s - loss: 0.2965 - acc: 0.9172 - val_loss: 0.2955 - val_acc: 0.9186
Epoch 4/5
60000/60000 [==============================] - 3s - loss: 0.2873 - acc: 0.9209 - val_loss: 0.2857 - val_acc: 0.9245
Epoch 5/5
60000/60000 [==============================] - 3s - loss: 0.2829 - acc: 0.9214 - val_loss: 0.2982 - val_acc: 0.9185Test loss:, 0.299
**Test accuracy: 0.918**
我们得到的结果不是很好,在 MNIST 数据集上 91.8%的准确率相当糟糕。当然,你可以说我们需要比 5 个时期多得多的时期,但是让我们画出损失:

你可以看到验证损失没有改善,我可以向你保证,即使经过 100 个时代也不会改善。我们可以尝试不同的技术来防止过度适应,或者让我们的网络更大更智能,以便更好地学习和提高,但让我们只是尝试使用sigmoid激活功能。
Sigmoid 函数看起来像这样:

它将输出压缩为(0,1)区间,并且是非线性的。让我们在网络中使用它:
model = Sequential()
model.add(Dense(512, activation='sigmoid', input_shape=(784,)))
model.add(Dense(10, activation='softmax'))
你可以看到架构是完全一样的,我们只改变了Dense层的激活功能。让我们再训练 5 个纪元:
Train on 60000 samples, validate on 10000 samples
Epoch 1/5
60000/60000 [==============================] - 3s - loss: 0.4224 - acc: 0.8864 - val_loss: 0.2617 - val_acc: 0.9237
Epoch 2/5
60000/60000 [==============================] - 3s - loss: 0.2359 - acc: 0.9310 - val_loss: 0.1989 - val_acc: 0.9409
Epoch 3/5
60000/60000 [==============================] - 3s - loss: 0.1785 - acc: 0.9477 - val_loss: 0.1501 - val_acc: 0.9550
Epoch 4/5
60000/60000 [==============================] - 3s - loss: 0.1379 - acc: 0.9598 - val_loss: 0.1272 - val_acc: 0.9629
Epoch 5/5
60000/60000 [==============================] - 3s - loss: 0.1116 - acc: 0.9673 - val_loss: 0.1131 - val_acc: 0.9668
Test loss: 0.113
**Test accuracy: 0.967**
那好多了。为了理解为什么,让我们回忆一下我们的神经元是什么样子的:

其中x是输入,w是权重,b是偏差。可以看到,这只是输入与权重和偏差的线性组合。即使在叠加了很多之后,我们仍然可以把它表示成一个线性方程。这意味着,它类似于一个完全没有隐藏层的网络,对于任何数量的隐藏层都是如此。!).我们将添加一些层到我们的第一个网络,看看会发生什么。看起来是这样的:
model = Sequential()
model.add(Dense(512, input_shape=(784,)))for i in range(5):
model.add(Dense(512))model.add(Dense(10, activation='softmax'))
这是网络的样子:
dense_1 (None, 784) ==> (None, 512)
dense_2 (None, 512) ==> (None, 512)
dense_3 (None, 512) ==> (None, 512)
dense_4 (None, 512) ==> (None, 512)
dense_5 (None, 512) ==> (None, 512)
dense_6 (None, 512) ==> (None, 10)
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 512) 401920
_________________________________________________________________
dense_2 (Dense) (None, 512) 262656
_________________________________________________________________
dense_3 (Dense) (None, 512) 262656
_________________________________________________________________
dense_4 (Dense) (None, 512) 262656
_________________________________________________________________
dense_5 (Dense) (None, 512) 262656
_________________________________________________________________
dense_16 (Dense) (None, 10) 5130
=================================================================
Total params: 1,720,330
Trainable params: 1,720,330
Non-trainable params: 0
_________________________________________________________________
None
这些是训练 5 个时期后的结果:
Train on 60000 samples, validate on 10000 samples
Epoch 1/5
60000/60000 [==============================] - 17s - loss: 1.3217 - acc: 0.7310 - val_loss: 0.7553 - val_acc: 0.7928
Epoch 2/5
60000/60000 [==============================] - 16s - loss: 0.5304 - acc: 0.8425 - val_loss: 0.4121 - val_acc: 0.8787
Epoch 3/5
60000/60000 [==============================] - 15s - loss: 0.4325 - acc: 0.8724 - val_loss: 0.3683 - val_acc: 0.9005
Epoch 4/5
60000/60000 [==============================] - 16s - loss: 0.3936 - acc: 0.8852 - val_loss: 0.3638 - val_acc: 0.8953
Epoch 5/5
60000/60000 [==============================] - 16s - loss: 0.3712 - acc: 0.8945 - val_loss: 0.4163 - val_acc: 0.8767
Test loss: 0.416
**Test accuracy: 0.877**

这很糟糕。我们可以看到网络无法学习我们想要的东西。这是因为没有非线性,我们的网络只是一个线性分类器,不能获得非线性关系。
另一方面,sigmoid是一个非线性函数,我们不能将其表示为我们输入的线性组合。这给我们的网络带来了非线性,使它能够学习非线性关系。让我们再次尝试训练 5 个隐藏层网络,这次使用sigmoid激活:
Train on 60000 samples, validate on 10000 samples
Epoch 1/5
60000/60000 [==============================] - 16s - loss: 0.8012 - acc: 0.7228 - val_loss: 0.3798 - val_acc: 0.8949
Epoch 2/5
60000/60000 [==============================] - 15s - loss: 0.3078 - acc: 0.9131 - val_loss: 0.2642 - val_acc: 0.9264
Epoch 3/5
60000/60000 [==============================] - 15s - loss: 0.2031 - acc: 0.9419 - val_loss: 0.2095 - val_acc: 0.9408
Epoch 4/5
60000/60000 [==============================] - 15s - loss: 0.1545 - acc: 0.9544 - val_loss: 0.2434 - val_acc: 0.9282
Epoch 5/5
60000/60000 [==============================] - 15s - loss: 0.1236 - acc: 0.9633 - val_loss: 0.1504 - val_acc: 0.9548
Test loss: 0.15
**Test accuracy: 0.955**

还是那句话,好多了。我们可能过拟合,但我们得到了一个显着的性能提升只是通过使用激活函数。
Sigmoid 很棒,它有许多积极的属性,如非线性、可微性和(0,1)范围为我们提供了返回值的概率,这很好,但它也有缺点。当我们使用反向传播时,我们必须将输出的导数反向传播回我们的第一个权重,换句话说,我们希望将最终输出值中的分类/回归误差传递回整个网络。这意味着我们应该派生我们的层并更新权重。sigmoid 的问题是,它的导数是这样的:

你可以看到导数的最大值非常小(0.25),这意味着我们只会将一小部分误差传递给前面的层。这可能会导致我们的网络学习缓慢(我所说的缓慢是指我们需要更多的数据或时期,而不是计算时间)。
为了解决这个问题,我们可以使用Tanh函数,如下所示:

tanh函数也是非线性和可微的。它的输出在(-1,1)范围内,没有(0,1)范围好,但是对于隐藏层来说还是可以的。最后,它的最大导数是一个很好的值,因为现在我们可以更好地传递误差。
要使用tanh激活功能,我们只需改变Dense层的activation属性:
model = Sequential()
model.add(Dense(512, activation=’tanh’, input_shape=(784,)))
model.add(Dense(10, activation=’softmax’))
还是那句话,网络架构是一样的,只是激活不同。让我们训练 5 个纪元:
Train on 60000 samples, validate on 10000 samples
Epoch 1/5
60000/60000 [==============================] - 5s - loss: 0.3333 - acc: 0.9006 - val_loss: 0.2106 - val_acc: 0.9383
Epoch 2/5
60000/60000 [==============================] - 3s - loss: 0.1754 - acc: 0.9489 - val_loss: 0.1485 - val_acc: 0.9567
Epoch 3/5
60000/60000 [==============================] - 3s - loss: 0.1165 - acc: 0.9657 - val_loss: 0.1082 - val_acc: 0.9670
Epoch 4/5
60000/60000 [==============================] - 3s - loss: 0.0843 - acc: 0.9750 - val_loss: 0.0920 - val_acc: 0.9717
Epoch 5/5
60000/60000 [==============================] - 3s - loss: 0.0653 - acc: 0.9806 - val_loss: 0.0730 - val_acc: 0.9782
Test loss: 0.073
**Test accuracy: 0.978**

太好了!仅通过使用不同的激活函数,我们就将测试精度提高了 1%以上。
我们能做得更好吗?似乎在大多数情况下,我们可以使用 relu 激活功能。Relu 长这样:


这个激活函数的范围是(0,inf),在零点不可微(这个有解)。关于relu最好的事情是它的梯度是总是等于1,这样我们可以在反向传播过程中通过网络传递最大数量的误差。
让我们训练一下,看看结果:
Train on 60000 samples, validate on 10000 samples
Epoch 1/5
60000/60000 [==============================] - 5s - loss: 0.2553 - acc: 0.9263 - val_loss: 0.1505 - val_acc: 0.9516
Epoch 2/5
60000/60000 [==============================] - 3s - loss: 0.1041 - acc: 0.9693 - val_loss: 0.0920 - val_acc: 0.9719
Epoch 3/5
60000/60000 [==============================] - 3s - loss: 0.0690 - acc: 0.9790 - val_loss: 0.0833 - val_acc: 0.9744
Epoch 4/5
60000/60000 [==============================] - 4s - loss: 0.0493 - acc: 0.9844 - val_loss: 0.0715 - val_acc: 0.9781
Epoch 5/5
60000/60000 [==============================] - 3s - loss: 0.0376 - acc: 0.9885 - val_loss: 0.0645 - val_acc: 0.9823
Test loss: 0.064
**Test accuracy: 0.982**
到目前为止,我们取得了最好的成绩。98.2%这是一个不错的结果,我们只使用了一个隐藏层。
需要注意的是,这里没有最好的激活功能。在许多情况下,一个可能比另一个更好,但在另一些情况下会更差。
另一个重要的注意事项是,使用不同的激活函数不影响我们的网络可以学习什么,只影响多快(它需要多少数据/时期)。这是我们尝试过的所有激活函数的曲线图,但这次是在一个更长的训练周期内。你可以看到所有的激活函数最终都达到了 98%的准确率。

希望你喜欢这篇文章。你可以在这里找到代码。
使用 pandas 和 Bokeh 探索和可视化芝加哥公交数据—第一部分(pandas 简介)

Source: Me
本系列的第 1 部分 是对 pandas 的介绍,其中我将描述如何用 python3 将大型开放存取数据集读入 Jupyter 笔记本,并演示 pandas 作为高性能数据操作/分析软件包的一些功能。
第 2 部分 将更深入地探讨散景软件包,在这里我将演示交互式可视化功能和地理空间映射特性,以便以引人入胜的方式呈现第 1 部分中的数据。
芝加哥市提供了大量的开放数据供市民探索。芝加哥数据门户(https://data.cityofchicago.org/)收藏了成千上万可供下载的数据集。它包括从电影拍摄地到你最喜欢的餐馆的卫生数据。人们已经创建了以非常独特和有用的方式集成这些数据的应用程序!例如,我发现了一个应用程序,当你的街道将被清扫时,它会通过短信提醒你(以避免城市在清洁期间因未能移动你的汽车而发放的可爱罚单):参见 https://sweeparound.us
我认为探索芝加哥数据门户上的数据集会很有趣,围绕的主题是大多数芝加哥人都熟悉的:芝加哥运输管理局(CTA)公共列车系统(也称为“L”列车)。对于非芝加哥地区的人,CTA 列车系统分为 8 条不同的“L”型列车线路:

每条铁路线都经过一组车站。有些车站有多条线路穿过。以下是 CTA 列车系统的地图:

CTA Transit Map. Source: https://www.transitchicago.com/assets/1/6/ctamap_Lsystem.png
数据
芝加哥数据门户有许多与公共交通系统相关的数据集。我们将在本教程中使用的两个数据集位于下面:
第一个数据集包含所有 CTA 火车站的每月乘客总数,并进一步按日类型细分。(工作日、周六或周日/假日)令人惊叹的是,这些数据可以追溯到 2001 年。相当令人印象深刻!
第二个数据集是一个地图,它包含关于每个 CTA 火车站的地理空间数据(包括车站名称和地图上的坐标)。您可以将信息导出为多种格式(JSON、TSV、XML)。我们将在本教程的第 2 部分更多地使用它。
制定问题/探索数据
作为一个芝加哥人,我坐过大部分的火车线(除了紫色线)。通过经常乘坐火车,你可以对某些交通模式有所了解。例如,你会知道在早上 7:30 带你的全家去红线州/湖站是一个非常糟糕的主意。使用这些交通数据,可以发现更多具体的和基于数据的模式。
在全力以赴分析数据和绘制曲线之前,你必须提出问题——或者开始探索数据。总的来说,你希望发现什么?你在查阅资料前后有哪些具体的疑问?你不知道你想知道什么?这个过程可以是迭代的:发现新信息后,可以开始提出新的问题。
我对 CTA 培训系统的一些一般性问题,这些数据将有助于回答:
问题
- 我公寓旁边的两个火车站哪个更受欢迎?
- 总体上最受欢迎(和最不受欢迎)的电台有哪些?
- 城市的哪个区域乘客最多?
- 随着时间的推移,有什么有趣的乘客趋势吗?
与大多数数据科学问题一样,首先要做的是读入和处理数据(并检查数据质量问题),开始回答一些基本问题。这将是本文的主要焦点(问题 1-2 的答案)。我计划在第 2 部分深入一些更高级的主题,包括使用散景和彩虹贴图的更高级的可视化方法(问题 3-4)。
Jupyter 笔记本入门
我将使用一个 Jupyter 笔记本和 python3,以及其他一些有用的软件包(熊猫和散景)来进行分析。如果你不知道什么是Jupyter笔记本,那你就错过了!这是一种令人难以置信的编程/进行探索性数据分析的可视化方式,它帮助我成为一名更好的 python 程序员,并使我摆脱了 Excel 的束缚。这里有一些在你的电脑上安装 Jupyter 的说明:http://jupyter.org/install
你还需要安装 python3 和 pandas / bokeh 包。我在命令行中使用了以下命令:
pip3 install pandas
pip3 install bokeh
要从命令行(在所需的目录中)启动 Jupyter 笔记本,请键入:
jupyter notebook
这将在浏览器中启动 Jupyter 笔记本仪表板(默认情况下,[http://localhost:8888](http://localhost:8888))。

这个 dasboard 视图显示了启动笔记本服务器的目录中的笔记本、文件和子目录的列表。
要创建一个新的笔记本,你点击顶部的新建按钮,并选择一个 Python 3 环境。

这将打开笔记本视图,您可以在这里开始用 python3 编码!

要想快速了解如何使用 jupyter 笔记本,请看 t 他的文章。
工具
我将在此分析中使用的两个主要工具是熊猫和散景:
- pandas:Python包提供了快速、灵活且富于表现力的数据结构,旨在使处理“关系”或“带标签”的数据变得既简单又直观。它的目标是成为用 Python 进行实际的、真实世界的数据分析的基础高级构建块”
- 散景 :“散景是一个交互式可视化库,面向现代 web 浏览器进行演示。它的目标是提供优雅、简洁的通用图形结构,并通过超大型或流式数据集的高性能交互来扩展这种能力。散景可以帮助任何想要快速轻松地创建交互式绘图、仪表盘和数据应用的人。”
底线是 pandas 将主要用于存储和操作数据(在数据帧中),而 Bokeh 将用于数据的呈现和可视化。
读入数据
为了读入数据,我导入了 pandas 包并读入了 L-stop 平均客流量的 CSV。我可以用 。read_csv() 函数执行此操作,传递文件名和一个分隔符作为参数:
import pandas as pdL_Rides = pd.read_csv('CTA-L-Monthly-Ridership.csv',sep=',')
L_Rides.head()

L_Rides 是包含乘客数据的数据帧。使用 。head() 功能允许我只查看数据帧的前几行。这是查看数据外观的好方法。
这里我们看到有几列数据:
- station_id,stationame,month_beginning,avg_weekday_rides,avg_saturday_rides,avg_sunday-holiday_rides,month_total
看起来每个车站和每个月都有工作日/周末的乘客统计,以及每个车站的每月总数。
熊猫还有一个有用的功能叫做 。describe() 用于汇总数据帧,提供关于数据集的有用统计信息(平均值、最小值、最大值等)。运行以下命令,将提供这些统计信息:
L_Rides.describe()

查看该数据框,我们可以看到该数据集中总共有 29,460 个数据点(行)。一些更有趣的花絮:
- 工作日最多乘车一站已给过24041。
- 一个普通的 CTA 站一个月大概给 100,573 次乘车。
- 一般来说,工作日的乘客最多,而周日的乘客最少。
查看这些单独的数字可以提供线索,了解哪些统计数据值得可视化,尽管创建表格和可视化可以提供更完整的图片并讲述更有说服力的故事。
回答问题
问题 1: 我公寓旁边的两个火车站哪个更受欢迎?
在阅读完数据后,我现在可以开始回答我最初的一些问题了。我住在城市的北边 Edgewater ,离我最近的两个站是 Bryn Mawr 和 Berwyn 红线站。想知道 2017 年这两个哪个最受欢迎?我可以使用熊猫非常有用的索引功能来做到这一点。
为了选择 Berwyn 站的数据,我最终回答了以下问题:
找到伯温站是【车站名称】的所有数据
您可以将此查询转换成熊猫索引选择,如下所示:
L_Rides[L_Rides['stationame'] == 'Berwyn']

您可以看到,这将数据帧过滤为只有那些以“Berwyn”作为“stationame”的电台。
好吧,那很酷。但是我怎么只得到 2017 年的伯温站数据呢?
简单。您可以添加更多布尔运算符来过滤日期。
查找 2017 年 1 月 1 日到 2017 年 12 月 31 日之间的所有数据
这里棘手的部分是导入的数据被分配了特定的变量类型。Pandas 尽力为每一列中的数据分配变量类型。例如,stationame 列作为一个字符串被引入(技术上是一个 python 对象:在这里阅读更多内容)。您可以使用以下命令对此进行检查:
L_Rides.dtypes

您可以在上面看到所有列及其关联的数据类型。有一些好消息和坏消息。
坏消息:‘month _ beginning’列不是日期-时间类型,我们不能很容易地进行日期比较
好消息:熊猫让改变这种类型变得容易
要在 pandas 中更改整列的数据类型,可以使用 到 _datetime() 函数。我通常的做法是为这些数据创建一个新列。我使用以下命令来完成此操作:
L_Rides['date_time'] = pd.to_datetime(L_Rides['month_beginning'])

您可以看到添加了另一个名为 date_time 的列,它现在是“datetime64[ns]”数据类型。
现在我们可以执行日期时间比较操作。我可以使用以下命令选择 2017 年 1 月 1 日至 2017 年 12 月 31 日之间的 Berwyn 数据:
Berwyn_Rides = L_Rides[(L_Rides['stationame'] == 'Berwyn') &
(L_Rides['date_time'] >= '01/01/2017') &
(L_Rides['date_time'] < '12/31/2017')]

现在,我们拥有 2017 年 Berwyn 站各月数据的 12 个数据点。
最后一步是获得全年的总乘客量。为此,我必须汇总我选择的不同数据行。同样,pandas 使这变得非常容易,因为数据框具有数学函数,可以应用于每一列数据。
不出所料,求和函数被称为 。求和() 。您可以直接使用这个函数来获得数据框中每一列的总和,或者您可以传递特定的列名。我使用以下命令获得了 Berwyn 2017 年的乘客总数:
Berwyn_Rides['monthtotal'].sum()

可以对布林莫尔站执行相同的命令:

最终,我们看到2017 年,布林莫尔站的受欢迎程度比伯温站高出近 50%(1,094,141 次伯温骑行到 1,509,613 次布林莫尔骑行)。
问题 2:最受欢迎(和最不受欢迎)的电台有哪些?
下一个问题是关于 CTA 运输系统中所有车站的数据,因此我们将使用整个 L 车站数据集。要获得最受欢迎的中转站的列表,我们必须首先按每个中转站对数据进行分组。
像我在前面的例子中所做的那样为每个站创建单独的总数将会是一堆不必要的工作。相反我们要用这个奇妙的 。groupby() 熊猫才有的功能!
groupby 函数在这里有很好的描述,但基本概念是执行以下一个或多个函数:
分割—将数据分组
应用—对组执行功能
合并-将结果合并到数据结构中
对于这个公交示例,我们希望将数据分成公交站组,对总乘客量应用求和函数,然后将结果组合成单个数据帧。
首先,我们可以使用以下命令按站点执行分割:
Station_Group = L_Rides.groupby(['stationame'])

上面我们看到这个组只是一个熊猫数据帧组对象。对于这个对象,你可以执行各种应用功能。若要查看数据已被拆分的唯一组,可以使用。群组功能:
Station_Group.groups

结果表明,该对象只是一个字典,其中包含作为键的组,以及作为值的该组的值。
创建分组对象后,我们可以对组执行聚合(应用)操作。我想对数据帧的“monthtotal”列应用求和运算。我用下面的命令做到这一点:
Station_Group['monthtotal'].sum()#orStation_Group['monthtotal'].agg('sum')

这里我们可以看到每个站点的月总数,一直到 2001 年初。
对此我们能做的最后一件事是将结果组合回一个数据帧中(并使用和对结果进行排序)。sort_values( ) 函数):
Station_Totals = pd.DataFrame(Station_Group['monthtotal'].sum())
Station_Totals.sort_values(ascending=False,by='monthtotal',inplace=True)
Station_Totals

现在我们有了每个站点的乘客总数的数据框,我们可以回答提出的问题了。我将使用一些方便的 pandas 命令返回前 5 个站点和后 5 个站点:
Station_Totals.head(5) # Top 5 stationsStation_Totals.tail(5) # Bottom 5 stations

现在我们有最受欢迎和最不受欢迎的 CTA 站(从 2001 年初开始)。
好了,现在关于霍曼上的那 27 次乘坐…
迷你历史课
来自维基百科:
H 阿曼是芝加哥运输管理局的绿线上的站。车站位于芝加哥的东加菲尔德公园附近的湖街和霍曼大道。霍曼位于普拉斯基以东和凯兹以西。霍曼于 1894 年 3 月开放,1994 年 1 月 9 日关闭,当时整条绿线因一项翻新和修复工程而关闭。1996 年 5 月 12 日,该车站没有与绿线的其他部分一起重新开放。【1】
所以很有可能在车站关闭之前/之后有 27 个人乘坐了一些车…
使用熊猫的基本情节
虽然 pandas 主要用于数据辩论,但它也有一些有用的绘图功能。熊猫可以从数据帧中绘制图表(使用引擎盖下的[matplotlib](https://matplotlib.org)库)。功能。plot() 可以追加到一个 dataframe 中来绘制所有的列。
Berywn_Rides.plot()

上图不是特别有用,尽管额外的参数(比如用于 x 和 y 轴的列)可以传递给。plot()函数来制作一个更有用的图形。下面,我将列名作为 x 和 y 参数传递,以绘制一段时间内工作日的平均乘车次数。
Berwyn_Rides.plot(x ='date_time', y='avg_weekday_rides')

The above graph displays the Berwyn stop average weekday rides over the course of 2017.
默认情况下,pandas 使用线条绘制数据,尽管也可以使用许多其他可视化类型:直方图、盒状图、饼状图等。
为了演示这一点,我将创建一个排名前 25 位的 CTA 站点的条形图。我可以使用我们上面制作的 Station_Totals 数据帧,并传递‘bar’作为‘kind’参数和 60 作为‘rot’参数,将标签旋转 60 度。
Station_Totals.head(25).plot(kind='bar',rot=60)

如您所见,pandas 中的绘图功能使用起来相当简单。因为 pandas 使用 matplotlib 库作为包装器,所以可以使用 matplotlib 的特性进一步定制绘图。
关于 pandas 的伟大之处在于数据帧可以在其他主要的 python 绘图包中使用。(即 plot.ly 和 Bokeh )。所以你不只是停留在一个选项来绘制你的数据。
在我的下一篇文章(第 2 部分)中,我将介绍散景可视化包,开始可视化一些 CTA 交通数据。我还将尝试将 CTA 地图集成到可视化中,以提供关于乘客数据的地理上下文信息!敬请期待!希望你喜欢第 1 部分。
使用 pandas 和散景探索和可视化芝加哥公交数据—第二部分(散景介绍)

Live Version of the Plot: https://cpreid2.github.io/Chicago-CTA/
本系列的第 1 部分是对 pandas 的介绍,其中我描述了如何使用 python3 将大型开放存取数据集读入 Jupyter 笔记本,并演示了 pandas 作为高性能数据操作/分析软件包的一些功能。
在这个大数据时代,从空间和地理角度进行思考从未如此重要,创建引人注目的地理空间数据可视化已经成为数据科学家的一项基本技能。
我上一篇文章的目的是帮助回答一些关于芝加哥交通数据的问题。我关于数据集的第三个问题如下:
3。这个城市的哪个地区有最多的火车乘客?
要回答这个问题,在地图上查看乘客数据很有帮助。随着 CTA 乘客数据加载到熊猫数据框架中,制作这样的地图是完全可能的。
在本文中,我将基于第 1 部分中使用的数据,介绍一个非常棒的交互式可视化库,名为散景,它可以使用熊猫数据帧作为输入来创建交互式图形。

Source: https://bokeh.pydata.org/en/latest/
什么是散景?
我喜欢子弹,所以这里有一些:
- Bokeh 是 python 的一个数据可视化库****
- 散景是为网络而建的
- 创建由数据驱动的动态和交互式图/图形****
为什么要用散景?
除了我说你应该使用散景之外,还有很多好的理由使用散景。您应该在以下情况下使用它:
- 你想构建交互式网络图形,但是比起 javascript,你更喜欢用 python 编码
- 您希望使用大型数据集。****
关于散景的另一个优点是,它有一个大型类库和函数库,所以你可以非常容易地构建非常高级的可视化效果。
总的来说,我发现它是一个制作漂亮的 web 2.0 可视化效果的非常简单的库。
散景积木
您可以将散景图视为一系列对象。在最底层是一个图形,,在它上面你可以添加*字形。*******

一个图是所有元素(即情节)的分组,而字形是散景可以显示的基本视觉标记。最基本的字形是一条线。还有很多其他字形,比如圆、条、楔等。最棒的是,你可以在一个图形上堆叠多个字形。****
在接下来的几节中,我将参考本系列第 1 部分中的数据帧。假设您已经在机器上安装了 Jupyter、pandas 和 Bokeh。
构建您的第一个散景图
用散景构建一个简单的情节只需要几行代码。我们将遵循这一循序渐进的过程:
- 导入必要的模块
- 创建一个图
- 添加字形
- 显示/导出图形
我将为一些样本值构建一个简单的 x/y 图,对该图应用一些格式,然后显示该图。我可以用下面的代码做到这一点:
*****# 1\. Import Modules
**from bokeh.io import show, output_notebook
from bokeh.plotting import figure**# 2\. Create Figure
p = figure(plot_width = 600, plot_height = 400, title = 'My First Plot')# 3\. Add Glyphs
x = [1, 2, 3, 4, 5]
y = [10, 20, 40, 80, 160]p.circle(x, y, color = 'red', alpha = 0.5, size = 15)# 4\. Show the plot
output_notebook()
show(p)*****

我将在下面的部分中分解生成该图的代码:
- ****导入模块:show()和 output_notebook()函数用于显示 Jupyter 笔记本中的图形。如果您想生成一个静态 HTML 文件(用于创建独立的 web 应用程序),您可以导入并使用 output_file()函数。还导入了 figure()类,它包含大多数用于显示对象的默认选项。
- 创建 Figure :要创建一个新的绘图,您需要实例化一个新的 Figure()类。用外行人的话来说,你创建一个新的人物对象。您可以向该函数传递参数来修改默认布局。例如,我设置了情节的高度和宽度,并给情节加了一个标题。
- ****添加字形:可视化的要点是显示数据。我创建了两个数据列表(标记为 x 和 y)。虽然我已经创建了 python 列表,但是您可以使用 NumPy 数组或 Pandas 系列作为输入数据。有了数据,您可以将它传递给一个 render / Glyph 函数来呈现数据。这里我使用了圆()字形。如果我愿意,我可以在这个列表中使用任何其他字形。
- ****显示/导出:我现在可以调用一些函数来显示剧情了。我调用 output_notebook()来渲染 Jupyter 笔记本中的情节。然后我调用 show()来实际渲染情节。
当剧情渲染时,你会注意到它是交互式的!您可以轻松地放大和缩小绘图。右边的工具控制这个功能。默认情况下,绘图包括缩放、保存和重置绘图的工具。你会看到这些都是可定制的。
这就是全部了!现在让我们开始处理芝加哥的交通数据。
创建 CTA 乘客的地理空间地图
散景映射功能
散景非常适合处理地理空间数据。将地图数据添加到地块的方法与将其他类型的图示符添加到地物的方法相同。您将使用 add_tiles() 命令和一个 tile provider 作为参数来传入 tiles,而不是使用 circle()之类的东西。
要创建一个非常简单的地图,您可以使用以下代码:
*******from** **bokeh.plotting** **import** figure, show, output_notebook
**from** **bokeh.tile_providers** **import** CARTODBPOSITRONp = figure(x_range=(-9780000, -9745000), y_range=(5130000, 5160000),
x_axis_type="mercator", y_axis_type="mercator")p.add_tile(CARTODBPOSITRON)output_notebook()
show(p)*****

这段代码生成了一张芝加哥周围的地图。就像其他散景可视化一样,该地图是交互式的,允许用户放大和缩小地图。
墨卡托投影:地图的拼贴使用了墨卡托投影。这里有一篇方便的维基百科文章描述了它是什么。本质上,地球的球面坐标(经纬度)可以投影到一个平面上(X 和 Y 坐标)。您在浏览器上以 2d 方式查看地图,因此这基本上就是用于显示数据的内容。
在上面的代码中,您可以看到图形是使用 X 和 Y 坐标绘制的。
- 在 figure()函数中,我可以传入 X 和 Y 范围,以便地图放大感兴趣的区域(芝加哥)。
- x/y_axis_type 参数指定我希望以熟悉的纬度和经度坐标显示坐标。
有了绘制地图的能力,我们现在可以开始准备将乘客数据投影到地图上。
读入 CTA 中转站位置数据
如第 1 部分所述,芝加哥市提供了每个中转站位于的信息。我可以将它读入数据框,并使用以下 pandas 命令查看数据:
*****L_Map = pd.read_csv('CTA-L-Stops-Map.csv',sep=',')
L_Map.head()*****

从这些数据中,我们注意到了一些情况:
- 每行代表一个不同的站点,由 STOP_ID 标识
- 每个站可以有个停靠点(即一个站在一个方向上停靠,另一个站在另一个方向上停靠)****
- 每个站点由站点名称和唯一的地图 ID 标识
- 该数据还包括关于每个站在哪条线上的信息(即绿色、红色、蓝色等)
- 最后一列包括纬度和经度坐标
正如我们在上一节中讨论的,为了绘图的目的,地图需要 X 和 Y 坐标(不是纬度和经度)。
为了改变这些,我们需要使用一些数学和一点熊猫魔法。
我创建了一个函数,它接受一串纬度和经度坐标(类似于 dataframe 中的坐标),并将它们转换为一个 X 和 Y 坐标的元组。
*****import math
from ast import literal_eval**def merc**(Coords):
Coordinates = literal_eval(Coords) lat = Coordinates[0]
lon = Coordinates[1]
r_major = 6378137.000
x = r_major * math.radians(lon)
scale = x/lon
y = 180.0/math.pi * math.log(math.tan(math.pi/4.0 +
lat * (math.pi/180.0)/2.0)) * scale return (x, y)*****

现在我们有了一个可以将坐标转换成 Bokeh 喜欢的东西的函数,我们可以将它应用到整个数据集,并将其保存为数据框中的一个新列。我在 的帮助下做到了这一点。熊猫中的 apply() 函数和 python 中的一个 lambda 函数。
*****L_Map['coords_x'] = L_Map['Location'].**apply(lambda x: merc(x)[0])**
L_Map['coords_y'] = L_Map['Location'].**apply(lambda x: merc(x)[1])*******

创建这些列后,我们现在有了可以在地图上绘制的数据。如前所述,L_Map 数据帧中的行对于每个站点都有重复的行(列车行驶的每个方向有 2 个站点)。因此,我们将想要删除这些重复,否则我们将有两个点每站。
为此,我使用了熊猫 。drop _ duplicates()命令:
*****L_Map.drop_duplicates(subset='MAP_ID', keep="last", inplace=True)*****
现在,我们可以在之前创建的地图上叠加车站。我只需添加一个圆形符号,将列作为 x 和 y 参数传递。
*****from bokeh.plotting import figure, show, output_notebook
from bokeh.tile_providers import CARTODBPOSITRONp = figure(x_axis_type="mercator", y_axis_type="mercator")
p.add_tile(CARTODBPOSITRON)**p.circle(x = L_Map['coords_x'],
y = L_Map['coords_y'])**output_notebook()
show(p)*****

太好了!现在我们知道了每个 CTA 站在地图上的位置。
结合地理空间和乘客数据
该图表的目标是可视化最受欢迎和最不受欢迎的电台。这可以通过改变每个圆形符号的直径(或比例)来表示每个车站的相对乘客量来实现。较大的圆圈代表繁忙的车站,较小的圆圈代表乘客较少的车站。
第一步是组合包含乘客数据的数据帧和包含站 GPS 坐标的数据帧。我们将使用熊猫 。merge()功能。****
此函数允许您指定 1)要合并的数据框,2)哪些列将用作键或合并两者的列,以及 3)它们的连接方式。
在下面的代码中,我将 L_Map 数据帧(包含坐标)与根据“station_id”列分组的 Station_Totals 数据帧(包含乘客总数)合并。
*****# 1\. Group ridership totals
Station_Group = L_Rides.groupby(['station_id'])
Station_Totals = pd.DataFrame(Station_Group['monthtotal'].sum())# 2\. Merge dataframes
Merged = pd.merge(L_Map, Station_Totals, left_on='MAP_ID', right_index=True)*****

我们现在已经合并了乘客数据和地图数据!
接下来要做的是将乘客数据缩放到适当大小的圆。我选择了 2000000 作为缩放因子,因为它不会使圆圈太大或太小。一些尝试和错误帮助我确定了这个数字。
*****Merged['circle_sizes'] = Merged['monthtotal'] / 2000000*****
我们现在准备绘制我们的最终地图!我将把“circle_sizes”列传递给圆形标志符号,并添加一些其他参数来更改圆形的颜色和填充。
*****from bokeh.plotting import figure, show, output_notebook
from bokeh.tile_providers import CARTODBPOSITRON# range bounds supplied in web mercator coordinates
p = figure(x_axis_type="mercator", y_axis_type="mercator")
p.add_tile(CARTODBPOSITRON)p.circle(x=Merged['coords_x'],
y=Merged['coords_y'],
**size=Merged['circle_sizes']**,
** line_color="#FF0000",
fill_color="#FF0000",
fill_alpha=0.05**)
output_notebook()show(p)*****

看起来棒极了!但是我们怎么知道哪个站是哪个站呢?
解决方案是定制默认工具。散景有交互式工具,可用于报告信息和更改绘图参数,如缩放级别或范围(如右侧面板所示)。
帮助我们的工具叫做 悬停工具 。当用户悬停在一个圆圈上时,我们可以用它来叠加每个站点的信息。
设置悬停工具需要两个部分:
- 创建一个 ColumnDataSource 对象,该对象将成为绘图的最终数据源。这个对象有其他功能,但是我们可以在另一篇文章中讨论
- 创建一个悬停工具对象并将其指向 ColumnDataSource 对象
*****from bokeh.plotting import figure, show, output_notebook
from bokeh.tile_providers import CARTODBPOSITRON
from bokeh.models import ColumnDataSource, HoverTool**source = ColumnDataSource(data=dict(
x=list(Merged['coords_x']),
y=list(Merged['coords_y']),
ridership=list(Merged['monthtotal']),
sizes=list(Merged['circle_sizes']),
stationname=list(Merged['STATION_NAME'])))****hover = HoverTool(tooltips=[
("station", "**[**@stationname**](http://twitter.com/stationname)**"),
("ridership","**[**@ridership**](http://twitter.com/ridership)**")
])**# range bounds supplied in web mercator coordinates
p = figure(x_axis_type="mercator",
y_axis_type="mercator",
**tools=[hover, 'wheel_zoom','save']**)p.add_tile(CARTODBPOSITRON)p.circle(x='x',
y='y',
**source=source,**
size='sizes',
line_color="#FF0000",
fill_color="#FF0000",
fill_alpha=0.05)
output_notebook()show(p)*****

现在我们有能力看到哪个站是哪个了!悬停框包括原始乘客号和站名。
我们现在可以开始研究数据并做一些笔记:

- 市区环路是 CTA 系统中最繁忙的部分(拥有最大的环路)。
- 95 号红线站作为终点站,客流量惊人。有一个项目来扩展 CTA 的这一部分是有意义的。
- 城西的蓝线和绿线并没有我想象的那么繁忙。
- 在芝加哥环线上,更南边和西边的火车站是最不繁忙的。
这里主持的剧情现场版:https://cpreid2.github.io/Chicago-CTA/
虽然我计划只制作这一系列的两个部分,但是我认为尝试在地图上添加一些动画特征会有所帮助,这样可以随着时间的推移查看数据。我将在以后的文章中介绍这一点,敬请关注!
用 Python 和 Tableau 探索抗生素处方
我最近参观了在伦敦卫生和热带医学院举行的“超级细菌——对抗细菌的军备竞赛”(哈佛大学出版社)的新书发布会。发起的作者和小组成员利用这个平台表达了他们对公共卫生的担忧,以及对开发新疗法的有限激励。据估计(2014 年)每年有 700,000 人死于耐药性感染,而只有很少的药物在研发中,这一警报需要保持在头条位置。

与此同时,我希望听到更多关于近年来取得的进展。2013 年,英国政府启动了一项五年战略来对抗抗生素耐药性。一年后,这本书的作者对英国的形势进行了一次广泛的回顾。甚至在审查之前就开始实施的战略效果如何?我决定使用由英国公共卫生部(PHE)维护和提供的 AMR 本地指标来探索这个问题,作为英国战略监测组成部分的一部分。我想看看我是否能够深入了解当地和地区的抗生素使用模式,以及我是否能够提供额外的可视化和分析模式。
我开始使用在临床委托组(ccg)级别获得的数据进行研究。英格兰保健委员会是 2012 年成立的 208 个区域组织,旨在组织英格兰的保健服务。他们的数据给出了不同地区处方模式的总体情况,随后可以在更精细的水平上进行探索。所有指标/ccg 的数据作为一个数据集可用,但使用由 PHE 数据科学小组开发的指尖库可以更方便地进行研究。使用 Python (pandas、seaborn、plotly)进行数据准备、清理和分析,使用 Tableau 的故事功能构建仪表盘。脚本可以作为 jupyter 笔记本和仪表盘在这里和在这里获得。
仪表板基于每个 CCG 地区每个标准化处方单位(STAR-PU)12 个月的抗生素处方项目滚动总数。这种标准化不仅考虑到每个地区的患者人数,还考虑到他们的年龄和性别构成以及周期性波动,因此只能呈现总体趋势。为了计算减少的变化,我提取了指标的数据,然后使用 pandas 的描述性模块收集该期间的最大值和最小值,并计算处方中的差异和相对差异。

结果表明,所有 ccg 在此期间都降低了他们的处方水平,但一些 ccg 的处方水平显著下降,降幅在 20-40%之间,大多数 ccg 的处方水平下降了 10-15%。因此,对所有 ccg的单个时间序列的比较显示,在活动开始时的起点和减排力度方面,情况非常不一致:

国民医疗服务体系(NHS)制定的处方目标中的绿线和红线:竞选开始时的目标(1.161,绿色)和 2018/19 年更雄心勃勃的目标(0.965,红色)。为了方便直观地比较所有 ccg 与这些目标的关系,我对数据集中最近一年(截至 2017 年 12 月的 12 个月)的值进行了切片,将数据连接到英国国家统计局提供的 ccg 边界,并使用 Tableau 的映射功能绘制了连接的数据框架。其结果是一张与国民保健制度设定的早期和晚期目标相关的处方减少图:

虽然大多数 ccg 尚未实现更雄心勃勃的目标,但迄今为止看到的减少应被视为减少处方的努力的标志。虽然该战略是在全国范围内进行评估的,但数据表明,地方努力也应得到考虑。伦敦的大多数 ccg 已经实现了这两个目标;诺丁汉一个 ccg 的评论员看了数据后指出,他们在早期阶段就实现了这两个目标。这些成就,从下面的时间序列中可以清楚地看到,主要是由于当地的努力。

观察到的总体减少表明,该战略确实对抗生素处方有显著影响,但也需要考虑地方努力的故事。成功的故事不仅能鼓舞人心,还能提示干预最有效的领域。另一方面,应该听取仍在努力实现目标的 ccg 代表的意见,以了解他们对需要做出更多努力的领域的看法。虽然地理空间和时间序列分析经常被用来可视化总体趋势,但我发现它们在公共卫生问题的局部空隙中是有用的。
附加说明
项目文件及成果:https://github.com/ronyarmon/AMR
总结并向英国议会健康和社会保健委员会(2018 年)设立的抗生素耐药性调查提交结果
仪表盘 : AMR 指标(PHE) ,药品优化(NHS),抗菌数据月报(PrescQIPP)
探索、聚类和映射多伦多的犯罪

Photo credit: Pixabay
我通过开放数据门户网站探索美国城市的犯罪数据,从中获得了很多乐趣,因为多伦多的犯罪数据根本不可用。
然而,在今年夏天,多伦多警方推出了一个公共安全数据门户网站,以增加公众和官员之间的透明度。因此,我有机会通过多伦多警察局公共安全数据门户探索多伦多的犯罪。我对2016 年主要犯罪指标(MCI)特别感兴趣,它包含了 2016 年 32,612 份报告的列表(这是唯一有数据可用的一年)。

我们用 R 来看看数据,看看有没有什么有趣的。
数据
library(ggplot2)
library(ggthemes)
library(dplyr)
library(viridis)
library(tidyr)
library(cluster)
library(ggmap)
library(maps)
经过一点探索,我发现有很多重复(event_unique_id),所以让我们从数据中删除它。
toronto <- read.csv('toronto_crime.csv')
toronto <- subset(toronto, !duplicated(toronto$event_unique_id))
unique(toronto$occurrenceyear)
unique(toronto$reportedyear)

发现什么有趣的东西了吗?发生年份从 2000 年到 2016 年不等,但所有犯罪的报告年份都是 2016 年。这意味着人们在 2016 年向警方报告了前几年发生的事件。让我们看看我们的数据中有多少延迟报告的事件。
year_group <- group_by(toronto, occurrenceyear)
crime_by_year <- summarise(year_group,
n = n())
crime_by_year

2 起发生在 2000 年,2 起发生在 2001 年,以此类推。但是,绝大多数事件发生在 2016 年,因此我们将只使用 2016 年的事件。我还删除了我们不需要的所有列,以及缺少值的四行。
drops <- c("X", "Y", "Index_", "ucr_code", "ucr_ext", "reporteddate", "reportedmonth", "reportedday", "reporteddayofyear", "reporteddayofweek", "reportedhour", "occurrencedayofyear", "reportedyear", "Division", "Hood_ID", "FID")toronto <- toronto[, !(names(toronto) %in% drops)]
toronto <- toronto[toronto$occurrenceyear == 2016, ]
toronto <- toronto[complete.cases(toronto), ]
探索
2016 年有哪些重大犯罪?
indicator_group <- group_by(toronto, MCI)
crime_by_indicator <- summarise(indicator_group, n=n())
crime_by_indicator <- crime_by_indicator[order(crime_by_indicator$n, decreasing = TRUE),]ggplot(aes(x = reorder(MCI, n), y = n), data = crime_by_indicator) +
geom_bar(stat = 'identity', width = 0.5) +
geom_text(aes(label = n), stat = 'identity', data = crime_by_indicator, hjust = -0.1, size = 3.5) +
coord_flip() +
xlab('Major Crime Indicators') +
ylab('Number of Occurrences') +
ggtitle('Major Crime Indicators Toronto 2016') +
theme_bw() +
theme(plot.title = element_text(size = 16),
axis.title = element_text(size = 12, face = "bold"))

Figure 1
袭击是多伦多最普遍的暴力犯罪形式。什么是攻击?在刑法和民法中,攻击是指试图与他人进行有害的或冒犯性的接触,或威胁这样做。
突击有哪些不同的类型?哪种类型最差?
assault <- toronto[toronto$MCI == 'Assault', ]
assault_group <- group_by(assault, offence)
assault_by_offence <- summarise(assault_group, n=n())
assault_by_offence <- assault_by_offence[order(assault_by_offence$n, decreasing = TRUE), ]ggplot(aes(x = reorder(offence, n), y = n), data = assault_by_offence) +
geom_bar(stat = 'identity', width = 0.6) +
geom_text(aes(label = n), stat = 'identity', data = assault_by_offence, hjust = -0.1, size = 3) +
coord_flip() +
xlab('Types of Assault') +
ylab('Number of Occurrences') +
ggtitle('Assault Crime Toronto 2016') +
theme_bw() +
theme(plot.title = element_text(size = 16),
axis.title = element_text(size = 12, face = "bold"))

Figure 2
这里没有太多的信息,因为最常见的攻击类别是…攻击。我最终通过 Attorneys.com 学会了不同类型的攻击。
然后让我们看看最严重的犯罪
offence_group <- group_by(toronto, offence)
crime_by_offence <- summarise(offence_group, n=n())
crime_by_offence <- crime_by_offence[order(crime_by_offence$n, decreasing = TRUE), ]ggplot(aes(x = reorder(offence, n), y = n), data = crime_by_offence) +
geom_bar(stat = 'identity', width = 0.7) +
geom_text(aes(label = n), stat = 'identity', data = crime_by_offence, hjust = -0.1, size = 2) +
coord_flip() +
xlab('Types of Offence') +
ylab('Number of Occurrences') +
ggtitle('Offence Types Toronto 2016') +
theme_bw() +
theme(plot.title = element_text(size = 16),
axis.title = element_text(size = 12, face = "bold"))

Figure 3
袭击是最常见的犯罪,其次是破门而入。根据 Wikibooks 的说法,最典型的破门而入形式是闯入商业地产或私人住宅以窃取财产。这表明破门而入最有可能发生在家里或办公室没有人的时候。
一天中的犯罪时间怎么样?
hour_group <- group_by(toronto, occurrencehour)
crime_hour <- summarise(hour_group, n=n())ggplot(aes(x=occurrencehour, y=n), data = crime_hour) + geom_line(size = 2.5, alpha = 0.7, color = "mediumseagreen", group=1) +
geom_point(size = 0.5) +
ggtitle('Total Crimes by Hour of Day in Toronto 2016') +
ylab('Number of Occurrences') +
xlab('Hour(24-hour clock)') +
theme_bw() +
theme(plot.title = element_text(size = 16),
axis.title = element_text(size = 12, face = "bold"))

Figure 4
最糟糕的时间是在午夜左右,另一个高峰时间是在中午左右,然后是晚上 8 点左右。
好吧,但是一天中的每个小时什么类型的犯罪最频繁?
hour_crime_group <- group_by(toronto, occurrencehour, MCI)
hour_crime <- summarise(hour_crime_group, n=n())ggplot(aes(x=occurrencehour, y=n, color=MCI), data = hour_crime) +
geom_line(size=1.5) +
ggtitle('Crime Types by Hour of Day in Toronto 2016') +
ylab('Number of Occurrences') +
xlab('Hour(24-hour clock)') +
theme_bw() +
theme(plot.title = element_text(size = 16),
axis.title = element_text(size = 12, face = "bold"))

Figure 5
虽然袭击是一天中最常见的犯罪,但它们发生在傍晚和夜间的频率高于清晨。另一方面,破门而入的犯罪更经常发生在早上和午夜左右(那时没有人在家或在办公室)。抢劫和汽车盗窃更有可能在深夜发生。所有这些模式都有意义。
这些犯罪最有可能发生在多伦多的什么地方?
location_group <- group_by(toronto, Neighbourhood)
crime_by_location <- summarise(location_group, n=n())
crime_by_location <- crime_by_location[order(crime_by_location$n, decreasing = TRUE), ]
crime_by_location_top20 <- head(crime_by_location, 20)ggplot(aes(x = reorder(Neighbourhood, n), y = n), data = crime_by_location_top20) +
geom_bar(stat = 'identity', width = 0.6) +
geom_text(aes(label = n), stat = 'identity', data = crime_by_location_top20, hjust = -0.1, size = 3) +
coord_flip() +
xlab('Neighbourhoods') +
ylab('Number of Occurrences') +
ggtitle('Neighbourhoods with Most Crimes - Top 20') +
theme_bw() +
theme(plot.title = element_text(size = 16),
axis.title = element_text(size = 12, face = "bold"))

Figure 6
最危险的街区是…滨水区。这个不断扩张的市中心包罗万象,不仅包括密集的公寓社区,还包括极度活跃的娱乐区。结果是:这里发生了数量惊人的暴力犯罪和纵火案。

Photo credit: Pixabay
第二危险的街区是教堂-央街走廊。它很受学生的欢迎,因为它靠近瑞尔森大学,而且它是多伦多同性恋村的一方的家。然而,这个地区也有它的犯罪问题,考虑到它离市中心有多近,这有点令人惊讶。
哪里是最安全的社区?
tail(crime_by_location, 5)

考虑搬到多伦多吗?我们已经为你选好了新家!森林山南是多伦多一个安全、华丽和富裕的社区,拥有许多漂亮的房子,比如这栋豪宅。

Photo credit: Torontorentals.com
让我们比较一下犯罪率最高的街区。
offence_location_group <- group_by(toronto, Neighbourhood, offence)
offence_type_by_location <- summarise(offence_location_group, n=n())
offence_type_by_location <- offence_type_by_location[order(offence_type_by_location$n, decreasing = TRUE), ]
offence_type_by_location_top20 <- head(offence_type_by_location, 20)ggplot(aes(x = Neighbourhood, y=n, fill = offence), data=offence_type_by_location_top20) +
geom_bar(stat = 'identity', position = position_dodge(), width = 0.8) +
xlab('Neighbourhood') +
ylab('Number of Occurrence') +
ggtitle('Offence Type vs. Neighbourhood Toronto 2016') + theme_bw() +
theme(plot.title = element_text(size = 16),
axis.title = element_text(size = 12, face = "bold"),
axis.text.x = element_text(angle = 90, hjust = 1, vjust = .4))

Figure 7
我没想到会这样。它不漂亮。然而,它确实告诉我们,除了袭击事件,教堂-央街走廊和海滨是破门而入犯罪最多的地方(不要去那里!),西亨伯-克莱尔维尔的车辆失窃率最高(不要把车停在那里!).
让我们试试不同的东西
crime_count <- toronto %>% group_by(occurrencemonth, MCI) %>% summarise(Total = n())
crime_count$occurrencemonth <- ordered(crime_count$occurrencemonth, levels = c('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'))ggplot(crime_count, aes(occurrencemonth, MCI, fill = Total)) +
geom_tile(size = 1, color = "white") +
scale_fill_viridis() +
geom_text(aes(label=Total), color='white') +
ggtitle("Major Crime Indicators by Month 2016") +
xlab('Month') +
theme(plot.title = element_text(size = 16),
axis.title = element_text(size = 12, face = "bold"))

Figure 8
好多了!
人身攻击是一年中每个月最常见的犯罪类型,无一例外。5 月份的袭击事件似乎比去年其他月份都多。
day_count <- toronto %>% group_by(occurrencedayofweek, MCI) %>% summarise(Total = n())ggplot(day_count, aes(occurrencedayofweek, MCI, fill = Total)) +
geom_tile(size = 1, color = "white") +
scale_fill_viridis() +
geom_text(aes(label=Total), color='white') +
ggtitle("Major Crime Indicators by Day of Week 2016") +
xlab('Day of Week') +
theme(plot.title = element_text(size = 16),
axis.title = element_text(size = 12, face = "bold"))

Figure 9
周六和周日比一周中的其他任何一天有更多的袭击,比其他任何一天有更少的盗窃。偷车贼几乎每天都很忙。
我希望发现一些季节性犯罪模式,如温度变化和日照时间可能与全年的犯罪有关,或者学年的开始和结束与全年的犯罪变化有关。但这一年的数据不足以解决我的上述担忧。我希望在不久的将来,多伦多警察局将通过其开放数据门户发布更多的数据。
凶杀案
homicide <- read.csv('homicide.csv', stringsAsFactors = F)
homicide$Occurrence_Date <- as.Date(homicide$Occurrence_Date)year_group <- group_by(homicide, Occurrence_year, Homicide_Type)
homicide_by_year <- summarise(year_group, n=n())ggplot(aes(x = Occurrence_year, y=n, fill = Homicide_Type), data=homicide_by_year) +
geom_bar(stat = 'identity', position = position_dodge(), width = 0.8) +
xlab('Year') +
ylab('Number of Homicides') +
ggtitle('Homicide 2004-2016') + theme_bw() +
theme(plot.title = element_text(size = 16),
axis.title = element_text(size = 12, face = "bold"))

Figure 10
2005 年被称为多伦多的“T2 枪年”。11 年后的 2016 年,多伦多的涉枪杀人案再次激增。
homicide$month <- format(as.Date(homicide$Occurrence_Date) , "%B")homicide_count <- homicide %>% group_by(Occurrence_year, month) %>% summarise(Total = n())
homicide_count$month <- ordered(homicide_count$month, levels = c('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'))
ggplot(homicide_count, aes(Occurrence_year, month, fill = Total)) +
geom_tile(size = 1, color = "white") +
scale_fill_viridis() +
geom_text(aes(label=Total), color='white') +
ggtitle("Homicides in Toronto (2004-2016)") +
xlab('Year') +
theme(plot.title = element_text(size = 16),
axis.title = element_text(size = 12, face = "bold"))

Figure 11
令人担忧的是,与 2015 年相比,2016 年多伦多的凶杀案总数大幅增加。希望我们有一个更好的 2017 年。然而,当我读到多伦多被经济学家评为北美最安全的城市时,我感觉安全多了。
K 均值聚类
K-Means 是最流行的“聚类”算法之一。它是将数据点组划分为少量簇的过程。使用我们的犯罪数据,当我们测量攻击数量和其他指标时,攻击数量高的街区将被分组在一起。K 均值聚类的目标是为每个数据点(邻域)分配一个聚类。我们首先将数据点(邻域)划分为 k 个聚类,其中每个邻域属于具有最近平均值的聚类(用作聚类的原型)。
作为一种无监督学习算法,我们使用 K-Mean 来建立模型,帮助我们更好地理解我们的数据。它使我们能够对未标记的数据点进行分组。
为了进行聚类分析,我们的数据必须如下所示:
by_groups <- group_by(toronto, MCI, Neighbourhood)
groups <- summarise(by_groups, n=n())
groups <- groups[c("Neighbourhood", "MCI", "n")]
groups_wide <- spread(groups, key = MCI, value = n)

第一列——定性数据应从分析中移除
z <- groups_wide[, -c(1,1)]
数据不能有任何缺失值
z <- z[complete.cases(z), ]
必须对数据进行缩放以进行比较
m <- apply(z, 2, mean)
s <- apply(z, 2, sd)
z <- scale(z, m, s)
确定集群的数量
wss <- (nrow(z)-1) * sum(apply(z, 2, var))
for (i in 2:20) wss[i] <- sum(kmeans(z, centers=i)$withiness)
plot(1:20, wss, type='b', xlab='Number of Clusters', ylab='Within groups sum of squares')

Figure 12
由于该图显示了一个非常强的肘形,基于该图,我们可以有把握地说,我们不需要两个以上的群集(质心)。
试衣模特
kc <- kmeans(z, 2)
kc

释义:
- 第一类有 121 个街区,第二类有 10 个街区。
- 聚类意味着:如果这些数字的范围看起来很奇怪,那是因为我们在进行聚类分析之前对数据进行了标准化。负值表示“低于大多数”,正值表示“高于大多数”。因此,集群 1 具有低攻击、低汽车盗窃、低破门而入、低抢劫和低盗窃的街区。第 2 类社区具有高攻击性、高汽车盗窃、高非法闯入、高抢劫和高盗窃率。这两组在每一个变量上都有显著的差异,这是好事,因为这表明每一个变量在聚类分类中都起着重要的作用。
- 聚类向量:第一、第二和第三邻域应该都属于聚类 1,第四邻域应该属于聚类 2,等等。
- 更相关的度量是“在内”和“在之间”。
withinss 告诉我们每个数据点到聚类中心的距离的平方和。越低越好。betwess 告诉我们聚类中心之间距离的平方和。理想情况下,我们希望聚类中心彼此远离。 - 可用组件不言自明。
绘制 k 均值结果
z1 <- data.frame(z, kc$cluster)
clusplot(z1, kc$cluster, color=TRUE, shade=F, labels=0, lines=0, main='k-Means Cluster Analysis')

Figure 13
看起来我们对集群数量的选择是好的,并且我们几乎没有噪声。
分层聚类
对于分层聚类方法,树状图是深入了解聚类解决方案的主要图形工具。
z2 <- data.frame(z)
distance <- dist(z2)
hc <- hclust(distance)
现在我们已经有了一个集群解决方案。让我们检查结果。
plot(hc, labels = groups_wide$Neighbourhood, main='Cluster Dendrogram', cex=0.65)

Figure 14
如果我们沿着树形图的 y 轴选择任意高度,并在树形图中移动,计算我们穿过的线的数量,每条线代表一个聚类。例如,如果我们观察高度为 10 的物体,并在该高度移动穿过 x 轴,我们将穿过两条直线。它定义了一个双集群解决方案;沿着这条线向下穿过它的所有分支,我们可以看到包含在这两个集群中的街区的名称。查看多伦多犯罪数据的树状图,我们可以看到我们的数据点非常不平衡。从树的顶端,有两个不同的组;一组由有分支和更多分支的分支组成,而另一组只由几个街区组成(我们可以看到这些街区是多伦多最危险的街区)。然而,我想立刻尝试许多不同的分组,开始调查。
counts = sapply(2:6,function(ncl)table(cutree(hc,ncl)))
names(counts) = 2:6
counts

解释:
- 对于双集群解决方案,集群 1 中有 128 个小区,集群 2 中有 3 个小区。
- 对于 3 个集群的解决方案,我们在集群 1 中有 128 个邻居,在集群 2 中有 2 个邻居,在集群 3 中有 1 个邻居。以此类推,直到我们得到一个 6 集群解决方案。
在实践中,我们希望有一个解决方案,其中没有太多只有少量观察值的聚类,因为这可能会使我们难以解释我们的结果。在这个练习中,我将坚持使用 3 集群解决方案,看看我将获得什么结果。
member <- cutree(hc, 3)
aggregate(z, list(member), mean)

在第一组中,所有犯罪指标都是负面的。与聚类 2 和聚类 3 相比,聚类 1 在每个变量上也有显著差异。除了汽车盗窃之外,第二组在大多数犯罪指标方面都高于第三组。
plot(silhouette(cutree(hc, 3), distance))

聚类 3 的轮廓宽度值是零,并且轮廓图表明我们确实不需要第三个聚类,绝大多数邻域属于第一个聚类,并且 2-聚类将是我们的解决方案。
制作多伦多犯罪地图
r 中有许多用于绘制和操作空间数据的包。我将使用 ggmap 来制作一个简单易用的多伦多犯罪地图。
lat <- toronto$Lat
lon <- toronto$Long
crimes <- toronto$MCI
to_map <- data.frame(crimes, lat, lon)
colnames(to_map) <- c('crimes', 'lat', 'lon')
sbbox <- make_bbox(lon = toronto$Long, lat = toronto$Lat, f = 0.01)
my_map <- get_map(location = sbbox, maptype = "roadmap", scale = 2, color="bw", zoom = 10)
ggmap(my_map) +
geom_point(data=to_map, aes(x = lon, y = lat, color = "#27AE60"),
size = 0.5, alpha = 0.03) +
xlab('Longitude') +
ylab('Latitude') +
ggtitle('Location of Major Crime Indicators Toronto 2016') +
guides(color=FALSE)

Figure 15
从地图上可以清楚地看到这个城市的主要犯罪发生地。大部分集中在滨水区,北约克以南比其他任何地区都更和平。然而,在比较高密度区域时,点叠加没有帮助,所以让我们优化这种可视化。
ggmap(my_map) +
geom_point(data=to_map, aes(x = lon, y = lat, color = "#27AE60"),
size = 0.5, alpha = 0.05) +
xlab('Longitude') +
ylab('Latitude') +
ggtitle('Location of Major Crime Indicators Toronto 2016') +
guides(color=FALSE) +
facet_wrap(~ crimes, nrow = 2)

Figure 16
这当然更有趣,信息量也更大。一些犯罪,如袭击、破门而入,在城市各处都有发生,集中在滨水区。其他犯罪,比如偷车,西边比东边多点。抢劫和盗窃主要发生在海滨地区。
摘要
通过查看多伦多重大犯罪指标的数据,可以回答的问题并不多。不过没关系。这些数据当然还有其他有趣的用途(比如在 MicroStrategy 上创建一个仪表板)。

Figure 17
和往常一样,所有代码都可以在 Github 上找到。我将很高兴收到关于上述任何反馈或问题。
将探索数据科学作为一种爱好
Credit: giphy.com
我不会深究我是如何偶然发现数据科学并立即确信这是我想长期追求的东西的故事。或者有一段时间我是如何处于不知从何开始的困惑状态。只是这一次似曾相识。事实上,一年多以前,我也在同样的地方从事编码工作。
我一圈又一圈地看了无数的文章和博文。我怀疑我的兴趣是否源于《纽约时报》的一篇文章,这篇文章将数据科学列为 21 世纪最性感的工作。通过它,所有关于获得这些技能的可能性的唠叨想法变得无法控制。
更不用说我可以玩我的两个爱好了——数学和编程。我非常喜欢这两个人,因为他们经常让我感到沮丧。然而,我很难想象没有他们的生活。我的意思是,你能想象计算机出现之前的生活吗?更别说笔记本电脑了?
一想到企业依赖人脑处理所有数据的时代,我就不寒而栗。该死,那些家伙和女孩真有耐心。你能想象手工计算一张数学表吗?(插入 gif geez)
所以我决定学习一些关于数据科学的东西。在非常好的朋友和同事(非常感谢你们)的建议下,我开始寻找一个在线课程。感谢上帝,我们生活在这样一个时代,无论身在何处,我们都可以在舒适的客厅里听哈佛大学、麻省理工学院、加州大学伯克利分校、斯坦福大学等等的讲座和课程笔记。mooc(大规模开放在线课程)的力量和潜力是另一个世界。只要你不屈服于打开多个浏览器的诱惑。
有一段时间陷入了瘫痪。读了这么多关于数据科学及其应用的东西,却没有采取任何实际步骤。我花了一段时间和一个村庄才开始。我开始觉得那些智者说得对,他们说“养育一个孩子需要一个村庄”。
从凯茜·奥尼尔和雷切尔·舒特的书《做数据科学》开始。然后阅读许多数据科学家的简介——既有经验丰富的,也有像我这样的新手。这一切花了我太多时间。很大程度上是因为我脱离了代码的轨道。阅读很有趣,也很有启发性,但归根结底,练习也是一种享受。所以如果你选了一本书,请不要像我一样把你的文本编辑器放在身边。
当我报名参加由神奇的 NairobiWIMLDS 组织的数据科学初学者马拉松时,我遇到了困难。我参加了数据科学 Python 入门课程。其他人做了数据科学的 R 简介。而一些胆大的人则一口气尝试了两种方法。所有这些都在 edX 上。
我喜欢上这门课,由于运行了实际的脚本,我终于明白了很多道理。
我接下来的帖子将分享我的一些笔记、旁注和更多见解。
- (长读)。查看freeCodeCamp 上的这篇文章对互联网上的每个数据科学课程介绍进行了排名。很久以前的事了。
数学的乐趣不在于将这门学科残酷化为表演行为的廉价竞争。
用视觉分析法探索英国工党投票中的人口统计变化
这篇文章改编自我在理学硕士数据科学课程中进行的一项分析,研究人口统计变量如何与 2017 年英国大选中工党选票的变化相关联,以及这些关系在全国各地如何变化。
这个项目的概要是非常公开的;选择一个研究问题,使用任何数据集和任何工具进行研究。唯一的限制是分析必须利用视觉分析方法,也就是说,“视觉输出的解释必须通知计算分析,计算输出必须通知你可视化和解释输出的方式。”
我所有的工作都是在 R 中进行的,代码、数据、完整报告都可以在 GitHub 上获得。
介绍
我选择关注最近一次英国大选的结果,部分原因是因为我需要的数据相当大、丰富且可以公开获得,但也因为我渴望看到,我是否可以超越我在新闻中读到的内容来理解这些结果。
过去三年里,英国和全世界都经历了一连串的选举冲击。最近的一次是 2017 年英国大选。竞选活动以保守党享有 20%的民意调查领先优势开始[1],但以非常接近的结果结束(保守党 42.4%,工党 40%[2])。尽管保守党继续执政,但相对于他们的预期表现,这一结果被广泛认为是工党的成功。工党的成功在很大程度上归功于年轻人和受过良好教育的中产阶级的支持,而不是工党传统的白人工人阶级基础[4]——这一群体的支持率下降,特别是在杰里米·科尔宾当选为工党领袖和 2016 年欧盟公投结果之后,被认为是他们失败的原因[5]。这种情况在多大程度上对英国两大政党的未来走向有着重大影响。
我的目标是通过回答三个问题,调查议会选区的人口构成与 2017 年投票方式之间的关系,重点是工党的意外成功:
- 工党选举表现的改善在多大程度上与选民的人口构成有关?
- 这种关系全国都一样吗?
- 这在多大程度上代表了工党支持者的社会构成的变化?
数据和指标
2015 年和 2017 年英国大选的选举数据由英国议会公布[6][7],给出了英国 632 个选区中每个政党的投票数。我排除了北爱尔兰,因为工党在那里没有候选人。人口统计数据来自 2011 年英国人口普查的结果,由英国国家统计局提供[8],人口普查输出区域到议会选区的映射也是如此[9][10][11],从而能够将人口普查与选举结果进行比较。
为了评估选举结果,我使用了两种方法:从保守党转向工党,这是衡量工党支持率的基线指标(他们在 2015 年大选中的投票份额)。摆动计算如下:

在哪里

分析
第一步是可视化这两项措施在全国的分布,这是通过议会选区的六边形地图来完成的,如下所示。这些地图清楚地显示了每一项措施的不同分布,表明驱动每一项措施的因素可能不同,而且它们可能因地区而异。

Figure 1: Left: The Labour Party’s share of the vote in the 2015 General Election. Right: Swing from Conservative to Labour in the 2017 General Election.
这一想法得到了对两个指标之间关系的评估的支持(图 2),该评估仅显示了一周的相关性,以及一些不同的区域模式。例如,伦敦和西北部在 2015 年显示出对工党的强烈支持,并进一步向那个方向摇摆,但东北部、约克郡和亨伯河在 2015 年显示出对工党的强烈支持,并在 2017 年转向保守党。

Figure 2: 2017 Swing to Labour vs 2015 Labour Vote Share. Only a week correlation is observed between the two measures.
为了研究人口统计数据并找出可能有助于解释选举结果的因素,我结合人口普查结果创建了 11 个变量,每个变量都可以作为预计投票给工党的群体的指标。这些在下表中列出。

Table 1: Census variables selected for analysis and the group or area characteristic which they are expected to represent.
下图的比较表明,一些变量与两种选举措施有类似的关系:代表年轻人(年轻成年人和更年轻的成年人)的变量有正相关性,代表“传统”英国(或缺乏社会多样性)的变量都有负相关性。然而,受教育程度和专业人士都显示出与劳动力的基线轻微负相关,但与摇摆有明确的正相关。穷人或工人阶级的指标都显示出与基线有很强的正相关性,但与摇摆关系不大。同样值得注意的是,在所有变量中,苏格兰的选区始终显示出比全国其他地区更倾向于工党。

Figure 3: Demographic Variables vs Labour Vote Share

Figure 4: Demographic Variables vs 2017 Swing
接下来,我想模拟这些变量和选举结果之间的关系,并评估它们的地理差异。图 1 表明,我们需要为每个度量使用不同的模型。我使用调整后的 R 分数来确定最强的解释变量(2015 年投票份额的无车(0.49)和 2017 年摇摆的学历(0.28)),并为每个变量创建线性回归模型。每个选区的每个模型的残差(模型预测和实际结果之间的差异)如图 5 所示。残差被标准化为[-1,1]的区间,以说明摇摆通常小于投票份额的事实。

Figure 5: Residuals from global univariate regression models, normalised to a range of [-1,1] Left: No Car vs 2015 Labour Vote Share. Right: Degree Educated vs 2017 Swing Towards Labour.
首先要注意的是,这两个模型都过度预测了工党在苏格兰的成功,这表明英国这一地区的投票行为可能有根本的不同。将苏格兰从模型中移除会增加调整后的 R 结果(分别从 0.49 增加到 0.55,从 0.28 增加到 0.38)。
无车模型低估了在英格兰北部和伦敦大部分地区的成功,而高估了在伦敦西部和南部其他地区的成功,这很好地反映了对工党传统基础的公认理解。受教育程度模型显示了英格兰和威尔士相当准确的统一结果,支持了 2017 年工党支持率上升的观点,这是由于不同的群体,而不是那些构成他们历史支持的群体。
对多变量模型的进一步实验显示了与图 5 所示相似的模式,但是调整后的 R 增加到 0.7 和 0.46。报告中详细描述了变量的最终选择以及这些选择的原因。
分析的最后一步是应用地理加权汇总统计数据,如图 6 所示。每张地图都显示了全国范围内两个变量之间的相关性是如何变化的。使用加权邻域为每个选区创建单独的模型,在本例中是 50 个最近的选区。蓝色区域显示负相关,红色区域显示正相关。

Figure 6: The first map shows the geographically weighted correlation between 2015 Labour Vote Share and 2017 Swing. Each subsequent map shows the weighted correlation between one demographic variable and one electoral measure.
回答我们的问题
那么,在建立了一系列模型,并绘制了一些漂亮的图表和地图之后,它对我们回答最初的三个研究问题有多大帮助呢?
1.工党选举表现的改善在多大程度上与选民的人口构成有关?
工党在 2017 年大选中的改善结果确实显示了与议会选区人口构成的相关性,尽管没有他们的基线支持那么强烈。
这种摇摆强度的最重要指标是那些代表年轻、受过教育、中产阶级(20 至 44 岁、具有学位水平资格或从事专业水平就业的居民比例)的指标,分别解释了结果中 20%、28%和 23%的变化。这与 2015 年投票份额的最强指标形成了对比,这些指标与较贫困或工人阶级社区有关(居住在社会住房、没有汽车或健康状况不佳的人口比例(36%、49%和 17%)。
社会多样性在 2015 年的结果和 2017 年的变化中都是不变的,在两种情况下都是负相关的,尽管这一类别在两种情况下都不是最重要的。
2.这种关系全国都一样吗?
全球模型的残差显示,尤其是苏格兰和英国其他地区之间存在差异。地理加权模型显示,基线支持指标往往具有相当的全球性(苏格兰的某些情况除外);在英格兰和威尔士,相关性通常在相同的方向,具有相似的强度,特别是多样性和工人阶级指标。
与挥杆的相关性通常较弱,并在几个测量中显示出较大的区域差异。然而,最强的指标确实显示了一种全球模式。
3.这在多大程度上代表了工党支持者的社会构成的变化?
在国家一级,没有一个指标显示从 2015 年的结果到 2017 年的波动从正相关转为负相关,这表明工党在已经支持它的群体中没有失去重要的支持。受教育程度和专业人士之间从负相关到正相关的转变可能表明工党支持者的人口构成发生了变化,但很难对问题 3 做出定量回答。对这些指标所贡献的相对票数进行进一步分析,并对较长时期内的结果进行检查,将有助于更详细地回答这个问题,但这超出了本分析的范围。
反射
方法的有效性
对于这种类型的分析,人们必须小心,不要试图对个人投票行为下结论。虽然我们观察了选区一级的关系,但我们不知道每个选区内的团体是如何投票的,也不知道他们的相对投票率是多少,我们也不能说某个团体以某种方式投票。分析也不试图捕捉可能影响投票行为的具体地方问题,也不能说明自 2011 年人口普查以来可能发生的人口变化。民意调查可能更容易建立这种联系,在民意调查中,一个人的人口统计、观点和投票之间有直接联系。然而,这些都是昂贵的,并且很少在足以揭示本研究调查的区域差异的规模上进行。这种分析的优势在于它包括每一个人和每一张选票,因此它的范围比民意测验分析要广得多。
选举措施的选择提供了有用的结果,但这些措施是有限的。在苏格兰,保守党和工党之间的摇摆可能过于简单,因为两者都不是那里的最大政党,而且它确实表现出与全国其他地区不同的模式。苏格兰也在 2014 年举行了自己的英国成员资格公投;一个非常重要和特殊的政治事件。包括苏格兰民族党在内的具体苏格兰分析可能会更好地理解这些关系。
选择六边形地图显示地理关系效果很好,可以对结果进行清晰的视觉解释,尽管地理失真意味着特定位置的身份并不总是立即明显。它们与全球回归模型一起使用对回答问题 2 特别有帮助。
六边形图是散点图的一个很好的补充,散点图提供了一个高层次的相关性视图,但由于大量的数据点和相对大量的区域,很难详细解释,使得很难区分图中心拥挤的模式。对单个区域的进一步分析将是有趣的,但作为这项工作的一部分是不可行的。
相关性的地理加权模型显示了有趣的区域差异,但理解这些不同的相关性如何组合成一幅整体图景并不简单,而且量化它们如何影响两个单独的选举措施组合尤其困难。使用基于分区的聚类的进一步工作可能对此有所启发,并有助于获得问题 3 的更可量化的答案。
此分析中使用的技术可高度推广到复杂空间多元数据常见的其他领域。除了政治之外,类似的方法可以应用于调查各种社会问题答案的空间变化,例如比较任何财富或收入平等、健康、教育成果或环境变化。
含义
在英国的多党、得票最多者当选的选举制度中,了解地方一级的投票模式是如何受到影响的非常重要。在选举之前,有很多关于全国民意调查的讨论,以及全国投票份额的变化如何反映在议会席位中。众所周知,这种推断很难,正如最近的几次选举所显示的那样,相对较小的民意调查并不总是能很好地概括全国的情况。因此,了解一个政党在人口统计和区域变量方面的表现是非常有价值的。然而,这种分析本质上是反应性的;它可以提供对过去结果的洞察,但这并不意味着它可以用来预测未来的选举,因为采样和未来事件之间的差距太大了。
结果显示,受教育程度变量与倾向于工党的相关模式类似,因为其他工作已经注意到在 2016 年欧盟公投中投票[12],尽管这种关系没有那么强。这支持了一种观点,即工党的部分成功是对公投结果的反应,不满的专业保守党,留欧选民转向工党,而工人阶级脱欧投票工党支持者的预期相反反应并没有成为现实。然而,也有人认为,这两个结果都反映了选民行为中更为根本的变化[13]。
如果工党能够保持这种模式,在保持现有支持的同时,扩大他们对新人口的支持基础,这显然对他们有利。对照人口指标分析选区一级目前的选举差额可能是一个值得探索的有趣途径,以便了解这些模式的继续会在未来产生多大的影响。
最后
谢谢你能走到这一步!请随时留下任何评论、反馈或掌声。如果你是一个真正喜欢惩罚的人,那么完整报告将会更详细地介绍你在这个过程中所使用的方法和做出的选择。
参考
[1] J. Holder、N. Kommenda、C. Barr 和 S. Clarke,“特里萨·梅的选举赌博是如何失败的?|政治|卫报。”【在线】。可用:https://www . the guardian . com/politics/ng-interactive/2017/jun/09/Theresa-may-election-gamble-fail-conservatives-majority-polls。【访问时间:2017 年 12 月 1 日】。
[2]“2017 年英国大选:全部结果|政治|卫报。”【在线】。可用:https://www . the guardian . com/politics/ng-interactive/2017/jun/08/live-uk-election-results-in-full-2017。【访问时间:2017 年 12 月 1 日】。
[3] P. Walker 和 J. Elgot,“当工党赢得席位时,科尔宾蔑视怀疑者|政治|卫报。”【在线】。可用:https://www . the guardian . com/politics/2017/jun/09/Jeremy-cor byn-labour-defies-doubles-gain-seats-election-2017。【访问时间:2017 年 12 月 31 日】。
[4] H .刘易斯,“是什么推动了工党的成功?对移民采取强硬路线,并向中产阶级发出呼吁。”【在线】。可用:https://www . newstatesman . com/politics/June 2017/2017/06/what-driven-labours-success-tough-line-immigration-and-appeal-middle-class。【访问日期:2017 年 12 月 31 日】。
[5] K .麦肯,“民意调查显示,工党现在是工人阶级选民中第三大受欢迎的政党。”【在线】。可用:http://www . telegraph . co . uk/news/2017/02/13/labour-now-third-popular-party-in-working-class-voters-poll/。【访问日期:2017 年 12 月 31 日】。
[6]英国议会,“2015 年大选结果—data . Parliament . UK”[在线]。可用:http://www . data . parliament . uk/dataset/general-election-2015。【访问时间:2017 年 12 月 13 日】。
[7] C .贝克等《2017 年大选:全部结果与分析》【在线】。可用:http://research briefings . parliament . uk/research briefing/Summary/CBP-7979。【访问时间:2017 年 12 月 13 日】。
[8] O .英国政府,“批量数据下载—国家统计局。”【在线】。可用:https://www . ons . gov . uk/census/2011 census/2011 census data/bulk data/bulk data downloads。【访问时间:2017 年 12 月 1 日】。
[9] O. for N. S. UK Government,“英格兰和威尔士地方当局辖区的输出区域(2016 年 12 月)查找|开放地理门户”,2016 年。【在线】。可用:http://geo portal . statistics . gov . uk/datasets/output-area-to-ward-to-local-authority-district-2016-12-lookup-in-England-and-Wales。【访问时间:2017 年 12 月 11 日】。
[10] O .对于 N. S. UK 政府,“从威斯敏斯特议会选区到地方当局选区(2016 年 12 月)在英国|开放地理门户中的查找。”【在线】。可用:http://geo portal 1-ons . open data . ArcGIS . com/datasets/f 52 c 48 ea 5 cf 2494 b 824d 35 f 4 be 88 F2 EC _ 0/data。【访问时间:2017 年 12 月 11 日】。
[11]苏格兰政府,“2011 年数据区和中间区查找”【在线】。可用:http://www . gov . scot/Topics/Statistics/SNS/SNS ref/dz 2011 lookups。【访问时间:2017 年 12 月 13 日】。
[12] R. Beecham,A. Slingsby 和 B. Chris,“英国投票脱离欧盟背后的地方差异解释”,2016 年。
[13] W .詹宁斯和 g .斯托克,“向世界主义轴心倾斜?英格兰的政治变化和 2017 年大选。Q. ,第 88 卷第 3 期,第 359–369 页,2017 年。
在 Azure 机器学习工作台中通过示例探索派生列
与我最近在博客上分享的关于Visual Studio Code Tools for AI的内容类似,Azure Machine Learning Workbench 或 AML Workbench 也是最新的人工智能工具之一,由微软在 2017 年 9 月的 Microsoft Ignite 上发布。
AML Workbench 是一个跨平台的桌面客户端(目前 Windows 和 macOS 都支持),用于数据辩论和实验管理。我发现 AML Workbench 的一个有趣的特性是“通过示例导出列”。
通过示例导出列转换使用户能够使用用户提供的导出结果示例来创建一个或多个现有列的衍生物。导数可以是支持的字符串、日期和数字转换的任意组合。
旁注:如果你还没有安装和设置你的 AML 工作台,你可以查看我的博客文章 设置你的 Visual Studio 代码工具用于人工智能 ,在那里我也分享了如何设置 AML 工作台,因为这是使用 VSCode 工具用于人工智能的先决条件。或者你可以直接查看他们的官方文档页面 这里 。
入门指南
为了向您展示该功能的工作原理,请打开您的 AML 工作台并创建一个新项目(在本教程中,它可以是一个空白项目)。

导入数据集
我将在这个例子中使用的数据集是来自 kaggle 的 NASA 宇航员,1959 年至今的数据集,你可以在这里下载。

NASA Astronauts, 1959-Present Data preview
创建项目并准备好数据集后,您需要:
- 点击“数据”图标
- 添加新的“数据源”

3.选择“文件/目录”
4.使用“本地”路径添加astronauts.csv文件
5.点击“完成”
成功创建了一个astronauts.dsource文件后,您应该能够看到:

创建数据准备包
既然我们已经有了数据源,现在我们将创建一个数据准备包,我们将使用它来转换我们的数据。
数据准备提供了一套有效探索、理解和解决数据问题的工具。它允许您使用多种形式的数据,并将这些数据转换成更适合下游使用的干净数据。
- 再次点击“数据”图标
- 右击
astronauts数据源并点击“准备” - 添加“数据准备包名称”,然后按“确定”

这将在您的项目目录中创建一个astronauts.dprep文件,并显示一个与我们添加数据源后看到的几乎相似的页面。

通过示例转换派生列
让我举几个例子来说明这种转变是如何进行的。
转换日期
假设我们想要将出生日期列的格式从yyyy-mm-dd 00:00:00更改为mmm-dd-yyyy。
- 右键单击“出生日期”列,然后选择“根据示例导出列”
- 键入您希望在“出生日期”列右侧新添加的列中使用的日期格式示例。
- 单击“确定”接受转换
日期转换应该如下所示:

Date Transformation
转换字符串
对于这个例子,让我们通过执行与上一个类似的步骤,尝试将性别格式从男性/女性更改为 M/F。

String Transformation
转换数
在下一个示例中,我们将更改 Space Flight (hr) 列的数字格式,为数字添加一个适当的逗号。

Number Transformation
您还可以通过转到“步骤”部分,右键单击特定步骤,然后按“编辑”来编辑您已成功做出的更改。从那里,您将能够更新列的值。

如何看待 Azure 机器学习工作台中的 Derive 专栏 By Example?如果你想要更多的例子,你可以去他们的官方文档页面这里。
使用 word2vec 探索情感组合

在这篇博文中,我们使用 word2vec 探索了两组情感组合。具体来说,一张是由罗伯特·普卢奇克在 1980 年制作的,另一张是由 vox.com 的 T2 制作的流行媒体图表。我们将范围限制在二元组,即两种基本情绪的组合,构成一种更复杂的情绪。
正如 蓝 和 红 紫;喜悦和惊喜给予喜悦。**

Above: The table has been extracted from the Wikipedia page.

Above: The wheel of emotions contains a superset of the previous table, where similar emotions in the wheel are near to each other. Also extracted from the Wikipedia page.

Above: Popular media ‘best-guess’ on emotions dyads based on characters from Inside Out. From Vox.com
给大家一些背景资料,这部电影描述了一个孩子进入青春期后如何产生复杂的情感。在这里,一个混合了的快乐和悲伤被描绘出来。**
方法
为了探索情绪的可加性,word2vec 是一个很好的候选模型。如前几篇文章所述,我们看到分布式表示模型(如 word2vec)可以解决以下不同复杂性的类比,并建议使用斜体单词。
男人:国王::女人:皇后**
Lady Gaga:美国::滨崎步:日本
等效地,上述词对类比可以表示为等式:
男人+国王-女人= 女王
Lady Gaga +美日= 滨崎步
在接下来的部分中,我们将演示单词向量的加法属性,以找到斜体的单词。
喜悦+惊喜= 喜悦
为了实现这一点,我们使用来自的预训练 word2vec 向量,这里是。有了 gensim ,我们可以轻松使用这些向量。
使用上面的代码,可以从 word2vec 中提取两种情绪之和的最相似的单词,计算建议单词和人类建议之间的余弦相似度。这个相似性度量的范围从-1(完全相反)到 1(相同的意思),最后,检查来自人类的建议情感是否在 word2vec 的前 10 个建议单词内。
这篇文章的其余部分被组织成两个研究,每个研究测试 word2vec 和一组特定建议之间的一致性。在每项研究中,我们将首先展示结果,然后进行讨论。
研究 1 —普卢奇克

Above: Study 1 results
此时,需要注意的是,预训练的 word2vec 模型已经在 Google News 数据集上进行了约 1000 亿字的训练。作为一个以新闻为中心的数据集,语料库并不期望产生一个模型来对情绪进行微妙的区分。
令人鼓舞的是,word2vec 显示出与 Plutchik 的暗示情绪基本一致,所有情绪对的积极得分相似。
我们观察到 word2vec 为一些情感对建议了相同的单词。例如,悲伤在第 9、11、16、17、18 对中暗示。每当悲伤被加上什么东西的时候,悲伤就被暗示出来。这突出了用新闻数据集训练的模型的情感之间的有限区别。
Pair 13 是一个有趣的组合,是惊喜和悲伤的总和。Plutchik 建议不赞成而 word2vec 建议失望我个人更喜欢这个。然而,这只是一个外行对心理学的看法。
Pair 7 是另一个有趣的,word2vec 认为恐惧对信任否定信任并暗示不信任,而 Plutchik 则暗示提交是恐惧和信任的累积。两者似乎都有道理,这表明单词可以以多种方式有意义地组合在一起。该组合可以通过句子中的词汇结构来修改。
对 21 接收 n/a,因为 word2vec 字典没有病态。
研究 2 —从里到外

Above: Study 2 results
研究结果与研究 1 非常相似,在研究 1 中,我们观察到人类建议和 word2vec 之间的一般一致性,以及跨情感对重复建议(例如悲伤和沮丧)。
结论
这结束了一个简短的帖子,说明了词的通用分布式表示的另一种用途,并强调了使用相关语料库来训练词向量的重要性,如果它将用于专门领域的话。
原载于 2018 年 1 月 30 日 joshuakyh.wordpress.com*。***
通过数据探索传染病:登革热

A 1920s photograph of efforts to disperse standing water and thus decrease mosquito populations — Wikipedia ( https://tinyurl.com/y8zcj7te) Public Health Image Library (PHIL) — This media comes from the Centers for Disease Control and Prevention’s Public Health Image Library (PHIL)
这一年是 1780 年,“胆汁返流热”的病例困扰着费城。国父和医生本杰明·拉什在 1789 年将其描述为“断骨热”,现在人们普遍认为这是我们现在称之为登革热的第一次有记录的爆发。拉什指出,他的患者出现了严重的发烧、头部、背部和四肢疼痛,在某些情况下还出现了出血症状(我们现在称之为登革出血热)。这种疾病通常是自限性的,在某些情况下是致命的,但在几乎所有情况下对受感染的个体来说都是创伤性的;突然出现难以忍受的发热和肌肉疼痛,许多患者还出现呕吐以及躯干、手臂、腿和面部出现明显皮疹。拉什在 18 世纪费城所描述的,尽管是第一个被完整记录在案的案例研究,被认为已经困扰了人类几个世纪。最近的证据表明,它起源于大约 1000 年前,但只是在最近几百年才在人类中确立了地方性传播。
现在对 21 世纪的登革热有了很好的了解。它是由登革热病毒引起的,登革热病毒是黄病毒属的一员(使其与其他令人讨厌的病毒如黄热病病毒、西尼罗病毒和日本脑炎病毒密切相关)。感染最常见的是由 T4 伊蚊传播,在一些罕见的病例中是由受感染的献血者输血引起的。
在有充分治疗的地方,死亡率低于 1%,但在没有这种治疗的地方,登革热仍然是一个严重的公共卫生问题,全球每年有数千人死亡。2013 年,全球报告有 6000 万例感染,约 13600 例死亡。不出所料,发展中国家受到的打击最大,这反映了全球伊蚊的分布。其中一个发展中国家是菲律宾,它将是本文感兴趣的主题。
我将通过观察 2008 年至 2016 年间菲律宾的登革热病例来探索用 R 编程语言进行时间序列分析的方法。该数据集可在 Kaggle 上访问,包含菲律宾每个地区每 100,000 人每月记录的登革热病例。我们的目标是观察这一时期登革热病例的趋势,并尝试预测 2016 年以后的趋势。
我假设读者对 R 有所了解。如果没有,我强烈推荐阅读 Garrett Grolemund & Hadley Wickham 的 DataCamp 或 R for Data Science,后者是免费的。
这个项目的所有 R 代码都可以在我的 github 页面上的 Jupyter 笔记本中找到。我个人是 Tidyverse 的忠实粉丝,我广泛使用这个 R 包集合。
先看数据
在使用readr包中的read_csv方法将数据加载到 tibble dataframe 中之后,我使用str函数来洞察数据的内部结构:

所以首先映入我眼帘的是,月份和地区存储在字符数据类型下,年份存储为整数。更恰当的做法是将这些变量存储为类别,我可以使用因子函数。
data$Month <- factor(data$Month, levels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
data$Region <- factor(data$Region)
data$Year <- factor(data$Year)
准备就绪后,我现在可以使用summary和str函数在继续之前查看数据。

可变月份有 12 个级别,这是有意义的,因为一年有 12 个月。该数据集描述了 9 年,17 个地区中的每一个都有一个类别。整个数据集的登革热病例平均数为 6.395,中位数为 11.297,最大值为 147.324。
现在是时候想象登革热病例如何逐月和逐年变化了。我总是喜欢从简单开始,然后逐步完善,所以我从一个按年份分面的条形图开始。

因此,我可以从上面看到,在 2012/13 年病例急剧增加,然后在 2016 年逐渐下降。以上也暗示了季节的变化。我不太喜欢多面条形图。所以我去寻找灵感,发现了这篇奇妙的博文和这篇 Kaggle kernal 。
data %>%
group_by(Year, Month) %>%
summarise(Total_Cases = sum(Dengue_Cases)) %>%
ggplot(aes(Year,Month,fill=Total_Cases)) +
geom_tile() +
scale_fill_gradient(low = "white", high = "red", name = "Dengue cases/ \n100,000 population") +
xlab(label="Year") +
ylab(label="Month")

data %>%
group_by(Year, Region) %>%
summarise(Total_Cases = sum(Dengue_Cases)) %>%
ggplot(aes(Year,Region,fill=Total_Cases)) +
geom_tile() +
scale_fill_gradient(low = "white", high = "red", name = "Dengue cases/ \n100,000 population") +
xlab(label="Year") +
ylab(label="Month")

在第一张热图中,我可以通过垂直方向的颜色变化看到季节性模式,然后通过水平方向的变化看到 2012/13 年左右的高峰。
第二张热图显示了每个地区的病例数。它显示了在 2012/13 年爆发期间,中非共和国地区是受影响最严重的地区,其次是第六区、第一区和第七区。
时间序列
让我们开始绘制一段时间内登革热病例的数量,并讨论时间序列分析。首先,我将创建一个包含登革热病例总数的数据框架,然后生成一个时间序列对象。
total_cases <- data %>%
group_by(Year, Month) %>%
summarise(Total_Cases = sum(Dengue_Cases))total_cases_ts <- ts(total_cases$Total_Cases, start=c(2008,1), end=c(2016,12), frequency=12)

上面显示了一个时间序列对象,这是一段时间内观察到的登革热病例的向量,其中频率被指定为 12,与公历的月份相对应。您会注意到我是如何指定开始和结束日期的。
一般来说,时间序列的历史模式可以用以下几个分量来描述:季节分量( St )、趋势分量( Tt )、周期分量、残差或误差( Et )。
并非所有的时间序列都由这些组成部分组成,但是当存在这些组成部分时,解构时间序列以独立观察它们可以获得巨大的洞察力,并形成时间序列分析的基础。提取成分的过程被称为分解。
加法与乘法分解
当分解一个时间序列时,我们要么使用加法模型,要么使用乘法模型。在一个附加模型中,我们假设季节性效应的幅度每年都是相同的。换句话说,比如说,10 月和 12 月之间的登革热病例差异不会逐年改变。
或者,乘法分解假设季节性成分以比例变化到序列的趋势,简单地将这些成分相加不足以重建序列。
在这里,我假设季节差异在多年的观察中保持不变,因此将使用一个加法模型。
稍后,我将创建一个 ARIMA 模型(见下文的完整解释)。这些模型可以适用于季节性和非季节性数据。季节性 ARIMA 模型有更多的参数,但是因为我将使用auto.arima()函数,它为我们搜索最佳订单参数,所以我不会将数据非季节性化。对于非季节性数据和普通非季节性 ARIMA 模型的完整解释和例子,我将读者引至此处。
我使用预测包中的stl()函数来生成一个分解(stl 默认使用一个附加模型)。
plot(stl(total_cases_ts, s.window = "periodic"))

我可以在这里看到 2012/13 年左右登革热病例的高峰,但也可以看到季节性成分和随机噪音的数量(由剩余部分显示)。
平稳时间序列和 Dickey-Fuller 检验
为了拟合 ARIMA 模型并预测未来的登革热病例,要求时间序列是平稳的。那么到底什么是平稳时间序列呢?
如果时间序列的均值、方差和自相关结构不随时间变化,则称该时间序列是平稳的。这对 ARIMA 很重要,因为它使用序列之前的滞后(时间段)来模拟其行为,并且模拟具有一致属性的序列涉及较少的不确定性(如果序列的统计属性在未来与过去相同,这使得预测任务变得简单!).
有一种简便的正式统计检验可以告诉我们一个时间序列是否是平稳的,这就是扩展的 Dickey-Fuller (ADF)检验。ADF 程序测试观察值的变化是否可以用滞后值和线性趋势来解释。如果 Y 的变化没有受到滞后值的显著影响,并且存在趋势成分,那么零假设(假设序列是非平稳的)不会被拒绝,并且该时间序列被称为“非平稳的”。
adf.test(total_cases_ts, alternative = "stationary")

p 值大于 0.05,因此不能拒绝零假设,因此我们说该数据是非平稳的。
快速浏览 ACF、PACF 和 ARIMA
登革热病例时间序列是非平稳的。那现在怎么办?我可以用一种叫做差分的技术让一个非平稳的时间序列平稳。趋势或周期是通过从上一个周期中减去一个周期的值来去除的。这背后的概念是,如果原始时间序列在一段时间内没有恒定的属性,那么从一个时期到另一个时期的变化可能会有。
有一些诊断可以帮助确定差异的顺序,或者您可以让auto.airma()为您解决这个问题。但是理解 ARIMA 模型的顺序参数是有好处的。但是等一下…ARIMA 到底是什么!?
ARIMA 代表“自回归综合移动平均线”。让我们来分析一下。MA 代表“移动平均数”,因此不是采用特定月份或年份的平均登革热病例,而是 1 月、2 月和 3 月的平均登革热病例,然后是 2 月、3 月和 4 月的平均病例,依此类推。
AR 代表“自回归”并代表内部回归,因此来自某个时间序列的数据被用于预测同一时间序列的数据。
“我”只代表“综合”。因此,当你把所有这些放在一起时,ARIMA 模型将根据同一时间序列的移动平均值来预测该时间序列的未来值。ARIMA 模型有时也被称为 Box-Jenkins 方法。
ARIMA 模型由三个序参量指定: p,和q。我们之前已经遇到过 d 。这是差异的程度,并在模型的集成组件中指定( I(d) )。 p 指定在模型中使用的滞后数,是自动回归分量 AR(p)的一部分。MA(q) 是移动平均分量,代表模型的误差,其中 q 定义要包含的项数。除了刚刚描述的参数,如果 ARIMA 模型具有季节性结构,还包括另外三个参数, (P,D,Q)m,描述了 m 周期的季节性成分。
虽然auto-arima将为您优化这些参数,但让我们讨论两个图,它们可以帮助您选择 p,d,和 q 的最佳值。它们是自相关图(ACF) 和偏自相关图(PACF) 。ACF 图显示了一个序列和它的滞后之间的相关性。该图可以告知要使用的差分顺序以及移动平均分量的顺序。另一方面,PACF 图显示了一个序列和它的滞后之间的相关性,这种相关性不能用以前的滞后来解释,因此有助于确定自回归分量的阶数。
r 生成具有 95%显著性边界的图,其中具有滞后的显著自相关将超过这些边界。我们可以使用 R 中的acf和pacf函数来生成这些图。
我们去做模特吧!
您会注意到下面我将通过auto.arima函数直接使用原始数据集。这是因为函数为我执行差分。它通过最小化一组信息标准来确定自回归函数、差分、移动平均函数的最佳参数,以及季节模型的最佳参数(阅读更多信息此处和此处)。
dengue_arima <- auto.arima(total_cases_ts)

然后,我可以使用定义的模型定义一个forecast对象,并指定我希望“预测”未来的月数。让我们试着预测一下 2017/18 年的病例数。
dengue_future <- forecast(dengue_arima, 24)
plot(dengue_future, ylab = "Dengue cases per 100,000 population")

该模型预测这两年的模式与 2016 年相似,但具有高度的不确定性。那么模型表现如何呢?从世卫组织的数据来看,与 2016 年相比,2017 年的病例数实际下降了 36.9%。

Figures from WHO (https://tinyurl.com/yblwvssk). Note that the unit for the y-axis is total number of cases observed, we divide by 100 to get cases per 100,000, showing a dramatic decrease in the peak number of cases in comparison to 2016.
ARIMA 模型成功地捕捉到了季节性趋势,但高估了登革热病例总数。
走向
我真的很喜欢这个项目,觉得这是一次很好的学习经历。当我刚开始的时候,我对 ARIMA 模型不是很熟悉,这是我第一次尝试用 R 语言进行时间序列分析。
基于菲律宾登革热病例的主题,我想探索递归神经网络在预测未来病例中的应用,但包括与登革热暴发相关的特征,如天气和迁移数据。我希望将此作为未来文章的主题。
对于这个项目,我要感谢互联网和每天在 medium 上发表的鼓舞人心的作品。下面列出了我用来学习时间序列分析和预测的一些极好的资源,以及关于登革热事实的来源:
- https://www.ncbi.nlm.nih.gov/pubmed/27374846
- 【https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4948936/ 号
- 【https://www.cdc.gov/dengue/epidemiology/index.html
- https://magazine . jhsph . edu/2010/spring/features/the _ devils _ disease _ 登革热/page_1/index.html
- https://www . r-bloggers . com/is-my-time-series-加法-或-乘法/
- https://www . analyticsvidhya . com/blog/2015/12/complete-tutorial-time-series-modeling/
- https://www . data science . com/blog/introduction-to-forecasting-with-ARIMA-in-r-learn-data-science-tutorials
- Philipp K.Janert 使用开源工具进行数据分析
通过数据探索传染病:美国麻疹的交互式可视化

在美国,1912 年,麻疹成为全国性的传染病。因此,美国所有的医疗保健提供商和实验室都必须向联邦政府报告确诊病例。今天我将关注从 1928 年到 2002 年在美国收集的麻疹数据。这是从项目 Tycho 获得的,该项目旨在向全球研究人员、数据科学家、学生和公众提供大规模公共卫生数据。这些数据来源于每周国家法定疾病监测系统报告,包括州一级的标准化计数和基于历史人口估计的每 100,000 人的发病率。
这个项目的目的是探索不同的数据可视化方法和 BokehJS 的能力。我被 BokehJS 的结果淹没了,我强烈推荐探索这个包。BokehJS 提供了一个强大的 Python API,允许你以 D3.js 的风格创建交互式绘图。我主要是从他们在网站上提供的文档和优秀教程中了解 BokehJS 的。
我也强烈推荐这些资源:
- 威廉·科尔森(William Koehrsen)关于 BokehJS 创建 BokehJS 仪表板的文章非常精彩,分为三部分:第 1 部分、第 2 部分和第 3 部分。
- Eugine Kang 在这里给出了一个很好的基本概述。
- 来自 FreecodeCamp 的 Mandi Cai 在这里对散景和 D3 做了一个很棒的对比。
- Eric Strong 可以帮助你开始在 Heroku 上运行一个散景应用程序。真是救命恩人(一般来说也是一个非常棒的博客!)
对于所有其他查询,Stackoverflow 和 Google 通常就足够了。
这个项目的所有代码可以在我的 Github 这里找到:https://github.com/burtonbiomedical/measles_map
我的 BokehJS 努力的最终产品在这里展示(这是一个在免费 Heroku dyno 上托管的 Bokeh Python 应用程序。它的性能落后于本地主机,可以从优化中受益。):【https://measles-bokeh.herokuapp.com/
麻疹是什么?

An electron micrograph of the measles virus. Photo Credit: Cynthia S. Goldsmith Content Providers(s): CDC/ Courtesy of Cynthia S. Goldsmith; William Bellini, Ph.D. — This media comes from theCenters for Disease Control and Prevention’s Public Health Image Library (PHIL), with identification number #8429
苏格兰医生弗朗西斯·霍姆发现麻疹是由血源性传染因子引起的。1758 年,爱丁堡爆发了一场麻疹流行病,霍姆开始试验麻疹疫苗。
麻疹传染性很强,通过感染麻疹病毒的人咳嗽和打喷嚏传播。该病毒有 10 至 12 天的潜伏期,随后症状会持续一周以上。这些症状最初包括高烧、咳嗽、其他类似流感的症状和眼睛发炎。症状期开始后三天内通常会出现明显的红色扁平皮疹,从面部蔓延至身体其他部位。大约有三分之一的病例会出现并发症,其中一些可能会改变生活,甚至是致命的,包括失明、脑炎和肺炎。尽管许多人可以存活并从感染中恢复,但每一千个病例中就有一个会导致急性脑炎,通常会导致永久性脑损伤,在不发达国家,死亡率已经高达 28% 。
尽管弗朗西斯·霍姆的疫苗接种尝试没有成功,但约翰·F·恩德斯和托马斯·C·皮布尔斯博士于 1954 年成功地从 13 岁的戴维·埃德蒙斯顿身上分离出麻疹,后来研制出第一种麻疹疫苗。但自 1968 年以来,莫里斯·希勒曼及其同事开发的改良弱麻疹疫苗为成功接种麻疹疫苗铺平了道路。
数据争论
我将在这里给出项目结果的简要总结,但是完整的细节请查看我的 Jupyter 笔记本。
让我们先来看看第谷项目提供的数据:

原始麻疹数据的时间变量有一个令人困惑的列,所以我在 apply 方法中用一个很好的 lambda 函数创建了一个年和周数列。熊猫图书馆对于数据争论来说确实是极好的。

然后,我为自己创建了一个总结函数,我可以在整个项目中使用它来生成汇总信息的数据框架,例如每年的总病例数、每周平均发病率以及每个州和年份组合的每周平均病例数:
def summarise(df, group_by):
#Group data
grouped = df.groupby(by = group_by)
#Summarise data as Series then convert back to Dataframe
cases_sum = pd.DataFrame(grouped["cases"].sum()).reset_index()
cases_avg = pd.DataFrame(grouped["cases"].mean()).reset_index()
avg_incidence_year = pd.DataFrame(grouped["incidence_per_capita"].mean()).reset_index()
#Give columns sensible names
avg_incidence_year = avg_incidence_year.rename(columns = {"incidence_per_capita": "avg_incidence_per_week"})
cases_sum = cases_sum.rename(columns = {"cases": "total_cases_per_year"})
cases_avg = cases_avg.rename(columns = {"cases": "avg_cases_per_week"})
#Merge dataframes
cases = pd.merge(cases_avg, cases_sum)
new_df = pd.merge(avg_incidence_year, cases)
return new_df
然后我得到了我需要的地理坐标(你看我要去哪里……敬请关注地图!)从散景库中下载,如下所示:
from bokeh.sampledata.us_states import data as States
我将地理信息嵌入到我的熊猫数据框架中,以便在项目后期使用。更多信息请参考我的 GitHub 上的笔记本。
Seaborn 的静态图
在我进入数据科学世界的旅程中,我非常喜欢使用 Python Seaborn 库。当我刚开始的时候,我经常发现 matplotlib 笨拙而令人沮丧(一些纯粹主义者可能会因此讨厌我)。发现 Seaborn 是一种享受。它与熊猫的集成非常好,最终,作为一名数据科学家,你希望能够专注于你的模型和交流你的发现,而不是与图形包搏斗。
我从一些简单的线条图开始;一段时间内人均周平均发病率的变化和一段时间内病例总数的变化。


我们可以立即看到疫苗接种计划在 60 年代末/70 年代初产生的巨大影响。但是州之间的差异呢?有季节性模式吗?
由于数据的多维属性,这类问题不能通过线图很好地强调。使用热图可以实现更合适的可视化。在 Seaborn 生成热图相对简单。您可以向热图函数传递一个“long”格式的 Pandas 数据帧,其中轴值由索引和列给出,每个单元格的值是您希望在热图的每个给定交叉点绘制的值。用pivot方法可以实现“长”格式的 Pandas 数据帧的格式化。您可以指定要用作索引的列、将用于生成新列的列(每个值将指定一个新列)以及每个交叉点的值。这将返回一个“长”格式的数据帧。
通过使用热图,我可以通过在 x 轴上绘制年份,在 y 轴上绘制周数,在每个交叉点上绘制麻疹的严重程度(由人均发病率给出),来展示季节模式;其中较亮的颜色表示较高的发病率。热图非常适合可视化这样的三维数据。然后,我可以通过在 y 轴上绘制州名来对州进行同样的操作。这已经是一种非常有效的可视化方法,证明了保持一致的季节模式,以及 60 年代和 70 年代疫苗接种计划的显著效果。


静态的剧情很无聊!让我们开始互动吧!
虽然热图在传达美国麻疹疫苗接种的效果方面非常有效,但我认为在这个项目中探索交互式可视化会很有趣。启发性的统计数据、伟大的模型和有洞察力的趋势都是强有力的工具,但如果没有有效的沟通,这些都是没有意义的。当观众不仅有机会获得数据的广阔视野,而且有机会与它互动,探索它,并提出自己的问题时,这就是数据可视化真正变得神奇的时候。这就是我要利用 BokehJS 力量的地方。
我不会在这里详细介绍 BokehJS 是如何工作的,但是在这个项目的笔记本中,我给出了创建我下面演示的产品的每个步骤的完整解释。我也强烈推荐我之前列出的资源,如果没有我从每个资源中获得的洞察力,我将无法完成这个项目。
BokehJS 的真正力量可以在我认为对学习这个库至关重要的几个关键方面找到:
- ColumnDataSource 对象:Bokeh 处理数据的核心是 ColumnDataSource 类。基本的 ColumnDataSource 对象是一个字典,其中的键与列名相关,值是这些列的内容。当在多个图中使用同一个 ColumnDataSource 对象时,它允许图之间的链接,这是我充分利用的。
- 检查员:一个非常简单的概念,立即让您创建强大的互动情节。只需几行代码,您就可以将静态二维图转换为交互式显示,使观众能够悬停在每个数据点上,并接触到原始数据集中包含的其他变量。
- 小部件和回调:散景库附带了大量的小部件,您可以使用它们来为您的绘图添加交互功能。我在应用程序中使用滑块并选择小部件。这些方法允许使用回调函数。您可以使用定制的 javascript 来完成这项任务,也可以像我在应用程序中那样使用 Python 函数。
所以,事不宜迟,这里是我的散景涂鸦的结果:
上面的两个视频显示了 Jupyter 笔记本中本地运行的完全交互式的情节。然后我将这些图组合成一个单独的 Python 应用程序,可以在 Heroku 上看到。
我希望这激发了你对 BokehJS 及其功能的好奇心。我已经在 GitHub 上的项目目录中包含了一个小教程,并试图让主项目笔记本尽可能的丰富。但是,如果您有任何问题,请不要犹豫,在下面留下您的评论。
探索和机器学习多伦多的 Airbnb 房源

Photo credit: Inside Airbnb
Airbnb 房源、特征工程、探索性分析、回归
Airbnb 不提供我们可以使用的巨型数据库或转储意义上的开放数据。然而,Airbnb 内部的利用从 Airbnb 网站汇编的公开信息,分析关于一个城市的 Airbnb 房源的公开信息,并提供过滤器和关键指标,以便我们可以看到 Airbnb 在世界各大城市的使用情况。Airbnb 内部的是一套独立的、非商业性的工具和数据,与 Airbnb 或 Airbnb 的任何竞争对手都没有关联,也没有得到它们的认可。****
然而,Airbnb 内 提供的信息对我们来说是不够的。我们将从那里下载数据用于我们自己的分析。
我将与多伦多数据合作。因为我住在这里,我知道这里的一些街区。欢迎你选择任何你喜欢的城市。
我们将查看 Airbnb 的房源和日历,并尝试提供一些关于预测房源价格的探索性分析,如果我们假设在 Airbnb 工作,也是为了消费者。我们开始吧!
日历
**calendar = pd.read_csv('calendar.csv.gz')
print('We have', calendar.date.nunique(), 'days and', calendar.listing_id.nunique(), 'unique listings in the calendar data.')**

**calendar.date.min(), calendar.date.max()**

该日历涵盖一年的时间范围,即下一年每天的价格和可用性。在我们的案例中,从 2018–10–16 到 2019–10–15。

Figure 1
日历上的可用性
当我们查看日历数据时,我们可能想问这样的问题:未来一年多伦多的 Airbnb 主机会有多忙?
**calendar.available.value_counts()**

f(假)表示不可用,t(真)表示可用。为了找出一年的日平均可用性,如果可用,我们将把 available 列转换为 0,如果不可用,则转换为 1。
**calendar_new = calendar[['date', 'available']]
calendar_new['busy'] = calendar_new.available.map( lambda x: 0 if x == 't' else 1)
calendar_new = calendar_new.groupby('date')['busy'].mean().reset_index()
calendar_new['date'] = pd.to_datetime(calendar_new['date'])plt.figure(figsize=(10, 5))
plt.plot(calendar_new['date'], calendar_new['busy'])
plt.title('Airbnb Toronto Calendar')
plt.ylabel('% busy')
plt.show();**

Figure 2
多伦多最繁忙的月份是刚刚过去的十月。接下来忙碌的几个月似乎是在四月之后,一直延续到夏天。这些都在我们的体验和预期之内。
日历上的价格
价格如何逐月逐年变化?
我们删除 price 列中的“$”符号,将其转换为数字,并将 date 转换为 datetime 数据类型。
**calendar['date'] = pd.to_datetime(calendar['date'])
calendar['price'] = calendar['price'].str.replace(',', '')
calendar['price'] = calendar['price'].str.replace('$', '')
calendar['price'] = calendar['price'].astype(float)
calendar['date'] = pd.to_datetime(calendar['date'])
mean_of_month = calendar.groupby(calendar['date'].dt.strftime('%B'),
sort=False)['price'].mean()
mean_of_month.plot(kind = 'barh' , figsize = (12,7))
plt.xlabel('average monthly price');**

Figure 3
多伦多的 Airbnb 价格在 7 月、8 月和 10 月上涨。同意,这三个月是游览多伦多最好的月份。
价格在一周中的某一天是如何变化的?
**calendar['dayofweek'] = calendar.date.dt.weekday_name
cats = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
price_week=calendar[['dayofweek','price']]
price_week = calendar.groupby(['dayofweek']).mean().reindex(cats)
price_week.drop('listing_id', axis=1, inplace=True)
price_week.plot()
ticks = list(range(0, 7, 1)) # points on the x axis where you want the label to appear
labels = "Mon Tues Weds Thurs Fri Sat Sun".split()
plt.xticks(ticks, labels);**

Figure 4
星期五和星期六比一周中的其他时间要贵 10 美元以上。
清单
每个街区的列表数量
**listings = pd.read_csv('listings.csv.gz')
print('We have', listings.id.nunique(), 'listings in the listing data.')**

**listings.groupby(by='neighbourhood_cleansed').count()[['id']].sort_values(by='id', ascending=False).head(10)**

Figure 5
列表数量最多的街区是海滨社区——岛屿,几乎是第二多的街区(尼亚加拉)的四倍。从上面的标题图,我们也可以看到这一点。
审核评分等级
**plt.figure(figsize=(12,6))
sns.distplot(listings.review_scores_rating.dropna(), rug=True)
sns.despine()
plt.show();**

Figure 6
**listings.review_scores_rating.describe()**

Figure 7
不出所料,大多数评论者都给出了高分。
探索价格
price 列需要一些清理,例如删除“$”并转换为数字。
**listings['price'] = listings['price'].str.replace(',', '')
listings['price'] = listings['price'].str.replace('$', '')
listings['price'] = listings['price'].astype(float)listings['price'].describe()**

Figure 8
多伦多最贵的 Airbnb 房源是 12933 美元/晚。从的列表网址,据我所知似乎是合法的。一位艺术收藏家在多伦多最时尚街区的顶层公寓。不错!

source: Airbnb
为了不受极端情况的影响,我决定删除超过 600 美元/晚的房源,以及 7 个价格为 0 的房源,以便进行下面的探索性分析。
剔除异常值后的列表价格分布
**listings.loc[(listings.price <= 600) & (listings.price > 0)].price.hist(bins=200)
plt.ylabel('Count')
plt.xlabel('Listing price in $')
plt.title('Histogram of listing prices');**

Figure 9
邻里关系与价格
neighbourhood vs. price

Figure 10
不仅是滨水社区——岛上的房源数量最多,它还享有最高的中位价,而米利肯的中位价最低。
物业类型与价格
property_type vs. price

Figure 11
当我们查看每种物业类型的中值价格时,我们必须小心,不能说“最贵的物业类型是公寓式酒店,帐篷和停车位的中值价格高于公寓和城堡。”,因为 Aparthotel、Tend 和 Parking Space 各只有一个列表。
房型与价格
room_type vs. price

Figure 12
不言而喻,整个房间/公寓的价格比其他类型的房间要高得多。
**listings.loc[(listings.price <= 600) & (listings.price > 0)].pivot(columns = 'room_type', values = 'price').plot.hist(stacked = True, bins=100)
plt.xlabel('Listing price in $');**

Figure 13
整个家/公寓也有最多的房源。Airbnb 内部已经表明整栋整栋的住宅或公寓全年对游客开放,可能没有主人在场,可能是非法的,更重要的是,正在取代居民。我们将暂时把忧虑放在一边。
床型与价格
bed_type vs. price

Figure 14
这里没有惊喜。
便利设施
便利设施文本框需要清理一下。
**listings.amenities = listings.amenities.str.replace("[{}]", "").str.replace('"', "")
listings['amenities'].head()**

Figure 15
20 种最常见的娱乐设施。
**pd.Series(np.concatenate(listings['amenities'].map(lambda amns: amns.split(","))))\
.value_counts().head(20)\
.plot(kind='bar')
ax = plt.gca()
ax.set_xticklabels(ax.get_xticklabels(), rotation=45, ha='right', fontsize=12)
plt.show();**

Figure 16
Wifi、暖气、必需品、厨房和烟雾探测器等都是最常见的便利设施。
便利设施与价格前 20 名
**amenities = np.unique(np.concatenate(listings['amenities'].map(lambda amns: amns.split(","))))
amenity_prices = [(amn, listings[listings['amenities'].map(lambda amns: amn in amns)]['price'].mean()) for amn in amenities if amn != ""]
amenity_srs = pd.Series(data=[a[1] for a in amenity_prices], index=[a[0] for a in amenity_prices])amenity_srs.sort_values(ascending=False)[:20].plot(kind='bar')
ax = plt.gca()
ax.set_xticklabels(ax.get_xticklabels(), rotation=45, ha='right', fontsize=12)
plt.show();**

Figure 17
有趣的是,便利设施功能似乎与价格有一定关系。
床位数量与价格
**listings.loc[(listings.price <= 600) & (listings.price > 0)].pivot(columns = 'beds',values = 'price').plot.hist(stacked = True,bins=100)
plt.xlabel('Listing price in $');**

Figure 18
绝大多数房源都有一张床,一张床的房源价格差异很大。有没有床的列表。
**sns.boxplot(y='price', x='beds', data = listings.loc[(listings.price <= 600) & (listings.price > 0)])
plt.show();**

Figure 19
有趣的是,无床房源的中值价格高于 1 床和 2 床房源,而 10 床房源的中值价格非常低。
数字特征
我们选择了几个数字特征,并尝试一起探索它们。
**col = ['host_listings_count', 'accommodates', 'bathrooms', 'bedrooms', 'beds', 'price', 'number_of_reviews', 'review_scores_rating', 'reviews_per_month']
sns.set(style="ticks", color_codes=True)
sns.pairplot(listings.loc[(listings.price <= 600) & (listings.price > 0)][col].dropna())
plt.show();**

Figure 20
**corr = listings.loc[(listings.price <= 600) & (listings.price > 0)][col].dropna().corr()
plt.figure(figsize = (6,6))
sns.set(font_scale=1)
sns.heatmap(corr, cbar = True, annot=True, square = True, fmt = '.2f', xticklabels=col, yticklabels=col)
plt.show();**

Figure 21
有一些不坏的消息,如卧室和住宿的数量似乎与价格相关。也容纳,床和卧室是相关的,我们将保留其中一个模型。
建模标价
数据预处理和特征工程
清理价格特征。我们将要建模和预测的特征。
**listings['price'] = listings['price'].str.replace(',', '')
listings['price'] = listings['price'].str.replace('$', '')
listings['price'] = listings['price'].astype(float)
listings = listings.loc[(listings.price <= 600) & (listings.price > 0)]**
娱乐设施功能的术语文档矩阵。
amenities
如果为“f”,则将以下特性中的值替换为 0,如果为“t”,则替换为 1。
**columns = ['host_is_superhost', 'host_identity_verified', 'host_has_profile_pic',
'is_location_exact', 'requires_license', 'instant_bookable',
'require_guest_profile_picture', 'require_guest_phone_verification']
for c in columns:
listings[c] = listings[c].replace('f',0,regex=True)
listings[c] = listings[c].replace('t',1,regex=True)**
用同样的方法清理其他货币值列。
**listings['security_deposit'] = listings['security_deposit'].fillna(value=0)
listings['security_deposit'] = listings['security_deposit'].replace( '[\$,)]','', regex=True ).astype(float)
listings['cleaning_fee'] = listings['cleaning_fee'].fillna(value=0)
listings['cleaning_fee'] = listings['cleaning_fee'].replace( '[\$,)]','', regex=True ).astype(float)**
以下是我们将使用的数字功能。
numeric_features
用中位数填充数值要素中缺失的值。
**for col in listings_new.columns[listings_new.isnull().any()]:
listings_new[col] = listings_new[col].fillna(listings_new[col].median())**
处理和添加分类特征。
**for cat_feature in ['zipcode', 'property_type', 'room_type', 'cancellation_policy', 'neighbourhood_cleansed', 'bed_type']:
listings_new = pd.concat([listings_new, pd.get_dummies(listings[cat_feature])], axis=1)**
添加我们之前从便利设施功能创建的术语文档矩阵。
**listings_new = pd.concat([listings_new, df_amenities], axis=1, join='inner')**
数据预处理和特征工程完成了!
随机森林回归器
RandomForestRegressor

随机森林的特征重要性
**coefs_df = pd.DataFrame()coefs_df['est_int'] = X_train.columns
coefs_df['coefs'] = rf.feature_importances_
coefs_df.sort_values('coefs', ascending=False).head(20)**

Figure 22
LightGBM
LightGBM
********
light GBM 的特征重要性
**feat_imp = pd.Series(clf.feature_importances_, index=X.columns)
feat_imp.nlargest(20).plot(kind='barh', figsize=(10,6))**

Figure 23
这两个模型产生的特征重要性是相似的。
因此,我们取得的最好结果是平均小于 60 美元的测试 RMSE 误差,该模型解释了 62.4%的上市价格波动。
结果好吗?不太好。然而,价格是一个很难建模的东西,似乎在功能中没有足够的信号。我们可能希望添加季节性、预订窗口、停留时间等功能。我将把它留给其他时间。
Jupyter 笔记本可以在 Github 上找到。享受这周剩下的时光。
用 AWS Athena 探索墨尔本的 Myki 数据
使用无服务器 SQL 查询对 S3 CSV 数据进行简单分析
编辑:应维多利亚数据中心的要求,本文中讨论的数据链接已被删除。
作为墨尔本居民和 Myki 公共交通票价系统的日常通勤者(无可奉告),当我听说 2018 年墨尔本数据大会的数据集将是大规模的真实世界 Myki 使用数据时,我很感兴趣。关于我们熙熙攘攘的城市如何使用公共交通网络,我们能收集到什么样的深刻见解?让我们来了解一下!最重要的是,我们将检查它,而不需要从 CSV 转换,甚至不需要将它移出 S3。
下面是我从这个 18 亿行的数据集中收集到的一些快速统计数据,SQL 查询只需几秒钟就能运行,比一杯咖啡的费用要低得多:
- 票价包括 65.65%的全票价,33.65%的付费优惠票价,以及少得可怜的 0.69%的免费乘车优惠
- 周日,维多利亚州老年人优惠卡持有者最喜欢去的地方是博克斯山火车站
AWS 雅典娜
AWS Athena 是一个完全托管的无服务器查询服务,允许您对存储在 S3 存储桶中的数据运行 SQL 查询——有点像魔术。基于 Apache Hive 和脸书的 Presto ,Athena 让你定义(甚至发现)你的数据模式,然后立即开始运行查询。你所支付的只是雅典娜运行你的查询所需要的数据,以及在 S3 存储这些数据的费用。
因此,首先让我们获取数据,将其放入 S3,并准备我们的模式。
在 S3 准备我们的 Myki 数据
要先看一眼并探索数据文件,请查看这个公开的 S3 链接:
*Edit: by request of Data Victoria, links to the data discussed in this article have been removed.*(bucket contents is 25.4gb)---Once again, so many thanks to Data Science Melbourne for organising the Melbourne Datathon and providing the data. Thanks also to PTV for releasing the dataset.[http://www.datasciencemelbourne.com/datathon/](http://www.datasciencemelbourne.com/datathon/)
[https://www.ptv.vic.gov.au/](https://www.ptv.vic.gov.au/)
以下是我们今天感兴趣的文件的简要描述:
[events/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=events/) # our myki usage dataset is in here
[Samp_0/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=Samp_0/) # data is split into ten chunks
ScanOffTransaction/ # myki 'touch on' events when people board
ScanOnTransaction/ # myki 'touch off' events from disembarking
2015/ # year partitions
...
2017/
Week1/ # week partitions
...
Week52/
[QID3530164_20180713_12510_0.txt.gz](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/Samp_0/ScanOffTransaction/2017/Week53/QID3530164_20180713_12510_0.txt.gz) # data!
[Samp_1/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=Samp_1/)
...
[Samp_9/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=Samp_9/)
[calendar/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=calendar/) # map dates to week numbers, days of week, etc.
[cardtypes/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=cardtypes/) # myki fare types: full fare, concession, etc.
[stops/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=stops/) # links stop information to a stop id
为自己创建一个存储桶并复制数据!(如果您想更好地了解数据,可以随意复制其中一个Samp_X目录)
aws s3 mb s3://mediumreader-myki-data
aws s3 cp --recursive s3://bucket-no-longer-exists/ s3://mediumreader-myki-data/
轻松点。现在,我们告诉 AWS Athena 我们的数据是什么样子,以便它可以查询它——我们使用 AWS Glue 中的数据目录来完成这一点,它与 Athena 集成在一起。
在 AWS Glue 数据目录中准备我们的数据模式
AWS Glue 是亚马逊完全托管的 ETL(提取、转换、加载)服务,可以轻松地从各种数据源准备和加载数据,以进行分析和批处理。今天,我们只对数据目录使用 Glue 感兴趣,因为这将允许我们在刚刚转储到 S3 的 Myki 数据上定义一个模式。AWS Glue 通过提供数据“爬虫”使这变得容易,这些爬虫可以窥视我们的数据并自动发现我们的大量模式。
- 导航到 AWS 胶水
- 从菜单中选择爬虫
- 选择添加爬虫

Getting started by adding a crawler to discover our schema
- 命名我们的爬虫 myki_crawler
- 点击下一步,这里我们不需要任何可选配置

Naming our crawler, other optional config is fine as defaults
- S3 数据仓库
- 我的账户中指定的路径
- 对于我来说,Include path 是S3://tomwwright-myki-data/,替换为您之前在复制数据时调用的 bucket
- 将排除模式留空,对于这个数据集,我们只清理爬虫发现的我们不想要的垃圾
- 点击下一步,s 选择否添加另一个数据存储,再次点击下一步

Pointing our crawler at our S3 data bucket
- 选择创建一个 IAM 角色(除非您已经为 Glue 准备好了角色)
- 输入 MykiCrawler 作为名字——或者随便你怎么想,我是一个中等职位,不是你的母亲
- 点击下一个

Creating an IAM role to give our crawler access to our bucket
- 选择“按需运行”作为频率,我们只想运行一次
- 点击下一个

We just want to run it the once anyway…
- 选择添加数据库,姑且称之为 myki ,不需要任何的可选配置,点击创建
- 保持所有可选配置不变
- 点击下一个
- 点击完成!

Creating a database for the tables discovered by the crawler
你应该已经回到 AWS Glue 的爬虫屏幕,所以选择 myki_crawler 并点击 Run crawler 。根据我的经验,跑步大概需要 7 分钟,所以你可以喝杯咖啡或者散散步。
一旦爬虫完成,我们将能够在数据库- >表下查看发现的表。我们要做的第一件事是删除一些垃圾表,这些垃圾表是爬虫通过检查我们的 S3 桶中的一些非数据文件而创建的——删除所有分类为 Unknown 的表,如下面的截图所示。我们本来可以通过忽略将它们复制到 bucket 中,或者将它们添加到 crawler 的 exclude paths 配置中来省去这个麻烦。哦,好吧,很容易删除它们。

Deleting junk tables the crawler inadvertently created by scanning everything in the bucket — that’s our bad, oops.
打开日历表,我们可以看到爬虫为我们发现的所有好东西:数据格式、分隔符、记录计数、列类型等等。缺少的一点是列名,因为 myki 数据文件中没有该信息。下面你会发现一些我们需要应用的列标签(不一定是全部),以便能够为我们的表编写可读的查询。选择一个表并点击右上角的编辑模式来更新列。
table: calendar1 col0 bigint dateid
2 col1 string date
3 col2 bigint year
6 col5 string month
13 col12 string daytype # 'Weekday', 'Weekend', 'Public Holiday'
16 col15 string dayofweek---table: cardtypes1 col0 bigint typeid
2 col1 string typedesc
3 col2 string paidorfree # 'Paid', 'Free'
4 col3 string concession # 'Full Fare', 'Concession'---table: events1 col0 bigint mode
2 col1 string date
3 col2 string datetime
4 col3 bigint cardid
5 col4 bigint cardtypeid
6 col5 bigint vehicleid8 col7 string routeid
9 col8 string stopid
10 partition_0 samplenum
11 partition_1 onoroff # 'ScanOffTransaction', 'ScanOnTra...on'
12 partition_2 year
13 partition_3 week---table: stops1 col0 bigint stopid
2 col1 string name
3 col2 string longname
4 col3 string stoptype
5 col4 string suburb
6 col5 bigint postcode
10 col9 double lat
11 col10 double long
有了我们的列名,我们终于准备好做一些查询了!
用 AWS Athena 查询我们的模式
通过点击 Athena 服务,我们发现自己首先出现在查询编辑器屏幕上。酷,让我们选择我们的myki数据库并插入一个简单的计数查询!

AWS Athena’s Query Editor makes it simple to develop queries against our Myki schema
当我们得到一个我们真正满意的查询时,我们可以点击Save as并给它一个名字,然后我们可以很容易地找到它并在Saved Queries下再次运行它。Athena 还允许我们在History下访问我们的查询历史,在那里我们可以下载任何查询结果。

AWS Athena’s query history allows us to find our past queries and download the results
这里需要注意的一个重要指标是 Athena 查询所扫描的数据,因为 Athena 的定价直接(且仅)与 Athena 在运行查询的过程中读取的数据量相关:
“Amazon Athena 会根据扫描的字节数向您收费,四舍五入到最接近的兆字节,每次查询最少 10MB。
扫描每 TB 数据 5 美元”
由于它操作的是普通的平面文件,Athena 很难智能地处理它所扫描的数据,通常它需要读取模式指定的构成表的所有文件。除非在创建模式时,指定了分区来定义映射到目录的“列”, Athena 可以使用这些目录来智能地判断对于给定的查询应该扫描哪些数据。举例来说,回想一下我们数据的文件夹结构:
[events/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=events/) # our myki usage dataset is in here
[Samp_0/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=Samp_0/) # data is split into ten chunks
ScanOffTransaction/ # myki 'touch on' events when people board
ScanOnTransaction/ # myki 'touch off' events from disembarking
2015/ # year partitions
...
2017/
Week1/ # week partitions
...
Week52/
[QID3530164_20180713_12510_0.txt.gz](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/Samp_0/ScanOffTransaction/2017/Week53/QID3530164_20180713_12510_0.txt.gz) # data!
[Samp_1/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=Samp_1/)
...
[Samp_9/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=Samp_9/)
[calendar/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=calendar/) # map dates to week numbers, days of week, etc.
[cardtypes/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=cardtypes/) # myki fare types: full fare, concession, etc.
[stops/](https://tomwwright-myki-data.s3.ap-southeast-2.amazonaws.com/lst.html?prefix=stops/) # links stop information to a stop id
我们的events文件夹由一系列子文件夹组成,这些子文件夹按照几个关键列整齐地划分我们的事件数据:一个编号的样本文件夹,无论它是一个接触式事件还是触发式事件,年份和星期。幸运的是,我们的 AWS Glue crawler 足够聪明,能够注意到所有这些,并且已经在我们的模式中组织了所有这些!不错!

You can view partitions for a table in the AWS Glue Data Catalogue
为了说明这些分区的重要性,我用两个不同的查询计算了 2016 年使用的唯一 Myki 卡的数量(顺便说一下,大约 740 万张):一个使用数据中date列的LIKE操作符,另一个使用我们的year分区列。

The power of partitioning: Athena scans only the relevant data for 2016, less than 30% of the entire dataset
我们使用date LIKE '2016%'的第一个查询必须扫描整个events表,总共 25gb,因为 Athena 无法确定哪些文件中可能有匹配行。此查询的成本约为 0.12 美元。
我们使用year = '2016'的第二个查询能够检索我们的结果,并且只扫描 8g 的events数据!这是因为year是映射到我们的 S3 数据中特定键模式的分区列之一。该查询的成本约为 0.04 美元,运行时间不到三分之一!
使用分区智能地组织数据是能够在 Athena 上运行快速且经济高效的查询的关键。好吧,我们继续!
触发的热门站点
所以,我的第一个想法是,人们使用 Myki 会去哪里?用 SQL 回答这个问题似乎很简单,让我们从获得最受欢迎的站点列表开始。
# top 20 stop ids for touch-off events select stopid, count(*) as count
from events
where onoroff = 'ScanOffTransaction'
group by stopid
order by count desc
limit 20;

Touch-off events aggregated by the stop ID
很好,我们可以用我们的stops表来连接这个,以获得一个更易于阅读的表示,就这么做吧。
# select our top stops like before, then join to our stops tablewith topstops (stopid, count) as (
select stopid, count(*) as count
from events
where onoroff = 'ScanOffTransaction'
group by stopid
)
select topstops.stopid, stops.longname, stops.suburb, topstops.count
from topstops left outer join stops
on topstops.stopid = stops.stopid
order by topstops.count desc
limit 20;

Results of running our “top touch-off stops” query
嗯。有一堆stopid行遗漏了stops信息……对我来说,鉴于它们是最受欢迎的车站,并且有正确的数字,我的猜测是64xxx站是城市环路铁路站,也许24001是里士满站?
除此之外,这些结果对我来说是有意义的,看到所有的顶级车站都是火车站一点也不奇怪。

Melbourne’s City Loop — map courtesy of Public Transport Victoria
票价类型的细分
似乎总是有一些关于向各种群体提供优惠公共交通出行的肆意支出的喋喋不休。全价票和优惠票的细目是什么?同样,看起来很简单。让我们首先根据events表中的卡类型进行汇总。
# aggregate our touch-on events by the card type usedselect cardtypeid, count(*) as count
from events
where onoroff = 'ScanOnTransaction'
group by cardtypeid
order by count desc

Touch-on events aggregated by the card type ID
很好,所以和上次一样,让我们加入到我们的cardtypes表中来,以提供更多人类可读的信息:
# aggregate by card type as before, then join to card types
# information to determine concession and paying statuswith cardtypecounts (cardtypeid, count) as (
select cardtypeid, count(*) as count
from events
where onoroff = 'ScanOnTransaction'
group by cardtypeid
)
select cardtypecounts.cardtypeid, cardtypes.typedesc, cardtypes.concession, cardtypes.paidorfree, cardtypecounts.count
from cardtypecounts left outer join cardtypes
on cardtypecounts.cardtypeid = cardtypes.typeid
order by cardtypecounts.count desc;

Top fare types and concession / paying status
全价乘客看起来占了绝大多数,是最常见(但标签模糊)优惠票价类型的 4 倍多。但是列表的其余部分是由各种不同的特许权类型组成的,所以可能不会这么简单。唯一进入前 14 名的免费乘车类型是Employee Travel Pass——有道理。
让我们通过再次汇总来进行更高层次的观察,我对全价、优惠和免费的总体细分很好奇。
# further aggregating our query by concession and paying
# statuseswith cardtypecounts (cardtypeid, count) as (
select cardtypeid, count(*) as count
from events
where onoroff = 'ScanOnTransaction'
group by cardtypeid
)
select cardtypes.concession, cardtypes.paidorfree, sum(cardtypecounts.count) as count
from cardtypecounts left outer join cardtypes
on cardtypecounts.cardtypeid = cardtypes.typeid
group by cardtypes.concession, cardtypes.paidorfree
order by count desc;

Full-fare vs. concession vs. free fare types
好吧,这就是全貌:65.65%的全价票,33.65%的付费优惠票,以及少得可怜的 0.69%的免费乘车优惠票。
老年人的最佳周日目的地
最后,让我们尝试一些稍微具体的东西。在一个星期天,我们的高级公共交通用户喜欢去哪里?
加入我们的calendar表将允许我们确定哪些日期是Sunday,我们之前对票价类型的查询显示cardtypeid = 9是我们需要寻找的Victorian Seniors Concession票价类型。厉害!
# selecting touch-on events that were on a Sunday using a Victorian Seniors
# Concession fareselect stopid, count(*) as count
from events, calendar
where onoroff = 'ScanOffTransaction'
and events.date = calendar.date
and events.cardtypeid = 9
and calendar.dayofweek = 'Sunday'
group by events.stopid;

Touch-on events on a Sunday by seniors, aggregated by the stop ID
现在就像我们的第一个查询一样,加入到stops来给我们一些人类可读的信息。再次记住有些止损点似乎错过了他们的信息…
# join or sunday seniors stops to stops informationwith seniorsundaystops (stopid, count) as (
select stopid, count(*) as count
from events, calendar
where onoroff = 'ScanOffTransaction'
and events.date = calendar.date
and events.cardtypeid = 9
and calendar.dayofweek = 'Sunday'
group by events.stopid
)
select seniorsundaystops.stopid, stops.longname, stops.suburb, seniorsundaystops.count
from seniorsundaystops left outer join stops
on seniorsundaystops.stopid = stops.stopid
order by seniorsundaystops.count desc;

我们神秘的未命名站点(几乎可以肯定是城市环路站点)仍然领先,但显然我们挥舞着 Myki 的老年人喜欢在 Box Hill,Caulfield 和 Footscray 度过时光。谁知道呢。
包扎
花点时间想想这种技术有多酷是有好处的,因为一旦你投入进去,就很容易忘记。能够运行带有连接的 SQL 查询,只针对位于 S3 的 CSV 文件。令人印象深刻。
这个 Myki 数据也不是一个可以分析的小数目。超过 18 亿行,我们能够在不到 10 秒的时间内处理它。而且它的成本非常低。本文中列出的查询扫描了大约 145 千兆字节的 S3 数据,总共花费了我巨大的…
$0.75
查询愉快!汤姆

Counting our data — it’s a decent bit to be crunching in under 10 seconds and paying next to nothing for
用交互式可视化探索电影数据

合著者:阿尔维拉·斯瓦林。
你有没有看过一部自己喜欢的电影,思考过让它成功的不同因素?
这是对 1910 年至 2016 年电影数据库(TMDB)数据的探索。一部商业上成功的电影不仅能娱乐观众,还能让电影制作人获得丰厚的利润。好的导演、有经验的演员和上映时间等几个因素对盈利很重要,但它们并不总是能保证一部电影的评级有多高。
在这个项目中,我们试图了解影响电影盈利能力的时间模式,了解流行类型如何随着时间的推移而变化,确定重要的演员和导演,并观察电影收视率和平均投票率随时间的变化。
时态模式分析
电影什么时候最赚钱?
从这张热图中,我们可以看到平均盈利能力在最近几年有所提高,6 月、11 月和 12 月对电影发行尤为重要。6 月份的平均利润是 1 亿美元,比 1 月份的平均利润多 10 倍!这可能是因为人们在夏天可能有更多的空闲时间看电影。

随着时间的推移,哪些流派已经盈利?
下图显示了不同类型电影的利润趋势。“家庭”和“冒险”类型的电影最近似乎变得越来越有利可图,而“戏剧”电影最近产生的利润越来越少。

哪种类型的电影最流行?
下面的单词云显示了我们的数据集中最常见的电影类型,我们可以看到这些年来最流行的电影类型是“戏剧”和“喜剧”。这意味着,虽然“冒险”和“家庭”最近更有利可图,但这不仅仅是因为这些类型的电影数量最多。

随着时间的推移,投票数和平均电影评分的分布如何变化?
以下两个图突出显示了从 20 世纪到 21 世纪,由于互联网设施使投票变得更加容易,电影的投票数急剧增加(增加了 3 倍)。此外,值得注意的是,随着平均投票率在每十年中不断下降,人们最近变得越来越挑剔。我们认为,这是因为人们将新电影与他们过去看过的电影进行比较,并认为这些电影是原创的,更好。

电影特色分析
电影预算是如何影响利润的?
下图显示了一部电影的利润与其预算的对比。标记的颜色和大小代表电影的平均评分(满分 10 分)。利润和预算之间存在某种正相关关系,因此预算较大的公司似乎实际上通过更高的利润看到了这些预算的好处。
如果你悬停在图表的最高点,你会发现《阿凡达》是有史以来最赚钱的电影。
电影放映时间如何影响利润?
同样,我们也可以研究一部电影在几分钟内的播放时间是如何影响其利润的。标记的大小和颜色再次表示电影获得的平均评级。有趣的是,运行时间似乎对电影利润没有太大影响。
演职人员分析
哪些导演平均利润最高?
这些都是导演过 5 部以上电影,平均利润最高的导演。执导《阿凡达》的詹姆斯·卡梅隆是获利最大的导演。将鼠标悬停在条形上会让您看到确切的值。
哪些导演的电影平均收视率最高?
而这些都是导演过 5 部以上电影平均电影评分最高的导演。评分水平接近,但导演《黑暗骑士》的克里斯托弗·诺兰获得了最高的电影整体平均评分。
有多少主演合作过?
接下来,我们想观察哪些演员彼此合作最多,因此创建了一个网络主要演员。为了创建这个网络,我们选择了大约 270 名在 3 部以上电影中出现过的演员作为主要演员(演员 1 或 2 ),并创建了这些演员的网络。这个网络中的每条边都表明这两个演员作为主要演员在同一部电影中合作过。将鼠标悬停在这个网络中的节点上会显示参与者的名称,连接数通过颜色表示,您可以放大查看子网络的详细信息。
谁是最有影响力的演员?如果您将鼠标悬停在连接数最多的黄色节点上,您会看到它是劳勃·狄·尼诺。
怎么才能比较顶级演员?
从上述 270 名演员中,我们根据他们与其他重要演员的合作次数选择了前 15 名演员,并使用平均投票率、盈利能力和他们所演电影的受欢迎程度等指标来比较他们的表现。您可以从下拉菜单中选择这些指标,参与者姓名旁边的括号中的数字是他们的连接数。
外卖
- 电影往往在六月最赚钱。
- 家庭和冒险电影往往是最近最赚钱的。
- 2010 年的平均电影评分一直在 6.5 左右。
- 詹姆斯·卡梅隆是电影平均利润最高的导演。
- 克里斯托弗·诺兰是电影平均收视率最高的导演。
- 阿凡达是有史以来最赚钱的电影。
- 放映时间对电影利润没有太大影响。
- 劳勃·狄·尼诺是一个主要演员,他和其他 24 个主要演员合作过。
- 在与其他主要演员合作最多的演员中,汤姆·克鲁斯的电影平均利润最高,凯特·温斯莱特的电影平均票数最高,克里斯蒂安·贝尔的电影最受欢迎。
感谢您花时间通读这部电影探索,如果您喜欢,请随时与阿尔维拉·斯瓦林和基尚·潘查尔联系。
同时,我们要感谢来自 USF 的 Alark Joshi 教授为我们讲授了有效的数据可视化技术和原理。
参考文献
- Github 存储库,其中包含用于创建这些图的所有代码:https://github.com/k7p/dataviz_project
- 所有视觉效果都是互动的项目网站:https://sites.google.com/dons.usfca.edu/movieviz/home
- Plotly 文档:https://plot.ly/python/
- 散景文档:https://bokeh.pydata.org/en/latest/
- 电影数据库(https://www.themoviedb.org/?language=en)
探索 NLP/AWS/BigData:第 1 部分
我必须承认,在我探索机器学习的时候,我对 NLP (自然语言处理)并不太感兴趣,实际上我把它和另一个 NLP (神经语言编程)混淆了。但是当我在大会上重温我的顶点项目的材料时,我偶然发现了由 YELP 提供的这个惊人的数据。数据集非常具有描述性,但是非常庞大,但是可以分为两条路线(NLP 或图像识别)。
在这个系列中,我将使用 yelp 提供的数据集回顾我探索 NLP 技术的过程。我将探索我的陷阱和策略,并希望我能帮助揭开一些概念的神秘面纱。在本系列中,我还将回顾我使用 AWS 弹性计算云( E2C )的经历,并用 Scala 语言复制 python 中的几种机器学习技术(我觉得这种语言可以完成的工作,但对于一个来自 Python 和 C++的人来说,这是一种如此丑陋的语言)。
Yelp 数据集
- 图像分类通过有 5 千兆压缩的 JPEGs。
- 来自几个主要城市的商业/用户/评论数据库。
英国:爱丁堡
德国:卡尔斯鲁厄
加拿大:蒙特利尔和滑铁卢
美国:匹兹堡、夏洛特、厄巴纳-香槟、凤凰城、拉斯维加斯、麦迪逊、克利夫兰

踪迹地图
- 规范化、清洗和 EDA。
- 模型选择(逻辑回归、贝叶斯、随机森林)
- 使用 AWS 的 Spark、Scala 和 Hadoop。
- Word2Vec。
设置和库:
我用的是 Python 3.5.2 |Anaconda 自定义(64 位)。
Git bash 终端。
我的电脑运行的是 I-7–5500 2.40 GHz 和 8GB RAM(我们将把它与 AWS 服务器进行比较,看看为什么后者是更好的选择)
- 空间(版本 1.8.0)。安装了英语“en”型号。这在处理“停用词”时很重要。
pip install spacy
sudo python -m spacy download en
- NLTK(3 . 2 . 1 版)另一个比 SpaCy 更老的 NLP 库。
- gensim(版本 2.1.0)是一个很棒的免费库,我用来实现 Word2Vec
- 全球。从路径名中读取文件。
- tqdm (4.11.2)这是可选的,但是当你想检查一个熊猫函数的进度时,这是必须的。这些文件是巨大的,当你运行所有的东西时,看到你在哪里是很棒的。

SpaCy 对 NLTK:
简而言之空间就是快。在我最初的 YELP 草稿中,我一直与这两个库合作,并且在“标记化”和“词汇化/词干化”过程中,我使用 SpaCy 做了许多繁重的工作,它非常快速和健壮。
JSON 到 CSV:
Yelp 提供的数据集由原始 json 组成。我的第一个挑战是将如此大的文件管理成可以翻译成 Python pandas 的东西。

Do not open this with pythons.read() . You’ll regret it.
我找到的解决方法是链接这里。这将需要一段时间来转换,尤其是 review.json。对于 Python 3 用户,您可能需要将这一行代码添加到上面的链接中。
**tqdm**(glob('yelp_academic_dataset_checkin.json')):
df = pd.DataFrame([convert(line) for line in **open**(json_filename)])
一旦 json 被转换成 CSV 格式,你可以用熊猫打开它,结果应该是这样的。

约束条件:
重要的是要记住,我的最终数据集不同于 YELP 提供的数据集。有大量的删改工作,包括将所有评论保留在美国和英国。原始数据集包含美国境内外的德国评论,因为拉斯维加斯是一个主要的旅游目的地,所以我看到一些德国评论并不奇怪。然而,我决定消除这些类型的审查,留在美国是基于领域知识。我不认为自己非常精通英语语言学,但我理解现代口语和基本的语法结构,作为美国公民,我也能理解每个城市/州的风味和内涵。当我探索欧洲城市时,我失去了这种能力(我不能告诉你英国哪个地区以炸鱼薯条闻名,但我知道最好的 Tocos 总是在边境以南,胸肉在德克萨斯州是国王)。另外,我唯一知道的德语单词是“幸灾乐祸”和其他。。。脏话。
YELP API 中的类别是另一个挑战。问题是如何处理数据框中的嵌套数组。最后,我决定将每个类别过滤成 7 个主要类别和一个空角色。
我们来看看数据:
使用美国大约 300 万条评论的整个数据集。

The bulk of the reviews came from NV,AZ,NC. With only 2 reviews for VT.

可视化:
这里有一个表格显示了 Q1 第四季度时间序列中平均商业得分最高的四个州。
后续步骤:
在我的下一篇文章中,我将探索模型选择过程。(逻辑回归、多项式朴素贝叶斯、随机森林)。我将讨论每种策略的利与弊,以及幕后发生的一些事情。
用高斯过程回归探索脉动变星
事实证明,高斯过程对于难以用经典单变量或多变量回归描述的现象建模非常有用。但是,在许多情况下,当处理定型数据域之外的特征值时,它们的预测能力会下降。然而,一个例外是依赖于三角函数的高斯过程协方差函数,例如 sin( x )。这些函数以其估计值的周期性为特征,可用于模拟观测数据所涵盖的时间段之外的稳定的周期性现象。
下面,我将逐步演示使用高斯过程回归和 ExpSineSquared 协方差函数来模拟一种脉动变星的光度曲线。在此过程中,我将分享我遇到的主要陷阱和见解,我希望你会发现这是对这一练习的相对直观的解释。
脉动变星
恒星的光度会因为各种不同的原因而波动。对于一些人来说,脉动的模式是混乱的,看起来是随机的,就像新星(恒星爆炸)或具有重复出现的太阳黑子的恒星的情况一样。对于其他人来说,比如我将在本次分析中使用的恒星,其模式是一致且稳定的。
长周期变星是由于恒星大小的变化而脉动的红巨星。我在这里要关注的恒星,塞特斯星座中的御夫座(Omicron Ceti),是长周期变星中最广为人知和研究最多的例子。米拉的光度变化源于恒星温度的变化,导致大小以及可见光范围内外光输出波长的波动。
我将利用 1985 年到 2007 年对米拉的光度观测来预测 2008 年以后的光度曲线。我将使用的数据可从 AAVSO 国际数据库免费获得,该数据库汇集了来自世界各地的恒星观测者的贡献。

拟合高斯过程回归
我使用 Scikit Learn 的高斯过程回归(GPR)来促进这一分析。最初的挑战是将数据缩小到可用的大小。GPR 运行时间与(样本大小)成比例,因此随着数据量的增长,GPR 运行时间很快变得不切实际。在我的分析中,我发现从训练数据中随机抽取 1,000 个观察值(总共超过 80,000 个观察值)产生了相对一致的结果,同时将运行时间保持在一分钟左右。
我从 ExpSineSquared 内核和 WhiteNoise 内核开始,以捕捉 Mira 亮度测量中固有的随机波动性。仔细选择先前的内核超参数,以及设置超参数的上限和下限,对于建立良好的拟合至关重要。我重复了这个过程无数次,每次都不太合适,直到我发现了两个不同的参数:
- 白化上界:在设置一个噪声水平上界之前,模型反复拟合一个高噪声值的“懒惰”后验核。一旦我定性地评估了训练数据曲线上任何给定点的“真实”噪音的程度,我就将上限设置为 0.5,理由是噪音的量永远不应该超过该量。
- expsine squared periodicity:类似于 WhiteNoise 参数,一旦我为 periodicity 超参数设置了上限和下限,我看到 GPR 拟合有了显著的改进。在这里设置界限很简单,只需查看光变曲线数据的散点图,目测波峰和波谷之间的距离。
以下是采用这两种超参数限制后的拟合结果:

在这张图中,我通过 2008 年至 2018 年的观察扩展了预测结果,在图上以红色显示。将拟合的单核 GPR 与训练窗口之外的数据进行交叉验证是我对预测准确性的主要测试。下图显示了 2008-2018 年实际观测亮度与同期拟合估计值的残差。

我想回答的另一个问题是:多核 GPR 是否比单个 ExpSineSquared (+WhiteNoise)核更适合 Mira 的亮度曲线?答案是肯定的,也是否定的。对于将 GPR 专门拟合到训练数据,将 ExpSineSquared 内核与任何数量的其他固定内核相结合提供了增强的拟合。然而,除了训练数据之外,添加第二个稳定的非周期内核的边际增益很快变得极小。下面,观察使用 ExpSineSquared 核乘以 RBF 的拟合 GPR。随着与训练数据的距离增加到 RBF 的 lambda 参数以上,RBF 下降到零,GPR 变得无用。

然而,这并不是说单核 GPR 总是优于多核 GPR。如果被建模的现象在一个以上的时间跨度上表现出周期性,则使用多个 ExpSineSquared 核可能是合适的。在这种情况下,每个 ExpSineSquared 核可以拟合到不同的周期性超参数,以实现较高的预测精度。
这是相同的数据,拟合到一个协方差函数,该函数将两个 ExpSineSquared 内核相加(+WhiteNoise)。

尽管 GPR 符合周期参数约为 1,500 天的 ExpSineSquared 内核之一,但该模型的预测能力(如以下残差图所示,以及 1 核和 2 核 GPR 之间的均方根误差比较)并没有实质性提高。

[## daso telo/Python _ Projects/Omicron _ ceti . py
通过在 GitHub 上创建一个帐户来为 Python_Projects 开发做贡献。
github.com](https://github.com/dasotelo/Python_Projects/blob/master/Omicron_Ceti.py)
探索 Tableau 与资本自行车共享和天气数据
在这篇文章中,我将向您展示如何使用 Tableau Public 2018 进行一些有趣的数据分析和可视化。
我们将在 2018 年夏天探索华盛顿 DC 地区的首都自行车共享用户。特别是,我们将看看天气、星期几和会员类型如何影响乘客量。

我们开始吧。🚀
(舞台上由人扮的)静态画面
Tableau 是一款超级强大的数据分析和数据可视化工具。它已被各种公司广泛采用,以帮助他们变得更加数据驱动。对于许多数据科学家、业务分析师和高管来说,这是一个能够使用的重要程序。

整个 DC 市区有超过 4300 辆自行车共享单车。我是一个自行车共享成员,并挖掘它。我只是希望有更多的自行车和码头:)
数据
首都自行车共享数据可在此免费获取:
开发者、工程师、统计学家和学者可以找到并下载首都自行车共享会员的数据…
www.capitalbikeshare.com](https://www.capitalbikeshare.com/system-data)
天气数据可在此免费获取:
[## 搜索|在线气候数据(CDO) |国家气候数据中心(NCDC)
气候数据在线(CDO)国家气候数据中心(NCDC)定位数据的主要一般搜索页面…
www.ncdc.noaa.gov](https://www.ncdc.noaa.gov/cdo-web/search)
Tableau Public 可在此免费获得:
Tableau 可以帮助任何人看到和理解他们的数据。连接到几乎任何数据库,拖放创建…
www.tableau.com](https://www.tableau.com/)
Bikeshare 数据只包含几个字段。
- 持续时间—行程的持续时间
- 开始日期—包括开始日期和时间
- 结束日期—包括结束日期和时间
- 起点桩号—包括起点桩号名称和编号
- 终点桩号—包括终点桩号名称和编号
- 自行车号码—包括旅行中使用的自行车的 ID 号
- 会员类型—表示用户是“注册”会员(年度会员、30 天会员或日间会员)还是“临时”会员(单程、24 小时通票、3 天通票或 5 天通票)
仅查看 2018 年 6 月、7 月和 8 月就有 100 万条记录,因此我们将在这三个月停下来做这个练习。进入 Tableau 工作表后,您可以创建一个计算字段,使持续时间更容易处理。持续时间如果你想以分钟而不是秒为单位工作,需要除以 60。或者你可以提前在 Excel 或 Google Sheets 中完成。
我从 NOAA 获取了里根国家机场(DCA)从 2018 年 6 月 1 日到 2018 年 8 月 31 日的温度和降水数据。当数据可以下载时,NOAA 会给你发一封电子邮件。只需要一分钟。我删除了。csv 文件除了降水,最高温度,和日期使用 Excel。🌦
导入和设置数据
确保在添加天气数据之前将 Bikeshare 数据添加到 Tableau。这将在您稍后更改 Bikeshare 数据的主键时派上用场。
在 Tableau 中,执行一个 union 来快速垂直连接所有观察结果(也称为添加更多行)。

然后是添加天气数据的时候了。我们需要在自行车共享数据中加入天气数据。为了使这个连接工作,需要使用一个日期列作为键,即两个表中的共享列。
如果不进行修改,Bikeshare 开始日期列将无法工作,因为它是日期时间格式,而天气数据的日期字段是日期格式。Tableau 的数据解释器可能在这方面有所帮助,但每当我试图使用它时,它都会抛出一个错误。这个问题发生在文本文件中,包括。csv 文件。如果你先把你的数据存成一个. xls 文件,它可能会工作——我没有测试过。
对于这个分析,我们并不真正需要开始日期和结束日期列,所以我将结束日期列转换为日期数据类型。

实际上花了一些时间来弄清楚如何让 Tableau 保存一个新的数据库字段用于连接。诀窍在于,在你点击工作表之前,Tableau 不会保存数据类型的改变。然后,您可以返回到数据源选项卡并进行连接。

数据可视化和分析乐趣
我制作了一些可视化的工作表,探索数据的各个方面。然后我把其中几个组合成一个仪表盘和一个故事,你可以在这里看到。仪表板和故事可以嵌入到大多数网站中,但 Medium 不允许真正的嵌入 html 或 javascript 代码,所以您在下面看到的是一个截图。

同样,对于交互式版本,请点击这里。Tableau 的强大之处在于它的交互式图表,所以我鼓励你去看看这个网站。
最上面的两个图表是双轴图表。我不喜欢双轴图表,因为它们通常不像单轴图表那样直观。然而,它们可以很好地显示三个变量之间的关系。
分析
在某些情况下,高降雨量确实与低乘车率相一致。看起来下雨和低客流量之间有关系。🌧
分解一天中的时间来观察乘客量会很有趣。深夜或清晨的雨可能对乘客没有什么影响。我们将把这个分析留到以后。😃
有趣的是,温度对乘车人数没有明显的影响。
我很惊讶地发现,夏季的周四和周五的客流量比一周前几天要高得多。一周中每天的乘车次数条形图清楚地表明了这种关系。
有趣的是,成员们骑行的时间比临时的、不骑马的成员要短得多。这是有道理的,因为会员可能主要是通勤者,而非会员可能是悠闲地参观购物中心周围景点的游客。
在这三个月中,会员的旅行次数几乎是非会员的三倍。随着旅游季节的结束,这种差距是否会扩大,这将是一件有趣的事情。
Tableau Public 没有很多内置的统计工具,尽管它增加了更多。你可以拟合一条趋势线,了解是否有一些相关性。唯一有意义的(p < .05) correlation I found via linear regression was between date and temperature — it got hotter over the summer. ☀️ Not a shock there.
Conclusion
In this article we found some interesting insights about Bikeshare ridership in Washington DC by using Tableau and combining two publicly available datasets. Tableau makes data analysis fast; it took just a few hours to find, clean, and join the data, make the dashboard, and write this article.
There are lots of related analyses and projects it would be neat to explore, in addition to the ones mentioned above. It would be interesting to look at data since the program’s inception in 2010 to see how ridership has increased.
It would also be interesting to create a forecast for ridership using machine learning. Tableau Public doesn’t allow easy links to python code, but the Tableau Desktop, which recently jumped to $70 per user, does.
Finally, Bikeshare is about to unveil its first electronic bikes. It could be interesting to dig into that data in a few months to see how they are used.
Wrap
Thanks for reading. 👍 I hope you found this article helpful. If you did, please share it on your favorite social media channel. 😃
I encourage you to try out Tableau if you haven’t. Udemy’s Tableau 10 A-Z:数据科学实践 Tableau 培训! 对任何想尝试的人来说都是一个很好的廉价训练。
我帮助人们了解 Python、云计算、数据科学和其他技术主题。查看我的其他文章,如果你对这些感兴趣,请关注我。
用餐愉快!📊
使用气泡图探索人口普查收入数据集
数据科学最美妙的事情之一是数据探索和可视化。那就是当数据告诉我们一个故事的时候,我们只需要花一些时间,去探索,去认真倾听。
在探索数据集时,我们会查看数据中不同特征之间以及特征和目标之间的联系。这可以为我们提供许多见解,如我们应该如何制定问题、所需的预处理(缺失值、归一化)、我们应该使用哪种算法来构建模型、我们应该分割数据并为数据集的不同子集构建不同的模型等。
人口普查收入数据集
为了演示这一点,我选择了人口普查收入数据集,它有 14 个属性和 48,842 个实例。该数据集的目标是根据人口普查数据预测收入是否超过 5 万美元/年。
数据的特征是:“年龄”、“工作阶级”、“fnlwgt”、“教育”、“教育人数”、“婚姻状况”、“职业”、“关系”、“种族”、“性别”、“T5”、“资本收益”、“资本损失”、“每周小时数”、“本国”。
目标是收入水平:> 50K 或者≤50K。
下面是一个人口普查收入数据集的例子:

年龄(数值)和收入(类别)之间的联系
让我们来看看年龄与收入的散点图。
y _ 轴: > 50K → 1,≤50K。→0, x 轴:年龄
from matplotlib import pyplot as plt
plt.scatter(data.age, (data.target==’<=50K’))

Scatter plot — Income vs. age - x_axis: age, y_axis: income >50K → 1 , ≤50K. →0
这并没有告诉我们太多,对不对?所有的点都是一个接一个的。我们可以给每个关卡添加一些随机噪声来实现更多的散乱点。
plt.scatter(data.age, (data.target==’<=50K’)+0.5*np.random.rand(len(data)))

Scatter plot — Income vs. age —x_axis: age, y_axis: >50K → values above 1 , ≤50K. → values below 0.5
这样更好,但是仍然,当有很多点时,很难理解模式。
现在让我们试试 泡泡剧情 (泡泡剧情的完整文档和代码可在https://github.com/shirmeir/bubble_plot获得)。
通过以下方式安装软件包:
pip install bubble_plot
我们需要提供数据帧,x 轴和 y 轴。
from bubble_plot.bubble_plot import bubble_plotbubble_plot(data,’age’,’target’, normalization_by_all=False)

bubble plot — target vs. age — P(y/x)
现在我们可以看到一个实际的模式!
对于数字特征,如年龄,气泡图会创建桶。每个气泡的大小与每个桶中的点数成比例(在这种情况下,还与颜色成比例)。
我们可以看到收入最高的人群大多在 39–45 岁左右(这个水桶的中间是 42.5)。
将参数 normalization_by_all 设置为 False 定义了我们想要绘制 P(y/x),也就是说,在给定年龄(x)的情况下绘制收入(y)的分布。该图中的每一列都是给定年龄的收入值的独立(1D)直方图。
将参数 normalization_by_all 设置为 True 将绘制年龄(x)和收入(y)的联合分布 P(x,y),这实际上是一个带有气泡的 2D 直方图。
bubble_plot(data,’age’,’target’, normalization_by_all=True)

bubble plot - target vs. age — P(x,y)
现在我们得到了收入(y)和年龄(x)的联合分布,P(x,y)。从这里我们可以看到,我们数据中的大多数人都处于较年轻的年龄段(大约 20-30 岁),一小部分年轻人(大约 20 岁)群体拥有高收入,因为他们的泡沫非常小。在高收入人群中,最大的年龄组是 42 岁左右。
这是分类特征和数字特征的对比图。但是如果我们想要可视化两个数字特征之间的联系呢?
绘制两个数字特征之间的联系
让我们回顾一下每周工作时间与年龄的关系。
plt.scatter(data.age, data[‘hours-per-week’])

Scatter plot — working hours per week vs. age — x_axis: age, y_axis: working hours
同样,由于这个数据集有许多点,从散点图中你无法了解这两个变量之间的联系。
使用气泡图,我们可以得到更清晰的东西。
bubble_plot(data,’age’,’hours-per-week’, normalization_by_all=False)

Bubble plot — working hours per week vs. age — P(y|x): x_axis: age, y_axis: working hours, distribution of the working hours given the age group. The bubble are normalized by the x-axis (age) so in each column the bubble size sums up to 100%
我们可以看到,给定一个人的年龄在 20 岁左右,一个人最有可能每周工作 15-20 小时,而如果一个人在 35-45 岁之间,一个人更有可能工作 45-90 小时。)一周小时。
气泡图为两个数字特征(年龄和每周工作时间)创建了存储桶,并且在给定年龄的情况下,气泡大小与每周工作时间的计数频率成比例。
现在我们来看看联合分布。
bubble_plot(data,’age’,’hours-per-week’, normalization_by_all=True)

Bubble plot — working hours per week vs. age, P(x,y): x_axis: age, y_axis: working hours
现在,气泡的大小与每周小时数和年龄值的频率成正比。我们可以看到,这个数据集中的大多数人年龄在 20-30 岁之间,每周工作 30-45 小时。
用气泡图可视化三个维度——年龄、工作时间和收入
现在我们来看年龄,每周工作小时,结合收入水平。这怎么可能呢?我们能在二维图中显示三维信息吗?
bubble_plot(df, x=’age’, y=’hours-per-week’, z_boolean=’target’)

Bubble plot — working hours per week vs. age —P(x,y): x_axis: age, y_axis: working hours, color — proportional to the rate of high income people within each bucket
在这个泡泡图中,我们再次看到了每周小时数与年龄(p(x,y))的联合分布,但这里的颜色与这个桶中所有人的高收入人的比率——(#>50K/(#>50K)+(#≤50K))—成比例。通过提供 z_boolean 变量,我们使用气泡的颜色向绘图添加了额外的维度。
颜色越浅,给定布尔特征/目标 z 的比率越高。请参见图像中的色彩映射表。

Cool colormap — Pink would stand for the higher ratios in our case, cyan would stand for the lower ratios
这张图清楚地向我们表明,在每周工作超过 40 小时的 30 岁以上的人群中,高收入更为普遍。
工作阶级与年龄与收入

p(x,y): y-axis - workclass, x-axis - age. color is proportional to the rate of high incomes within each bucket.
这里,y 轴是工作阶层,x 轴是年龄,颜色与每个区间内的高收入比率成比例。
你可以看到,如果你是 30-60 岁之间的自营职业者,你收入超过 5 万英镑的可能性最大。联邦政府也有更高的税率获得收入超过 50K,但在 40-60 岁之间。州政府在 48-52 岁之间有较高的收入。
职业 vs 关系与收入

p(x,y): y-axis — occupation, x-axis — relationship. color is proportional to the rate of high incomes within each bucket.
专业、行政管理和技术支持的高收入人群比例最高。已婚人士似乎有更高的概率获得高收入。请注意,在经理层中,丈夫的高收入比率比妻子略高(更高)。
总结
虽然散点图和箱线图可以为我们提供数据分布和汇总统计的高级视图,但这有时是不够的,尤其是在数据有许多点并且变量之间的联系不是一个平凡函数的情况下。
使用气泡图来可视化我们的数据可以帮助我们清楚地看到数据集中特征之间的关系,即使是大型数据集,对于分类特征和数字特征也是如此,这可以帮助我们以更合适的方式对数据建模,并为连接和特征找到正确的函数。
安装气泡图:
pip install bubble_plot
在 python 上运行 bubble_plot:
import pandas as pd
from bubble_plot.bubble_plot import bubble_plot
from sklearn.datasets import load_boston
data = load_boston()
df = pd.DataFrame(columns=data['feature_names'], data=data['data'])
df['target'] = data['target']
bubble_plot(df, x='RM', y='target')
探索数据丛林
关于发现、驯服和研究解决实际问题所需数据的免费电子书

一些人认为数据来自简单、有组织的表格——数字和文本整齐地排列成小行,每个值用逗号隔开。还有一些人认为所有的数据值都是 100%正确的,因为它们源自一台从不出错的自主数据收集机器。有些人认为,每个数据库,开箱即用,可以存储任何东西,并使其在几分之一秒内容易检索。在一个完美的世界里,这些信念可能与真理一致,但在这个世界里,远非如此。
野外的数据杂乱无章。它并不总是在你想要的地方。它可能以一种奇怪的格式存在。它可能缺少值或值不正确。它可能是有偏差的,或者不能代表你想要研究的人群。可能有太多的东西需要管理。可能不存在。一个优秀的数据科学家对这样的问题并不陌生;他们是天生的。为了避免或解决这些问题以及类似的问题,熟悉数据的位置、格式和质量是很有帮助的。
这本书的三个章节分别展示了你在寻找数据时可能会发现的东西。第一章——摘自我自己的书 像数据科学家一样思考——将数据的世界描述为一片值得探索和细致调查的荒野。在这里,数据在现代世界中的作用已经发展到不能再被忽视的程度;因此,我们需要为可能找到我们想要的数据的许多方法和形式做好准备。第二章来自 Nina Zumel 和 John Mount 的 【实用数据科学与 R】—全面介绍了检查数据的多种方法。这种特定于 R 的观点的指示和建议可以推广到使用任何统计软件来全面理解您的数据,而不仅仅是 R。第三章-来自 Henrik Brink、Joseph W. Richards 和 Mark Fetherolf 的 真实世界的机器学习-为您准备真实世界的机器学习数据提供了一个深思熟虑的蓝图。如果不进行一点清理、组织和修饰,来自野外的数据通常不会被输入到一个高度智能但冷冰冰的确定性算法中。
数据并不总是容易获得的。它可能是混乱的、错误的或难以访问的。但是尽管如此,它仍然可以回答真正的商业问题,解决有意义的问题。这一系列章节向你展示了如何在野外处理数据以获得最大的洞察力和利益。
点击此链接下载曼宁的免费电子书。
让我知道你的想法!
Brian Godsey 博士是一名数学家、企业家、投资者和数据科学家,他的著作 像数据科学家一样思考 现在有印刷版和电子书。——briangodsey.com
如果你喜欢这个,请点击💚下面。
**[## 数据科学的过程被低估了
编码和统计很重要,但是选择先做什么和下一步做什么也很重要
medium.com](https://medium.com/towards-data-science/the-process-of-data-science-is-underrated-87ea58d5f70c)**
探索知识的新领域

人工智能
人工智能是让机器变得聪明的科学,但它们有多聪明,我们希望它们有多聪明?在这篇文章中,我邀请你深入研究制造智能机器的哲学,并帮助我探索我们对我们生活的世界的知识前沿,以及人工智能可能如何改变这种情况。
“人工智能系统将成为我们大脑的延伸,就像汽车是我们双腿的延伸一样,它们不会取代我们,它们将放大我们所做的一切,增强你的记忆,给你即时的知识,让我们专注于做正确的事情。” —脸书人工智能研究
我们对人工智能做了什么?
从语音识别系统、自主系统和自动驾驶汽车、自动机器翻译、计算机视觉和自然语言处理(照片中的对象检测和分类、图像字幕生成),许多领域都有许多涉及人工智能的创新,不胜枚举。以下是人工智能使用的一些常见用例列表。
- 营销个性化、广告(谷歌广告感知、赞助广告)和推荐引擎(网飞、亚马逊)
- 个人安全
- 医疗保健(在早期阶段检测疾病),如果你想了解该行业对这场斗争的重视程度,最近有一个关于提高肺癌检测的挑战,现在又有一个关于预测基因变异的影响以实现个性化医疗的挑战。
- 金融交易
- 欺诈检测
- 网上搜索
- 数据安全
- 太空、天文学和机器人学
- 天气预报
- 计算神经科学
人工智能的目标
你认为什么样的人工智能会给我们带来完整的体验?我们知道,我们需要人工智能做得更好的事情之一是当涉及到感知时,即看到和理解语言的能力,以便与我们周围的事物进行交互和描述。我们不能否认我们对卷积神经网络(CNN)、递归神经网络、生成对抗网络(GAN)和许多更复杂的算法的热爱和热情,这些算法在学术界和工业界都产生了最先进的结果,但即使如此,主要问题仍未解决。现在你可能会问我,人工智能的终极目标是什么?
答案:人工通用智能 ( AGI )
其他人也会认为人工智能的目标之一是奇点,技术奇点是一种假设,即人工智能超智能的发明将突然引发失控的技术增长,从而导致人类文明发生深不可测的变化。根据这一假设,一个可升级的智能代理(如运行基于软件的人工通用智能的计算机)将进入自我改进周期的“失控反应”,每一代新的更智能的一代出现得越来越快,导致智能爆炸,并产生一个强大的超级智能,从质量上讲,它将远远超过所有人类智能。
人工通用智能(AGI)
AGI 是一台智能机器,它能成功地完成人类能完成的任何智力任务。它是一些人工智能研究实验室的首要目标,也是科幻小说和未来研究中的常见话题。AGI 也被称为强人工智能或通用人工智能,你可以在 AGI 学会上找到更多信息,还有这个通用人工智能挑战赛。
我们有什么样的人工智能?
现在我们知道人工智能的目标,但我们还没有达到,但这里还缺少一些东西,那就是描述什么样的人工智能目前对我们可用?
人工狭义智能(狭义 AI)
狭义人工智能(Narrow AI),也称为 Week AI,是人类迄今为止实现的唯一人工智能形式。这是一种擅长执行单一任务的人工智能,例如下棋或下围棋,提出购买建议,销售预测和天气预报。计算机视觉、自然语言处理现阶段仍属于狭义 AI。语音和图像识别是狭义的人工智能,即使它们的进步看起来很迷人。甚至谷歌的翻译引擎和许多我们习惯看到甚至钦佩的人工智能,尽管它们很复杂,但它们是狭义人工智能的一种形式。
为什么是艾将军?
我认为 Google DeepMind 的两份使命声明确实有助于回答这个问题。
DeepMind 任务
- 求解智能
- 用它来解决其他一切
这里的前提是,如果人类曾经达到解决智能的地步,那么我们将利用它来解决其他一切问题,从而使世界变得更加美好。在这个关于万有理论的演讲中,戴密斯·哈萨比斯说:“为了找到万有理论,结果可能是我们必须解决智力”。这源于这样一种想法,即关于这个世界,我们仍然有许多事情不了解,人类不断面临着困难的问题(治愈疾病,星际探索……),并且有这样一种信念,即人工智能将帮助人类以不同的方式处理这些问题,并更快地解决它们,从那时起,我们将开始突破知识的前沿。在我忘记之前,AlphaGo 是科学的巨大突破,但还不是 AGI。
是什么让求解智能如此困难?
为什么一直没能解决一般情报?事实是,这个问题没有明确的答案,但让这句话帮助我们:
我无法建造的东西,我并不真正理解。—理查德·费曼
最近,深度学习的爆炸式发展带来了许多进步和新发现。深度学习表示一组基于深度人工神经网络的架构。现在另一个问题可能会出现在你的脑海中,什么是人工神经网络?人工神经网络是受人脑工作方式启发的算法。

Anatomy of neuron
我不会谈论太多细节,但现在你应该知道,在神经科学中,生物神经网络是一系列相互连接的神经元,它们的激活定义了一条可识别的线性路径。神经元与其邻居相互作用的界面通常由几个轴突终末组成,这些轴突终末通过突触连接到其他神经元上的树突。
许多人误解了这一点,人工神经网络不像我们的大脑那样工作,人工神经网络只是简单的原始比较,神经元之间的连接比通过人工神经网络架构实现的连接要复杂得多,记住,我们的大脑要复杂得多,我们需要从中学习更多。关于我们的大脑,有许多事情我们不知道,这也使得我们很难知道我们应该如何在人类层面上模拟一个人工大脑来进行推理。
如果有人说大脑是宇宙中最复杂的机器,他有充分的理由这样想。
最终注释
也许这里的标题应该是“最终问题”,这个帖子是为了陈述一些还没有最终答案的问题。很难说哪里会有突破,但我们仍然可以提出一些问题,思考解决真正人工智能的问题。
- 我们已经有解决智能问题的正确算法了吗?
- 我们是否受到当前可用硬件的限制?
- 我们还需要发明智能数学吗?
- 如果我们不知道我们的大脑是如何工作的,构建人工智能也将成为一项艰巨的任务,人类的大脑是我们了解学习如何发生、记忆如何储存的最佳工具?推理是怎么做的?我们应该如何模拟一个人造大脑
- 理解深度神经网络如何学习变得越来越难,许多其他人工智能被视为黑盒,因为我们不太明白它为什么或如何工作或做什么,如果它们中的一个达到了人类水平的智能,我们将如何知道?
我个人认为这个话题还有很多东西需要探索,不可能一篇文章或者一本书就能完全涵盖我在这里提出来讨论的主题。这是一个公开的讨论,我对人工智能和世界各地正在开发的改善人们生活的东西很感兴趣。显然,人工智能的未来仍是未知的,世界仍在探索这一强大技术的其他用途。
这是一个公开的讨论,我很想听听你对这个话题的看法,并找到可以一起探讨更多想法的人。欢迎回复本帖或 微博我 。
如果你喜欢这些作品,请留下你的掌声👏推荐这篇文章,让别人也能看到。
用最新的维基百科点击流探索人工智能、数据科学和机器学习的意义

数据科学、机器学习和人工智能等术语在科技流行语的“万神殿”中找到了一个当之无愧的位置。
我们几乎每天都听到和读到关于他们的报道。事实上,它们经常被互换使用,尽管根据来源的不同会有明显的偏好(你可能已经注意到市场营销和媒体对术语 AI 的某种偏好)。

上图是根据普华永道 改编的 ,这是互联网上众多试图解释术语之间关系的维恩图中的一个,但并不十分直观。
我们可以使用数据和分析方法来捕捉这些术语的含义和语义上下文吗?好吧,让我们试一试,试着以毒攻毒。维基百科点击流数据集对此会有很大帮助。
维基百科点击流
维基媒体基金会最近决定对几种主要语言的每月点击流进行开源。一个典型的英语点击流包含数百万个不同的维基百科网址,被互联网用户请求数十亿次。
拥有如此全面的资源是一个好消息。它可以对全球最繁忙的网站之一的在线用户行为进行多种复杂类型的分析。事实上,有几篇发表的学术论文从不同的科学角度研究了点击流数据集,尤其是行为角度。
这将是一种使用网络分析的实用方法。不仅是为了回答上面的问题,也是为了激励点击流和网络分析在其他应用和领域的使用。关键词研究、内容开发、网络流量可视化浮现在脑海中,我相信还有很多其他的。
数据集
我们将使用 2018 年 3 月的最新可用数据集,其中包含 2330 万对英文引用和目标 URL,占维基百科服务器总页面请求数的 62 亿。
该数据集使得基于用户从一个维基百科页面导航到另一个页面的方式来可视化不同术语之间的关系成为可能,要么通过跟随链接,要么使用内置的搜索功能——有时会成为维基百科兔子洞的受害者。
节点、边和邻域
数据集实际上是一个巨大的节点网络(维基百科文章),这些节点根据用户会话期间请求的页面顺序通过边连接到其他节点(相关文章)。
边的大小可以被认为是反映两个节点之间流量的权重因子。使用网络分析的一个好处是其输出可以制成图表。这让我们可以看到所有这些点击和页面转换可能意味着什么的整体视图。
注意:下面的图表已经过配置,可以在移动设备上正常查看。然而,它们最好在大屏幕上观看。
接下来,我们将研究以下术语的点击流图:
- 数据挖掘和数据科学
- 机器学习
- 人工智能和人工通用智能。
数据挖掘热身
作为热身,为了解释分析方法,我们将从数据挖掘开始,这是一个过去经常使用的术语。

这个初始图隔离了网络中涉及“数据挖掘”的部分及其相邻节点(文章)。两个节点之间的边是它们之间的流量,节点的颜色和大小反映了它们所连接的邻居的数量。这在某种程度上已经是有用的了。为了更好地理解相关术语,作为第二步,节点被分组到相关类别中,以便更清楚地看到更广泛的关系。

这种做法的缺点(除了我个人对使用标签的偏见之外)是图表可能会有过多的文本和颜色。此外,在某些情况下,例如人工智能,很难将组的数量控制在可管理的水平。在人工智能的情况下,节点不够同质,无法创建有意义的类别。在这两种情况下,节点都是故意不分组放置的。还要注意的是,为了使图形更加清晰,一些节点是不可见的——要么是因为它们的通信量低,要么是因为它们的邻居数量非常少。
数据科学
首先要注意的一点是,维基百科中关于数据科学的条目相对有限。在这篇文章中,它是所有其他术语中超链接数量最少的。然而,内容一直在大幅增长。自 2017 年 11 月第一个数据集发布以来,页面上的链接几乎翻了一番。

- 在观察了图表之后,我们可以说,从维基百科的角度来看,数据科学围绕着机器学习(主要)和统计学(其次)以及一点计算机科学(当考虑到节点的长尾时,这变得更加明显)。
- 实际上,我认为大多数人都会同意数据科学比这更广泛。随着文章内容的不断增长,希望很快会有更多的证据。
- 对于机器学习是否应该被视为数据科学的重要组成部分这一常见问题,从维基百科点击流的角度来看,答案显然是肯定的。
(关于数据科学的有趣事实:与它相关的一个页面实际上是维基百科关于流行语的文章,尽管它的顶点度数不足以让它进入图表)。
数据科学—数据挖掘比较
关于数据挖掘的文章更加全面,因为它已经存在了很长时间。
也就是说,在相关术语的类型之间仍然有相当多的相似性。数据科学图表中的大多数术语也出现在数据挖掘图表中。这可能会给那些认为数据科学是 90 年代和 21 世纪初使用的数据挖掘的更名版本的人提供一些依据。
然而,就目前而言,数据科学缺乏与业务相关术语的强关联,如商业智能、分析,可能还有数据挖掘的 OLAP 等术语,但随着数据科学文章的发展,这些和其他关联可能会出现。
机器学习
机器学习似乎是最直接的例子。它在很大程度上与涉及知识发现或预测的不同科学方法的术语有关(被称为机器或统计学习方法)。

- 我们看到以下两种类型的许多节点:经典方法,如统计分类和逻辑回归,以及其他更现代的方法,如支持向量机、随机森林和人工神经网络。
- 机器学习的概念主要与方法、模型和技术相关联。许多人——但不是所有人——的目标是在给定一组观察结果的情况下预测结果。事实上,ML 相关节点的列表可以很容易地转换成一本关于 ML 的书的目录。
- 深度学习或强化学习等几种“x”学习类型的出现也令人印象深刻。这不再仅仅是有监督和无监督的学习。这一发现表明,ML 本身可能正在演变成一个总括术语,以容纳越来越多的学习型家庭。
- 机器学习“需要”统计数据吗?就像之前维基百科的答案是肯定的,因为在许多与最大似然相关的方法中存在统计或统计学习。
人工智能
这是迄今为止最广泛、最多样的术语,但也是最难转换成图表的术语。AI 本身与超过 450 个节点相关联,我不得不为邻居的数量设置一个高阈值,这样图形就不会看起来像一个巨大的毛球。节点的多样性仍然很难定义有意义的类别。

- 许多节点具有非常一般的性质:科学(心理学、哲学)或科学领域(逻辑学、博弈论等)的名称,这是多学科人工智能的证据。
- 大多数相关节点本质上是对人工智能某些特定方面的引用,例如人工智能的应用、人工智能术语表、时间轴、历史等。这是我们在之前的术语中没有观察到的。
- 同样,在这里我们第一次看到了一家公司的存在:Deep Mind,这可能是该组织在将人工智能应用到现实世界中所发挥的作用的结果。
- 最后,有两个关于艾伦图灵的节点,他自己的页面和同名测试的页面。令人印象深刻的是,可以追溯到 1950 年的图灵测试经受住了时间的考验,并且仍然与今天的人工智能环境相关。
人工通用智能
为了跟上时代精神,最后一张点击流网络图是为人工智能设计的。

图中的节点不够均匀,无法创建多个有意义的群集。然而,在带有“头脑上传”和“智能爆炸”等名称的节点之间,我们可以看到编辑和用户似乎感兴趣的两个主题。
让我们称第一个集群为“邪恶的人工智能”,包括如下页面
- 来自人工一般智能的存在风险
- 人工智能接管
- 全球灾难风险
让我们以“AI for good”集群结束,它包括:
- 友好的人工智能
- 人工智能和哲学
- 人工智能伦理
聚类本身不能明显地定义人工一般智能,但是它们指示了与它们相关联的流行内容。
人工神经网络的普遍性
我们研究了这 5 个术语,人工神经网络(ANN)是所有 5 个术语中唯一存在且突出的相关术语。
很难接受这是一个巧合。人工神经网络结合现代计算技术的进步与人工智能领域的最新进展密切相关。在某种程度上,他们帮助人工智能在经历了多年的“人工智能寒冬”后重新崛起。
目前最先进的深度学习模型是基于人工神经网络的。Tensorflow 是 Deep Mind 最著名的开源项目,在 Github 交互和 Stackoverflow 流量方面,它是最受欢迎的人工神经网络应用程序库之一。从各方面考虑,人工神经网络似乎很可能会继续存在,我们将会听到越来越多关于它们的消息(我的预测)。
密码
使用 R 语言生成图形的代码可在github repo中找到,其中一些参数和过滤器选项(如边数过滤器、阶数、阶数)可用。
您可以使用简单的开始脚本,快速试验您选择的其他概念是如何相互关联的。
动机
这篇文章是由一些内容组合而成的,这些内容是我最近接触到的,我强烈推荐这些内容。
- 米哈伊尔·波波夫关于创建网络中立图的博客文章
- 米克·库尼在都柏林数据科学会议小组的网络分析培训材料
- 大卫·罗宾逊的 blogpost 和 WinVector 的文章从实用的角度解释了 AI、ML、数据科学(和公司)的区别
我还想强调像 ggplot 和gg graph这样的开源库在处理网络数据可视化时是多么有用。
最终意见
当你现在正在判断你刚刚阅读的内容,并且可能已经有了一些异议,请记住:我们的目标不是定义任何术语,而是通过维基百科编辑和用户行为的角度来看待它们。在我看来,这有点像在玩拼图游戏。
当然,文章反映了作者的偏见,这是一种固有的偏见。然而,积极的一面是,在维基百科的情况下,由于维基的编辑模式和控制过程,我们可以依靠群众的智慧来减轻任何强烈的偏见或极端/错误的观点。举个例子,维基百科关于人工智能的文章有数以千计的编辑和观察者。
总之,对维基百科点击流进行网络分析的一个重要好处是,它可以揭示世界上最大的百科全书的用户和贡献者都认为重要的内容。基于他们书写和点击的方式。
你怎么看,维基百科点击流还有其他值得探索的术语吗?你认为这个数据集还有其他有趣的用途吗?数据科学从业者:有没有一种方法可以使用例如 NLP 来自动对图中的节点进行分组?
亚历克斯·帕帕乔治
关于我
我是营销分析和数据科学方面的独立顾问,帮助转化驱动的数字企业做出明智的营销决策。我在我的 博客 和 上,通过 Twitter 和LinkedIn分享我关于数字、营销和数据分析的故事。
探索 2018 年的 SAR 工具前景
使用 SAR 数据处理应用程序时,有许多工具可供选择。其中大部分是已经存在多年的商业或开源软件。功能范围从基本的 SAR 处理和可视化,到干涉测量和时间序列分析。如今,支持普通开发人员处理 SAR 数据的全功能云原生平台的选项越来越少。
题目
我想了解有哪些商业和开放工具可用于从 SAR 数据中获取信息。我非常熟悉光学影像工具的前景,并且知道因为它们主要只是地理空间栅格处理的引擎,所以它们中的大多数在某种程度上用于基本的 SAR 数据处理。然而,我想专门探索那些构建时考虑了 SAR 功能并具有独特或明确的 SAR 特性的工具。我把这些工具分为四类:商业云平台、开源平台、商业软件、开放软件。我没有使用过所有这些工具,但是我尝试给出一个从我能找到的信息中提炼出来的简要描述。我有意不讨论数据发现工具。这里的目的不是要全面,而是要给人一种对地形的感觉。
商业云平台
如今,相对而言,很少有云原生的SAR 工具作为服务提供给应用程序开发人员和科学家。总的来说,云原生地理空间平台才出现了几年,所以我想这并不奇怪。我没有遇到任何平台提供内置功能,比如多视角或干涉处理。随着更多合成孔径雷达数据的出现,我预计在未来几年内,这一领域的能力和选择的数量都会增加。
谷歌地球引擎 是一个平台,它使任何科学家或开发人员都可以相对容易地进行大规模的 SAR 数据处理。如果你能用 javascript 编写一些代码,你就可以使用他们的代码编辑器和可视化工具来进行大规模的 SAR 数据处理。到目前为止,我看到的所有 SAR 用例都围绕着 Sentinel-1 数据,但是有一个强大的用户社区开发脚本来支持 SAR 处理。最棒的是,这些工具可以免费用于非商业目的(目前)。如果你正在处理自己的数据,并把它存储回谷歌云中,你可能需要支付一点存储费用。对于使用 Sentinel-1 数据的学者和非政府组织来说,这是一个很好的选择,但对于支持企业的平台来说,这不是一个很好的选择。
GBDX是 DigitalGlobe 云原生平台,用于处理他们的卫星图像。随着 MDA 和 DigitalGlobe 的合并,他们已经开始引入一些工具来处理 Radarsat-2 数据,就像这个 SAR 振幅变化检测工作流程。由于 GBDX 平台的核心似乎只是一个将“任务”链接到“工作流”的大型容器编排系统,开发人员可以使用任何库来构建自己的 Radarsat-2 数据处理工作流。GBDX 还在他们的平台上提供了来自 Harris ENVI 的一些算法。对于试图构建使用 Radarsat-2 数据的工作流的软件工程师来说,这将是一个很好的云原生选项。

A SAR Amplitude Change Detection Result from the GBDX Platform. Borrowed from their public docs.
笛卡尔实验室 将他们的平台标榜为“数据精炼厂,为了解这个星球而建”。它在概念上类似于 GBDX,但是可能更加数据不可知。用户可以通过目录 API 添加自己的数据。用户利用几个预定义环境中的之一,用 python 代码编写一个“任务”。这些环境包含用于地理空间数据、数据科学和机器学习的典型 python 库。似乎没有任何独特的更高级别的工具可以更容易地处理 SAR 数据,尽管他们已经用他们的平台建立了一个 Sentinel-1 数据的全球复合图。对于试图构建 SAR 工作流的公司来说,这将是一个很好的云原生选择,但是工程团队仍然需要 SAR 专家。
Planetwatchers 预见 最近宣布成为地理空间分析平台,最初专注于利用 SAR 和光学数据解决林业、农业和能源使用案例。他们的平台上没有多少公开信息。
开源平台
包含 SAR 相关特性的开源平台选项似乎相对有限。我似乎找不到任何好的例子。目前有几个值得注意的处理栅格数据的开源平台选项,如 RasterFoundry 和 Geotrellis (由 Azavea 开发)和 Cumulus (由开发种子开发)。虽然它们都没有特定的 SAR 焦点,但它们都可以用作执行一些常规数据管理和大规模栅格数据处理(通常为无服务器)的起点。例如, Radiant Earth 正在使用 RasterFoundry 作为他们开放数据平台的基础(尽管还没有 SAR)。

Raster Foundry Lab for examining wildfire damage with optical imagery. Borrowed from their blog post.
开源软件
对于各种类型的 SAR 数据处理,似乎有太多好的开源软件包。与平台选项一样,有许多有用的项目不一定是特定于 SAR 的,比如 GDAL ,但是我将坚持探索那些具有 SAR 焦点的项目。这只是我经常看到提到的一些例子。我将留给读者去更深入地探究这个来自 RadarCODE 或poke about github的两年前的列表。
SNAP , Sentinel-1 工具箱 ,PolSARPro都是在欧洲航天局(ESA)的资金支持下开发的软件包。PolSARPro 是一个较老的偏振处理和教育工具。积极开发似乎在 2013 年停止了。SNAP 是一个通用的架构和接口,用于处理来自所有 Sentinel 任务的数据以及来自一些 Copernicus 贡献任务的数据。Sentinel-1 工具箱是所有欧空局搜救任务和一些第三方数据提供商(如 COSMO-SkyMed)的处理工具、数据产品读取器和写入器的集合。Sentinel-1 工具箱包含了从它所支持的任务中获取信息产品所需的任何功能。你可以通过 SNAP GUI,或者使用 SNAP python 接口来实现。****

Working with some Sentinel-1 data in the SNAP interface.
RAT 和 是通用的 SAR 后处理工具。RAT 项目在柏林技术大学启动,现在已经退役。它以 PyRAT 的形式存在,PyRAT 是一个用于 SAR 处理的 GUI、CLI 和 python 框架。这似乎是一个面向专家的选项…这里没有训练轮。
InSAR ISCEGM tsarDoris都是干涉 SAR 处理工作流程的成熟工具。它们在许多期刊文章中被很好地记录和引用。对于科学家和学者来说,这些都是很好的工具。任何打算将该软件用于商业目的的人都应该仔细阅读许可证。虽然 GMTSAR 是 GPL,但其他两个似乎有更复杂的许可条件。****
迪诺萨尔 是一个有趣的项目,旨在云中按需处理干涉图(目前是 AWS,ISCE 在引擎盖下)。我希望在未来看到更多像这样的更高级别的项目,因为它们将使没有深厚遥感或信号处理背景的开发人员仍然能够进行有趣的地理空间分析。
六 是一个跨平台的 C++ API(带有一些 python 绑定),用于读写 NGA 的复相历史(CPHD)、复相(SICD)、派生(SIDD)传感器无关雷达格式。该项目的目的是为开发人员提供一种简单的方法来确保他们的文件和元数据符合 NGA 标准,并为多源数据提供一种通用格式。
商业软件
通常的嫌疑人都有内置或附加的 SAR 数据处理能力。这些工具中的大多数已经存在了许多年(> 20 年),并且已经迭代了许多版本。它们主要是桌面工具,尽管一些供应商已经开发了跨多台机器编排更大规模工作流的引擎(例如 PCI GXL )。性能、许可模式和成本各不相同,但不同软件包的功能似乎相似:正射校正、协同配准、斑点滤波、InSAR、相干变化检测等。
哈里斯 ENVI&sar scape是用于多源图像分析的桌面和服务器软件。基本的 ENVI 包允许一个分析师在桌面上做数据处理,或者一个开发者从服务器配置中使用 ENVI API 建立一个工作流。与 ESRI T21 的软件生态系统也有相对深度的整合。SARScape 是一个附加模块,有三个模块,允许您进行基本的 SAR 处理、干涉测量和干涉测量叠加。
PCI Geomatica &雷达套件 似乎在功能上与 ENVI 相似。Geomatica 有一个桌面版本和一个面向开发人员的版本,提供对 python API 的访问。雷达套件提供了用于基本 SAR 分析、干涉测量、正射校正和 DEM 生成的工具。

SAR Change Detection using PCI.
BAE SOCET GXP是另一个多源遥感软件包,功能与上述类似。根据用户需求,GXP 还提供各种许可捆绑包选项。
ERDAS IMAGINE是商业套装的另一个好选择。这里没有惊喜。****
GAMMA 是一个专注于 SAR 的软件包,由瑞士的一家小型软件提供商提供,支持从原始数据到衍生产品的整个处理链。GAMMA 在他们自己的咨询活动中使用该软件,并提供商业许可。********
MATLAB对于那些希望其信号处理链具有近乎无限灵活性的人来说,是一款强大的工具。如果你仔细观察,会发现有一些库可以使摄取和处理 SAR 数据集变得更容易,比如 NGA 的 MATLAB SAR 工具箱。****
包扎
商业和开放软件选项比比皆是,但具有更高级工作流的平台选项对于 SAR 来说仍然有点有限。如果普通开发人员对在他们的应用程序中从 SAR 数据中获取信息感兴趣,他们仍然有一个陡峭的学习曲线和许多行代码要写。随着可用 SAR 数据量的增加,是否会有更多的平台选项和功能变得可用,这将是一件有趣的事情。
我错过了什么有趣的软件包或项目吗?请在评论中告诉我。
用动态话题模型探索联合国一般性辩论

Credit: Vladislav Klapin on Unsplash
在本文中,我介绍了动态主题模型背后的直觉,并通过对演讲语料库的应用,展示了这种方法在非结构化文本中发现不断发展的叙事的能力。
通过阅读,我希望你能了解动态主题模型,它们试图解决的问题,使用文本数据完成项目的实用技巧,以及对现代世界事务的一些见解!如果你想跟随代码,你可以在这里找到。
每年秋天,世界各国领导人聚集在纽约,参加联合国大会的一般性辩论。在围绕核武器和叙利亚战争等问题进行讨论后,今年的会议于本月早些时候结束。
一般性辩论中的发言形成了国际社会关注的问题的历史记录。隐藏在这些文本数据中的是关于对话如何随时间变化的见解,而动态主题模型可以帮助我们定量地模拟这种演变。
动态主题模型
主题建模是一个通用术语,用于描述在非结构化文本语料库中查找主题的过程。一种流行的方法是潜在狄利克雷分配(LDA ),这是一种学习预定义数量的潜在主题的生成模型,其中每个主题被表示为词的分布,每个文档被表示为主题的分布。下面的文章很好地解释了这个想法,并且维基百科页面也是一个很好的参考。
在我们开始之前,我做了一个工具(这是源代码),可以在你的浏览器中运行 LDA(非常简洁)。是…
medium.com](https://medium.com/@lettier/how-does-lda-work-ill-explain-using-emoji-108abf40fa7d)
LDA 由于其高度可解释的主题而对于大语料库的定性分析是一种非常强大的技术,并且由于其将稀疏的文档术语矩阵转换成固定的低维文档主题矩阵而对于维数减少也是有用的。然而,LDA 忽略了存在于许多文档集合中的时间方面。
考虑一下 LDA 在过去十年的新闻语料库中发现的一个关于美国政治的话题。你可能认为最有可能的术语是“国会”、“选举”、“投票”等等。然而,该模型在术语概率方面将 2010 年的文件与 2018 年的文件视为相同,因此它无法了解到,例如,“特朗普”一词直到最近才在政治背景下几乎不存在。
Blei 和 Lafferty 在这里提出的动态主题模型(DTM)通过扩展 LDA 的思想来解决这个问题,以允许主题表示在固定的时间间隔(如几年)内发展。具体地,每个时间片内的文档用相同维度的主题模型建模,时间片t内的每个主题由时间片t-1内的相应主题演化而来。
LDA 的生成过程大体上保持相同,除了关键的差异,即整体主题分布和每个主题的术语分布根据时间片而不同。特别地,这些分布的参数在每个时间片上“发展”,这是通过从以前一个时间片的相应值为中心的分布中提取的。
这样做的最终结果是一系列类似 LDA 的主题模型,它们按顺序连接在一起。因此,DTM 学习的主题是一系列相关的术语分布。带着这种直觉,我现在转向它的应用。
一般性辩论数据集
由 1970 年至 2015 年一般性辩论中的发言组成的语料库由托管在 Kaggle 上(总共 7507 篇)。该数据集最初是由英国和爱尔兰的研究人员在去年发布的(见本文见),他们用它来研究不同国家在不同政策维度上的立场。
每篇演讲都标有发表的年份和会议,以及演讲者代表的国家的 ISO Alpha-3 代码。

Sample rows from the dataset
数据预处理
在这个数据集中的一个关键观察是,这些演讲中的每一个都包含了对大量话题的讨论。如果每个演讲都包含关于贫困和恐怖主义的讨论,那么在整个演讲上训练的主题模型将无法理解像“贫困”和“恐怖主义”这样的术语应该代表不同的主题。
为了解决这个问题,我将每个演讲分成段落,并将每个段落作为一个单独的文档进行分析。一个简单的基于规则的方法,寻找由换行符分隔的句子,在这个数据集的段落标记化任务中表现得相当好。在这一步之后,文件的数量从 7,507(完整的发言)增加到 283,593(段落)。
在将每个语音扩展成多个文档后,我进行单词标记化,通过小写和词条化来规范化每个术语,并从词汇表中删除低频术语。最终结果是 7,054 个术语的词汇表和每个文档的单词包表示,可以用作 DTM 的输入。
Word, sentence, and paragraph tokenizers for the General Debate corpus

Sample rows after paragraph tokenization

Sample rows after word tokenization of paragraphs
推理
为了确定要使用的主题数量,我使用不同数量的主题(10、15、20、30)在几个不同的时间片上分别运行了 LDA,以便对问题有所了解。通过手工检查,15 似乎产生了最可解释的主题,所以这就是我为 DTM 选定的。更多的实验和严格的定量评估肯定可以改善这一点。
使用[gensim](https://radimrehurek.com/gensim/models/wrappers/dtmmodel.html) 的 Python 包装器到的原始 DTM C++代码,推断 DTM 的参数是简单明了的,尽管很慢。在 Google 云平台上的 n1-standard-2 (2 个 vCPUs,7.5 GB 内存)实例上,推理耗时约 8 小时。然而,我是在单核上运行的,所以如果您能够编译原始 C++的并行版本,这个时间可能会缩短。
结果
该模型发现了非常容易解释的主题,我在这里深入分析了其中的几个。具体来说,我为几个主题展示了时间片样本中的顶级术语,以及随着时间推移显著术语的概率图。该模型发现的主题及其热门术语的完整列表可以在本文末尾的附录中找到。
人权
《联合国宪章》序言指出:
我联合国人民决心……重申基本人权、人格尊严与价值、男女平等权利和大小国家平等权利的信念。
因此,毫不奇怪,人权是一般性辩论中的一个永恒主题,也是该模型能够发现的一个主题。尽管上文引用的《宪章》中出现了两性平等的概念,但模型显示,“妇女”和“性别”这两个术语真正流行起来还需要相当长的时间。此外,请注意“humane”的使用在增加,而“mankind”的使用在减少。


Topic 3 (Human Rights): Top ten terms by probability at sampled time slices (left) and selected term probabilities over time (right)
以色列
自 1948 年现代以色列成立以来,围绕阿拉伯-以色列冲突、边界、定居点和巴勒斯坦人民的待遇,一直存在着争论,而联合国一直密切参与其中。事实上,维基百科上有整整一个页面专门讨论这个问题。
该模型显示,在 2007 年以色列和埃及封锁加沙之后,人们越来越关注加沙,并不断围绕以色列定居点展开讨论,根据国际法,联合国认为这种做法是非法的。“两个”一词的出现很有趣,可能来自于围绕“两国解决方案”的讨论。


Topic 5 (Israel): Top ten terms by probability at sampled time slices (left) and selected term probabilities over time (right)
非洲
关于非洲的讨论已经从过去的殖民地发展到独立、种族隔离时代,最后是新政府的诞生、选举和民主。


Topic 8 (Africa): Top ten terms by probability at sampled time slices (left) and selected term probabilities over time (right)
核武器
冷战时代带来了美国和苏联之间的军备竞赛,以及随后关于裁军的讨论。最近,焦点集中在伊朗。


Topic 2 (Nuclear Weapons): Top ten terms by probability at sampled time slices (left) and selected term probabilities over time (right)
发展
千年发展目标和可持续发展目标是联合国分别于 2000 年和 2015 年推出的倡议,旨在解决贫困、教育和性别平等等问题。这个话题似乎已经从围绕国际发展的一般性讨论发展到这些结构化的项目。


Topic 4 (Development): Top ten terms by probability at sampled time slices (left) and selected term probabilities over time (right)
结论
这个练习演示了 DTM 是如何表示主题的,以及这种方法在非结构化文本中发现叙事的惊人能力。请记住,该模型在没有任何人类智能的情况下完成了上述所有工作!
我有可能通过试验更大的词汇量、不同数量的主题及其评估、短语提取(例如,“human_rights”可以是一个标记,而不是分别具有“human”和“rights”),以及不同的词干分析器或词尾分析器来改进所使用的方法。其他超出单词表示范围并使用单词嵌入的方法也值得探索。
这里没有利用 DTM 的一个方面(但是我想进一步探讨的一个方面)是学习文档的向量表示。这不仅有助于计算文档之间的相似性值,也有助于找到每个主题的代表性文档。例如,获取美国代表的所有发言,为每个时间段挑选出最具代表性的段落,比如说人权主题,并使用这些段落来构建美国人权话语演变的线索,这将是很有趣的。
总的来说,这是一个令人着迷的练习。如果您想亲自试验或更深入地了解实现细节,可以在 repo 这里的中再次找到该分析的所有代码。感谢您的关注,如果您有其他想法或问题,请留下您的评论!
附录
以下是 DTM 发现的主题的完整列表。对于每个主题,显示了 1975 年、1995 年和 2015 年时间片的前十个术语。
Topic 0
1975 1995 2015
0 security council council
1 non security security
2 state member member
3 council state reform
4 cyprus general united
5 international reform nation
6 principle nation permanent
7 nation united state
8 aligned international must
9 charter must international
Topic 1
1975 1995 2015
0 sea international state
1 law state island
2 state island small
3 latin drug international
4 america country country
5 resource small sids
6 american america crime
7 country caribbean caribbean
8 conference convention developing
9 international crime pacific
Topic 2
1975 1995 2015
0 nuclear nuclear weapon
1 disarmament weapon nuclear
2 weapon treaty iran
3 arm disarmament treaty
4 state proliferation arm
5 soviet non agreement
6 treaty arm international
7 power state use
8 union test non
9 race international chemical
Topic 3
1975 1995 2015
0 right right right
1 human human human
2 people respect law
3 international democracy woman
4 freedom people people
5 principle international respect
6 justice law freedom
7 political freedom rule
8 respect principle international
9 must society peace
Topic 4
1975 1995 2015
0 economic economic economic
1 international development country
2 world international world
3 country world global
4 new new international
5 order social social
6 development political development
7 relation country political
8 political global crisis
9 co cooperation new
Topic 5
1975 1995 2015
0 east peace state
1 middle east peace
2 arab middle solution
3 israel resolution palestinian
4 peace people conflict
5 palestinian palestinian international
6 people israel syria
7 right process people
8 territory region east
9 palestine agreement israel
Topic 6
1975 1995 2015
0 republic united united
1 people nation nation
2 united peace international
3 state operation peace
4 nation keeping conflict
5 government republic role
6 korea conflict peacekeeping
7 peaceful bosnia mission
8 viet organization support
9 country herzegovina republic
Topic 7
1975 1995 2015
0 operation cooperation region
1 co region cooperation
2 peace regional international
3 country european country
4 europe country security
5 security europe regional
6 relation union european
7 european state terrorism
8 region security union
9 detente stability effort
Topic 8
1975 1995 2015
0 africa africa african
1 south african country
2 african country people
3 people government government
4 regime peace republic
5 southern community africa
6 namibia people political
7 apartheid democratic community
8 independence process democratic
9 racist effort peace
Topic 9
1975 1995 2015
0 world war climate
1 u world change
2 one conflict world
3 war cold global
4 problem many threat
5 time u challenge
6 situation peace must
7 peace one country
8 power problem crisis
9 conflict must conflict
Topic 10
1975 1995 2015
0 people people people
1 struggle country war
2 country refugee year
3 independence year world
4 national state country
5 force force one
6 liberation war terrorist
7 state government today
8 imperialist one state
9 imperialism life many
Topic 11
1975 1995 2015
0 nation nation nation
1 united united united
2 organization organization world
3 world world u
4 peace must must
5 member international challenge
6 international u future
7 charter role peace
8 role peace year
9 state new global
Topic 12
1975 1995 2015
0 country country development
1 developing development country
2 development economic goal
3 economic developing sustainable
4 world trade per
5 developed resource agenda
6 resource economy cent
7 trade financial poverty
8 price programme health
9 assistance assistance education
Topic 13
1975 1995 2015
0 mr general general
1 general session assembly
2 president assembly session
3 assembly mr president
4 session president mr
5 delegation secretary like
6 also also would
7 like like secretary
8 wish election also
9 election wish sixty
Topic 14
1975 1995 2015
0 session conference development
1 assembly development 2015
2 general general 70
3 conference year agenda
4 resolution agenda year
5 year assembly sustainable
6 special meeting conference
7 government summit pv
8 united held 15
9 meeting last post
通过可视化计算暴露错误的想法

Struck by Data (Jasper McChesney)
我们经常使用可视化来呈现数据。但是我们对数据 做的***的可视化呢?我指的是聚合、算法和流程。*****
通常这些计算非常简单。但是人们总是把简单的事情弄错——尤其是数学方面的事情。可视化可以帮助显示正在发生的事情,以及为什么一种方法可能行不通。你知道,同事的方法。
目标和“解决方案”
我在和某人一起写一份报告。我们需要向非技术观众解释如何根据行业趋势做出基本的预算预测。这些“趋势”实际上是逐年的百分比增长;以及在此期间的总体增长。它可能看起来像这样:

假设明年的增长将与过去几年的变化相似。但是我们不能规定任何花哨的建模:我们正在帮助人们用 Excel 或台式计算器进行粗略的猜测。
我的同事给人们提供了两种选择
- 取历史增长(%)的算术平均值。
- 求总体涨幅(%),除以年数。
我不确定这些是否有意义。但是说服我的同事?没那么容易。什么有帮助?会议议程背面潦草的图表。
每张图都是一组示例数据,加上您要进行投影的操作。每一个都说明了为什么上面的方法有问题。
错误
在数学层面上,这里的问题是根本性的:我的同事想要处理百分比增长,即比率,就像他会处理美元增长一样,美元增长只是值。
但是比率不是价值——事实上,它们将两个价值联系在一起。他们与自己互动的方式也不同。通常它们是通过乘法而不是加法结合在一起的;他们复合。所以把每年的利率加在一起得到最终利率在概念上是没有意义的。
(你可以用量纲分析来证实这一点。我们在这里的增长是无量纲的比例。所以把一堆加在一起,然后除以年,就产生了 1/年的单位。这对预算有什么用呢?)
但是这个论证依赖于数学。也许我是一个坚持理论严谨的混蛋,当我们只需要一些有用的东西。好吧,让我们看看是不是这样。
选项 2 拆卸(恒定百分比变化)
选项#2 是额外的攻击,值得首先反驳。但是为什么一开始会有人想这么做呢?
如果我们处理的是简单的数量,比如预算金额的变化(T1),选项 2(T2)就可以了(T3):你可以将总的变化除以年数,得到一种年平均值。它之所以有效,是因为它在数学上 等同于 选项 1,即每年数值的平均值。
这是我们的第一个例子,对两个选项都进行了计算:

处理简单数值时,变化总和与总体变化相同。这就是为什么选项 2 很诱人。**
百分比变化打破了这一点
现在,让我们看看当我们尝试这些相同的计算时,百分比会发生什么变化(正如我的同事提议的那样):

在这个整洁的例子中,每个百分比变化都是相同的,这使得我们的“预测”非常容易:我们允许的任何解决方案都应该肯定产生 50%。然而,选项 2 没有。它不仅在数学上没有意义,也不能产生合理的结果。我不仅仅是个混蛋!
选项 1 下降(振荡变化)
看到这个例子后,您可能会认为选项 1 是可行的。在这个简单的例子中,它确实是这样的,不断地变化。但那不是真正的测试。我们需要一个稍微现实一点的例子:年复一年的变化。

认识到一种模式,我们人类当然期待明年有+20 的变化。但是我们粗略估计的目标是简单地使用前几年的主要趋势;而不是去寻找不同的模式或体重年份。这些变化的中心趋势显然是相互平衡;以产生零净变化。
事实上,当使用原始的数字变化时,我们的两个选项都计算零平均变化。
百分比再次打破了事物
但我们任务的另一个假设是,任何真正的趋势都将是百分比变化的趋势,而不是原始值(正如我们在上面看到的,这些显然是不一样的)。在本例中,我们看到两种百分比变化:+100%和-50%。如果我们把这些输入算法,我们会得到什么?

这一次,选项 1 是明显的失败。变化的线性平均值为 25%。这意味着,如果我们假设所有年份都一样,那么每年都会有 25%的增长。但是如果我们算一下,从 20 岁开始,到 60 岁结束。差远了!
为什么不管用?
同样,这是因为我们误用了简单的汇总统计数据(矩),比如平均值。均值允许我们通过在所有项目之间分配总价值来假装所有项目都是相同的。通过加法,这种扩散是线性的。但是百分比不能把普通的数字相加。
让我们通过例子来说明这一点。数据中没有上升或下降的总趋势:上升抵消了下降,所以它们是无用的。这意味着**200%的变化必须被50%的变化抵消。**(我已经将增加的百分比转换为原始百分比;200%和 50%当然相当于+100%和-50%)。
但是在加法的土地上,这两项并不平衡:200% + 50% = 250%,平均变化 125%。我们应该得到的结果是 100%。

什么会起作用?
我们的变化如何平衡?与相乘。200%和 50%的乘积是 100%。没有变化。

乘法不仅仅是发生计算出来:它在概念上是有意义的,因为百分比是这样运作的:增加的大小取决于之前的值。(而加法与它们无关:如果你在银行账户上增加更多的钱,你就获得了总数;你现有的平衡不会改变它。不像按揭付款!)
另一种意思是
当然,我们不只是想要组合百分比,我们想要它们的平均值;我们想知道如果它们都一样的话,哪一年会是什么样。通俗说法的“平均”就是算术平均值。但是均值有很多种,包括几何均值,它的工作原理是等效的,但是用于乘法运算。你不是把值相加,而是把它们相乘;你不用除以数值的个数,而是取那个的根。
如果我们回到我们的第一个例子,恒定+150%的增长,我们可以看到它是如何工作的,使用选项 1。我们将再次使用基本百分比而不是增加额(即 250%):
*2.5 x 2.5 x 2.5 x 2.5 x 2.5 = 97.6697.66 ^(1/5) = **2.5***
在第二个示例中也是如此,没有任何变化:
*2 x 0.5 x 2 x 0.5 x 2 x 0.5 = 11 ^ (1/6) = **1***
所以我们至少可以在我们的(奇怪的)测试案例中确认合理的行为。
选项 1 和 2 再次变得等效
我们也可以放心使用几何平均,因为这两个选项再次产生相同的结果。也就是说,百分比增长的几何平均值与总体增长百分比的几何平均值相同。(因为将每一个连续的乘数相乘自然会产生总乘数。)

结论
这里的一个小教训是要小心利率!更一般地说,要小心看似基本的数学,尤其是当你关注更大的问题时。
但是另一个主题是使用视觉来谈论思维,特别是关于数据的数学或统计思维——即使操作很简单。这可能会为你赢得一场争论。
基于扩展聚类质心的多数欠采样技术

在我的上一篇文章“Python 中基于聚类质心的多数欠采样技术(CCMUT)的实现 ”中,我试图重温基于聚类质心的多数欠采样技术(CCMUT),并给出了它的 Python 实现。在这篇文章中,我将首次介绍 CCMUT 的扩展版本,并将其命名为 E-CCMUT 。
在 CCMUT 中,要求通过在属于多数类的特征空间中的数据点上平均所有特征的特征向量来找到聚类质心。但是,聚类质心是一个点,该点可能是也可能不是特征空间中的一个假想点,相对于该点,大多数类实例被划定其重要程度。聚类质心为虚的概率高得多,因为仅在一些非常特殊的情况下,聚类质心最初可能作为数据集中的样本作为数据点存在。
因此,由于聚类质心在大多数情况下仍然是特征空间中的一个假想点,直观上,它对于相对于真实存在的数据点(而不是假想的数据点)来划分多数实例的重要程度肯定是更有效和正确的,认为它是最重要的。
E-CCMUT 正是处理这种修改。这里,最接近群集质心的多数类实例,比如说 M (使用与 CCMUT 中相同的过程找到群集质心)被视为最重要的实例(如在 CCMUT 中),但是其他多数类实例的重要程度的划分是相对于该实例进行的,这是针对 CCMUT 中的群集质心进行的。同样,离 M 最远的多数类实例被认为是最不重要的,而离属于多数类的 M 、最近的数据点被认为是最重要的。
E-CCMUT 的伪代码如下:
- n:特征的数量。
- n:多数实例的原始数量。
- x:大多数实例存储在一个(N×N)矩阵中。
- f:欠采样的百分比。
- euclidean(x1,x2):返回特征空间中点 x1 和 x2 之间的欧氏距离。
- rev(l):它返回列表的反向排序形式
1\. under_sample(X,f)
2\. {
3\. d[N]
4\. cluster_centroid = sum(X[1], X[2], X[3],.., X[N])/N
5\. for i = 1 to N:
6\. {
7\. d[i] = euclidean(cluster_centroid,X[i])
8\. }
9\. cluster_centroid = X[index of the minimum element in d]
10\. for i=1 to N-1:
11\. {
12\. d[i] = euclidean(cluster_centroid,X[i])
13\. }
14\. indices = original indices list of elements in rev(d)
15\. x = delete(X, indices[:(f*N)])
16\. return x
17.}
使用函数 under_sample()构造伪代码,该函数将多数实例矩阵和欠采样百分比作为参数,并在欠采样后返回多数样本矩阵 x。
E-CCMUT 被认为比 CCMUT 直观地获得更好的结果。
在我即将发表的文章中,我将拿出实验证据,证明 E-CCMUT 比 CCMUT 表现得更好。
扩展卡尔曼滤波器:为什么我们需要一个扩展版本?
这篇文章是我上一篇关于卡尔曼滤波器的文章的延续。我的同事 Larry 对卡尔曼滤波器的工作原理非常感兴趣,但他能理解非线性和扩展卡尔曼滤波器的概念吗?让我们找出答案。
拉里:我知道卡尔曼滤波器,我现在可以预测和更新,我现在基本上知道一个重要的预测工具。
我:你能告诉我在阅读卡尔曼滤波器时我们做了什么假设吗?
拉里:假设…?你什么意思?你刚才说卡尔曼滤波器只对高斯函数有效。就是这样。不是吗?
我:嗯,说对了一半。上一篇文章中隐藏的另一个重要假设是线性函数。所以两个假设是-:
1。卡尔曼滤波器将始终与高斯分布一起工作。
2。卡尔曼滤波器将始终与线性函数一起工作。
拉里:哦,天哪!那么线性函数是从哪里出现的呢?
Me:对于线性函数,我的意思是预测和更新步骤都只包含线性函数。如果你仔细观察所有的方程,它们已经存在了。
线性函数看起来有点像这样:

Figure 1. Linear Function. (Source)
另一方面,非线性函数看起来像这样:

Figure 2. Non Linear Function. (Source)
从这些图中可以看出,直线方程是线性函数,而 cos 函数是非线性函数。
赖瑞:是的,没关系。我们的方程中没有任何角度,所以它们看起来只是线性的。那 KF 现在的问题是什么?我:大多数现实世界的问题都涉及到非线性函数。在大多数情况下,系统会观察某个方向,并在另一个方向进行测量。这涉及到角度和正弦、余弦函数,它们是非线性函数,然后会产生问题。
拉里:嗯,但是非线性函数是如何产生问题的呢?
我:如果你给高斯函数输入一个线性函数,那么输出也是高斯函数

Figure 3. Gaussian + Linear Function = Gaussian (Source)
如果用非线性函数输入高斯函数,则输出不是高斯函数。非线性函数导致非高斯分布。

Figure 4. Gaussian + Non Linear Function = Non Gaussian (Source)
因此,如果我们应用非线性函数,它将不会以高斯分布结束,我们不能再应用卡尔曼滤波器了。非线性破坏了高斯分布,计算平均值和方差是没有意义的。
拉里:哦,不,那样的话,我们的卡尔曼滤波器坏了。那么解决办法是什么呢?
我:你能想到的最琐碎的解决办法是什么?
拉里:我?嗯。我只能说使用线性函数:D:虽然这没有意义,但这确实是解决方案。
拉里:什么?你是说我是对的??怎么会这样 T2:是的,你是对的。我们将只研究线性函数。
拉里:但是你说成本、收益函数呢?它们仍然是非线性的,对吗?
我:绝对。它们是非线性的,但是我们将通过近似使它们线性。在这里,我们将借助一个叫做泰勒级数的强大工具,它将帮助我们得到非线性函数的线性近似。应用近似后,我们得到的是一个扩展卡尔曼滤波器。
拉里:新工具不断涌现!这个泰勒是怎么工作的?
Me:我们取一个点,对那个点进行一堆求导。在 EKF 的情况下,我们采用非线性曲线上的高斯平均值,并对其进行多次求导以逼近它。

Figure 5. Taylor Series
假设我们想在 x=0 时逼近 sin(x)。
假设我们要找一个多项式函数P(x)= c _ 0+c _ 1 * x+c _ 2 * x+c _ 3 * x来近似 sin(x)。所以我们需要找出 c0,C1,C2 和 C3 的值
在 x=0 时,sin(x) = 0,P(x) = c_0 + 0 + 0
如果我们的近似值必须更接近 sin(x),那么 sin(x)的值必须等于 x=0 时 P(x)的值。所以,0 = 0
如果我们的近似值与 x=0 处的 sin(x)具有相同的正切斜率也是很好的所以 1 = 1
发生..我们可以发现 sin(x)= x x/3 的近似值!+ x⁵/5!x⁷/7!+ x⁹/9!…
拉里:酷!那真的很酷。但是这又会给出一条非线性的曲线,我们不是只对线性化感兴趣吗?
我:正是,我们对线性化感兴趣,所以我们只是对泰勒级数的一阶导数感兴趣。对于每一个非线性函数,我们只需在平均值周围画一条切线,并尝试线性逼近该函数。
赖瑞:嗯。好的。KF 只研究线性函数,但在现实生活中,我们会遇到破坏高斯分布的非线性函数,所以我们尝试用泰勒级数来线性逼近这些函数,这属于扩展卡尔曼滤波。对吗?
我:绝对。完全正确!看看这个。

Figure 6. Scenario after applying Taylor’s Approximation to Linearize our function
拉里:我想知道这对我们为卡尔曼滤波器写的方程有什么影响,但在那之前,提供数据的传感器是什么?
我:假设我们有两个传感器激光雷达和雷达。激光雷达以笛卡尔坐标系的形式为我们提供距离。另一方面,雷达为我们提供了极坐标系统中的距离和速度。
Lidar => {px,py}
雷达= > { ρ,φ,ρ_dot}
px,py ->物体在笛卡尔坐标系中的坐标
ρ - > 是到物体的距离
φ->是 ρ 与 x 轴
ρ_dot - > 是 ρ
的变化 x 轴始终在汽车前进的方向。

Figure 7. Polar Coordinates as reported by Radar. ([Source](http://Taken from Udacity Nanodegree))
拉里:我们能从两个传感器都获取数据吗?
我:你当然要带。从不同的传感器获取数据并将它们组合在一起称为传感器融合。
拉里:好的,据我猜测,来自雷达的测量结果是非线性的,因为它们涉及到角度。现在我有兴趣知道扩展卡尔曼滤波器的方程!
我:对!当然可以。
预测步骤
x′= f . x+b .μ+ν p′=fpfᵀ+q 预测步骤与卡尔曼滤波完全相同。无论数据来自激光雷达还是雷达,预测步骤都是完全相同的。
更新步骤(仅在 EKF 情况下,即来自雷达的非线性测量)
等式 1:
y = z-h(x′)
z ->极坐标中的实际测量值
h - >指定我们的速度和位置如何映射到极坐标中的函数
x′->预测值
y - >测量值和实际值之间的差值
h(x’)
这是一个指定我们在笛卡尔坐标和极坐标中的预测值之间的映射的函数。此映射是必需的,因为我们在笛卡尔坐标中进行预测,但来自传感器的测量值(z)在极坐标中。

Figure 8. Mapping between Cartesian and Polar coordinates ([Source](http://Taken from Udacity Nanodegree))
等式 2:
s =hⱼp′hⱼᵀ+r
k =p′hⱼᵀs⁻R ->测量噪声
K - >卡尔曼增益
S- >总误差
s⁻->s 的逆
Hⱼ - >雅可比矩阵
Hⱼ
Hⱼ是雅可比矩阵。雅可比矩阵是我们刚刚在泰勒级数中讨论过的一阶导数。因为我们在这里处理矩阵,我们需要找到矩阵形式的微分。
J_kl = d F_k / dX_l
J_kl 是雅可比矩阵的 k,l 元素,F_k 是向量函数 F 的第 k 个元素,X_l 是向量变量 X 的第 l 个元素。
这里 F_k = { ρ,φ,ρ_dot} X_l = {px,py,vx,vy}
因为在雷达的情况下,我们有 4 个测量值,2 个用于距离,2 个用于速度。

Figure 9. Jacobian matrix ([Source](http://Taken from Udacity Nanodegree))

Figure 10. Jacobian Matrix after applying derivatives
等式 3:
x = x′+k . y
p =(I-khⱼ)p′
拉里:哦,明白了!因此,在激光雷达的情况下,我们将应用卡尔曼滤波器,因为来自传感器的测量是线性的。但是在雷达的情况下,我们需要应用扩展卡尔曼滤波器,因为它包括非线性的角度,因此我们使用泰勒级数的一阶导数来近似非线性函数,称为雅可比矩阵(Hⱼ)。然后我们用 h(x′)把笛卡尔空间转换到极空间,最后我们用 Hⱼ替换了 KF 的所有方程中的 h。
我:10/10。谢谢大家!
雅可比矩阵确实有点神奇,因为它将非线性空间转换成线性空间。但是相信我,这不是魔术,这都是数学。如果你发现任何错误,请务必与我联系。你可以在 LinkedIn 这里找到我。
你可以在这里阅读卡尔曼滤波器的基础知识。无迹卡尔曼滤波器这里。





浙公网安备 33010602011771号