通过 Twitter feed 分析进行社交倾听
twitter feed 的客户情感分析
什么是社交倾听,为什么它很重要?
社交媒体现在被广泛用于个人对各种话题、个人和企业的赞美或发泄。企业确定其品牌如何被客户感知的一个好方法是通过社交倾听,企业考虑他们的客户在网上对他们说了什么,并利用这些信息 1)改变他们的产品和服务,2)创造更好的客户参与度,3)设计其营销活动。
乔治·帕甘三世在 Unsplash 上的照片
使用 R 编程分析社交媒体数据
我们可以很容易地抓取的一个社交媒体渠道是 Twitter,因为 R 包含了抓取 Twitter 数据的可用包,Twitter 平台允许用户创建一个开发者帐户用于研究目的。
Twitter 开发者帐户入门
我不打算详细介绍如何创建一个 Twitter 开发者帐户,因为这篇博文更多的是关于使用 R 进行分析,但是我发现下面的链接非常有帮助。
[## 获取和使用访问令牌
这篇短文介绍了如何获取和使用 Twitter API 访问令牌,以便在 rtweet 包中使用。要创建 Twitter…
cran.r-project.org](https://cran.r-project.org/web/packages/rtweet/vignettes/auth.html)
一旦你创建了一个账户,确保你把你的 API 密匙保存在一个安全的地方(比如一些 R 代码),因为这些将被用于认证和允许 tweet 抓取。
按照下面的代码片段,我保存了我的 API 键,然后用它们连接到浏览器。
#### 2\. Set parameters for twitter app access ####
## store api keys (replace with your own keys)
api_key <- "aHGiOIWCubjkMmitanwyIiPaDA"
api_secret_key <- "WlbDGVZU8zy6frwvUlxY2j0aBNMTLsutp9VL0z6EsxOzC8SgjXmNTY"
access_token <- "1310431451433360898-ry6VoVI6CpzVA5dix7J3gzsvhQLHtw"
access_token_secret <- "MZiVtV4dddCGF9LSQ7qvRj35B46BI0RflEKUZYx00AHiuX"## authenticate via web browser
token <- create_token(
app = "rexploretweets",
consumer_key = api_key,
consumer_secret = api_secret_key,
access_token = access_token,
access_secret = access_token_secret)setup_twitter_oauth(api_key, api_secret_key, access_token, access_token_secret)## Check to see if token is loadedget_token()
抓取 Twitter
我将假装我是一个豪华汽车品牌,正在考虑将我的范围扩大到自动驾驶汽车。然而,我不确定这是否是一个好主意。媒体上有正面也有负面的评论,我觉得挺混乱的。我想在不阅读 Twitter 页面的情况下,找到人们对无人驾驶汽车的看法。
由于我对某个特定的话题或某个# (hashtag)感兴趣,我使用下面的代码来获取所有与自动驾驶汽车相关的推文。不幸的是,由于我的 Twitter 开发者账户,我只能发布过去 6-9 天的推文。
include_rts 选项是删除转发。我还想删除对推文的回复,因为我想在我的分析中只包括个人或有机的推文。
sd_cars<- rtweet::search_tweets(
q = "#selfdrivingcars",
n=5000,
include_rts = FALSE) # exclude retweetssd_cars_organic <- sd_cars## Remove replies
sd_cars_organic <- subset(sd_cars_organic,is.na(sd_cars_organic$reply_to_status_id))
推文的探索性分析
然后,我对推文做一些初步分析,以了解一些基本信息。
我提取的推特信息主要是有机推特。预期的转发不在抓取的数据集中。
图 1: Tweet 类型饼图(图片由作者提供)
Twitter 用户使用情况的独特位置柱状图显示,大多数人在美国发推,其次是巴黎(需要做一些清理以避免重复)。
图 2:不同地点的 Twitter 用户(图片由作者提供)
每隔 3 小时的推文频率显示了过去 9 天人们最有可能在推文中谈论自动驾驶汽车的时间。它还显示了最受欢迎的日子。如果我有更长时间的数据,作为一个豪华汽车品牌的老板,我可以根据推文的频率来确定人们对自动驾驶汽车的兴趣是随着时间的推移而增加还是减少。
图 3:按时间排序的推文(图片由作者提供)
因为我是一个非常重要和忙碌的人,所以我不想看单独的推文,所以我想知道人们在谈论什么,也就是说,推文中使用频率最高的词是什么。这需要一点数据清理。
Twitter Feed 上的文本分析
我使用了 R 中的 tm 包来清理数据集,如下图所示。
## most frequent words ##
sd_cars_organic$text <- gsub("https\\s*","",sd_cars_organic$text)
sd_cars_organic$text <- gsub("@\\s*","",sd_cars_organic$text)
sd_cars_organic$text <-gsub("amp","",sd_cars_organic$text)
sd_cars_organic$text <-gsub("[[:punct:]]","",sd_cars_organic$text)#draw out only the text column because we are interested in cleaning it with tm
text_corpus<-Corpus(VectorSource(sd_cars_organic$text))#remove words like car, selfdriving cars, autonomous vehicles as they are synonyms of selfdriving cars
#rt = retweet, re = reply
text_corpus<-tm_map(text_corpus,removeWords, c("selfdrivingcars","driverlesscars","autonomousvehicles","cars","car","rt","re","vehicle","selfdriving","driverless","autonomous"))#remove stop words
text_corpus<-tm_map(text_corpus,removeWords,stopwords("english"))
然后我想把最频繁出现的单词形象化,但是为了让它们频繁出现,它们至少需要出现 10 次。生成的单词云如图 4 所示。
我发现单词云真的很酷,因为它们总是能提供我从未想过的信息,但很有意义。我从未想过自动驾驶卡车或自动驾驶飞机(尽管我相信它们已经存在)。显然,我预计物联网将会出现,因为自动驾驶汽车需要可能产生大量数据的传感器;因此,大数据和数据分析。这些推文还显示,人们将优步和特斯拉与自动驾驶汽车联系在一起。
此外,似乎我的停用词删除工作不是很好,但你得到了要点。😃
图 4:文字云#无人驾驶汽车(Twitter 数据)——作者图片
现在来了解一下 Twitter 用户对无人驾驶汽车的看法。
使用 R 的情感分析
我必须做进一步的数据转换,以便绘制用户情绪,如下面的代码片段所示。
情感分析的结果如图 5 所示。同样,我喜欢数据分析证实我的假设。大多数人对自动驾驶汽车的看法是积极的。他们对它也很信任,并期待着自动驾驶汽车的出现。也许我应该开始制造自动驾驶汽车,但在此之前,我想了解负面推文的内容。
##Converting tweets to ASCII To get rid of strange characters
sd_cars_tweets$text_clean<-iconv(sd_cars_tweets$text_clean,from="UTF-8",to="ASCII",sub="")#removing mentions, in case needed
sd_cars_tweets$text_clean<-gsub("@\\w+","",sd_cars_tweets$text_clean)
tweet_sentiment<-get_nrc_sentiment((sd_cars_tweets$text_clean))
sentimentscores<-data.frame(colSums(tweet_sentiment[,]))
names(sentimentscores)<-"Score"
sentimentscores<-cbind("sentiment"=rownames(sentimentscores),sentimentscores)
rownames(sentimentscores)<-NULLggplot2::ggplot(data=sentimentscores)+
geom_bar(mapping=aes(x=sentiment,y=Score),stat="identity")+
theme(legend.position="none")+
xlab("Sentiments")+ylab("Scores")+
ggtitle("Total sentiment based on scores")+
theme_minimal()
图 5: Twitter 用户对#无人驾驶汽车的情感分析(图片由作者提供)
推文—主题分析
查看与负面情绪相关的推文的一种方法是查看每个单词;然而,由于语言是复杂的,有时它有助于将单词聚集成主题。有各种复杂的包来做主题分析,但是我想用一种快速而简单的方法,那就是通过探索性的图形分析。
探索性图形分析是一种将单词分组为簇或主题的技术。这个我用的是 R 包 ega 。我的代码如下所示。
首先,我使用analyze sensition命令将推文与几个字典进行比较,以便将它们与积极或消极分类的单词进行匹配,从而给每条推文一个相应的情感分数。
第二,我只保留了度量的子集。该命令给出 13 个情感分数。
第三,我计算了每个情绪的平均值,去掉了所有正面情绪(分数> 0)。为了检查我是否只保留了负面情绪,我快速查看了结果数据框(见图 6)。
我必须将我的数据框转换回文档术语矩阵,以便执行进一步的文本清理步骤。由于推文可以包含像表情符号这样的特殊字符,我将字符串转换成了“ASCII”。
我降低了文档术语矩阵中的稀疏度,通过使用阈值 0.98 来加速分析。
## Only look at negative sentiment ##sd_cars_sentiments<-analyzeSentiment(sd_cars_tweets$text_clean)##select subset of measures
sd_cars_sentiments_subset<-dplyr::select(sd_cars_sentiments,
SentimentGI,SentimentHE,
SentimentLM,SentimentQDAP,
WordCount)#create a mean value for each tweet's sentiment level, leaving us with a single sentiment value for each tweet
sd_cars_sentiments_subset <-dplyr::mutate(sd_cars_sentiments_subset,
mean_sentiment=rowMeans(sd_cars_sentiments_subset[,-5]))# remove unnecessary sentiment measures
sd_cars_sentiments_subset<-dplyr::select(sd_cars_sentiments_subset,
WordCount,
mean_sentiment)sd_cars_df<-cbind.data.frame(sd_cars_tweets,sd_cars_sentiments_subset)#only keep negative sentiments
sd_cars_df_negative<-filter(sd_cars_df,mean_sentiment<0)nrow(sd_cars_df_negative)#topic analysis of negative sentiments
sd_cars_tokenized_list<-tokens(sd_cars_df_negative$text_clean)sd_cars_dfm<-dfm(sd_cars_tokenized_list)#turn this list object into a document feature matrix with the dfm command.
#use the colsums command to get the count of use for every word, which we assign to the vector "word_sums"
word_sums<-colSums(sd_cars_dfm)length(word_sums)#number of words#which are the most frequent words
freq_negative_words<-data.frame(word=names(word_sums),
freq=word_sums,
row.names=NULL,
stringsAsFactors = FALSE)sorted_freq_neg<-freq_negative_words[order(freq_negative_words$freq,decreasing=TRUE),]#remove odd characters
sd_cars_df_negative$text_clean<-sapply(sd_cars_df_negative$text_clean,
function(row) iconv(row,"latin1","ASCII",sub=""))neg_corpus_tm<-Corpus(VectorSource(sd_cars_df_negative$text_clean))neg_tm<-DocumentTermMatrix(neg_corpus_tm)neg_tm<-removeSparseTerms(neg_tm,0.98)neg_df_cluster<-as.data.frame(as.matrix(neg_tm))#Create clusters using exploratory graph analysisega_neg_sd_cars<-EGA(neg_df_cluster)
图 6:对#无人驾驶汽车的负面看法(图片由作者提供)
我得到的探索图如图 7 所示,有 15 个集群。这些簇用缩写词标记,这可能很容易让人混淆。另外,15 个集群有点多。
图 7:自驾汽车负面推文数量的探索图(图片由作者提供)
为了更好地理解每个词群是由哪些词组成的,并创建我自己的话题或主题,我快速浏览了属于每个词群的词。这如图 8 所示。从下面的表格中,我可以看出与撞车相关的推文组成了第三组。所以,也许,这一组的主题可以是安全。
图 8:每个聚类中的单词(图片由作者提供)
后续步骤
为了进一步完善这种分析,我可以做以下事情:
- 删除更多的停用词以获得更好的输出
- 下个月重新运行我的分析,并可能在几个月内重复这一过程,这样我就有很多样本来围绕自动驾驶汽车做出决定
- 调整 EGA 函数的参数以减少聚类数
- 尝试其他相关主题(#),甚至旨在从与自动驾驶汽车相关的 Twitter 账户中获取数据,并结合我现有的分析,就用户对自动驾驶汽车的情绪做出丰富的决定。
总结
在这篇博文中,我已经成功地使用 R 对 Twitter 数据进行了网络搜集,以更好地了解 Twitter 用户对自动驾驶汽车的感受。根据我的分析,似乎大多数人对无人驾驶汽车持积极态度。除了其他关注之外,还存在对与致命事故相关的驾驶员和乘客安全的关注。
如果你想分析 Twitter 数据,我的 R 代码在下面。
社交媒体分析
分析推文以获得见解并回答业务问题
社交媒体(Twitter)可以用来推广新的活动或产品吗?
简介
社交媒体是为每个人创造地球村的重要工具。这是一个人们分享他们对正在发生的事情或事件的看法的地方。这篇文章的本质是指导如何从 Twitter 中提取数据并对其进行基本分析,以回答诸如名人中使用最多的标签是什么?谁是被提及最多的 Twitter 用户?等等。我会解释我是如何得到这些数据的,并把我的发现告诉你。敬请关注…
先决条件
- python 编程知识
- 首先确保你有一个 T witter 账户和一个 twitter 开发者账户点击这里获得一个 Twitter 开发者账户。这为我们提供了对 API 的访问,这将帮助我们进入 Twitter 应用程序,以便我们能够挖掘与我们将在 API 调用中指定的任何有效和公共用户相关的所有推文。
本文分为五个部分,分别是
- 数据采集
- 数据清理和分析
- 结果/发现
- 结论
数据采集
在这篇文章中,我试图启发并让你注意到 Twitter 是如何被用来推广产品和活动的。我特别关注了非洲著名的 Twitter 用户,包括政治领袖和名人。使用的数据包括从 twitter 上搜集的有影响力的推文。这些用户是根据一些指标选出的,这些指标包括
1.受欢迎程度得分=转发次数+点赞次数(每条推文)
2.触及分数=关注者数量-他们关注的人数
3.相关性分数=共享状态数+流行度分数+到达分数
有了这些数据,像非洲最受欢迎的名人,最受欢迎的话题,谁在谈论它等等。用数字和统计来回答。得出的结论是,Twitter 作为一种社交媒体,可以用来推广活动和产品。
使用 Twitter 提供的应用程序编程接口(API)和 Tweepy 库从 Twitter 中抓取推文,以提取影响者共享的推文。提取的推文构成了数据的基础。每条推文都有许多相关元素,比如点赞数、转发数、推文身份、回复数等。这些信息让我能够进行分析,以回答一些普遍的问题,如哪个影响者分享了最多的推文,以及此类推文的赞数和转发数。这些数据还具有地理位置,这使我能够根据非洲大陆的不同地区对推文进行分组,我能够确定这些地方的影响者在谈论哪个主题。该数据包括名人影响者和领导者的 7099 条推文,其中领导者有 1729 条推文,名人影响者有 5370 条推文。每条推文都附有大量信息,在处理和清理推文后,23 条不同的信息解释了推文的文本是什么,来自哪个位置等,这些信息被用于分析。
数据清理和分析
用 python Web 抓取库 Beautiful Soup 抓取并格式化网页后,用正则表达式从网页中提取 twitter 句柄。
获取 twitter 句柄的正则表达式代码
基于 html 元素获取网页的请求代码
预处理前
加工和清洗后
结果
对有影响力的人的推文进行分析、评分和加权,以回答商业问题“twitter 是否可以用来推广一项活动”。有 829 个标签被影响者使用,出现最多的标签是 COVID 19。大多数推文来自南非,几乎 75%的推文来自南非约翰内斯堡。领导者总数为 34 人,名人影响者为 91 人,总计 125 人。
新闻 24 一个新闻报道 twitter 页面分享的推文数量最多,但与其他推文数量较少的影响者相比,它的受欢迎程度和到达分数非常低。
平均而言,如果一条推文包含标签 COVID19 并由 GautengProvince 发布,将有 106 条转发和 191 个赞。这显示了当 GautengProvince 在推特上发布关于 COVID19 的消息时人们的反应,也显示了 COVID19 这个话题有多受欢迎。此外,如果一条推文使用标签尼日利亚,并由 MadeInAfrica 发布,它将有 4 个转发计数和 11 个赞。这意味着#尼日利亚不是一个常见的词,因为 MadeInAfrica 的粉丝数量和过去的推文不包含这样的标签。大多数非洲人在他们的推文中不使用标签,例如尼日利亚总统姆布哈里在他过去的 300 条推文中只使用过一个标签,那是在 2020 年 6 月 12 日民主日。世界卫生组织(世卫组织)有最高的得分,但是它不是最受欢迎的,MagufuliP 在图表中名列前茅。
结论
非洲十大领袖
从分析和结果部分来看,很明显,当合适的人使用合适的词语时,twitter 对促进商业活动有很大的影响。由于社交媒体等工具,信息在世界范围内传播得非常快,并且使用来自受欢迎的影响者的正确标签将使这些信息迅速成为趋势。正确的标签将在几秒钟内形成影响者趋势,像艺人这样的影响者,例如特雷弗·诺亚有非常高的受欢迎度和到达分数,尽管事实上与 News24 或世卫组织和特雷弗·诺亚相比,他的共享推文数量明显较低。在推文中使用标签并不意味着推文会流行,也不会增加影响者的受欢迎程度。为了进行更深入和详细的分析,需要更多的数据。像回复计数这样的数据,关于评论推文的人的信息以及他们的评论是什么,将使我们能够详细了解人们如何对影响者的推文做出反应。此外,要进行更深入的分析,需要考虑的一个重要因素是基于影响者的感受或特定地方的趋势的标签。
在这个 GitHub 库中可以找到关于分析的完整笔记本。
谢谢你,干杯
社交媒体和主题建模:如何在实践中分析帖子
主题建模的实际应用
我们讨论主题建模可以用来分析社交媒体上各种文本帖子的方法以及这样做的好处。
图片由 Unsplash 上的 Alina Grubnyak 提供
互联网上每秒钟都会产生大量数据——帖子、评论、照片和视频。这些不同的数据类型意味着有很多内容需要讨论,所以让我们集中讨论一个——文本。
所有的社交对话都是基于书面语言——推文、脸书帖子、评论、在线评论等等。作为一名社交媒体营销人员,一名脸书小组/个人资料版主,或者试图在社交媒体上推广你的业务,你需要知道你的受众对你上传内容的反应。一种方法是全部读完,标记可恶的评论,把它们分成相似的主题组,计算统计数据,然后……仅仅为了看到有成千上万的新评论要加到你的计算中,你就浪费了一大块时间。幸运的是,这个问题还有另外一个解决方案——机器学习。从这篇课文中,你将学到:
- 为什么你需要社交媒体分析的专业工具?
- 你能从主题建模中得到什么,它是如何完成的?
- 如何自动在评论中寻找仇恨言论?
为什么社交媒体文本是独一无二的?
在开始分析之前,理解为什么社交媒体文本如此独特非常重要:
- 帖子和评论都很短。它们大多包含一个简单的句子,甚至是一个单词或短语。这使得我们只能从一篇文章中获得有限的信息。
- 表情符号和笑脸——几乎只在社交媒体上使用。它们提供了关于作者情感和背景的更多细节。
- 使帖子更像口语而不是书面语的俚语。它使陈述显得更随意。
这些功能使社交媒体成为一个完全不同的信息来源,在使用机器学习进行分析时需要特别注意。相比之下,大多数开源机器学习解决方案都基于冗长的正式文本,如维基百科文章和其他网站帖子。因此,这些模型在社交媒体数据上表现很差,因为它们不理解所包含的其他表达形式。这个问题叫做域转移,是一个典型的 NLP 问题。不同的数据也需要定制的数据准备方法,称为预处理。这一步包括从 URL 或提及等无价的标记中清除文本,并转换为机器可读的格式(在 Sotrender 中有更多关于我们如何做的内容)。这就是为什么使用专门为你的数据源创建的工具以获得最佳结果是至关重要的。
社交媒体的主题建模
用于文本分析的机器学习(自然语言处理)是一个广阔的领域,有许多不同的模型类型可以洞察你的数据。其中一个领域可以回答“给定文本的主题是什么?”就是话题建模。这些模型有助于理解人们通常在谈论什么。它不需要任何带有预定义主题的特别准备的数据集。它可以在没有监督和帮助的情况下独自找到隐藏在数据中的模式主题——这使它成为一种无监督的机器学习方法。这意味着很容易为每个单独的问题建立一个模型。
有许多不同的算法可用于这项任务,但最常见和最广泛使用的是 LDA(潜在狄利克雷分配)。它基于文本中的词频和主题分布。简而言之,这种方法对给定数据集中的单词进行计数,并根据它们的同现率将它们分组到主题中。然后计算每个文档中主题的百分比分布。因此,这种方法假设每个文本都是主题的混合物,这对于每个段落都涉及不同内容的长文档非常有用。
图一。 LDA 算法(鸣谢:哥伦比亚大学
这就是为什么社交媒体文本需要不同的程序。其中一个新算法是 GSDMM (针对狄利克雷混合模型的吉布斯采样算法)。是什么让这个如此不同?:
- 它很快,
- 专为短文本设计,
- 很容易用一个老师(算法)想要将学生(文本)分成兴趣相似的组(主题)的类比来解释。
图二。组分配算法
学生们被要求在两分钟内写下他们喜欢的一些电影名称。大多数学生能够在这个时间段内列出 3-5 部电影(这对应于社交媒体文本的有限字数)。然后他们被随机分配到一个组。最后一步是每个学生选择不同的桌子,记住两条规则:
- 选择学生多的小组——更喜欢大的小组
- 或具有最相似电影标题的群组—使群组更有凝聚力。
这最后一步重复多次。有利于较大群体的第一条规则对于确保群体不会过度分散至关重要。由于每个学生(文本)的电影标题(单词)的数量有限,每个组(主题)必然会有成员在其列表中具有不同的电影,但来自相同的流派。
作为 GSDMM 算法的结果,您获得了每个文本到一个主题的分配,以及每个主题的最重要单词的列表。
**图三。**记录主题分配并获取主题词
棘手的部分是决定主题的数量(每个无监督方法的问题),但当你最终做到这一点时,你可以从数据中获得相当多的洞察力:
- 数据中主题的分布
**图 4。**数据中的主题分布
- 词云——允许我们理解主题并命名。这是一个快速简单的解决方案,可以取代阅读整个文本集,并节省您数小时的繁琐工作,将它分成几组。
**图 5。**你可以在上图中看到三个单词云的例子。从左到右看,第一个包含单词:总统,政府,迪塞斯,covid——我们可以假设主题是政治。还有一些不太突出的词,如咳嗽、生病和健康,所以这是一个关于政府在健康问题上的行动的话题。
- 主题的时间序列分析——正如我们在下图中看到的,一些主题可能会获得更多的关注,如第 7 个主题,而一些主题会像第 4 个主题一样逐渐消失。试图理解什么是流行的或者将来会流行是一件好事,回顾过去,看看话题是如何变化的。
**图 6。**主题随时间的分布
用例
在我们最近为 Collegium Civitas 开展的一个项目中,我们分析了 50 000 条社交媒体帖子和评论,并对它们进行了主题分析。它允许我们的客户回答如下问题:
1)在社交媒体 2 个月的时间跨度里讨论了什么?
在数据集中,我们能够区分围绕新冠肺炎的 10 个不同的主题。讨论内容包括统计数据和新冠肺炎病因学、日常生活、政府对疫情的反应、旅行限制的后果、贸易市场和供应、日常生活、疫情期间的医疗保健、教会和政治、新冠肺炎的常识和阴谋论、政治和经济、垃圾短信和广告。
2)疫情局势对讨论有什么影响?
在疫情爆发期间,最大的主题是新冠肺炎的起源和统计。人们谈论着形势是如何变化的,并就疾病传播的方式交换信息。要阅读更多内容,请访问 Collegium Civitas 网站(仅波兰版)。
仇恨语音识别
另一个可以用机器学习回答的问题是“人们在评论或帖子中表达的是一种什么样的情绪?"或"我的内容是否产生了仇恨评论?”。在波兰语中,这些任务只有几种解决方案。这就是为什么我们在 Sotrender 建立基于社交媒体文本的情绪和仇恨言论识别模型。我们的解决方案分两步构建。
第一步是将文本和表情符号转换成数字向量表示(嵌入),以便稍后在神经网络中使用。该步骤的主要目标是实现某种语言模型(LM ),该语言模型具有人类语言的知识,使得表示相似单词的向量彼此接近(例如:queen 和 king 或者 paragraph 和 article ),这意味着这些单词具有相似的意思(语义相似性)。该属性如下图所示。
**图 7。**词语相似背后的直觉
训练这种模型类似于通过与孩子交谈来教他们如何说话。孩子们通过听父母说话能够理解单词的意思,他们听得越多,理解得越多。
根据这个类比,我们必须使用一组庞大的社交媒体文本来训练我们的模型理解它的语言。这就是为什么我们使用一组 1 亿条帖子和评论来训练我们的模型,这样它就可以正确地给单词和表情符号分配向量。用嵌入模型矢量化的记号向神经网络提供输入。
第二步是为特定任务设计神经网络——仇恨言论识别。最重要的是数据集——该模型需要仇恨言论和非仇恨文本的例子,以学习如何区分它们。为了获得最佳结果,您需要试验不同的架构和模型的超参数。
作为仇恨言论识别模型的结果,我们得到了数据集的另一个分组。现在我们可以看到我们的观众如何反应,它创造了多少仇恨的评论或帖子。更重要的是,通过再次结合每条评论的发布时间,我们可以看到是否有一个特定的时间段产生了最可恶的评论,如下图所示。
图图 **8。**仇恨言论随时间分布
将这种分布与最近的帖子或事件结合起来,可以让你洞察到激怒人们的内容类型。仇恨言论贡献的时间变化也可能与话题分布的变化相关。综合分析得到的所有信息可以提供数据集的深度图像。
**图九。**每周文字计数含仇恨言论
如上图所示,大多数仇恨与话题 3、6 和 7 有关。知道什么让人生气,给了以后避开敏感话题的机会。
情感分析也是如此。我们可以为正面、负面或中性的评论生成类似的可视化效果,并查看它们在时间或主题上的分布。如果您想阅读基于我们 8 周数据分析的完整报告,您可以在这里找到(仅波兰版本)。
结论
在 Sotrender 中,我们有仇恨言论和情绪识别的模型,这些模型会针对社交媒体文本不断改进和更新。此外,我们还拥有为个别案例构建主题建模模型的经验。如您所见,这种类型的分析有很多好处:
- 了解你的观众
- 深入研究评论的主题
- 发现流行主题
- 在我们的内容中寻找仇恨或消极的根源
仅举几例!
参考
[1]尹,建华,,一种基于 dirichlet 多项式混合模型的短文本聚类方法,(2014),14 .
风险投资中的社会网络分析
洞察新加坡的在线风险投资格局
将社会资本作为一种资源
风险资本家利用各种积累的资源(筛选、监控、顾问等)来改善他们的战略和投资过程。尽管它们可能不像财务报表或研究报告那样显而易见,但社交媒体提供了风投可以利用的替代数据金矿,其形式为社会资本。
社会网络分析的相关性
SNA 是通过使用网络和图论来调查社会结构的过程。它是现代社会学中的一项关键技术,我们的目标是将它应用于网络数据,以识别市场中不同参与者的社会资本:投资者、初创企业、新闻机构、生态系统合作伙伴和政府机构。我们的目标是使用 SNA 来识别市场中的关键参与者,制定投资组合战略以管理风险,寻找新的机会,并规划在线关系以抢先采取任何必要的防御或进攻行动。
抓取 Twitter 数据
我们的目标是用 Twitter 数据构建知识图表。为了防止冷启动问题,我们进行了初步的人工搜索,从新加坡的大型初创公司、风投、政府法定委员会和新闻网站收集了 79 个企业账户。他们总共有 100 万粉丝,5 万粉丝,40 万推文。
使用 Twitter API 从帐户中收集原始数据的示例
我们维护了单独的字典,以包含用户之间的 4 种不同类型的关系,具有以下键:值对:
- 遵照
- 提及—选择以“@”开头的标记
- Hashtags —选择以’ # '开头的标记
- 常见关键词——使用基于宾夕法尼亚树库项目的词性标注从所有推文中选择名词和形容词
然后,我们通过递归地从关注和提及列表中抓取用户来扩展我们的数据集。我们可能会有很多噪音和垃圾邮件帐户,所以我们根据他们帐户的活动来过滤他们。然后,字典将用于构建图表。
理解图表
初始用户集的标签图示例
节点代表用户,边代表他们通过关注、提及、关键词或标签的双向关系。对于 Hashtag 和关键字图,当两个节点具有共同的关键字/hashtag 时,在它们之间形成一条边。图形的大小受限于完成的抓取量。
调查的结果
1.社交网络的整体属性
(1)密度= 2E / (V(V-1))其中 E 和 V 是边和节点计数。(2)铰接点是如果被移除,则将图分成更多部分的节点。如果没有这样的点,每个用户都以这样或那样的方式相互连接
社交网络是稀疏的,可能意味着与 SG 中的风投相关的整个在线社交社区是断开的。不同的参与者可能有非常不同的兴趣,并且可能属于不同的行业。对于 79 大小的小图,衔接点是跟随图中的 @BluzelleHQ 、@ society on&@ FintechSIN和提及图中的@ PayPal&@ SG innovate。这些可能是将不同社区联系在一起的关键客户。
2.社交网络中的子社区
我们使用无监督学习算法在没有任何标签的输入图形数据中寻找模式。
NetworkX 的最大团发现算法在我们的图中识别更小的组。形成团,使得每两个不同的顶点是相邻的。最大团是一个不能通过增加一个相邻顶点来扩张的团。突出显示的最大集团出现在提及图中。
@JimMarous 是金融科技的发言人&出版商, @drspangenberg 法学教授, @enricomolinari 创新经理, @wef 世界经济论坛的官方账号。尽管很可能是天马行空的想象,一段关系可能是在世界经济论坛的一次活动中形成的,一个新的项目可能正在进行中,或者他们可能只是对一些话题有相同的兴趣。风投可以利用这一点来探索潜在的战略伙伴关系,甚至进行投资。
3。社交网络中的桥梁
它类似于连接点,但是被表示为关系而不是单个实体。
桥是图中的重要关系,它将几个社区联系在一起。在提及图中,发现了@SlackHQ 和@vertexventures 之间的桥梁。这很有意思,因为根据 Vertex Ventures 的投资组合,他们似乎没有投资 Slack,但他们可能对该公司有特殊兴趣。
4.用户之间的间接关系
Dijkstra 的算法用于查找提及图中两个帐户之间的最短路径。
@500Startups 可能对初创公司 @BluzelleHQ 感兴趣,并且想知道联系他们的最佳方式。虽然他们可以冷接触或找到一个线索,但联系他们之间的普通人可能更有效。这位恰巧是沃顿商学院和易贝商学院的董事顾问 @Alka_Gupta 。
另一个有趣的例子是智能资产公司 @monkshillvc 到 @DigixGlobal 之间的路径。 @SGX 和@纳斯达克都从事证券交易业务,有与投资方 monkshillvc 合作的可能。
5.有影响力的账户
度中心性
一个节点的度是它有多少条边。
除了那些显而易见和受欢迎的名字,还有几个有趣的账户值得注意。
@英特尔资本的简历:“通过合作的力量帮助建立伟大的公司”。这可能是英特尔投资在风险投资领域脱颖而出的方式。
@UrsBolt 是瑞士财富科技和金融科技大使。他的人脉很广,对那些对这些行业感兴趣的人来说,他可能是一笔财富。
@jpaine 是 @GoldenGateVC 创始合伙人、 @Founding 新加坡董事。他通过关键词建立了良好的关系,这可能意味着他的推文与生态系统中的其他人非常相关。
接近中心性
表示网络中一个节点与所有其他节点的距离。计算为从该节点到所有其他节点的最短路径长度的平均值。
@vertexventures 通常与网络中的大部分账户直接连接或“一跳之遥”。这似乎与他们的简历“Vertex Ventures 是一个全球性的运营商-投资者网络,管理美国、中国、以色列、印度和东南亚的投资组合”相一致。
@salesforce 是一个有趣的发现,因为他们在网络中直接或至少通过另一方(通常可能是组织中的员工)被多次提及。这突出了网络中对 CRM 软件的潜在需求,并可能成为风险投资家与此类供应商合作的机会,以降低其整个公司组合的成本。
中间中心性
量化一个节点作为两个其他节点之间最短路径上的桥的次数。
@nihsingapore 和 @ICE71_ 都是基于 SG 的社区平台/生态系统。这是有道理的,因为他们经常作为关系的中间人“介于”初创公司和投资者之间。
6.“富人俱乐部”
使用谷歌流行的 PageRank centrality,“富人俱乐部”由关系良好的账户组成,这些账户之间也有联系。
@ImpactTap 是高影响力,但与其他有影响力的账户联系不紧密。这可能是一个风险投资或创业公司与这个新闻来源组织合作的机会。
@OriginateLabs 是一家来自柏林的数码产品公司, @SynergisCAD 是一家来自美国的工程创新公司,这两家公司都很有影响力,但只与“富人俱乐部”中的 @FintechSIN 有联系。他们可能对 SG 市场感兴趣。
@KaporCapital 是一家总部位于加州的风险投资公司,与 GoldenGateVC 的 @jpaine 有关联,他们的集体影响力可能会为跨境共同投资机会提供一个更有说服力的理由。
7.预测新的关系
我们训练二进制分类模型来基于图的特征预测是否在 2 个节点之间形成边。该图由通过 node2vec 从嵌入层获得的特征表示,node2vec 是一种半监督算法,它最大化了在 d 维特征空间中保存节点的网络邻域的可能性。图中的边将被移除以形成模型的训练数据。移除的边缘将成为验证预测的基础事实。
各种分类模型通过其 AUROC 分数进行评估。
下图中有趣的链接预测
( @tekjau ,@ j Paine)—Razer fin tech Malaysia 的技术 AVP 可能与 GoldenGate 的创始合伙人有关联。
( @peignoir ,@ 500 startups)—Startup Weekend(最大的创业活动之一)的联合创始人和 VC 500Startups 未来可能会有一个协会,甚至在一个活动上合作。
( @TerenceLeungSF , 【路透社) - TerenceLeungSF 在一家初创公司 One Network Enterprises 工作,这种预测的关系可能意味着路透社风投部门的潜在兴趣。
标签图中有趣的链接预测
有几个 VC:@ singtelinnov 8, @GobiPartners , @500Startups 潜在与创业公司形成关系的: @Snapcart_sg , @Haulio_io , @ViSenze , @DathenaScience 。
结论
网络数据形式的社会资本有可能破坏风险投资生态系统。在一个运营和通信日益数字化的时代,用户之间在网上形成的关系变得更加普遍。社交网络分析让我们能够从 Twitter 等公共来源的数据中挖掘出真知灼见。我们使用图形表示社交媒体数据,并实现算法来揭示有趣的信息。
这些数据包含个人但公开的信息。如果需要,我会毫不犹豫地记下任何信息。请让我知道。这些见解也是不可信的,因为它具有高度的投机性。
这个项目是学校数据挖掘课程的一部分。我的队友阿诺德、简斌、尼古拉斯和炙心功不可没。
用社交网络分析信任
社交网络可以用图的形式来表示,其中用户用节点来表示,用户之间的关系形成边。除了像脸书和推特这样最受欢迎的社交网络,其他类型的网络也可以被分析。在这篇文章中,我们将从 Epinions 网站用户的评论中分析建立在信任基础上的社交网络。Epinions 曾经是一个人们可以评论产品的网站。用户可以免费注册,并根据他们的评论被发现有用的程度来赚钱。由于有人试图利用这个系统,作为一个可能的解决方案,一个信任系统被放置在适当的位置。用户可以将人们放入他们的信任网中,他们可以将那些评论一贯被认为有用的人放入他们的“黑名单”,即“那些评论一贯令人反感、不准确或总体上没有价值的作者”。
预处理数据集从 SNAP(斯坦福网络分析项目)网站下载。这个项目是用 Python 完成的,使用了库 NetworkX。为了生成图表并获得其他有用的统计数据,我们制作了一个数据框,其中包含每个节点所有类型度数的统计数据。
结构分析网络以有向加权图的形式给出,其中权重为 1 的边表示信任关系,权重为-1 的边表示不信任关系。重要度量的值如下。
重要措施。
这是一个稀疏网络,聚集系数很高,对于一个社交网络来说很常见。平均聚集系数很高,因为它比随机网络要大得多。传递性是对平均聚类系数。相对于网络大小,直径较小。正边约占边总数的 85%。
边缘重量分布。
当我们使用信任网络时,我们对至少有一个度的节点的度分布感兴趣(也就是说,至少有一个人信任或不信任那个人)。这里的“程度”是受欢迎程度的代表。我们的第一个假设是,这种分布遵循幂定律(少数高信任节点,大量低信任节点)。检查它是否存在的一种方法是看度数分布的双对数图是否是线性的。
对数对数指数分布。
这种关系是线性的,所以我们对幂律分布的假设是正确的。接下来我们要检查的是度数分布是否处于无标度状态,也就是说
其中 k 表示度数大小,2 < γ < 3。我们运行内置函数,得到幂律系数等于 1.70,所以这个网络不在无标度区。即使我们不在无标度区,度数分布也是异质的,平均值没有多少统计意义。
小世界现象最大弱连通分量的平均最短路径为 4.1,小于过渡基线 6 和 11(其中节点总数的对数)。所以我们网络的底层有向图是一个小世界模型。这对于具有中枢的网络来说是常见的:对于无尺度机制,它与 log logN 成比例(在这种情况下,如果我们处于无尺度机制中,它将是 2.4)。
蝶形结构我们可以通过检查连接的组件来获得关于网络结构的更多信息。最大强连通分量和最大弱连通分量由 41441 和 119130 个节点组成。第二大强连通分量等于 15,第二大弱连通分量等于 20。因此,我们可以得出结论,我们的图有一个很大的组成部分,其中人们相互跟随,占整个网络的大约 30%,大约 90%的节点以某种方式连接。这些分量中的边数分别为 693737 和 833695,分别占边总数的 0.825%和 0.991%。我们用网络的结构做了一个类比,最后检查它是否有一个蝶形结构。我们找出了外部组件的尺寸,并得到以下结果:
其他组件。
我们确实有一个蝶形结构。它与原始的网状结构相当,只是卷须和导管的总体比例比原始情况下小得多。这很正常,考虑到我们有一个小世界网络。
互惠对于这个网络来说,最重要的措施就是互惠。互惠可以和社会选择联系在一起(我信任信任我的人)。对于我们的图表,整体互易性等于 0.31。对于最强的连通分量,互易性等于 0.37。
学位对图不同类型的学位之间有什么关系?
程度与程度的关系。
平均而言,外向度较高的节点往往具有较高的内向度。在具有小内度和外度的节点之间,没有明显的相关性。
积极与消极的程度。
从这个情节中,我们看到最受信任的作者并不倾向于最不受信任的作者。高度不被信任的作者通常有大约 100 个负面的边缘。
正与负输出度。
从图中,我们看到大多数人更喜欢信任而不是不信任的关系。但是我们已经从边权重分布中知道了。
我们记得,同配性意味着节点倾向于连接到具有相似能力的其他节点,而异配性意味着具有较高程度的节点连接到具有较低程度的节点。
外向度匹配度。
从该图中,我们看到节点基于它们的出度是分类的,即它们连接到具有相似出度的节点。
不同程度的协调性。
然而,进入的边缘往往是轻微的异配。这并不奇怪,因为高进入度的边倾向于连接到低进入度的边,这仅仅是因为它们没有太多相似的边。
富人俱乐部效应我们想看看最可信的边缘之间有多少互连。由于我们网络的规模和幂律性质,我们无法观察到一定比例的节点,只能观察到前一百个节点。我们研究了两种迹象的密度。
热门节点的丰富俱乐部效应。
从剧情上看,我们没有富人俱乐部效应。在十个最受欢迎的边之后,密度保持在 0.4 左右。由于密度接近一半,我们要检查的是连接倾向于单侧还是随机的一对节点相互跟随。这个子图的互易性是 63%,所以我们得出结论,流行的边通常是不相连的,但当它们相连时,下面是互易的。一种解释是,我们可能认为这些流行节点来自不同的组,因此不在网络中通信。从剧情中我们也看到了一些最信任的成员对其他高信任成员的不信任。
负富俱乐部这有点不常见,但我们也想检查负度数最高的边之间是否存在某种关系。想象一下,在我们的社交网络中,我们有一群人的观点偏离了共识(想想阴谋论者或一群网络巨魔),他们通常不喜欢,但在他们的群体中非常受欢迎。通过检查这些节点之间的富人俱乐部效应,我们可以检查这样一个群体的存在。
冷门节点的富人俱乐部效应。
由于顶部四个最不可信的顶点之间没有连接,我们将它们删除并绘制了另一个图形。然而,我们看到不信任的节点之间没有高度的互连(有一定程度的信任,但不显著)。我们看到它很快变成了不信任。所以,这个网站不被信任的成员倾向于像孤岛一样运作。
社区结构我们的图表没有任何关于图表中潜在社区结构的先前信息。因此,我们使用 Louvain 算法来检测它们。与同类算法相比,它的优势在于速度非常快,即使对于大型网络也是如此。我们的主要目标是找到最中心的社区,因此我们观察了最大 SCC 的基本无向图(忽略了边权重,因为不信任的成员仍然是社区的一部分)。
Louvain 算法产生了少量的大组件和大量的非常小的社区。总共有 11 个社区至少有 100 名成员,它们的规模如下:10032、10540、453、11587、221、143、945、311、111 和 124。
因此,有三个大的社区,每个社区占最大 SCC 的大约 25%。由于这是一个大型网络,因此该算法可能无法检测小型网络(分辨率限制)。然而,由于总模块性等于 0.43,我们对获得的结果感到满意。
行为采纳我们感兴趣的是,在可信网络中,某种行为的采纳会是什么样子。例如,假设这是一个医生网络,新的疗法已经出现。开始时,一些高度信任的医学家会开始认为这种疗法是好的(我们假设他们越被信任,在某种程度上就越了解医学进步)。此外,一些极不被信任的医学家也会采取同样的观点。但是,网络中的节点不知道其他节点的受欢迎程度。因此,只有当他们信任的一定比例的人也会采纳某个观点时,他们才会采纳这个观点。此外,被收养人的行为收养将否定可信节点的行为收养的影响。我们假设一个观点一旦被采纳,就不会被改变(否则这个人可能会改变观点,因为不信任的人会否定它)。通过这种方式,我们实施了单调传播(这种疗法可能有效,人们不会检查他们不信任的人的行为)。为了产生这些结果,我们设置了相同的随机种子。我们假设最初,300 个最信任的人中有 200 个采纳了一个观点,同时 100 个最不信任的人中有 50 个会采纳这个观点(他们可能知识渊博,但是由于各种其他原因而不被信任)。
采用一种行为。
从剧情中我们看到,对于较小的门槛,意见采纳会比较快,而对于较大的门槛,则不会扩散太多。然而,我们希望看到更多有趣的动态。我们通过将阈值设置为 0.4 来生成它们。
每一步的收养数量。
我们看到,在某些时候,人们几乎已经停止采纳意见,但在某些时候,它开始上升。我们知道,由于幂律结构,观点最初传播得很快,但后来传播速度变慢了。这发生在它到达一个密集的星团时,在它的边界度过一段时间后,它开始膨胀。平均每采纳一个意见需要 17.12 个时间单位!这是整个过程持续时间的一半。此外,由于幂律结构,我们可以将意见的大的初始传播归因于这样的事实,即相当多的少数节点大多只关注受欢迎的节点,因此使他们更愿意采纳意见。接下来,我们看进化图。
行为采纳的进化。
我们有兴趣看看其他结构属性是如何强制采纳意见的。似乎合乎逻辑的是,观点不会在外部组件中传播,这是事实,因为只有 26%的成员采用了新的观点。
我们检查的下一件事是在创建的社区中采纳意见。我们想知道这种观点在他们中间传播了多少。我们观察了包含至少一百个节点的六个最小的社区。
小型社区的采用率。
我们看到在这些社区中有密集的集群阻止采纳意见。这进一步表明该数据集包含一定数量的小型异质社区。这是为什么我们在这种情况下没有信息级联的原因之一。其他原因包括:
- 一些节点没有外部度,因此它们没有可信用户的基础。
- 位于最大弱连通分量之外的节点与主事件隔离开来。
- 不信任比信任多得多的节点(就像在现实生活中,有些人只关注消极的方面)。
结论我们已经看到 Epinions 网络展现了社会网络的典型行为:稀疏性、幂律结构和高聚集系数。我们分析了不同程度类型的配对图及其相关性,并获得了有价值的见解。我们已经证明了存在社会选择,我们没有丰富的俱乐部效应。我们隔离了 11 个明显的社区,并检查了其中最小的社区的行为采纳情况。
由于信任是基于所接收信息的质量,我们将它的结构与一般的网络结构进行了比较,我们发现它们是相似的。我们还检查了我们社区的收养行为,发现它基本上不受外界影响。
意见采纳的模拟显示了网络如何对不同阈值的意见采纳做出反应,以及它如何通过组件和社区传播。
代号:https://github.com/radenjezic153/ComplexNetworkAnalysis
Sofa 移动性报告
走还是留?或者如何建立类似苹果和谷歌坐在沙发上的移动分析。
三个月前,在隔离最活跃的阶段,我和我的同事亚历克斯坐在不同城市的沙发上,保持着可接受的社交距离。我们想知道是否有一种简单的方法来了解哪些地方是“安全”的,哪些地方由于疫情而太拥挤了。什么时间在路上遇到的人少,走哪条路线?
这甚至导致了一个服务的原型,该服务从谷歌收集像流行时间这样的数据(对开发者不可用),并显示拥挤和不太拥挤的地方的热图。
众所周知,由于新冠肺炎事件,苹果和谷歌联合起来为医疗机构提供关于人们的移动模式如何变化的统计数据。苹果的报告根据苹果地图中的方向请求,反映了步行、驾驶和运输中的变化,而谷歌则专注于“不同地理位置的移动趋势,跨不同类别的场所,如零售和娱乐、杂货店和药店、公园、公交车站、工作场所和住宅”。
这两个来源都反映了与基线(疫情之前的平均水平)相比,人们开始减少(或增加)通勤、步行、驾车和参观地点的变化百分比。这些公开的数据对好奇的人来说是一个发现,对需要做出明智决定的当局来说是一个资源。
回头看看原型,我们细心的用户假装住在伦敦的梅菲尔区。伦敦成为测试原型的首选城市是有原因的。它有很多公开的实时闭路电视摄像头。你可以通过伦敦交通摄像头网站访问近 900 个摄像头。它还有一个每 5 分钟捕获一次的快照存档,并保存一个半月。
我们假设,如果我们分析流并计算快照上的人数(实时处理对于 sofa 报告来说太繁重了),它可能会为我们提供一些关于特定时间内这些地方有多受欢迎的见解,以及整个流量如何随着时间的推移而变化。所以,我们从市中心拿了 50 个摄像头。我们圆圈的中心是大本钟,而被覆盖的区域从西边的哈罗德百货公司到东边的伦敦桥,从北边的国王十字车站到南边的巴特西公园。相当一个中心区域,所以不能代表整个城市,仍然足够大,直径超过 5 公里。
50 台摄像机观察区
不幸的是,当这个聪明的想法出现在我们脑海中时,可用的快照档案有点过时,无法捕捉 3 月下旬社交距离规则越来越严格导致的流动性大幅下降。所以,我们分析了可用的时间范围:从 4 月 16 日到 7 月 8 日,差不多三个月。
这一分析背后的技术是 OpenCV、YOLOv3 和 tensor flow——现成的开源库和框架。在人物检测方面,我们完全依赖于 YOLO,这是最先进的(最好的)机器学习模型,用于对象检测。
我们对所有 50 台摄像机的计算得出每天的人数大约在 5,000 到 29,000 之间。虚线是趋势线——我们跳跃的每日数字的线性近似值。正如你可能注意到的,有几个数据丢失的日期,这些是我们这边的一些技术问题,或者只是存档中丢失的日期。
中央电视台:每天人
我们得到的数字有多合理?嗯,或多或少,当我们回想起我们只处理一次 5 分钟快照。这是每小时 12 幅图像。在现实中,人们更经常出现在摄像机前,所以理想情况下,我们大约每 20-30 秒拍一张照片,这将使我们每小时拍摄 120-180 张照片,比我们现有的多 10-15 倍。将它乘以我们的数字,在疫情时代,我们会在空旷的一天得到 50,000-75,000 人,在拥挤的一天得到 290,000-435,000 人。考虑到有限的摄像机视野,在伦敦中心 5 公里的范围内似乎是合法的。
伦敦市中心的摄像流示例
苹果公司允许下载原始数据集,这样你就可以与 y 轴上 100%的基线数据进行比较(他们也缺少几天)。图表上 33%的数值意味着总共 67%的伦敦人走得更少。
苹果:移动性降至基线以下
虽然苹果的报告描述了整个伦敦,但相机分析只观察了伦敦市中心的一部分,主要由办公室和公共场所组成,住宅建筑较少。因此,我们的假设是,当居住在卧室社区的人们继续步行去杂货店、公园和其他场所时,在隔离期间,市中心的交通应该会大幅减少。
因此,我们使用两个图表的标准化表示来比较结果。
从我们可以看到,这种增长趋势对市中心来说更具侵略性。由于最初的强劲下跌,更快的增长是我们应该期待的。随着时间的推移,限制变得越来越弱,越来越多的人回到正常的生活,参观位于市中心的地方。
如果我们仔细观察 6 月和 7 月,我们会发现尽管实际数字有波动,但市中心和大伦敦的趋势(虚线)几乎相同。这可能意味着市中心和城市其他地方的步行模式正在以大致相同的速度恢复正常。
细看六七月:央视 vs 苹果
作为 Sofa 报告的结论,我想说我们的方法肯定不适用于更大的区域,仅仅因为缺少视频监控。然而,对于配备摄像头的当地社区来说,这与苹果和谷歌等巨头的结果相当。
这里的所有计算都是使用临时的桌面 CPU 完成的,而不是最新一代的 GPU。
开发人员的 10 大软技能
技能没有你想象的那么重要,要知道为什么
当我开始做开发人员时,我认为技术能力是我们的工作。因此,我继续训练自己,试图每天都成为更好的开发人员。我一开始忽略的是,我们的专业背景不仅仅需要是技术性的。很明显,如果你想玩机器学习,你必须掌握 python、Keras、TensorFlow 和我们现在拥有的所有其他酷东西。这些是你的工具。这是你的操场。这些都是你的硬技能。你可能错过的是,也要关注那些柔软的东西。软技能有助于更好地与他人合作,更容易获得结果,让你的工作更有价值。如果你认为软技能不能产生有效的软件,请阅读这篇文章。我也是这么想的,但是只有当我开始审视整个职业生涯,而不仅仅是技术部分时,我的职业生涯才会有所提升。在这篇文章中,你会发现成为一名更好的 IT 专业人员的十项重要技能,以及一些有助于提高这些技能的建议。
我和❤️一起创作的
沟通
杰森·罗斯韦尔在 Unsplash 上的照片
写好提交评论是必要的,但还不足以成就辉煌的职业生涯。在大多数公司,IT 专业人员与非技术人员一起工作。许多顾问直接在客户办公室工作,或者一些开发人员仍然在小组中工作,并直接与业务委员会联系。在这些情况下,但总是在生活中,用简单的术语解释复杂事物(技术细节)的能力是拥有良好职业生涯的基础。这有助于你要求加薪,或者在日常工作中被非技术人员理解。我的建议是始终使用可以理解的语言,对听者背景之外的事情进行类比,记住解释他们错过的每一个故事片段。
交流对那些从事交流的人有用。
—约翰·鲍威尔
灵活性
照片由 Rawan Yasser 在 Unsplash 上拍摄
接受需要做的事情,拥抱改变。这并不意味着做一个被动的人,做他们要求的事情而不做回答。灵活性意味着什么呢?它意味着知识不是完美的。所以事情可以改变,这种改变是受欢迎的。如果需要的话,你将准备好转换技术栈、架构,或者使你的软件适应不同的规范。无论如何,另一方面,你会努力防止返工或不利的变化。在自然界中,对变化反应更快、适应环境的个体有很多变化可以生存。接受改变让我们更加意识到我们将会是什么样的机会,并给我们机会将改变推向正确的方向。对抗改变就像推迟不可避免的事情。
"衡量智力的标准是改变的能力."阿尔伯特·爱因斯坦
倾听
照片由 Alireza Attari 在 Unsplash 上拍摄
不管是不是技术性的,你必须倾听每个人告诉你的东西。倾听不仅仅意味着让它说话,等他说完。我们需要提高的是积极倾听的能力。积极倾听意味着试图理解别人告诉我们的话,如果我们不明白为什么别人这么说,就提出问题,或者只是要求解释我们不清楚的部分。如果没有形成强有力的倾听态度,就不可能成为好的队友和沟通者。当人们说话时,要完全倾听。
成为一个优秀的谈话者只有一条规则——学会倾听。
—克里斯托弗·莫利
创造力
照片由 Dragos Gontariu 在 Unsplash 上拍摄
大多数人认为在 IT 领域工作不需要灵感。是的,大部分工作被过程、工具和需求所覆盖——一些非常枯燥和重复的东西。问题是,要掌握这一套东西,你需要思考很多。在解决问题或设计新的解决方案时,你必须有创造力。创造力是他们在学校不教的东西,但是在一个问题面前,你需要它。所以,不要害怕说出意识形态界限之外的话,找到独特的解决方案。我们每天都在努力改进我们的程序,使工作的每一部分标准化,但是当形势需要时,我们不得不把兔子从缸里扔出来。
创造力是充满乐趣的智慧。
——阿尔伯特·爱因斯坦
协力
普里西拉·杜·普里兹在 Unsplash 上的照片
开发是一项你通常独自完成的活动。有你,你的键盘,也许还有一杯咖啡。你的重点是代码。问题是,如今,独自完成一个项目是相当大的努力。垂直化需要掌握完成一个 web 应用程序的每一项技术。完成这项工作所需的人工日是如此之多,以至于你会明白为什么我们不需要个人,而是需要团队。
如果你想走得快,那就一个人走。但如果你想走远,那就一起走。
无论如何,团队工作并不容易。小组中的每个成员可能不同意在团队中工作。也许这个团队已经有了另一个团队而不是你。你可能不同意团队的决定。可能有了这些问题,单干会更好?我认为没有,如果你不想在假期带着你的电脑以防你需要修复生产中的一些 bug。
谈判
有时候,团队中不同的人有不同的愿景。人们并不总是时间一致的。人们可能有不同的兴趣或约束。当事情不是非黑即白时,你必须找到正确的灰色点。对于一个开发者或者技术人员来说,很容易陷入不知所措的境地。只需考虑任务期限、项目期限或功能需求。或者只是你老板做出的一些技术性决定。在这样的情况下,你必须找到一个能让双方都满意的解决方案。在这个谈判过程中,你必须把对方的鞋。你得明白别人立场背后的原因。只有这样做,你才能把利己动机和真正的动机分开。也许你的项目经理把截止日期定得这么近是因为客户不允许任何谈判,所以你也是一样。或者,也许他正试图节省一些预算日,以获得更好的结果。这个概述让你知道在哪一点上你必须毫不妥协,在哪里你可以放手。
在每次谈判中,在不放弃你的目标的情况下,找到最大化对方利润的解决方案是最好的选择——不要只从经济意义上理解。
关系是一种不断的协商和平衡。
克莱尔·丹尼斯
介绍会;展示会
作为一名技术人员,我们太专注于工作,以至于经常忽略了演示阶段。就好像我们在最关键的一点上耗尽了所有的能量。做是必须的,但你需要一个出色的输出演示来赋予它正确的价值。我不是让你夸大其词,只是实话实说。重要的不是内容,而是你如何呈现。做一个好的陈述,清晰地表达想法,向他人陈述事实,你所做的有更多的机会被理解和正确评价。这适用于解释概念,展示你已经完成的任务,或者简单地告诉你正在咖啡机旁做什么。在试图向别人推销你的想法之前,先把他们推销给你。
营销不再是关于你制造的东西,而是关于你讲述的故事。
——塞思·戈丁
指导
团队是一种解决方案,允许许多不同技能的人进行生产,就好像所有人都是最好的一样。也许你会认为花时间帮助初级同事是浪费时间。我理解你的观点。你很忙,充满了问题,为什么要浪费时间去帮助别人呢?你需要关注“浪费”这个词,这就是问题所在。换成“投资”,你可能会更关注收益而不是成本。如果你训练一个低年级学生,如果你让他学习程序,下一次他将会是自主的。他会自己完成任务,不会影响你的工作。你将能够开始授权。
天赋赢得比赛,但团队合作和智慧赢得冠军。
—迈克尔·乔丹
决心
弗兰克·布施在 Unsplash 上拍摄的照片
通往项目竞赛的道路是漫长的。不要放弃。沿途会遇到困难,但你必须解决它。作为专业人士,你必须继续。有时需要额外的努力才能看到项目的结束。你需要每天醒来,开始为你的目标而努力。这不是一场战争。这就是生活。
我们最大的弱点在于放弃。成功最可靠的方法总是再试一次。
—托马斯·A·爱迪生
领导力
佩里·格罗内在 Unsplash 上的照片
什么是领导力?领导能力与职位、资历或文化无关。领导力不仅仅意味着告诉人们做什么。与管理无关。领导力是带领人们前进的态度。
领导力是将愿景转化为现实的能力
—沃伦·本尼斯
在一个团队中,你不是唯一的玩家。每个运动员需要尽最大努力赢得比赛。作为一名领导者,你必须将正确的任务委派给正确的人,并根据人们的态度来指导每个人。你必须忘记你作为团队领导的生产力。你必须专注于团队生产力。这需要很强的授权能力和优秀的沟通技巧。你必须是一个好的倾听者,谈判者…但是所有这些技能都已经提到了。
如何获得这些技能
也许这些软技能是无法通过网络课程学到的。和生活中的大多数事情一样,你需要每天训练它。训练意味着理解你想要提高什么,然后每天关注如何做得更好。
生活是一个大型的回顾会议,在这里你致力于你生命中最重要的项目:你自己。
也就是说,一旦你明白你需要在哪方面努力,你就可以找到很多可以帮助你成长的自助书籍。我可以在这里写下对我有效的方法,但是我认为最好自己去找。
你必须开始倾听自己,学会如何回应自己的需求。
解释了 Softmax 激活功能
并从零开始实现。
如果你做过深度学习,你可能会注意到两种不同类型的激活函数——一种用于隐藏层,一种用于输出层。
照片由 Aaron Burden 在 Unsplash
用于隐藏层的激活函数对于所有隐藏层来说几乎是相同的。不太可能看到 ReLU 用在第一个隐藏层上,后面是双曲正切函数——一般都是 ReLU 或者 tanh。
但是我们在这里说的是输出层。这里我们需要一个函数,它接受任何值,并将它们转换成概率分布。
Softmax 功能来拯救。
该函数对于分类问题非常有用,尤其是当你处理多类分类问题时,因为它会报告每个类的“置信度”。因为我们在这里处理的是概率,所以 softmax 函数返回的分数总和将为 1。
因此,预测类是列表中置信度得分最高的项目。
现在,我们将看到 softmax 函数是如何用数学方法表达的,然后将它翻译成 Python 代码是多么容易。
数学表示
根据官方维基百科页面,下面是 softmax 函数的公式:
乍一看可能会令人望而生畏,但这是你在研究深度学习时会遇到的最简单的函数之一。
它指出,我们需要对输出层的每个元素应用一个标准指数函数,然后通过除以所有指数的总和来归一化这些值。这样做可以确保所有取幂值的总和等于 1。
如果需要,请花时间多次通读前一段,因为这对进一步理解至关重要。如果仍然有点模糊,我们准备了一个(希望)有用的图表:
以下是步骤:
- 对输出图层的每个元素取幂,并将结果相加(本例中约为 181.73)
- 取输出层的每个元素,对其取幂并除以步骤 1 中获得的和*(exp(1.3)/181.37 = 3.67/181.37 = 0.02)*
到目前为止,我希望您已经了解了 softmax 激活函数在理论上是如何工作的,在下一节中,我们将在 Numpy 中从头开始实现它。
履行
如果你已经理解了前一部分,这一部分将会很容易和直观。如果没有,简单的 Python 实现应该仍然有助于一般的理解。
首先,让我们声明一个模拟神经网络输出层的数组:
output_layer = np.array([1.3, 5.1, 2.2, 0.7, 1.1])
output_layer**>>> array([1.3, 5.1, 2.2, 0.7, 1.1])**
把这想成 K 类分类问题,其中 K 是 5。接下来,我们需要对输出层的每个元素求幂:
exponentiated = np.exp(output_layer)
exponentiated**>>> array([ 3.66929667, 164.0219073 , 9.0250135 , 2.01375271,
3.00416602])**
现在我们准备计算概率!我们可以使用 Numpy 将每个元素除以取幂和,并将结果存储在另一个数组中:
probabilities = exponentiated / np.sum(exponentiated)
probabilities**>>> array([0.02019046, 0.90253769, 0.04966053, 0.01108076, 0.01653055])**
就是这样-这些是从输出图层的原始值中获得的目标类概率。
之前我们提到过概率之和应该等于 1,所以让我们快速验证一下这句话是否有效:
probabilities.sum()**>>> 1.0**
我们结束了。如果你明白了这一点,你就明白了 softmax 的激活功能。让我们在下一部分总结一下。
在你走之前
softmax 函数应该很容易理解。由于 TensorFlow 和 PyTorch 等复杂的库,我们不需要手动实现它。这并不意味着我们不应该知道他们是如何工作的。
我希望这篇文章足够容易理解和理解。感谢阅读。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
Softmax 激活功能——实际工作原理
法托斯 Bytyqi 在 Unsplash 上的照片
在处理机器学习问题,具体来说,深度学习任务时,Softmax 激活函数是一个流行的名称。它通常被放在深度学习模型的最后一层。
它通常用作神经网络的最后一个激活函数,将网络输出标准化为预测输出类别的概率分布。—维基百科[ 链接
Softmax 是一个将数字/对数转换成概率的激活函数。Softmax 的输出是一个向量(比如说,v
),包含每种可能结果的概率。对于所有可能的结果或类别,向量v
中的概率总和为 1。
数学上,Softmax 定义为:
例子
考虑一个 CNN 模型,该模型旨在将图像分类为狗、猫、马或猎豹(4 种可能的结果/类别)。CNN 的最后(全连接)层输出 logit 向量 L,该向量通过 Softmax 层将 logit 转换为概率 p。这些概率是 4 个类别中每个类别的模型预测。
输入图片来源:Victor Grabarczyk 在 Unsplash 上拍摄的照片。作者图解。
让我们计算应用 Softmax 后第一个 logit 生成的概率
您可以用同样的方式计算其他值。
在 python 中,我们可以如下实现 Softmax
from math import expdef softmax(input_vector):
# Calculate the exponent of each element in the input vector
exponents = [exp(j) for j in input_vector] # divide the exponent of each value by the sum of the
# exponents and round of to 3 decimal places
p = [round(exp(i)/sum(exponents),3) for i in input_vector] return pprint(softmax([3.2,1.3,0.2,0.8]))
输出:
[0.775, 0.116, 0.039, 0.07]
**符号:**我们可以将所有的 logits 表示为一个向量, v ,并在这个向量上应用激活函数, S ,以输出概率向量, p ,并表示操作如下
注意标签:狗、猫、马、猎豹都是字符串格式。我们需要定义一种将这些值表示为数值的方式。
将分类数据转化为数值数据
真相标签是分类数据:任何特定的图像都可以被归类到这些组中的一组:狗、猫、马或猎豹。然而,计算机不理解这种数据,因此我们需要将它们转换成数字数据。有两种方法可以做到:
- 整数编码
- 一键编码
整数编码(也叫标签编码)
在这种编码中,标签被赋予唯一的整数值。例如在我们的例子中,
0 代表“狗” 1 代表“猫” 2 代表“马” 3 代表“猎豹”。
*何时使用整数编码:*当标签本质上是有序的,即具有某种顺序的标签时,使用整数编码。例如,考虑一个分类问题,其中我们想要将服务分类为差、中性或好,那么我们可以如下编码这些类
0 为“不良”,1为“空档”,2为“良好”。****
显然,标签有一定的顺序,并且标签相应地赋予标签权重。
相反,当标签是名义上的(没有特定排序的名称)时,我们避免使用整数编码,例如,考虑花卉分类问题,其中我们有 3 个类别:鸢尾、杂色鸢尾和海滨鸢尾,
0 为“刚毛鸢尾” 1 为“杂色鸢尾” 2 为“海滨鸢尾”。
该模型可以采用标签的自然排序(2>1>0 ),并且给予一个类别比另一个类别更多的权重,而事实上这些只是没有暗示特定排序的标签。
一键编码
对于不存在这种顺序关系的分类变量,整数编码是不够的。独热编码是优选的。
在独热编码中,标签由二进制变量(1 和 0)表示,从而对于给定的类,生成二进制变量,其中 1 表示对应于该特定类的位置,0 表示其他位置,例如,在我们的情况下,我们将为 4 个类生成以下标签
【1,0,0,0】【狗】【0,1,0】【猫】【0,0,1,0】【马】【0,0,0,1】【猎豹】。
**备注:**尽管我们已经回答了“何时使用哪种类型的编码系统?”。有一种方法可以实际使用任何一种编码方法。对于 TensorFlow 和 Keras 来说,这取决于你如何定义你的损失函数。我们稍后会谈到这一点。
回想一下:Softmax 函数的分母是一个归一化项。它确保函数的输出是介于 0 和 1 之间的值。
但有人可能会问,为什么不使用标准归一化,即取每个 logit,然后除以所有 logit 的总和,以获得概率?为什么要拿指数?这里有两个原因。
- Softmax 归一化对小的和大的变化/改变有不同的反应,但是标准归一化不通过强度区分刺激,因此最长比例是相同的,例如,
Softmax 标准化
softmax([2,4]) = [0.119,0.881]
softmax([4,8]) = [0.018,0.982]
#标准标准化
def std_norm(input_vector):
p = [round(i/sum(input_vector),3) for i in input_vector]
return p
std_norm([2,4]) = [0.333,0.667]
std_norm([4,8]) = [0.333,0.667]
注意到区别了吗?对于标准归一化,一个矢量和由标量缩放的同一个矢量产生相同的输出。对于上述情况,第一个向量[2,4]乘以 2 得到[4,8],两者产生相同的输出。根据相同的推理,以下对将产生相同的输出:{[8,24],[2.4,7.199]}比例因子为 0.3。事实上,任何按因子缩放的矢量都会产生与原始矢量相同的输出。
- 当逻辑中有负值时,就会出现另一个问题。在这种情况下,您将在输出中以负概率结束。Softmax 不受负值的影响,因为任何值(正或负)的指数总是正值。
我希望读完这篇文章后,你现在对 Softmax 激活功能实际上是如何工作的有一个更清晰的理解。
您可能也会对以下文章感兴趣
在大多数分类问题中用于优化机器学习模型的损失函数…
towardsdatascience.com](/cross-entropy-loss-function-f38c4ec8643e) [## 基于实例的目标检测度量
AP、mAP、AP50 等指标,并举例说明。
towardsdatascience.com](/on-object-detection-metrics-with-worked-example-216f173ed31e) [## 端到端机器学习项目:综述和分类
将评论分为正面或负面的项目
towardsdatascience.com](/end-to-end-machine-learning-project-reviews-classification-60666d90ec19)
在https://medium.com/@kiprono_65591/membership加入 medium,全面了解 Medium 上的每个故事。
每当我用这个链接发帖时,你也可以把文章发到你的邮箱里:【https://medium.com/subscribe/@kiprono_65591
感谢您的阅读😊
到 2030 年,软件开发人员可能会被淘汰
意见
为什么你不会丢掉工作
软件开发是扯淡的工作吗?我不这么认为。安妮·斯普拉特在 Unsplash 上的照片
1930 年,约翰·梅纳德·凯恩斯预测到本世纪末我们将拥有 15 小时工作周。但到了 2013 年,很明显这位伟大的经济学家犯了一些错误。
欢迎来到人类学家大卫·格雷伯创造的狗屁工作时代。自 20 世纪 30 年代以来,全新的行业如雨后春笋般涌现,但这些行业并不一定给我们的生活增加多少价值。Graeber 可能会称软件开发中的大多数工作为扯淡。
我不同意 Graeber 的观点,尤其是在软件方面。但他确实触及了一个有趣的问题:随着越来越多的流程实现自动化,大多数工作在某个时候都会过时。据估计,使用目前的技术,45%的工作可以自动化。随着时间的推移,他们可能会。
在软件开发中,事情发展得非常快,你可以实时看到这种情况:软件测试一成为热门话题,自动化工具就开始涌现。这仅仅是软件中废话部分——迭代和耗时的部分——被自动化的众多领域之一。
然而,这回避了一个问题,即开发人员是否会因为构建自动化工具而变得过时。如果越来越多的机器可以自己写代码,我们还需要人类做什么?
函数式编程的鼓吹者们,你们把枪口对准了错误的敌人
towardsdatascience.com](/object-oriented-programming-is-dead-wait-really-db1f1f05cc44)
从设计逻辑到设计思维
软件开发人员本质上是建设者。他们构建逻辑链接、算法、程序、项目等等。关键是:他们建立逻辑的东西。
随着人工智能的兴起,我们看到了范式的转变。开发人员不再设计逻辑链接。相反,他们在这些逻辑联系的启发上训练模型。
许多开发人员已经从构建逻辑转向构建思维。换句话说,越来越多的软件开发人员开始从事数据科学家的活动。
自动化的三个层次
如果你曾经使用过 IDE,那么你就会知道辅助软件开发是多么的神奇。一旦您习惯了像自动完成或语义代码搜索这样的功能,您就不想再没有它们了。
这是软件开发中自动化的第一个领域。当机器理解你想要实现的东西时,它们可以帮助你完成这个过程。
第二个领域是封闭系统。考虑一个社交媒体应用程序:它由许多相互链接的不同页面组成。然而,它是封闭的,因为它没有被设计成直接与另一个服务通信。
尽管构建这样一个应用程序的技术变得越来越容易使用,但我们还不能谈论真正的自动化。到目前为止,如果您想创建动态页面、使用变量、应用安全规则或集成数据库,您需要能够编码。
第三也是最后一个领域是集成系统。例如,银行的 API 就是这样一个系统,因为它是为了与其他服务通信而构建的。然而,在这一点上,自动化 ATM 集成、通信、世界模型、深度安全和复杂的故障排除问题几乎是不可能的。
自动化的三个领域。图片由作者提供,但改编自埃米尔·沃纳在 InfoQ 的演讲。软件开发是一条坎坷的道路,我们并不真正知道未来何时到来。
电脑眼中的世界
当被问及未来是否会被机器人取代时,人类工人通常不这么认为。这适用于软件开发以及许多其他领域。
他们的理由很清楚:创造力、同理心、协作或批判性思维等品质不是计算机所擅长的。
但通常,这并不是完成工作的关键。即使是最复杂的项目也包含许多可以自动化的小部分。深度思维科学家 Richard S. Sutton 这样说:
“研究人员寻求利用他们在该领域的人类知识,但从长远来看,唯一重要的是利用计算。”
不要误会我;人类的素质是惊人的。但是当涉及到常规任务时,我们高估了这些问题的重要性。例如,在很长一段时间里,即使是研究人员也认为机器永远无法识别照片上的猫。
如今,一台机器可以一次分类数十亿张照片,而且比人类更准确。虽然一台机器可能无法惊叹一只小猫的可爱,但它非常擅长处理未定义的状态。这就是机器眼中的小猫照片:一种未定义的状态。
走向新的流形和尺度
除了处理未定义的状态之外,还有两件事计算机可以比人做得更有效率:首先,大规模地做事。第二,研究新颖的流形。
我们都经历过计算机在一定规模下工作得有多好。例如,如果你要求一台计算机print("I am so stupid")
两百次,它会毫无怨言地这样做,并在几分之一秒内完成任务。问一个人类,你将需要等待几个小时来完成这项工作…
流形基本上是一种奇特的或数学的方式,指的是共享特定属性的空间子集。例如,如果你拿一张纸,那是三维空间中的二维流形。如果你把这张纸揉成一团或者折叠成一个平面,它仍然是一个流形。
事实证明,计算机确实擅长在人类难以想象的流形中工作,例如,因为它们延伸到二十个维度,或者有许多复杂的扭结和边缘。由于许多日常问题,如人类语言或计算机代码,可以用数学流形来表达,因此在未来部署真正高效的产品有很大的潜力。
我们在计算机可扩展性和新流形探索方面的进展。我们在第一区和第二区工作,但几乎没有触及第三区。图片由作者提供,但改编自埃米尔·沃纳在 InfoQ的演讲。
现状
当前的发展
看起来开发者已经使用了很多自动化工具。但是我们仅仅处于软件自动化的尖端。迄今为止,自动化集成系统几乎是不可能的。但是其他领域已经实现了自动化。
首先,代码审查和调试可能很快就会成为过去。瑞士公司 DeepCode 正在开发一款自动识别 bug 的工具。谷歌的 DeepMind 已经可以为现有代码推荐更优雅的解决方案。脸书的 Aroma 可以自动完成小程序。
更有甚者,机器推断代码相似度系统,简称 MISIM ,号称可以像 Alexa 或 Siri 理解人类语言一样理解计算机代码。这是令人兴奋的,因为这样的系统可以让开发人员自动化常见且耗时的任务,如将代码推送到云或实现合规性流程。
激动人心的地平线
到目前为止,所有这些自动化在小项目中表现很好,但是在更复杂的项目中却毫无用处。例如,错误识别软件仍然会返回许多误报,如果项目有一个非常新颖的目标,自动完成功能就不起作用。
由于 MISIM 还没有出现很长时间,这个自动化还没有定论。然而,你需要记住,这些仅仅是开始,这些工具有望在未来变得更加强大。
即将到来的应用
这些新的自动化设备的一些早期应用可能包括跟踪人类活动。当然,这并不意味着像一个间谍软件;更确切地说,像安排工人的工作时间或为学生个性化课程这样的事情可以通过这种方式进行优化。
这本身就提供了巨大的经济机会,因为学生可以更快地学习重要的东西,工人可以在他们碰巧更有生产力的时间工作。
如果 MISIM 像它承诺的那样好,它也可以用来重写遗留代码。例如,许多银行和政府软件都是用 COBOL 语言编写的,而这种语言现在已经很难教授了。将这段代码翻译成一种更新的语言会使它更容易维护。
在未来的很长一段时间里,成为一名软件开发人员仍将令人兴奋不已。布鲁克·卡吉尔在 Unsplash 上的照片
开发商和企业如何保持领先
所有这些新的应用都令人兴奋。但是在他们头上悬着一把巨大的达摩克利斯之剑:如果竞争对手在你赶上之前就利用了这些自动化,那该怎么办?如果他们让开发人员完全过时了怎么办?
投资于持续交付和自动化测试
这无疑是自动化世界中的两个流行语。但是它们仍然很重要。
如果你在发布前没有测试你的软件,你可能会损害用户体验或者遇到安全问题。经验表明,自动化测试涵盖了人类测试人员甚至没有想到的案例,尽管它们可能是至关重要的。
有大量的自动化软件用于测试,还有版本控制(和许多其他框架)用于持续交付。在大多数情况下,花钱购买这些自动化产品似乎比自己开发要好。毕竟,你的开发人员是被雇来构建新项目的,而不是自动化枯燥的任务。
如果你是一名经理,把这些购买视为一项投资。通过这样做,你尽你所能支持你的开发者,因为你利用了他们真正擅长的东西。
左移:在每个项目的早期阶段包括开发人员
通常,项目是在高层管理或 R&D 团队附近的某个地方创建的,然后向下传递,直到他们到达开发团队——然后开发团队的任务是使这个项目想法成为现实。
然而,由于不是每个项目经理都是经验丰富的软件工程师,项目的某些部分可能由开发团队实现,而其他部分可能成本高昂或者几乎不可能实现。
这种方法在过去可能是合法的。但是作为软件开发中许多单调的部分——是的,这些部分是存在的!—正在被自动化,开发人员有机会变得越来越有创造力。
这是一个让开发人员离开的绝佳机会,也就是说,让他们参与到项目的规划阶段。不仅要他们知道什么可以实施,什么不可以。凭借他们的创造力,他们可能会以事先无法想象的方式增加价值。
让软件成为重中之重
自从微软的塞特亚·纳德拉宣称“每一项业务都将是软件业务”以来,已经过去了短短的五年。他是对的。
开发人员不仅应该在管理上向左转。软件应该提高优先级。
如果说当前的疫情教会了你什么,那就是如今很多生活和价值创造都发生在网上。
软件为王。矛盾的是,自动化程度越高,这一点就越明显。
自动化正把软件爱好者变成领导者。在 Unsplash 上由Christina @ wocintechchat.com拍摄的照片
底线是:极客正在成为领导者
当我在学校的时候,喜欢电脑的人被认为是不合群的孩子、书呆子、极客、不可爱的生物、缺乏人类感情和激情的僵尸。我真希望我是在夸大其词。
然而,随着时间的推移,越来越多的人看到了开发商的另一面。编写代码的人不再被认为是书呆子,而是被认为是能做出很酷的东西的聪明人。
自动化程度越高,软件就越强大。从这个意义上来说,你担心由于自动化而失去开发人员的工作是没有根据的。
当然,十年后——甚至几个月后——你可能会做一些你现在都无法想象的事情。但这并不意味着你的工作会消失。而是会升级。
你真正需要克服的恐惧不是你可能会失业。你需要摆脱对未知的恐惧。
开发者,你不会过时的。你们不会再是书呆子了。相反,你们会成为领导者。
数据科学家的软件工程——写干净代码的艺术
照片由来自 Pexels 的 Markus Spiske 拍摄
这是本系列的第二篇文章。有关该系列文章的列表,请查看部分的前几篇文章。
简介
“代码被阅读的次数比它被编写的次数多”是软件工程师中的一句名言。当我们不考虑目标(数据科学与否)、语言(R、Python 或 Scala)或项目性质而编写代码时,干净的代码风格使开发人员的生活变得容易。我个人相信 CRUM 哲学,容易合作,容易理解,容易保持。如何带领你的团队走向一个干净的代码大军,是一个具有挑战性的任务。编码标准的重要性来了。一个定义良好的标准,一个由工程师和数据科学家团队遵循的定制编码标准,总是能确保我们拥有可维护的软件工件。但是在一堆笔记本的世界里。rmd 文件编码标准的空间在哪里?本文试图讨论编码标准这个主题,以及如何构建自己的标准。
编码标准
编码标准与最佳实践指南一致,这是一组开发人员想要遵循的。同意指南告诉我们必须如何编写代码,以便项目代码在开发人员之间保持一致。所有成熟的软件开发和产品团队总是创建和维护这样一个标准作为参考。自从多技术和多语言开发开始以来,人们在不同语言之间切换就成了一种需求。Data Scientist 使用笔记本和类似技术中的探索性(可视化)和开发支持。在这种情况下,焦点更多的是在“模型”而不是代码上,直到它到达部署。在本文中,我们将研究 Python 和 r。
Python 和 PEP8
一般来说,Pythonista 喜欢遵循 PEP-8 编码标准。当吉多·范·罗苏姆创建 Python 时,可读性是基本的设计原则之一。一般来说,Python 代码被认为是可读的。但是简单和强大的电池使得阅读简单的代码变得困难。PEP-8 的存在是为了提高 Python 代码的可读性。大多数时候,有经验的 Python 开发人员会为团队制作一个定制的 Python 指南。主要关注领域(总体而言)包括:
命名规格
代码布局
刻痕
评论
表达和陈述
一般编程建议
这将是一个起点。一般来说,对于数据科学项目和软件项目,还有更多的情况需要处理。大多数基于 Python 的项目现在都在使用 Python3.X。类型提示是 P3.x 的关键特性之一。建议将其作为编码指南的一部分。数据科学项目中典型的[模式和反模式之一是 lambda 函数的使用和滥用。大多数时候,lambdas 在生产中进行调试。关于数据帧操作的 lambda 的使用以及可追溯性和调试的目的应该被强制执行。
需要关注框架驱动的模式,例如 Pandas 和其他框架。其中一个例子是在 to_sql API 中使用 SQL 数据类型。大多数情况下,一个长字典直接输入到 to_sql 中。为简单起见,变量可以管理这种模式;更多地指定数据类型是一次性的需求。
Google 的 Python 编码指南[1]是为你的团队精心设计 Python 编码标准的一个很好的起点。另一个有用的参考是 RealPython 的‘如何用 PEP 8 写出漂亮的 Python 代码’[2]。
R 和代码风格指南
在最性感的工作头衔“数据科学”之前,R 是统计学家、数据挖掘者和 ML 研究人员最喜欢的编程语言。在冬天到来之前,R 在企业中被大量采用。由于非软件专业人员编写代码的本质,编码标准没有被广泛执行。尽管如此,当企业范围的采用开始时,一些标准已经存在。这三个标准分别是 Tidyverse 风格指南[3]、Hadley Wickham 的指南[4]和 Google R 风格指南[5]。如果我们非常依赖 RShiny 应用程序,最好在关闭标准文档之前咨询一下 UI/UX 团队。
IDE 和笔记本
在软件工程中,IDE 插件总是作为虚拟攻击者来维护编码标准。但是笔记本和 IDE 环境不一样。当我们成为数据科学家和 ML 工程师时,建议证明编码标准的方向。我们应该包括团队特定的最佳实践以及可重用的组件。
大多数时候,大多数笔记本都充满了程序代码(没有函数类,等等…).该代码可以重复几次;探索性数据分析是这方面的典型案例。最好创建可重用的函数。这将在一个高度迭代的模型构建环境中消除复制粘贴错误和头发拉扯。从长远来看,我们最终可能会创建一个好的集合或库,供整个企业使用。
工具
有一些优秀的工具可以帮助格式化和检查编码标准。Flake8 是我最喜欢的工具,我和 VSCode 一起使用。用 R 和 RStudio 编码时,我更喜欢安装‘lintr’;除此之外,我还要确保编辑器是为静态代码分析配置的。
在项目代码评审期间,根据团队经验,我为 lint 分数设置了一个可接受的阈值。所以并不总是 10!如果你开始执行标准,最好从一个可能的点开始,逐步提高期望值。
接下来的步骤
到目前为止,我们讨论了编码标准和指针,以开始数据科学和机器学习项目的编码标准。在一个多样化的、熟练的机器学习/数据实际执行的团队中,这是不容易的。一个人可能必须通过非常耐心的再教育来克服阻力。在接下来的文章中,我们将讨论模型构建者的测试驱动开发。
快乐模型建筑!!! 往期文章
[1]AI/ML/数据科学项目的软件工程—https://medium . com/@ jaganadhg/Software-Engineering-for-AI-ML-Data-Science-Projects-bb73e 556620 e
参考
[1]谷歌 Python 风格指南,https://google.github.io/styleguide/pyguide.html
【2】如何用 PEP 8 写出漂亮的 Python 代码,https://realpython.com/python-pep8/#why-we-need-pep-8
[3]《时尚指南》,https://style.tidyverse.org/syntax.html#control-flow
[4]高级 R 作者哈德利·韦翰,http://adv-r.had.co.nz/Style.html
[5]谷歌的 R 风格指南,https://google.github.io/styleguide/Rguide.html
面向数据科学家的软件工程——测试驱动开发
这是本系列的第三篇文章。有关该系列文章的列表,请查看部分的前几篇文章。
简介
测试驱动开发(TDD)在软件工程实践中非常流行。当涉及到数据科学/机器学习项目时,它收缩到验证和交叉验证。在最好的情况下,我们将讨论 A/B 测试模型。在目前的情况下,ML 模型正在成为 leger IT 系统组件的一部分。现在是企业在数据科学和机器学习项目中考虑 TDD 的时候了。
TDD 是一种软件工程实践,它要求在代码被验证之前编写单元测试。我们不打算讨论软件工程中测试驱动开发的内容和方式。关于这个主题有大量的资源。我们的主要焦点是讨论如何将 DS/ML 项目中的测试范围扩展到交叉验证和测试数据之外。
数据科学中的代码生命周期
数据科学项目有从业务理解到模型操作化的坚实阶段。在每个阶段,我们都会产生不同的结果,并且依赖于多种工具或平台。简而言之,数据理解和分析(或探索性数据分析)、特征选择和工程、模型构建和模型操作化是关键阶段。exploration(或 EDA)阶段实际上是在输入数据中执行一些测试(没有明确地将其称为测试)。之后执行的唯一测试是使用维持数据的验证/测试。从特征工程到模型构建的代码总是在模型操作化部分被重用。这是最关键的阶段,你的 AI ops(AI/ML 的 DevOps)团队将开始与你互动。测试用例的可用性将使 AiOps 的生命周期和部署的验证更加顺利。
考哪里,考什么?
机器学习/数据科学过程中的几乎每一步都是编写测试用例的候选。但是有一些特定的领域需要编写测试用例。需要测试用例的阶段包括:
探索性数据分析
数据预处理
特征工程(非统计)
数据管道
模型和模型管道
部署脚本和 API
有些情况下,我们可能不坚持测试用例。在对数据(不是概念证明)和纯探索性数据分析阶段应用 ML/DS 的可行性研究中,可以忽略测试用例/TDD。在这个阶段,TDD 是一个奢侈和妥协的交付时间。让我们探索一下提到的测试途径。
TDD 和探索性数据分析
在这个阶段,编写测试用例不是必须的。大多数时候,我们可能会检查数据类型、属性特征和数据的统计属性。这个阶段对构建数据管道有很大的帮助。这些管道显然是测试用例的目标。如果我们觉得我们将在固定的时间间隔内重复数据探索,那么最好创建可重用的代码工件。和可重用的工件是测试用例的候选对象!请记住,如果探索性数据分析是唯一的目标,那么就不值得投资创建测试用例。
数据预处理
数据预处理函数是测试用例的优秀候选者,这是必须的。让我们检查一些用例场景来证明我们的论点。
用例-
这个团队正在研究一个文本分类问题。数据的来源是员工和客户之间的公司电子邮件通信。项目的目标是确定意图和主题。
预处理—从 exchange 服务器中提取电子邮件文本,它可以作为。txt 文件。回复和通信线程包含带有唯一标记(如“> > > .”)的以前的消息有电子邮件 ID,电子邮件签名,个人身份信息,如身份证号码,信用卡等。预处理的目的是清理这些数据。
数据科学家或数据工程师将获取可用样本,并开发数据清理功能。由于此活动包括正则表达式的使用,因此有可能出现误报。在这种情况下,最好与脚本一起编写测试用例。这将确保对功能的增量更改不会破坏初始功能或必要的行为。应该为测试用例确定一组覆盖各种场景和组合的输入数据。
注意——作为数据科学家或数据工程师,人们可能会觉得这是一项费力的工作。但是这个测试用例将会帮助你减少有时候等待你的惊喜。
对于文本和结构化数据场景,我们可以考虑同样多的用例。
特色工程
将数据从源系统提取到数据框并创建新要素是一个标准流程。建议测试为特征工程生成的代码。我们将在生产中重复/重新使用相同的代码。这一步使得编码成为编写测试脚本的候选。当代码准备好进行部署时,可以运行一个快速测试来确保流水线在生产线上按预期运行。让我们用一个简单的用例来检验一下。
用例——团队在时间序列数据集中工作。数据科学家根据时间戳创建了两个新属性。时间戳作为 Unix 时间戳存储在数据库中。在构建要素之前,需要对数据进行日期时间格式化并创建要素。
通常,数据科学家/数据工程师会编写一个效用函数。这一职能将是生产管道的一部分。在这种情况下,花时间编写测试用例是值得的。
数据管道
数据管道是机器学习工作流不可或缺的一部分。数据提取、数据验证和数据准备是三个高层次的过程。取决于源系统(Hadoop、SQL、文件和流数据等)…),涉及到转换,我们可能需要设计全面的测试用例。这些测试用例可能包括测试执行数据提取所需的时间,确保数据类型和属性以及输出属性和类型。人们应该计划为这个场景编写一些测试用例。我们将写一篇单独的文章,介绍用例及工作示例。
模型和模型管道
教科书上的说明是模型测试是使用验证和测试数据集。度量标准是根据问题类型选择的,项目目标仍然是标准流程。就一会儿,想想如果我们的模型在做随机预测会怎么样?!这种测试在监督和非监督模型中都是有用的。我们可以写一个虚拟的分类器或者抑制类来模仿这个行为。如果你觉得写一个不舒服,sklearn 就是来救你一命的。sklearn 提供了一个虚拟分类器和回归类。对于聚类来说,这就变得棘手了;我们可能需要创建自定义的集群分配器。
最重要的测试用例之一是预测一致性,这是必需的,但从未讨论过。预测一致性背后的直觉是,对于给定的模型,如果我们将一个输入传递任意次,它应该返回相同的结果。不管模型类型如何,这应该是正确的,也许强化学习是一个例外情况。如果您在一个受监管的环境中工作,这个测试用例是必要的。有时候这个测试可以发现一些惊喜!
最后一个但正在出现的领域是对抗性测试用例。由于人工智能/人工智能将成为几乎每个 IT 系统的一部分,下一轮网络攻击将以对抗性人工智能的形式出现。这种对抗性攻击的影响包括毒害你的自动化训练管道;甚至没有模型漂移检测设置就发出警报。对抗性机器学习是 2010 年代早期的一个感兴趣的领域。深度学习极度火爆之后,成为了一个活跃的讨论话题。无论深度学习还是传统的机器学习,对抗性攻击都可能危及你的 AI/ML 系统。准备测试对你的模型的不利影响。
机器学习框架和平台提供管道 API。sklearn 管道和 Azure 管道 API 就是例子。确保无缝集成和预期行为的测试用例是一个很好的实践。当我们向 AIOps 进行部署时,测试用例将确保部署顺利进行。
我们将在本系列中润色一篇详细的技术文章。
测试模型部署
模型部署是 AI/ML 项目中一个不断发展的领域。创建 Flask API 来利用容器和容器编排平台的能力是技术前景的一部分。如果涉及到 API,我们应该考虑 API 的测试用例。无论我们有一个容器还是容器编排系统,它都是我们所期望的——对于批处理和特别推理系统来说都是一样的。
下一步
到目前为止,awe 以技术不可知的方式讨论了数据科学中的 TDD 途径。在随后的文章中,我们将通过示例和用例详细讨论其中的一些概念。
尽管如此,还是有很多争论的空间。普遍的理解是测试驱动开发会增加 10%到 15%的开发时间。但同时,投入的时间会保证 95%的 bug 和惊喜。一个成熟的 AI/ML 团队应该考虑在正确的测试策略上投入时间。
往期文章
[1]AI/ML/数据科学项目的软件工程,https://medium . com/@ jaganadhg/Software-Engineering-for-AI-ML-Data-Science-Projects-bb73 e 556620 e
[2]面向数据科学家的软件工程—编写干净代码的艺术,https://medium . com/@ jaganadhg/Software-Engineering-for-Data-Scientist-Art-of-Writing-Clean-Code-f 168 bf8a 6372
最初发表于【https://www.linkedin.com】。
面向数据科学家的软件工程——测试驱动开发(示例)
图片来源 pix abay—https://www . pexels . com/photo/abstract-business-code-coder-270348/
这是本系列的第四篇文章。有关本系列文章的列表,请查看前几篇文章部分。
上一篇文章可在— 数据科学家软件工程—测试驱动开发https://medium . com/@ jaganadhg/Software-Engineering-for-Data-Scientist-Test-Driven-Development-65 f1 CDF 52d 58获得
介绍
在上一篇文章中,我们讨论了数据科学中的测试驱动开发。本文介绍的两个具体测试案例包括针对虚拟/猜测机器的模型检查和预测一致性检查。本文是同一主题的快速教程。
在本教程中,我们正在建立一个二元分类器。本练习中使用的数据是取自 Kaggle [1]的口袋妖怪数据。本练习将构建一个随机森林分类器,并将其与猜测机器(参考 ROC AUC 得分)进行比较,以及预测的一致性。
资料组
这个练习的数据是“用于数据挖掘和机器学习的口袋妖怪”[1]。该数据集包括第 6 代之前的口袋妖怪。该数据共有 21 个属性,包括身份属性(“数字”)。我们为该练习选择了以下属性:“isLegendary”、“Generation”、“Type_1”、“Type_2”、“HP”、“Attack”、“Def”、“Sp_Atk”、“Sp_Def”、“Speed”、“Color”、“Egg_Group_1”、“Height_m”、“Weight_kg”、“Body_Style”。属性“Generation”用于拆分数据,然后从数据集中删除。属性“isLegendary”是此处的目标。有五个分类属性,它们是‘Egg _ Group _ 1’,‘Body _ Style’,‘Color’,‘Type _ 1’,‘Type _ 2’。我们在训练/验证/测试之前一次性转换了这些属性。
软件
对于本教程,我们将使用以下 Python 包。
熊猫
sklearn 0.23.2
pytest 6.1.0
ipytest 0.9.1
数字版本 1.19.1
工具 z 0.11.1
模型结构
让我们建立我们的模型!
%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import sklearn as sl
import pytest
import ipytest
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.dummy import DummyClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import (confusion_matrix,
classification_report,
roc_auc_score)
import toolzipytest.autoconfig()data = pd.read_csv("../data/pokemon_alopez247.csv")
我们从数据中选择以下属性。
selected_cols = ['isLegendary','Generation', 'Type_1', 'Type_2', 'HP', 'Attack',
'Defense', 'Sp_Atk', 'Sp_Def', 'Speed','Color','Egg_Group_1',
'Height_m','Weight_kg','Body_Style']data = data[selected_cols]
属性“isLegendary”是我们的类标签。让我们把这个转换成 int。
data.isLegendary = data.isLegendary.astype(int)
转换分类变量
以下函数用于转换分类变量。
def create_dummy(data: pd.DataFrame, categories: list) -> pd.DataFrame:
""" Create dummay varibles a.k.a categorical encoding in a DataFrame
Parameters
-----------
data : A pandas DataFrame containing the original data
categories: the arribute/column names to be transfromed
Returns
-----------
data_tf : Transfromed DataFrame
"""
for category in categories:
dummy_df = pd.get_dummies(data[category])
data = pd.concat([data,dummy_df],
axis=1)
data.drop(category,
axis=1,
inplace=True)
return datacateg_cols = ['Egg_Group_1', 'Body_Style', 'Color','Type_1', 'Type_2']data = create_dummy(data,categ_cols)
创建培训测试和验证数据
首先,我们通过训练和测试来拆分数据。所有属于第一代的口袋妖怪都被选作训练。其余数据用作测试数据。训练数据被进一步分割以创建验证数据集。
train_data = data[data.Generation != 1]
test_data = data[data.Generation == 1]train_data.drop("Generation",
axis=1,
inplace=True)
test_data.drop("Generation",
axis=1,
inplace=True)d:\anaconda2\envs\sweng\lib\site-packages\pandas\core\frame.py:4167: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
errors=errors,def create_x_y(data: pd.DataFrame, col_name : str) -> list:
""" Cerate training X and y values
Parameters
-----------
data : DataFrame of data
col_name : Y column name
Returns
-----------
x_y_list: a list contaning DataFrem and y as list
"""
X = data.drop(col_name,
axis=1).values
y = data[col_name].values
return (X,y)X_train, y_train = create_x_y(train_data, "isLegendary")X_train, X_val, y_train, y_val = train_test_split(X_train,
y_train,
stratify=y_train,
test_size=0.25)X_test, y_test = create_x_y(test_data, "isLegendary")
最小-最大缩放比例
使用最小-最大缩放技术进一步处理数据。
def scale_data(dataset: pd.DataFrame) -> np.array:
""" Scle the data
Parameters
-----------
dataset : input DataFrame
Returns
-----------
scled_data : a numpy array
"""
transformer = MinMaxScaler()
sclaed_data = transformer.fit_transform(dataset)
return sclaed_dataX_train_scaled = scale_data(X_train)
X_test_scaled = scale_data(X_test)
X_val_scaled = scale_data(X_val)
创造一个猜测机器!
为了创建一个猜测机器,我们使用了 scikit-learn 的“DummyClassifier”。虚拟分类器设计用于制作快速基线模型。分类器为基线提供了不同的策略。分类器忽略除目标之外的输入数据。在本练习中,我们将使用分层方法来构建模型。
dummy_classifier = DummyClassifier(strategy="stratified",
random_state=1995)
_ = dummy_classifier.fit(X_train_scaled,
y_train)
创建随机森林分类器
现在让我们创建一个随机森林分类器。
rf_classifier = RandomForestClassifier(criterion='entropy',
max_depth=5,
warm_start=True,
random_state=1925)_ = rf_classifier.fit(X_train_scaled,
y_train)
编写测试用例
现在我们正在编写模型和预测一致性的测试用例。我们使用 pytest 和 ipytest 来编写和执行 JupyterNotebook 中的测试用例。为测试用例创建了两个夹具。
pytest fixture 'fixture_isbetter '使用虚拟分类器和随机森林分类器来创建预测。它返回虚拟分类器、随机森林分类器和实际标签的结果。下一个 fixture 是‘pred _ consist _ data’;它从验证数据中随机挑选五个例子。
测试用例“test_is_better”检查随机森林分类器的 ROC AUC 分数是否优于猜测机器。理想情况下,应该是通过考验!接下来的两个测试用例“test_prediction_consistency”和“test_pred_proba_consistency”测试模型的一致性。测试背后的直觉是,如果相同的输入被提供给模型 n 次,它应该提供相同的结果(除了 Reenforcemtn 学习)。这里,第一个测试用例检查标签的一致性,第二个测试用例检查概率的一致性。
例如,一致性测试的目的被分成两个测试用例。它也可以和一个结合。
%%run_pytest[clean]
@pytest.fixture
def fixture_isbetter():
""" Fixture for checking if model is better than guess"""
dumm_pred = dummy_classifier.predict(X_val_scaled)
clf_pred = rf_classifier.predict(X_val_scaled)
return (dumm_pred,clf_pred, y_val)
@pytest.fixture
def pred_consist_data():
""" Generate random 5 records from validation data
for prediction consistency test.
"""
num_records = X_val.shape[0]
raandom_indics = np.random.choice(num_records,
size=5,
replace=False)
sample_for_test = X_val[raandom_indics, :]
return sample_for_test
def test_is_better(fixture_isbetter):
""" Test if the target classifier is better than the dummy classifier
Parameters
"""
actuls = fixture_isbetter[-1]
pred_dummy = fixture_isbetter[0]
pred_clf = fixture_isbetter[1]
roc_auc_dummy = roc_auc_score(actuls, pred_dummy)
roc_auc_clf = roc_auc_score(actuls, pred_clf)
print(f"ROC AUC for dummy classifer is {roc_auc_dummy} \
and ROC AUC score for RandomForest is {roc_auc_clf}")
assert round(roc_auc_clf,4) > round(roc_auc_dummy,4)
def test_prediction_consistency(pred_consist_data):
""" Test the prediction consistency"""
#import toolz
predictions_list = list()
for iteration in range(5):
preds = rf_classifier.predict(pred_consist_data)
predictions_list.append(list(preds))
unique_if = list(map(list, toolz.unique(map(tuple,predictions_list))))
assert len(unique_if) == 1
def test_pred_proba_consistency(pred_consist_data):
""" Test prediction consistency"""
#import toolz
pridct_proba = list()
for iteration in range(5):
preds = rf_classifier.predict(pred_consist_data)
pridct_proba.append(list(preds))
unique_if = list(map(list, toolz.unique(map(tuple,pridct_proba))))
assert len(unique_if) == 1... [100%]
3 passed in 0.17s
瞧。三个测试用例全部通过!。可以有额外的测试用例来部署重新训练的模型。在这种情况下,最好用先前的模型替换测试用例的虚拟分类器。sklearn 提供了一个虚拟分类器和回归器。如果您想将它应用到任何其他类型的模型,我们可能需要编写我们的模块来实现目标。!
以前的文章
面向数据科学家的软件工程—测试驱动开发https://medium . com/@ jaganadhg/software-Engineering-for-Data-Scientist-Test-Driven-Development-65 f1 CDF 52d 58
面向数据科学家的软件工程—编写干净代码的艺术—https://medium . com/@ jaganadhg/software-Engineering-for-Data-Scientist-Art-of-Writing-Clean-Code-f 168 bf8a 6372
AI/ML/数据科学项目的软件工程—https://medium . com/@ jaganadhg/software-Engineering-for-AI-ML-Data-Science-Projects-bb73e 556620 e
参考
[1]口袋妖怪数据集,https://www.kaggle.com/alopez247/pokemon
数据科学家的软件工程基础
来源:克里斯里德@ unsplash-免费库存图片
不是软件工程师我学到的东西🙃
作为一个领域,自从数据科学开始流行以来,它已经引起了与其他学科的争论。统计学家抱怨从业者缺乏基本的统计知识,数学家反对在没有充分理解应用原则的情况下应用工具,软件工程师指出数据科学家在编程时对基本原则的无知。老实说,他们都有道理。在统计学和数学方面,的确,你需要对概率、代数和微积分等概念有扎实的理解。知识需要有多深?嗯,这很大程度上取决于你的角色,但基本原则是没有商量余地的。编程时也会发生类似的事情;如果您的角色意味着编写生产代码,那么您至少需要了解软件工程的基础知识。为什么?原因很多,但我认为可以概括为五个原则:
- 代码的完整性,根据它写得有多好,对错误的弹性,捕捉异常,测试和被其他人审查
- 代码的可解释性,配有适当的文档
- 代码在真实环境中运行的速度
- 你的脚本和对象的模块化,以便可重用,避免重复,提高代码类的效率
- 慷慨与你的团队一起,让他们尽快审查你的代码,并在将来理解你为什么要写任何一段代码
根据这些观点,在这个故事中,我们将看到一些我认为最有用的基本原则,不是天生的程序员,而是从一个完全不同的背景进入这个领域。他们帮助我写出了更好的产品代码,节省了我的时间,也让我的同事在实现我的脚本时更加轻松。
编写干净代码的重要性
来源:奥利弗·黑尔@ unsplash——免费库存图片
理论上,我们在这个故事中涉及的几乎所有东西都可以被认为是编写更干净代码的工具或技巧。然而,在这一特定的部分,我们将集中在单词 clean 的严格定义上。正如 Robert Martin 在他的书 Clean Code 中所说,即使是糟糕的代码也可以运行,但是如果代码不干净,它会让一个开发组织崩溃。怎么会?老实说,可能性有很多,但是想象一下审查糟糕的代码所浪费的时间,或者开始一个新的角色,却发现你将处理一些很久以前写的难以辨认的代码。或者更糟的是,想象某个东西中断了,导致某个产品功能停止工作,而在你之前写代码的人(如此肮脏的代码)已经不在公司了😱。
这些都是比较常见的情况,不过咱们就不那么戏剧化了;谁从来没有写下一些代码,让它挂起一段时间去做更紧急的事情,然后当回来时却不记得它实际上是如何工作的?我知道这发生在我身上。
这些都是为编写更好的代码付出额外努力的正当理由。因此,让我们从基础开始,看看一些编写更简洁的脚本的技巧:
- 在你的代码中用名字来描述。我从未忘记几年前在大学上 Java 课时学到的一个概念:让你的代码成为助记符。助记法指的是一种系统,如帮助记忆某些东西的字母、想法或联想的模式。也就是说,这意味着编写不言自明的名称
- 只要有可能尽量暗示类型。例如,对于一个返回布尔对象的函数,可以用 is_ 或 has 作为前缀
- 避免缩写,尤其是单个字母
- 另一方面,避免长的名字和行。写长名字并不意味着更具描述性,就行的长度而言,PEP 8 Python 代码风格指南中的指南建议行长度不超过 79 个字符。
- 不要为了一致性而牺牲清晰性。例如,如果您有代表雇员的对象和包含所有这些对象的列表,那么 employee_list 和 employee_1 比 employees 和 employee_1 更清晰
- 关于空行和缩进,让你的代码更容易阅读用类似银行的字体分隔部分并使用一致的缩进
编写模块化代码的重要性
来源:莎伦·麦卡琴@ pexels-免费股票图片
我认为这是数据科学家和数据分析师最重要的观点之一,也是软件工程讨论的一个非常常见的来源,因为我们非常习惯于在 Jupyter 笔记本等工具中编码。这些工具对于探索性的数据分析来说是惊人的,但是对于编写生产代码来说却不是这样。事实上,Python 本质上是一种面向对象的编程语言,深入讨论它的含义不在此范围之内,但简而言之,与编写一系列指令供脚本执行的过程式编程不同,面向对象编程是关于构建具有自身特征和动作的模块。举以下例子:
来源:图片由作者制作
在实践中,这些特征被称为属性,而动作将是方法。在上面的例子中,对象 Computer 和 Printer 是独立的类。一个类是一个蓝图,包含所有特定类型对象的属性和方法。也就是说,我们创建的所有计算机和打印机将共享相同的属性和方法。这个想法背后的概念叫做封装。封装意味着您可以将所有功能和数据合并到一个实体或模块中。当你把一个程序分解成模块时,不同的模块不需要知道事情是如何完成的,如果它们不负责做的话。为什么这很有用?这不仅仅是为了代码的可重用性,避免重复和提高效率,就像前面提到的那样,而且如果需要的话,这也使得调试更加容易。
同样,如果您所做的只是在 Jupyter 笔记本中进行探索性的数据分析,这可能并不相关,但是如果您正在编写一个将成为真实环境一部分的脚本,尤其是随着应用程序规模的增长,将您的代码分成单独的模块是有意义的。通过在将所有部分组合在一起之前完善程序的每个部分,您不仅可以更容易地在其他程序中重用单个模块,还可以通过查明错误的来源来更容易地修复问题。
编写模块化代码的一些进一步的技巧:
- 干:不要重复自己
- 使用函数不仅减少了重复性,而且通过描述性的名称提高了可读性,便于理解每个模块的功能
- 尽量减少实体(函数、类、模块等)的数量。)
- 单一责任原则:一个类应该有且只有一个责任的思想。比人们想象的要难。
- 遵循开放/封闭原则。即对象应该对扩展开放,但对修改关闭。这样做的目的是编写代码,这样您就能够在不更改现有代码的情况下添加新功能,从而防止出现这样的情况:对一个类的更改也需要您修改所有依赖的类。面对这个挑战有不同的方式,尽管在 Python 中使用继承是很常见的。
- 每个函数尽量少用三个参数。如果它有很多,也许把它分开。类似的标准适用于函数的长度;理想情况下,一个函数应该有 20 到 50 行。如果它有更多,那么你可能想把它分成单独的功能
- 也要注意你的课时长度。如果一个类有超过 300 行,那么它应该被分成更小的类。
如果您已经在使用 Python,但对面向对象编程一无所知或知之甚少,我强烈推荐这两个免费课程:
- data camp 的 Python 面向对象编程
- 在 https://realpython.com/举办的面向对象编程的 Python 介绍
重构的重要性
来源: RyanMcGuire @ pixabay —免费股票图片
维基百科对重构的定义如下:
在计算机编程和软件设计中,代码重构是在不改变现有计算机代码外部行为的情况下对其进行重构的过程。重构旨在改进软件的设计、结构和/或实现,同时保留其功能。重构的潜在优势可能包括提高代码可读性和降低复杂性;这些可以提高源代码的可维护性,并创建一个更简单、更清晰或更具表现力的内部架构或对象模型来提高可扩展性。
我认为这个定义本身就说明了问题,但是除此之外,我们可以补充一点,重构给了我们一个机会,在我们让代码工作起来之后,清理和模块化我们的代码。这也给了我们一个提高代码效率的机会。到目前为止,我所了解到的是,当软件工程师谈论高效代码时,他们通常指的是以下两者之一:
- 减少运行时间
- 减少内存空间
让我们简要介绍一下这两点…
以我的经验来看,随着你写越来越多的产品代码,减少代码的运行时间是你需要慢慢学习的。当你在 Jupyter 笔记本上做一些分析时,计算这些成对的距离花费你两分钟、五分钟或十分钟都没关系。你可以让它运行,回复一些无聊的消息,去洗手间,灌满一杯咖啡,然后回来看你的代码完成。然而,当有用户在另一边等待时会发生什么呢?当你的代码编译时,你不能让它们一直挂着,对吗?
在 Python 中,有几种改进方法,让我们快速介绍其中的一些:
使用向量运算让你的计算更快。例如,当检查一个数组的元素是否在另一个数组中时,你可以使用 NumPy 的 intersect1d ,而不是编写循环。您也可以使用向量根据条件搜索元素,以便执行加法或类似操作。让我们看一个简单的例子,当我们必须遍历一个数字列表并执行一个给定条件的操作时:
而不是使用这样的东西:
# random array with 10 million pointsa = np.random.normal(500, 30, 10000000) # iterating and checking for values < 500t0 = time.time()total = 0for each in a: if each < 500: total += eacht1 = time.time()print(t1-t0)
时间:3.64595947 秒
# same operation only using numpyt0 = time.time()total = a[a<500].sum()t1 = time.time()print(t1-t0)
时间:0.06348109245300293 秒
快了 58 倍以上!
我知道熊猫数据框架非常容易使用,我们都喜欢它们,但是,当编写产品代码时,最好避免使用它们。我们用熊猫做的很多手术也可以用 Numpy 来做。让我们看看其他一些例子:
- 根据条件对矩阵行求和
# random 2d array with 1m rows and 20 columnn
# we’ll use the same in following examplesa = np.random.random(size=(1000000,20))# sum all values greater than 0.30(a * (a>0.30)).sum(axis=1)
在上面的代码中,乘以一个布尔数组是可行的,因为 True 对应于 1,False 对应于 0👍🏻
- 根据某种条件添加一列
# obtain the number of columns in the matrix to be used as index of the new one to be placed at the endnew_index = a.shape[1]# set the new column using the array created in the previous examplea = np.insert(a, new_index, (a * (a>0.30)).sum(axis=1), axis=1)# check new shape of aa.shape
Prints: (1000000,21) |新列已添加🎉
- 根据多个条件过滤表格
# filter if the new last column is greater than 10 and first column is less than 0.30b = a[(a[:,0]<0.30)&(a[:,-1]>10)]b.shape
打印:(55183,21) | 55183 行符合条件👍🏻
- 如果条件满足,更换元件
# change to 100 all values less than 0.30a[a<0.3] = 100
除了上面的代码,另一个减少运行时间的好方法是并行化。并行化意味着编写一个脚本来并行处理数据,使用机器中几个或所有可用的处理器。为什么这能让我们的速度大幅提升?因为大多数时候我们的脚本是串行计算数据的:它们解决一个问题,然后是下一个,然后是下一个,等等。当我们用 Python 编写代码时,通常会发生这种情况,如果我们想利用并行化,我们必须明确这一点。我将很快就此写一个独立的故事,但是,如果你渴望了解更多,在所有可用于并行化的库中,我最喜欢的是:
关于减少内存空间,减少 Python 中的内存使用是困难的,因为 Python 实际上并没有将内存释放回操作系统。如果您删除对象,那么内存可用于新的 Python 对象,但它不会被释放()回系统。此外,如前所述,Pandas 是一个很好的探索性数据分析工具,但除了生产代码较慢之外,它在内存方面也相当昂贵。然而,我们可以做一些事情来控制内存使用:
- 首先:如果可能的话,使用 NumPy 数组代替 Pandas Dataframes。即使是字典也比数据帧占用更少的内存
- 减少熊猫数据帧的数量:当我们修改数据帧时,不是创建一个新的对象,而是尝试使用参数 inplace=True 来修改数据帧本身,这样就不会创建副本。
- 清除您的历史:每次您对一个数据帧(例如 df + 2)进行更改时,Python 都会在内存中保存该对象的副本。您可以使用%reset Out 清除该历史记录
- 注意你的数据类型:与数字相比,对象和字符串数据类型在内存方面要昂贵得多。这就是为什么使用 df.info()检查 Dataframe 的数据类型总是有用的,如果可能的话,使用 df[‘column’] = df[‘columns’]对它们进行转换。astype(类型)
- 使用稀疏矩阵:如果你有一个包含大量空值或空单元的矩阵,使用稀疏矩阵会更方便,它通常占用更少的内存空间。您可以使用*scipy . sparse . CSR _ matrix(df . values)*来完成
- 使用生成器而不是对象:生成器允许你声明一个行为像迭代器的函数,但是使用单词产生而不是返回。生成器不会创建一个包含所有计算的新对象(例如,一个列表或一个 NumPy 数组),而是生成一个保存在内存中的值,只有在您需要时才会更新。这就是所谓的懒惰评估。在《走向数据科学》中 Abhinav Sagar 的精彩故事中找到更多关于生成器的信息。
测试的重要性
来源:pix abayat @ pexels-免费库存图片
需要数据科学方面的测试。其他软件相关领域通常抱怨数据科学家的代码缺乏测试。虽然在其他类型的算法或脚本中,如果出现错误,程序可能会停止工作,但在数据科学中,这甚至更危险,因为程序可能会实际运行,但由于值编码不正确、功能使用不当或模型实际所基于的数据破坏假设,最终会产生错误的见解和建议。
当我们提到测试时,有两个主要概念值得讨论:
- 单元测试
- 试驾开发
先说前者。单元测试之所以这么叫是因为它们覆盖了一个小的代码单元,目标是验证我们代码的每一个单独的部分都按照设计执行。在面向对象的编程语言中,比如 Python,一个单元也可以被设计为评估整个类,但也可以是一个单独的方法或函数。
单元测试可以从头开始编写。事实上,让我们这样做,这样我们可以更好地理解单元测试实际上是如何工作的:
假设我有以下函数:
def my_func(a,b):c=(a+b)/2*1.5return c
我想测试以下输入是否返回预期的输出:
- 4 和 2 返回 4.5
- 5 和 5 返回 5.5
- 4 和 8 返回 9.0
我们完全可以这样写:
def test_func(function, output): out = function if output == out: print(‘Worked as expected!’) else: print(‘Error! Expected {} output was {}’.format(output,out))
然后简单地测试我们的功能:
test_func(my_func(4,2),4.5)
版画:果然奏效!
然而,对于更复杂的函数,当我们想一次测试几个函数,甚至是一个类时,这就变得更棘手了。没有这些 faff 的单元测试的一个很好的工具是 pytest 库。Pytest 要求您创建一个包含要测试的一个或多个函数的 python 脚本,以及另一组断言输出的函数。该文件需要以前缀“test”保存,然后只需像任何其他 Python 脚本一样运行即可。Pytest 最初是为了从命令行使用而开发的,但是如果您仍然处于项目的早期阶段,有一种从 Jupyter 笔记本使用它的简单方法;您可以使用神奇的命令 %%writefile 创建并保存一个. py 文件,然后直接从笔记本中使用命令行语句运行该脚本。让我们看一个例子:
import pytest%%writefile test_function.pydef my_func(a,b): c=(a+b)/2*1.5 return cdef test_func_4_2(): assert(my_func(4,2)==4.5)def test_func_5_5(): assert(my_func(5,5)==7.5)def test_func_4_8(): assert(my_func(4,8)==9.0)
只需运行脚本:
!pytest test_function.py
如果一切按预期运行,会看到如下输出:
将来,我会写另一个故事来讨论单元测试的更复杂的例子,以及如果你需要的话,如何测试整个类。但同时,这应该足够让您开始并测试您的一些功能了。请注意,在上面的例子中,我测试的是返回的确切数字,但是您也可以测试数据帧的形状、NumPy 数组的长度、返回的对象的类型等等。
我们之前在本章开头提到的另一点是试驾开发或 TDD 。这种测试方法包括编写要为一段代码执行的单元测试,甚至在开始开发之前。下一步,你会想要写最简单和/或最快的代码,以通过你最初写下的测试,这将帮助你确保质量,通过在写代码之前关注需求。此外,根据最初编写的一个或多个测试,它将迫使您通过将代码分解成小代码块来保持代码简单、干净和可测试。一旦你有了一段真正通过测试的代码,你就可以专注于重构来提高代码的质量或进一步的功能。
来源:https://me.me/—模因库
TDD 的一个主要好处是,如果将来需要对代码进行更改,而你不再从事那个项目,你转到了另一家公司,或者你只是在度假,了解最初编写的测试将帮助任何人获取代码,以确保一旦更改完成,它不会破坏任何东西。
值得考虑的其他几点:
- 笔记本:探索的理想选择,TDD 的不理想选择
- 乒乓 TDD:一个人写测试,另一个人写代码
- 为您的测试设置性能和输出指标
代码审查的重要性
来源:Charles Deluvio@ unsplash-免费图片
代码审查有益于团队中的每个人,促进最佳编程实践并为生产准备代码。代码审查的主要目标是捕捉错误,然而,它们也有助于提高可读性,并检查团队是否符合标准,因此不会将脏的或慢的代码投入生产。除此之外,代码评审对于分享知识也是很棒的,因为团队成员可以阅读来自不同背景和风格的人的代码片段。
如今,excellence 的代码审查工具是 GitHub 和 pull requests 这样的平台。“拉”请求是将一段代码或一个全新的脚本中的变更集成到某个代码环境中的请求。它被称为拉请求,因为它们的提交意味着准确地请求某人将您编写的代码拉进存储库。
从 GitHub 的文档中,我们可以看到他们对拉请求的定义:
Pull 请求允许你告诉其他人你已经推送到 GitHub 上的一个存储库中的一个分支的变更。一旦打开了一个拉请求,您就可以与协作者讨论和评审潜在的变更,并在您的变更被合并到基础分支之前添加后续提交。
拉式请求本身就是一门艺术,如果你有兴趣了解更多,那么这个由雨果·迪亚斯写的名为《完美拉式请求的剖析》的故事一定会派上用场。但是,在审查代码时,您可以问自己几个问题:
- 代码是否干净、模块化?寻找重复、空白、可读性和模块化
- **代码是否高效?**看循环,对象,函数结构,能不能用多重处理?
- **文件是否有效?**查找内嵌注释、文档字符串和自述文件
- **代码测试过了吗?**寻找单元测试
- **伐木 **够好吗?查看日志信息的清晰度和正确频率
嗯,我想这已经足够了😅。一如既往,我渴望阅读您的评论和反馈。
别忘了看看我的其他一些故事:
包括特征向量和特征值
towardsdatascience.com](/the-most-gentle-introduction-to-principal-component-analysis-9ffae371e93b) [## 4 门免费数学课程,用于隔离和提升您的数据科学技能
因为没有数学数据就没有科学
towardsdatascience.com](/4-free-maths-courses-to-do-in-quarantine-and-level-up-your-data-science-skills-f815daca56f7) [## 5 更好的绘图工具和技术
充分利用您的数据
towardsdatascience.com](/5-more-tools-and-techniques-for-better-plotting-ee5ecaa358b)
或者访问我在 Medium 上的个人资料,查看我的其他故事🙂。还有如果你想直接在你的邮箱里收到我的最新文章,只需 订阅我的简讯 **😃。**再见,感谢阅读!
接下来查找一些我用作故事来源的优秀网站:
- https://programminghistorian.org
- https://www.kevinlondon.com
- https://stackify.com/
- https://stack overflow . com/questions/39100971/how-do-I-release-memory-used-by-a-pandas-data frame**
一位工程师对机器学习的探索
我和我的徒步旅行伙伴正在攀登印度北阿坎德邦和喜马拉雅山的马亚丽山口
面向开发者的机器学习
地形图和软件开发人员着手 ML 探险的指南针。
你是一名软件工程师。你会注意到人工智能、机器学习、深度学习、数据科学这些流行词汇无处不在。你想知道这些短语是什么意思,是否所有这些都是真实和有用的,或者是另一种炒作和短暂的时尚。
你想弄清楚它正在或将要如何改变计算机/IT 行业,以及你为什么要关心它。你在谷歌上搜索,阅读各种文章、博客和教程。你有了一些想法,但也被你发现的大量数学、工具和框架所淹没。
Y 你希望有人能给你一个概述,比如说,一张适合工程师的地图和指南针,来帮助你踏上掌握这一切的旅程。这篇博文是写给你的。
和你一样,我也是一名软件工程师,也经历过那段旅程。我的经验是相关的,你可以用它来规划你自己的道路。除了编程,我还喜欢在喜马拉雅山徒步旅行。我在我的 ML 旅程和高海拔旅行中看到了有趣的相似之处。通过这些对比,我将解释你如何计划和进行一次 ML 探险。
徒步探险
长途跋涉有以下四个阶段。
**不可抗拒的诱惑:**我会因为听到或读到徒步旅行而被吸引。山峰、小径、山谷和地形。人们滔滔不绝地说这是一次美丽而富有挑战性的跋涉。这是一种难以抗拒的诱惑。但是在我投入时间、精力和资源之前,我会问:这条路值得吗?体验是怎样的?我为什么要上?我读人们的博客,看照片,花时间在谷歌地球上。最后,我要么说“啊!”或者我更想这么做。
**研究地形:**那才是真正工作开始的时候。每一次跋涉都有挑战。所以我在谷歌地图和谷歌地球上研究地形。我花时间看海拔地图,阅读博客,了解没有回报的点,以及可能的逃跑路线。我想知道主要的地理特征、困难和危险。
努力训练:一旦我清楚自己要做什么,我就会计划并准备。我开始努力训练,制定详细的计划,定期评估自己的进步。
**检查你的装备:**最后,我储备物资,检查我的装备,尤其是地图和指南针。我确保这张地图在我的脑海中根深蒂固,并且我对附近地区有足够的了解,能够有一个直观的方向感。
然后冒险就开始了!
让我们来考察学习机器学习的这四个阶段。
不可抗拒的诱惑:为什么要学习机器学习
像大多数软件工程师一样,我没有接受过机器学习方面的正式训练。在我职业生涯的大部分时间里,我构建编译器、程序分析和编程工具以及 IDEs 与机器学习非常不同的东西。但在微软研究院工作时,我看到我的同事们应用机器学习和统计学来解决困难的程序分析和软件工程问题。这些技术的成功吸引了我。但是让我们来检查一下:这真的值得你花时间去做吗?还是所有这些都只是昙花一现?
四个最常见的流行语是人工智能(AI)、机器学习(ML)、深度学习(DL)、数据科学(ds)。让我们看看谷歌趋势中的这些短语,俗话说:我们相信上帝;其他人必须提供数据。
谷歌趋势面向人工智能(AI)、机器学习(ML)、深度学习(DL)、数据科学(ds)
自 2012 年 9 月 AlexNet 以来,这四个短语有了显著增加。 AlexNet 以将近 11%的优势赢得 ImageNet 竞赛这是一个分水岭时刻。在研究中,提高几个百分点是一件大事,但超过 10%是非常罕见的。
2015 年微软研究院 CNN 超越人类级别视觉性能。考虑到焦点调节和色觉锥赋予人类眼睛动物界中最好的深度和颜色感知能力,在视觉任务中击败人类水平是惊人的!
目前,不仅仅是趋势数据。事实上,消费者每天都会使用 ML 几次:网页搜索结果排名、垃圾邮件检测、地图中的预计到达时间(ETA)、围绕主题的新闻故事聚类、谷歌和脸书上的广告、亚马逊和网飞等网站上的推荐系统,以及 Alexa 和谷歌助手。
企业也越来越依赖 ML 进行欺诈检测、定价/财务建模、客户流失预测、设备故障预测、网络入侵检测、客户细分、情感分类、图像/视频分析和语音/音频处理。
它闯入我们的日常生活有两个原因:
- 大量的数据正在生成,而且
- 经济的按需云计算的可用性。
很明显,ML 不仅仅是炒作或短暂的时尚。它是真实的,就在此时此地。所以这趟旅程是值得的。
研究地形:机器学习导论
一旦你决定开始这趟旅程,研究地形是很重要的。让我们从理解四个流行短语开始。
人工智能(AI): 机器通过像人类一样的表现所展示的智能。
机器学习(ML): 通过识别数据中的模式,使用统计模型进行预测,而不需要明确的指令。
深度学习(DL): 使用深度神经网络的机器学习方法。
数据科学(DS): 使用统计技术从结构化和非结构化数据中提取知识和见解。
人工智能是最广泛的术语,包括统计以及其他技术。ML 是 AI 的子集,DL 是 ML 的子集。数据科学与 AI、ML 和 DL 有重叠。
DS、ML 和 AI 之间的差异的一个过于简单的定义是:
- 数据科学产生洞察
- 机器学习产生预测
- 人工智能产生动作
数据管理和 ML/DL 模型的持续部署正在成为主流。公司正在对编程和工程学科进行大量投资。
人工智能 vs 机器学习 vs 深度学习 vs 数据科学。图片由作者创作,并在Creative Commons BY-NC-ND 4.0 International许可下发布。
传统程序与机器学习
这些定义都可以,但是机器学习和传统程序有什么区别呢?
在传统编程中,程序员设计逻辑或算法来解决一个问题。程序将该算法应用于输入并计算结果。
但是在机器学习中,程序员并不编写计算结果的逻辑。相反,她从数据中建立了一个模型。模型是逻辑。随着更新的数据(用户对输出正确性的反馈)的到来,模型(也就是逻辑)也会改变。所以程序自己“学习”。
机器学习程序有两个不同的阶段:
- **训练:**输入和期望输出用于训练和测试各种模型,选择最合适的模型。
- **推论:**模型应用于输入计算结果。这些结果有时是错误的。在这种情况下,建立一种收集用户反馈的机制。
这种反馈被添加到训练数据中,从而导致模型的改进。这个循环被称为数据管道或数据工程。
传统程序与机器学习
这一切还是抽象的。让我们以检测垃圾邮件的问题为例,比较传统和机器学习解决方案。
在传统编程解决方案中,程序员将分析人类将如何确定一封电子邮件是否是垃圾邮件,并列举一份详尽的规则和模式列表。例如:
- 免费这个词出现了好几次
- 有像减肥这样的短语,
- 声称你中了彩票的信息
- 来自特定国家或 IP 地址的消息等等。
随着垃圾邮件发送者改变策略,程序员需要不断更新这些规则来跟上他们。这就是过去知识或专家系统的构建方式。
在机器学习解决方案中,程序员将:
- 准备数据集:大量被人为标记为垃圾邮件或非垃圾邮件的电子邮件
- 训练、测试和调整模型,并选择最佳模型。
- 在推理过程中,该模型用于确定是将电子邮件保存在收件箱还是垃圾邮件文件夹中。
- 统计模型不是 100%准确的。垃圾邮件发送者也不断想出新的策略。所以有时垃圾邮件分类是不正确的。用户会将此类电子邮件从收件箱移动到垃圾邮件文件夹(反之亦然)。
- 这种用户动作被跟踪并被视为新的人类标记的数据。
- 这些示例被添加到数据集中,并且新的模型被训练以保持与垃圾邮件趋势同步。
机器学习
机器学习有三种技术:
**监督学习:**训练一个将输入映射到输出的函数。训练在给定的带标签的输入-输出对示例(称为训练数据集)中推断关系。两种常见的方法是回归和分类。
**无监督学习:**在没有预先存在标签的情况下,训练寻找数据集中以前未知的模式。两种常见的方法是聚类和主成分分析(也称为降维)。
**强化学习:**训练软件代理在一个环境中采取行动,以最大化某种累积回报的概念。它的应用是在机器人,游戏,技能学习和适应。
让我们再了解一下三种最常见的技术:回归、分类和聚类。
线性回归
回归是一种监督学习技术,从一个或多个自变量中估计因变量的值。一个例子是从房子的大小、位置、卧室数量、浴室数量等来估计房子的价值。
这就像在给定点上拟合一条曲线,以便在一个大样本数据集上最小化估计值和实际值之间的差异。在估计函数中,Y = f(X),Y 被称为结果,X 被称为特征向量。
线性回归
分类是一种监督学习技术,用于从对象的特征中识别类别/组。一个例子是识别给定照片中的车辆是轿车、卡车还是摩托车。
就像画线一样,将一个区域划分为多个区域(在本例中为 3 个,代表汽车、卡车、摩托车),使得不在它们区域内的物体数量最少。在分类函数中,Y = f(X),Y 称为标签(而且是有限集,像程序中的 enum),X 称为特征向量。
使聚集
聚类是一种无监督学习技术,将对象分组为相似对象的聚类。换句话说,根据给定的相似性标准,一个聚类中的对象比其他聚类中的对象彼此更相似。一个例子是根据主题对相似的新闻文章进行聚类。
分类和聚类的基本区别在于,在分类中,标签集是有限的和给定的;但是在聚类中,类的数目和定义是事先不知道的,是从数据中推断出来的,所以标签集既不是有限的,也不是给定的。
现在,让我们尝试将开头列出的一些问题映射到这些技术之一:
- 网页搜索结果排名/评分:回归
- 垃圾邮件检测:分类
- 地图中的 ETA:回归
- 展示能使收入最大化的广告:回归
- 推荐系统:聚类
我想暂停一下,强调一下机器学习不是灵丹妙药。这完全取决于你用于训练的数据,因为在 ML 中,数据就是逻辑。如果你在收集和管理数据时不小心,最大似然预测会有严重的错误。它被称为垃圾入,垃圾出。
对于监督学习,你训练系统的目的很重要。例如,如果你训练了一个分类系统来区分汽车、卡车和摩托车,你就不能用它来区分红色汽车和蓝色汽车。如果您的问题发生变化,您必须更改训练数据中的标签,并重新训练模型。
深度学习
深度学习是使用深度神经网络(DNN) 模型的机器学习的子集。这些模型有一个输入层、一个输出层和几个中间隐藏层。
有各种适合不同问题的专业网络设计。一些例子是卷积神经网络(CNN)、递归神经网络(RNN)、长短期记忆(LSTM)神经网络。在这篇文章中,我们不会详细讨论各种类型的 dnn。
dnn 解决同样的问题:回归、分类、聚类等。但是 dnn 是计算密集型的(因此很昂贵),它们用于某些类型的数据。
其他机器学习技术通常足以处理结构化数据。DNNs 在非结构化数据上给出更好的结果。dnn 通常用于三种非结构化数据:
**视觉:**处理图像和视频数据。常见的应用是图像中的对象识别、视频摘要。
**自然语言:**用自然语言处理文本。常见的应用有情感分类、意图识别、实体识别、机器翻译。
**语音:**处理语音音频数据。常见的应用是语音识别(语音到文本)和语音合成(文本到语音)。
深度神经网络的一个例子(DNN)
工具和框架
Python 是机器学习从业者中最受欢迎的语言。有一个丰富的库和框架生态系统。
对于数据科学和机器学习,可以使用 NumPy 、 Pandas 、 SciPy 和 SciKit-Learn 。对于数据可视化, MatplotLib 和 Seaborn 很有用。
在实验和探索想法的过程中, Jupyter Notebook 、 Kaggle kernels 和 Google Colabs 非常方便地记录代码以及可视化和实验输出。
对于深度学习来说, TensorFlow 和 PyTorch 以及 Keras API 是构建神经网络最流行的框架。
要在云上部署,所有主要的云提供商都有替代方案:谷歌云 AutoML ,亚马逊 SageMaker ,微软 Azure ML 。
刻苦训练:如何进入机器学习
正如你所看到的,机器学习是一个广阔的领域,有很多地方要覆盖。这并不容易。所以你需要努力训练。
好消息是,这是人类历史上最好的自学时间,即使是计算机科学的前沿课题。你只需要动力和一台网络连接良好的电脑。
不缺乏好的文章,教程,和优秀和负担得起的在线课程。我重申,如果你有动力自己学习机器学习,这是前所未有的好时机。
机器学习的在线课程和教程
我列出了一些我喜欢的课程,但是还有很多其他非常好和有用的在线资源。
- 机器学习基础知识:吴恩达著名的 ML 课程
- 面向从业者的机器学习:DS/ML Python boot camp @ Udemy
- 谷歌的 ML 速成班
- 张量流:教程
- PyTorch: 教程
- 深度学习:课程@ DeepLearning.ai
- 深度学习:程序员实用深度学习@ FastAI
- 生产中的 ML:全栈深度学习
- 云:谷歌 Cloud AutoML ,亚马逊 SageMaker ,微软 Azure ML
- Kaggle 拥有丰富的数据集和比赛来源。
机器学习书籍
一旦你开始学习 ML,你可能想挑选一些这样的书来巩固你的理论基础。这些是一些最受尊敬的教授写的一些最好的书。这些都可以在网上免费获得。
- 统计学习的要素,作者:Hastie,Tibshirani,Friedman
- 统计学习介绍,作者:詹姆斯、威滕、哈斯蒂、提布拉尼
- 深度学习,作者古德菲勒、本吉奥、库维尔、巴赫
- 模式识别和机器学习,作者毕晓普
- 机器学习的向往,作者吴恩达
- 语音和语言处理,作者 Jurafsky,Martin
快速入门指南
如果您想快速了解一个特定的问题,这里有一个文章列表,可以帮助您快速开始处理特定的技术或问题。
- 一个简介、教程、完整指南到 数据操作 与 NumPy 和熊猫
- 提示在上绘制和数据可视化 用 Matplotlib 和 Seaborn ,并拥有乐趣做 探索性数据分析
- 一个动手操作 介绍到Scikit-学习 用举例
- 一个初学者指南到 线性回归 与 Scikit-Learn
- 概述中的逻辑回归 或 分类 与 Scikit-Learn
- 概述解释支持向量机(【SVM】**)**与 Scikit-Learn 以及各种内核
- 简介到 决策树实现了解被施魔法 随机森林 与 Scikit-Learn
- 简介,教程,解释,以及的实现朴素贝叶斯 分类器与 Scikit-Learn
- 一个概述 时间序列 数据处理和预测用 Scikit-Learn
- 理解偏差-方差权衡
- 准确度、精确度、召回率和 F1 分数 ,这些指标将用于评估 ML 算法
- 山脊(L2)和拉索(L1) 正规化 同 Scikit-Learn
- K 最近邻 或 k-NN 分类器用 Scikit-Learn ,一个教程
- K-Means 聚类 用 Scikit-Learn 解释
- DBSCAN 聚类与 Scikit-Learn
- 主成分分析 ( 降维)用 Scikit-Learn 举例
- 一简要说明的建设一的推荐系统的
检查你的齿轮:工程师的机器学习
当你开始你的 ML 之旅时,是时候检查你的装备,掌握地图和指南针了。
当心盲点
确定性逻辑在软件工程师中根深蒂固。但是机器学习本质上是统计的。我们需要学会接受这一事实,即该模型不会在所有输入上都正确工作。针对特定的输入进行修复很可能会降低整体性能。这是我经历的最大的挣扎。
您可能会感到惊讶,一个已经通过的单元测试甚至可能在没有任何代码更改的情况下就开始失败。这可能是因为将训练数据随机划分为训练集、验证集和测试集。随机分区会导致稍微不同的模型。并且该模型可能恰好在单元测试中使用的输入上失败。你需要将统计正确性的概念内在化。
面向工程师的机器学习地图
您了解了三种最重要的机器学习技术:线性回归、分类和聚类。你知道神经网络和深度学习的应用。你还得到了深入知识的课程和书籍清单。您还有一个关于最重要的主题和技术的文章列表。所有这一切给你一个 ML 景观的概述。那是你的地图。您已经准备好踏上学习 ML 模型如何工作的旅程。
工程师用机器学习指南针
数据科学家擅长数学。他们已经掌握了处理数据和设计高效模型的技巧。这些可能不完全是你的强项,但是你需要慢慢培养这些能力。没有这一点,模型将仍然是一个黑箱。
请记住你作为软件工程师的优势。你有很强的编程能力。您是构建高可伸缩性应用程序的专家。您已经掌握了持续的开发-测试-部署流程。您设计的系统可以 24x7 全天候运行,并具有自动监控和警报功能。
这些技能在数据科学家中并不常见。他们可能不关心在 24x7 生产系统中建立 ML 模型的正确性保证。他们通常为给定的数据集构建批处理程序。将它投入生产可能需要大量的(重新)工作和工程。你必须使你的工程实践适应 ML 的世界。你可以把工程纪律和严谨带到 ML。
数据科学家和软件工程师都需要更好地理解对手。他们必须不断向右上象限移动。那是你的罗盘。
तमसोमाज्योतिर्गमय(tamasmājytirgamaya)。引领我从黑暗走向光明。
冒险开始了
关键要点是:
- AI 是真实的,未来就在这里。正如吴恩达所说: AI 是新的电。就像工业革命时期的电力一样,AI 会对一个又一个行业进行革命。
- 这仅仅是人类开始人工智能冒险的开始。
- 通过培训你可以学到任何东西,从今天开始!
祝你好运,一路顺风!!!
如果你喜欢这个,请:
原载于ML4Devs.com。
软件测试和机器学习
关于如何测试和信任软件中包含的机器学习的基础知识
概观
让我们面对它,机器学习(ML)正在成为许多软件系统的标准部分。您系统中的训练模型可能会直接向用户显示预测,以帮助他们做出人类决策,或者它可能会在软件系统本身中做出自动决策。无论系统中的 ML 是内部开发的还是从第三方预先训练的模型 API 中检索的,如果正在使用利用训练模型预测的生产软件,则需要像测试软件的任何其他方面一样对其进行严格测试。在这篇文章中,我们将回顾一个经验法则框架,当涉及到 ML 时,如何测试你的软件,并识别一些常见的陷阱。
作者注:ML 中的测试和变更管理是一个庞大的主题。本文的目的不是通过测试来帮助评估模型的准确性和性能有多强,而是理解模型的预测界面和行为。也就是说,通过以这种方式测试您的软件系统,您可能会发现常见的模型缺点和限制。
不变测试
在我们深入研究 ML 的引入如何改变系统之前,让我们快速讨论一下测试软件系统的原因。测试有助于开发人员确保系统的行为按照规定运行。程序和软件是不断变化的系统,如果由于各种原因而没有捕捉行为变化的自动化测试,系统就容易出错、失败和有缺陷。
也就是说,我们所说的测试是什么意思?虽然有许多方法可以对一段代码进行单元测试,但是一种常见的测试方法是通过不变量。我们可以测试函数的哪些普遍真理?
def is_above_threshold(value):
return value > THRESHOLD
这是一个我们可以测试的函数的基本例子。立即浮现在脑海中的三个测试用例是检查一个低于THRESHOLD
的数字、一个高于THRESHOLD
的数字和THRESHOLD
值本身。
def test_over_threshold():
assert is_above_threshold(THRESHOLD + 1)def test_under_threshold():
assert not is_above_threshold(THRESHOLD — 1)def test_threshold_edge():
assert not is_above_threshold(THRESHOLD)
太好了。因为这是 Python,我们可能还需要一些测试来尝试一些不同的输入类型。我们接受浮点数、整数、浮点数、无穷大吗?这些例子应该相当简单。我们唯一需要改变这些测试的时候就是函数的不变量改变的时候。假设我们把>改成> =。这将导致一个或多个测试失败,因为我们测试的不变量发生了变化。
然而,我们知道这不是软件系统需要的所有测试。系统不仅仅是一两个相互调用的 Python 函数;它们通常由大型互连的功能层组成,通过网络协议与其他软件系统对话。为了处理这种复杂程度,我们需要集成测试。
集成测试
像单元测试一样,不同的开发人员对集成测试到底需要什么有不同的定义。为了这个例子的目的,我们想要测试我们的代码与我们系统的另一个组件一起工作。这个组件可以从数据库中读取数据,或者调用 rest API 并获取信息。这里有一个简单的例子,使用了前面的is_above_threshold
函数:
def make_decision(user_input):
collected_value = component.get(user_input) if is_above_threshold(collected_value):
return “Do it!”
else:
return “Don’t do it!”
我们要测试的这个函数的属性是什么?
首先也是最重要的,我们要确保我们正确地使用了component.get
的界面。我们需要向make_decision
提供足够多不同的输入,以测试component.get
的各种输出,确保我们没有错过其接口的任何可能的结果。这方面的一些例子:
- 给定文档,什么值可以作为输入传入?就像我们的单元测试示例一样,尝试边缘案例来捕获非正常情况下的行为。
- 如果输入错误,
component.get
会引发错误吗?如果是,我们是在这个函数中处理它,还是将其提交给make_decision
的调用者? - 如果
component.get
有时候返回非数值怎么办?在更复杂的情况下,如果component.get
根据传入的输入返回不同的数据类型会怎样?
这些都是我们可以执行的有效测试,因为我们是在测试我们的代码是否为component.get
的接口做好了准备,而不是深入到函数的实现中。
我们还想测试我们的代码是否工作正常。为了做到这一点,我们可以举几个user_input
的好例子,确保我们最终得到预期的决策。
在大多数软件系统中,当我们使用一个库或组件时,我们可以期望组件已经通过了它自己的一套不变量和集成测试。因此,我们只需要测试交集的有效性。
什么会导致这些测试发生变化?如果我们以任何方式更新了代码,改变了我们一些优秀的user_input
例子的结果,那么我们将不得不更新测试以适应新的行为。
现在,假设我们更新了库组件的主要版本,并且接口发生了变化。get
函数不再是我们想要使用的方法。我们不希望我们的make_decision
函数的行为改变。我们可以改变make_decision
来适应新的 API,如果我们写的测试是正确的,它们不应该改变。
现在我们已经完成了一些测试基础,真正的问题是当我们将 ML 添加到我们的软件系统中时会有什么不同?
让我们加上 ML
让我们马上弄清楚,许多用于构建 ML 模型的库都经过了很好的测试。[1]然而,在你的软件系统中使用 ML 通常不是直接使用那些测试良好的库函数,而是从库中创建的工件,你的训练模型。
当您的代码调用model.predict
时,您可以保证所有相互调用的方法和函数层都在不变的级别上工作,但是您不能保证库知道您提供给模型的数据是什么样子。在前面的不变测试例子中,我们谈到了对可变类型的测试,比如 floats、ints、inf 等等。这同样适用于测试训练模型,但是数据类型可能要复杂得多。例如,数字 3 比有 30 个级别的分类特征更容易测试。那么,当我们讨论一个大得多的输入数据集时,我们之前为不变测试开发的三到八个测试成立吗?不完全是。
用 ML 进行不变测试
经过训练的 ML 模型比我们之前用>符号比较两个数字的例子要复杂得多。那么,当用一个经过训练的模型工件进行预测时,我们应该保持哪些不变量是正确的呢?让我们从一些基础开始:
- 模型的预测应该是确定性的。这意味着当我为一个预测传入一行数据时,每次都应该得到相同的预测。同样,在进行单行预测和批量预测时,预测一致性也应该成立。例如,不管第 3 行是单独的还是与第 1-10 行一起,对第 3 行的预测应该是相同的。
- 从单个兼容行扩展,我们应该能够在用于评估模型的相同测试数据上再现相同的误差度量分数。忽略度量分数是好是坏的事实,我们希望能够测试它没有改变。
- 该模型应在一定时间内做出预测。一些复杂的输入数据可能会导致模型比不太复杂的输入数据花费更长的时间来进行预测,但是应该有一个您可以测量的上限。
确定性模型
模型会做出预测,但它们的预测应该是一致的。很像人,除非模型学习新的东西,否则它只能用当前已知的信息产生一个结果。在线机器学习有一个时间和地点,但我不会在这篇文章中深入探讨这个主题。
为了测试一致性,我们需要我们的测试用例查看更多类型的输入数据。考虑使用用于评估模型的整个样本外数据集。这是在定型模型时未包括的数据,但具有实际结果,您可以将这些结果与模型预测进行比较。为了确保模型的确定性,我们不会将模型的预测与实际结果进行比较,而是与该模型对同一组数据做出的原始预测进行比较。如果您在每次测试运行时对这些数据进行预测,无论是作为合并请求的自动化的一部分,还是作为集成管道的一部分,您都将确保模型产生一致的预测。
也许您担心原始的样本外数据没有覆盖足够多的可能输入到您的模型中的潜在输入。您可以计算彻底测试您的模型所需的总行数。让我们看一个玩具的例子:
假设您的模型使用 1000 行数据对五个特征进行了训练。其中三个特征分别为 5、10 和 30 级。另外两列是数字,每列有 500 个唯一值。若要计算总行数以彻底测试模型对每个数据组合的预测行为,您需要提供 5 * 10 * 30 * 500 * 500 = 3.75 亿行。这种级别的测试会告诉你你的模型在每一种可能的情况下会有什么样的表现,但是只针对模型已经学习的数据。
上面的详尽测试对于软件系统的 CI 管道来说是不切实际的。即使这个模型可以在十分之一秒内做出一个预测,测试仍然需要一万多个小时才能完成。这忽略了加载、预测和断言大量数据所需的硬件和基础设施。
有了样本外数据及其结果,您就有了可以测试模型的良好数据样本,因为这是模型构建者和评估者用于评估目的的标准。它应该足以捕捉模型中的不变变化。在这种情况下,测试应该改变以适应不变的变化。不要忘记测试“边缘”案例,例如空值和数字数据或不属于模型定型数据的类别。
如果系统中的库或依赖项升级导致预测改变,这些测试也将失败。然而,正如我们前面提到的,通常库和依赖项升级不应该影响我们系统的外部行为,因此在这种情况下,模型代码可能需要以某种方式进行更改,以确保一致的预测。围绕训练模型的存储格式及其运行时环境,还有许多测试考虑事项。如果环境依赖关系被更新,当试图将模型加载到内存中时,一些存储格式,如 pickle,可能会导致运行时错误。[2]
用 ML 进行集成测试
我们已经讨论了测试使用 ML 模型的软件系统所需的一些非常基本的不变量。在集成层面,幸运的是,我们可以保留一些与之前相同的概念。让我们看看如果用model.predict
代替component.get
,我们的make_decision
函数会是什么样子:
def make_decision(user_input):
prediction = model.predict(user_input) if is_above_threshold(prediction):
return “Do it!”
else:
return “Don’t do it!”
model.predict
调用的功能类似于component.get
,从用户那里获取数据并产生我们需要评估的值。为了满足集成测试,您同样需要测试您是否正确地覆盖了model.predict
接口,在必要的时候捕获或抛出错误。如果我们知道一个值中的空特性会导致 predict 产生一个错误,那么测试这种情况并让您的函数相应地处理它。再次提供几个输入系统的出色例子。
结论
我们已经回顾了在您的系统中添加 ML 时需要考虑的一些基本问题。这一组初始测试是一个合理的基线,但是您还可以做得更多。[3]
例如,在部署模型之后对其进行监控。生产软件系统确实需要监控,以确保它们按预期工作。虽然我们的测试断言模型的行为不会改变,但我们无法测试模型的真实世界输入是如何改变的,并导致做出糟糕的预测。这是模型变更管理的重要一步。
测试模型的预测界面和行为将确保开发人员理解模型的行为,并保持系统抗 bug。ML 模型将会被更多地使用,因此如何测试它们的通用最佳实践对于未来的软件开发将是至关重要的。
脚注和参考文献:
[1]不是所有的图书馆都是完美的。你最终会遇到错误,发现库接口的局限性。在这些情况下,这是一个很好的机会来找到存储库,检查问题,看看其他人是否已经发现了 bug,提供一个最小的可重复的案例,并可能建议一个修复方法。
[2]参见酸洗文件
[3] D .斯卡利、加里·霍尔特、丹尼尔·戈洛文、尤金·达维多夫、托德·菲利普斯、迪特马尔·埃布纳、维奈·乔德里、迈克尔·杨、让-弗兰克 ois Crespo、丹·丹尼森,《机器学习系统中隐藏的技术债务》(2014 年),NIPS’15