TowardsDataScience-博客中文翻译-2016-2018-十五-

TowardsDataScience 博客中文翻译 2016~2018(十五)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

扩展卡尔曼滤波器

原文:https://towardsdatascience.com/extended-kalman-filter-ee9bd04ac5dc?source=collection_archive---------2-----------------------

在我以前的博客中,我已经介绍过卡尔曼滤波器。在这篇博客中,我将讨论扩展滤波,并看看它如何解决卡尔曼滤波的问题。

这篇博客是我之前关于卡尔曼滤波器的博客的延续,所以如果你还没有读过,请在这里阅读。

为什么要使用扩展卡尔曼滤波器?

为了解决卡尔曼滤波中的非线性问题,引入了扩展卡尔曼滤波。在现实生活中,可能有许多场景,系统可能会从一个方向观察,而从另一个方向进行测量。这涉及到解决这些问题的角度,导致非线性函数,当输入高斯函数时,导致非高斯分布。并且我们不能对非高斯分布应用卡尔曼滤波器,因为计算非高斯函数的均值和方差是没有意义的。

它是如何工作的?

扩展卡尔曼滤波器利用泰勒级数、将非线性函数转化为线性函数,有助于得到非线性函数的线性逼*

泰勒级数:

在数学中,泰勒级数是一个函数的表示,它是由函数在一个点的导数的值计算出来的无穷多个项的总和。简单来说,我们可以说,在泰勒级数中,我们取一个点,对它进行一系列求导。

当我们对一个多项式执行泰勒级数时,结果也是一个多项式,因此 EKF 所做的是首先在一个平均值处评估非线性函数,该平均值是分布的最佳*似值,然后估计一条斜率在该平均值附*的直线。该斜率由泰勒展开的一阶导数确定,因为一阶导数给出了线性值。因此,这种从泰勒级数的一阶导数获得斜率的方法被称为一阶泰勒展开。

如何进行泰勒展开?

泰勒级数由下式给出

Taylor Series

非线性函数 f(x)在均值(μ)处的泰勒级数方程的一般公式由下式给出:

By appling first order taylor expansion method

得到泰勒展开式需要遵循的步骤:

  • 用一个给定的等式代替 f(x)
  • 求偏导数
  • 插入值μ,并进行评估,以获得μ值处的泰勒展开式。

让我们通过一个例子来理解这一点:

假设我们必须找到方程 sin(x)在μ = 0 时的泰勒展开式

所以按照上面讨论的步骤:

  • h(x) = sin(x)
  • ∂h = cos(x)
  • h(x)≈h(μ)+∂x∂h(μ)(xμ)

h(x)≈sin(μ)+cos(μ)(xμ)= 0+1 *(x-0)= x

EKF 对 KF 预测和更新方程的影响

当我们谈到 EKF 对 KF 方程的影响时,有必要知道数据的来源。也就是说,对于自主车辆,我们需要知道我们必须执行预测的数据是来自激光雷达还是雷达。

因为激光雷达以笛卡尔坐标系统的形式为我们提供距离,而雷达以极坐标系统为我们提供距离和速度。两者的测量向量如下:

激光雷达:{px,py}

雷达:{ ρ,φ,ρ_dot }

其中 px:物体在笛卡尔坐标系中的 x 坐标

py: 物体在笛卡尔坐标系中的 y 坐标

**:物体与车辆的距离

φ:x 和ρ之间的逆时针角度**

ρ_ dot:ρ的变化率**

x 轴决定汽车移动的位置。

Polar coordinate System

到目前为止,你可能已经理解了激光雷达提供的数据本质上是线性的,而雷达提供的数据是非线性的。因此,激光雷达数据的等式将保持与卡尔曼滤波器的等式相同,但是对于雷达测量,等式将如下:

预测步骤:

x′= f . x+b .μ+ν

p′=fpfᵀ+q

无论使用何种设备,它都将保持与 KF 相同的状态。

雷达测量更新步骤:

y = z—h(x’)

z: 极坐标下的实际测量

h(x’):预测笛卡尔坐标系到极坐标的映射。这里的x′*是笛卡尔坐标系中的预测值。*

Mapping of Cartesian to Polar Coordinate system [Taken from udacity Nano degree]

y: 实测值与实际测量值之差。

s =hⱼp′hⱼᵀ+r
k =p′hⱼᵀs⁻

R: 测量噪音

这些噪声决定了器件的校正参数。它由设备制造商提供,并在整个周期中保持不变。

Hⱼ: 雅可比矩阵

正如我们已经看到的,为了将非线性函数转换为线性函数,我们使用泰勒级数展开,并对其进行一阶导数。当我们在方程中处理矩阵时,这个一阶导数由雅可比矩阵给出。

Jacobian matrix

因为雷达的状态向量由 px、py、vx 和 vy 组成。

通过应用导数,我们将得到 Hj 的最终值,如下所示:

Jacobian matix after applying derivative

K: 卡尔曼增益

我们通过简单的公式计算卡尔曼增益,这个公式我已经在我的关于卡尔曼滤波的博客中展示过了。唯一的事情是,在矩阵中我们不能分割,所以这里我们采取 S⁻。

x = x′+k . y
p =(I-khⱼ)p′

最后,我们更新状态向量和协方差矩阵,并继续下一个预测步骤以获得其他值。

扩展卡尔曼滤波器的问题

在扩展卡尔曼滤波器中,*似是基于单点即均值来完成的。这种*似可能不是最佳的*似,并导致较差的性能。你可以通过下图来理解:

mean and variance [Left] approximation based on mean[center] best possible approximation vs EKF approximation.[right][Image Source]

使用无迹卡尔曼滤波器解决了扩展卡尔曼滤波器的这个问题

女子网球比赛的广泛分析

原文:https://towardsdatascience.com/extensive-analysis-of-women-tennis-matches-5c98333f338a?source=collection_archive---------5-----------------------

Photo by Ben Hershey on Unsplash

在这里找到的 Kaggle 数据集涵盖了在 WTA (女子网球协会)注册的球员的统计数据,每年每场巡回赛发生的比赛,结果,以及巡回赛的一些资格赛。

从 2000 年到 2017 年的数据中发现了一些有趣的分析(其中一部分)。分析是在 R Markdown 中完成的,在这里作为 Kaggle 内核托管

玩家统治

  • 除了 2014 年和 2015 年由塞雷娜·威廉姆斯主导之外,2017-2003 年没有完全的优势
  • 1984 年至 1996 年由三名球员主宰,他们是玛蒂娜·纳芙拉蒂洛娃、施特菲·格拉芙和莫妮卡·塞莱斯。1997 年到 2002 年左右由林德赛·达文波特和玛蒂娜·辛吉斯主导
  • 在 2000 年至 2017 年(部分时间)的分析中,塞雷娜统治了大满贯赛事,赢得了 7 个澳大利亚公开赛、3 个法国公开赛、7 个温布尔登公开赛和 5 个美国公开赛

输掉第一盘或第二盘后获胜

  • 在决赛输掉第一盘后赢得美网决赛的概率是****
  • 在一场决赛输掉第一盘后赢得法网决赛的概率是 5 % 。这种情况只在 2001 年珍妮弗·卡普里亚蒂击败吉姆·克里斯特尔斯时发生过一次****
  • 在一场决赛输掉第一盘后赢得澳网决赛的概率是 22%****
  • 在一场决赛输掉第一盘后赢得温网决赛的概率是 17%****
  • 在所有比赛中输掉第一盘后获胜的概率是 16%
  • 在所有比赛中输掉第二盘后获胜的概率是 14%

表面分析

Photo by Aaina Sharma on Unsplash

2000 年至 2017 年期间(有 2017 年的部分数据),观察如下

  • 威廉姆斯姐妹占据了中奖名单的第一和第二名
  • 从各方面来看,俄罗斯人、美国人和法国人赢得了最多的比赛
  • 在硬面上,俄罗斯人、美国人和法国人占据了前三名的位置
  • 在红土表面,俄罗斯人、西班牙人和美国人占据了前三名
  • 面上,美国人、俄罗斯人和澳大利亚人又占据了前三的位置**
  • 地毯表面,俄罗斯人、法国人和美国人占据了前三的位置**

锦标赛等级分析

我们调查了不同锦标赛级别的顶级赢家****

  • 威廉姆斯姐妹和玛丽亚·莎拉波娃占据了大满贯的前三名
  • 伊琳娜·德门蒂耶娃、贾斯汀·海宁和玛蒂娜·辛吉斯占据了 T1 锦标赛的前三名。比赛最多的 T1 锦标赛是迈阿密、印第安维尔斯和罗马
  • 陈月娇·毛瑞斯莫、林德赛·达文波特和吉姆·克里斯特尔斯占据了 T2 锦标赛的前三名。比赛最多的 T2 锦标赛是阿米莉娅岛、洛杉机和悉尼

镦粗分析

Photo by Davon King on Unsplash

如果赢家排名比输家排名至少高 10 位,我们可以认为是一个冷门。我们绘制了大满贯冠军和失败者之间的排名差异。

  • 我们注意到大满贯决赛中冷门很少。但是他们中的一些在那里,让我们找出他们是什么。维纳斯·大威廉姆斯在大满贯决赛中创造了两次爆冷。2017 年美国网球公开赛爆冷,半决赛斯隆·斯蒂芬斯击败维纳斯·大威廉姆斯决赛麦迪逊·凯斯**
  • 吉姆·克里斯特尔斯和丹尼埃拉·汉图楚娃在 T1 锦标赛决赛中创造了两次冷门
  • 查达·鲁宾在 T2 锦标赛决赛中创造了两次冷门

如果您对 代码感兴趣,请在下面查找详细信息。 分析是在 R Markdown 中完成的,在这里作为 Kaggle 内核托管。****

加载库

我们需要加载库来进行数据分析。

****library(tidyverse)
library(stringr)
library(lubridate)
library(DT)****

读取数据

将数据放在项目的输入目录中,并读取文件。数据集托管在这里

****fillColor = “#FFA07A”
fillColor2 = “#F1C40F”players = read_csv(“../input/wta/players.csv”)
rankings = read_csv(“../input/wta/rankings.csv”)
matches = read_csv(“../input/wta/matches.csv”)matches$tourney_name = str_replace(matches$tourney_name,”Us Open”,”US Open”)****

国家和选手

该图显示了从 2000 年到 2017 年代表他们国家的国家和球员人数。我们观察到美国是最大的赢家,澳大利亚、俄国、法国、德国、日本和中国都有超过五十名玩家参加

****matches_country_winner = 
 matches %>% 
 select(winner_name,winner_ioc) %>%
 rename ( name = winner_name,ioc = winner_ioc)matches_country_loser = 
 matches %>% 
 select(loser_name,loser_ioc) %>%
 rename ( name = loser_name,ioc = loser_ioc)matches_country = unique(rbind(matches_country_winner,matches_country_loser))matches_country %>%
 group_by(ioc) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(ioc = reorder(ioc,Count)) %>%
 head(20) %>%

 ggplot(aes(x = ioc,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”, fill = fillColor) +
 geom_text(aes(x = ioc, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Country’, 
 y = ‘Count’, 
 title = ‘Country and Count’) +
 coord_flip() +
 theme_bw()****

排名和年份

我们显示球员和他们每年排名第一的位置。我们绘制了一个条形图,显示了他们至少获得 1 级排名的年数。同年,这些球员的排名可能下滑至第一名以下。**这显示了玩家的坚持和长寿****

在过去的 20 年里,施特菲·格拉芙、小威廉姆斯、林德赛·达文波特、莫妮卡·塞莱斯和玛蒂娜·辛吉斯这些普通的名字主宰了女子网球。

Years in No 1 Rank

****players_rankings = inner_join(players,rankings)
players_rankings$year = str_sub(players_rankings$ranking_date,1,4)
players_rankings$month = str_sub(players_rankings$ranking_date,5,6)players_rankings_rank_one = players_rankings %>% filter(ranking == 1)players_rankings_rank_one_year = 
 players_rankings_rank_one %>% 
 group_by(first_name,last_name,year) %>% 
 tally()
players_rankings_rank_one_year = players_rankings_rank_one_year %>% select(-n)
players_rankings_rank_one_year = unique(players_rankings_rank_one_year)players_rankings_rank_one_year %>%
 mutate(FullName = paste0(first_name,” “,last_name,””)) %>%
 group_by(FullName) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(FullName = reorder(FullName,Count)) %>%
 head(10) %>%

 ggplot(aes(x = FullName,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”, fill = fillColor) +
 geom_text(aes(x = FullName, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Name’, 
 y = ‘Count’, 
 title = ‘Name and Count’) +
 coord_flip() + 
 theme_bw()****

每年排名第一的网球选手数量

我们绘制了一年中排名第一的网球运动员的数量。这显示了一年中有多少玩家排名第一。

2017 年至 2003 年排名第一的网球运动员人数

如柱状图 所示,2017 年至 2003 年没有完全的优势,除了 2014 年和 2015 年由小威廉姆斯 主导。

****players_rankings_rank_one_year %>%
 group_by(year) %>%
 summarise(Count = n()) %>%
 arrange(desc(year)) %>%
 ungroup() %>%
 head(15) %>%

 ggplot(aes(x = year,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”, fill = fillColor2) +
 geom_text(aes(x = year, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Year’, 
 y = ‘Count’, 
 title = ‘Year and Count’) +
 coord_flip() + 
 theme_bw()****

排名数据如下所示

****datatable(head(players_rankings_rank_one_year %>% arrange(desc(year)),10), style=”bootstrap”, class=”table-condensed”, options = list(dom = ‘tp’,scrollX = TRUE))****

1984-2003 年世界排名第一的网球运动员人数

1984 年至 1996 年由三名球员主导 玛蒂娜·纳芙拉蒂洛娃、施特菲·格拉芙和莫妮卡·塞莱斯。1997 年至 2002 年左右由 林德赛·达文波特和玛蒂娜·辛吉斯主导。

****players_rankings_rank_one_year %>%
 group_by(year) %>%
 summarise(Count = n()) %>%
 arrange(desc(year)) %>%
 ungroup() %>%
 tail(20) %>%

 ggplot(aes(x = year,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”, fill = fillColor2) +
 geom_text(aes(x = year, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Year’, 
 y = ‘Count’, 
 title = ‘Year and Count’) +
 coord_flip() + 
 theme_bw()****

排名数据如下所示

****datatable(tail(players_rankings_rank_one_year %>% arrange(desc(year)) ,34), style=”bootstrap”, class=”table-condensed”, options = list(dom = ‘tp’,scrollX = TRUE))****

小威廉姆斯排名趋势

****plotTrendsRankings = function(players_rankings,firstname,lastname,plottitle)
{
 players_rankings %>% 
 filter(first_name == firstname) %>%
 filter(last_name == lastname) %>%
 mutate(YearMonth = make_date(year=year,month=month) ) %>%

 ggplot(aes(x=YearMonth,y=ranking,group = 1)) +
 geom_point(size=2, color=”red”) +

 labs(x = ‘Time’, y = ‘ranking’,title = plottitle) +
 theme_bw() 

}plotTrendsRankings(players_rankings,”Serena”,”Williams”,”Trend of Ranking for Serena Williams”)****

排名在 100 名以上

****rankingsAboveThreshold = function(players_rankings,firstname,lastname,threshold)
{
 players_rankings %>% 
 filter(first_name == firstname) %>%
 filter(last_name == lastname) %>%
 filter(ranking >=threshold)
}serena100 = rankingsAboveThreshold(players_rankings,”Serena”,”Williams”,100) %>%
 select(year,month,ranking) %>% 
 arrange(desc(ranking))datatable(serena100 %>% arrange(desc(year)), style=”bootstrap”, class=”table-condensed”, options = list(dom = ‘tp’,scrollX = TRUE))****

很明显,小威在 2006 年和 2011 年的排名分别下降了 50 位和 100 位。

施特菲·格拉芙排名趋势

****plotTrendsRankings(players_rankings,”Steffi”,”Graf”,”Trend of Ranking for Steffi Graf”)****

西蒙娜·哈勒普排名趋势

****plotTrendsRankings(players_rankings,”Simona”,”Halep”,”Trend of Ranking for Simona Halep”)****

Sania Mirza 排名趋势

****plotTrendsRankings(players_rankings,”Sania”,”Mirza”,”Trend of Ranking for Sania Mirza”)****

澳网冠军

下面的柱状图展示了澳网冠军

****getTournamentWinners = function(tournamentname,roundname)
{
 return(
 matches %>%
 filter(tourney_name == tournamentname) %>%
 filter(round == roundname) %>%
 mutate(agediff = winner_age — loser_age) %>%
 mutate(rankingdiff = loser_rank — winner_rank) %>%
 mutate(htdiff = winner_ht — loser_ht)
 )
}getGrandSlamWinners = function(roundname)
{
 return(
 matches %>%
 filter(tourney_level == “G”) %>%
 filter(round == roundname) %>%
 mutate(agediff = winner_age — loser_age) %>%
 mutate(rankingdiff = loser_rank — winner_rank)
 )
}plotTournamentWinners = function(tournament,titleName)
{
 tournament %>%
 group_by(winner_name) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(winner_name = reorder(winner_name,Count)) %>%

 ggplot(aes(x = winner_name,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”, fill = fillColor2) +
 geom_text(aes(x = winner_name, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Winner’, 
 y = ‘Count’, 
 title = titleName) +
 coord_flip() + 
 theme_bw()

}ausopen = getTournamentWinners(“Australian Open”,”F”)
plotTournamentWinners(ausopen,’Aus Open Winners Count’)****

澳网冠军年龄分布

****summary(ausopen$winner_age)ausopen %>%
 ggplot(aes(x = winner_age)) +
 geom_histogram(binwidth = 1,fill = fillColor) +
 labs(x= ‘Winner Age’,y = ‘Count’, title = paste(“Distribution of”, ‘ Winner Age ‘)) +
 theme_bw()****

该图显示澳网冠军大多在 23 至 28 岁之间。

法网冠军

下面的柱状图展示了法国网球公开赛的获胜者

****french = getTournamentWinners(“French Open”,”F”) 
plotTournamentWinners(french,’French Open Winners Count’)****

法网冠军年龄分布

****summary(french$winner_age)french %>%
 ggplot(aes(x = winner_age)) +
 geom_histogram(binwidth = 1,fill = fillColor) +
 labs(x= ‘Winner Age’,y = ‘Count’, title = paste(“Distribution of”, ‘ Winner Age ‘)) +
 theme_bw()****

该图显示法网冠军大多在 22 至 27 岁之间。

温布尔登冠军

下面的柱状图展示了温布尔登的获胜者

****wimbledon = getTournamentWinners(“Wimbledon”,”F”) 
plotTournamentWinners(wimbledon,’Wimbledon Winners Count’)****

温布尔登冠军的年龄分布

****summary(wimbledon$winner_age)wimbledon %>%
 ggplot(aes(x = winner_age)) +
 geom_histogram(binwidth = 1,fill = fillColor) +
 labs(x= ‘Winner Age’,y = ‘Count’, title = paste(“Distribution of”, ‘ Winner Age ‘)) +
 theme_bw()****

该图显示温布尔登网球公开赛的获胜者大多在 21 岁至 29 岁之间。

美国公开赛冠军

下面的柱状图展示了美国公开赛的获胜者

****usopen = getTournamentWinners(“US Open”,”F”) 
plotTournamentWinners(usopen,’US Open Winners Count’)****

美国公开赛冠军的年龄分布

****summary(usopen$winner_age)usopen %>%
 ggplot(aes(x = winner_age)) +
 geom_histogram(binwidth = 1,fill = fillColor) +
 labs(x= ‘Winner Age’,y = ‘Count’, title = paste(“Distribution of”, ‘ Winner Age ‘)) +
 theme_bw()****

该图显示,美国公开赛的获胜者大多在 21 岁至 28 岁之间。

成功者和失败者的身高差距

我们绘制了大满贯冠军和失败者之间的身高差。数据显示,大满贯冠军比失败者的身高更低,尽管数据没有 19 个条目。

****grandslam= rbind(ausopen,french,wimbledon,usopen)summary(grandslam$htdiff)****

直方图

****grandslam %>%
 ggplot(aes(x = htdiff)) +
 geom_histogram(binwidth = 1,fill = fillColor) +
 labs(x= ‘Height Difference’,y = ‘Count’, title = paste(“Distribution of”, ‘ Height Difference ‘)) +
 theme_bw()****

密度图

****grandslam %>%
 ggplot(aes(x = htdiff)) +
 geom_density(fill = fillColor2) +
 labs(x= ‘Height Difference’,y = ‘Count’, title = paste(“Distribution of”, ‘ Height Difference ‘)) +
 theme_bw()****

表列数据

****grandslamhtdiff = grandslam %>% select(winner_name,loser_name,htdiff)datatable(grandslamhtdiff, style=”bootstrap”, class=”table-condensed”, options = list(dom = ‘tp’,scrollX = TRUE))****

成功者和失败者之间的年龄差距

我们绘制了大满贯冠军和失败者之间的年龄差距。

****summary(grandslam$agediff)grandslam %>%
 ggplot(aes(x = agediff)) +
 geom_histogram(binwidth = 1,fill = fillColor) +
 labs(x= ‘Age Difference’,y = ‘Count’, title = paste(“Distribution of”, ‘ Age Difference ‘)) +
 theme_bw()grandslam %>%
 ggplot(aes(x = agediff)) +
 geom_density(fill = fillColor2) +
 labs(x= ‘Age Difference’,y = ‘Count’, title = paste(“Distribution of”, ‘ Age Difference ‘)) +
 theme_bw()****

从图中可以明显看出,年纪大的选手比年轻选手更容易赢得决赛。

特征工程:第一、第二、第三组赢家和输家

我们提取第一组、第二组和第三组获胜者的特征

****whowon = function(scores,setnumber)
{
 scores2 = str_split(scores,” “)set = scores2[[1]][setnumber]set_score = str_split(set,”-”)winner_score = as.numeric(set_score[[1]][1])
 loser_score =as.numeric(str_split(set_score[[1]][2],””)[[1]][1])

 if( (is.na(winner_score)) ||
 (is.na(loser_score))
 )
 {
 setwinner = “”
 }else
 {
 if(winner_score > loser_score)
 {
 setwinner = “winner”
 }else
 {
 setwinner = “loser”
 }
 }

 return(setwinner)

}matches$first_set = sapply(matches$score,whowon, setnumber = 1)
matches$second_set = sapply(matches$score,whowon, setnumber = 2)
matches$third_set = sapply(matches$score,whowon, setnumber = 3)****

输掉第一盘后赢家的百分比

****first_set_loser = matches %>% 
 filter(first_set == “loser”)nrow(first_set_loser)/nrow(matches) *100****

大多数人在输掉第一盘后获胜

条形图显示了第一盘失败后的获胜者

****first_set_loser %>%
 group_by(winner_name) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(winner_name = reorder(winner_name,Count)) %>%
 head(10) %>%

 ggplot(aes(x = winner_name,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”, fill = fillColor2) +
 geom_text(aes(x = winner_name, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Winner’, 
 y = ‘Count’, 
 title = ‘Winner’) +
 coord_flip() + 
 theme_bw()****

输掉第二盘后赢家的百分比

****second_set_loser = matches %>% 
 filter(second_set == “loser”)nrow(second_set_loser)/nrow(matches) *100****

大多数人在输掉第二盘后获胜

条形图显示了输掉第二盘后的赢家

****second_set_loser = matches %>% 
 filter(second_set == “loser”)second_set_loser %>%
 group_by(winner_name) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(winner_name = reorder(winner_name,Count)) %>%
 head(10) %>%

 ggplot(aes(x = winner_name,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”, fill = fillColor) +
 geom_text(aes(x = winner_name, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Winner’, 
 y = ‘Count’, 
 title = ‘Winner’) +
 coord_flip() + 
 theme_bw()****

在大满贯赛事中输掉第一盘后的赢家比例

我们在输掉第一盘后计算赢家的百分比

****gs_final_firstset_loser = matches %>%
 filter(tourney_level == “G”) %>%
 filter(round == “F”) %>%
 filter(first_set == “loser”)gs_final_secondset_loser = matches %>%
 filter(tourney_level == “G”) %>%
 filter(round == “F”) %>%
 filter(second_set == “loser”)gs_final_thirdset_loser = matches %>%
 filter(tourney_level == “G”) %>%
 filter(round == “F”) %>%
 filter(third_set == “loser”)gs_final = matches %>%
 filter(tourney_level == “G”) %>%
 filter(round == “F”)nrow(gs_final_firstset_loser)/nrow(gs_final) *100****

在大满贯赛事中输掉第二盘后的赢家比例

我们在输掉第二盘后计算赢家的百分比

****nrow(gs_final_secondset_loser)/nrow(gs_final) *100****

澳大利亚网球公开赛输掉第一盘后的赢家比例

我们在输掉第一盘后计算赢家的百分比

****percentWinnersTourney = function(matches,tournamentName)
{
 gs_final_firstset_loser = matches %>%
 filter(tourney_name == tournamentName) %>%
 filter(round == “F”) %>%
 filter(first_set == “loser”)
gs_final_secondset_loser = matches %>%
 filter(tourney_name == tournamentName) %>%
 filter(round == “F”) %>%
 filter(second_set == “loser”)gs_final = matches %>%
 filter(tourney_name == tournamentName) %>%
 filter(round == “F”)nrow(gs_final_firstset_loser)/nrow(gs_final) *100}displayGrandSlamWinnersAfterLosingFirstSet = function(matches,tournamentName)
{
 gs_final_firstset_loser = matches %>%
 filter(tourney_name == tournamentName) %>%
 filter(round == “F”) %>%
 filter(first_set == “loser”) %>% 
 select(winner_name,loser_name,year,score)

 datatable(gs_final_firstset_loser, style=”bootstrap”, class=”table-condensed”, options = list(dom = ‘tp’,scrollX = TRUE))
}percentWinnersTourney(matches,”Australian Open”)
displayGrandSlamWinnersAfterLosingFirstSet(matches,”Australian Open”)****

在温布尔登输掉第一盘后的赢家比例

我们在输掉第一盘后计算赢家的百分比

****percentWinnersTourney(matches,”Wimbledon”)
displayGrandSlamWinnersAfterLosingFirstSet(matches,”Wimbledon”)****

法国网球公开赛输掉第一盘后的赢家比例

我们在输掉第一盘后计算赢家的百分比

****percentWinnersTourney(matches,”French Open”)
displayGrandSlamWinnersAfterLosingFirstSet(matches,”French Open”)****

美国网球公开赛输掉第一盘后的赢家比例

我们在输掉第一盘后计算赢家的百分比

****percentWinnersTourney(matches,”US Open”)
displayGrandSlamWinnersAfterLosingFirstSet(matches,”US Open”)****

很明显,输掉法美第一盘就意味着几乎输掉了决赛。零次,只有一次,一名选手在输掉第一盘后分别赢得了美国和法国。

表面

不同表面上的匹配数量显示在条形图中。

****matches %>%
 filter(!is.na(surface)) %>%
 filter(!str_detect(surface,”-”)) %>%
 group_by(surface) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(surface = reorder(surface,Count)) %>%

 ggplot(aes(x = surface,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”,fill=fillColor2) +
 geom_text(aes(x = surface, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Surface’, 
 y = ‘Count’, 
 title = ‘Surface and Count’) +
 coord_flip() + 
 theme_bw()****

2000 年至 2017 年期间(有 2017 年的部分数据),观察如下

  • 威廉姆斯姐妹占据了中奖名单的第一和第二名
  • 从各方面来看,俄罗斯人、美国人和法国人赢得了最多的比赛
  • 在坚硬的地面上,俄罗斯人、美国人和法国人占据了前三名的位置
  • 在红土表面上,俄罗斯人、西班牙人和美国人占据了前三名的位置
  • 面上,美国人、俄罗斯人和澳大利亚人又占据了前三的位置
  • 在地毯上,俄罗斯人、法国人和美国人占据了前三名的位置

所有表面

所有表面的前 10 名获奖者如下所示

****matches %>%
 group_by(winner_name) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(winner_name = reorder(winner_name,Count)) %>%
 head(10) %>%

 ggplot(aes(x = winner_name,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”,fill=fillColor) +
 geom_text(aes(x = winner_name, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Winner’, 
 y = ‘Count’, 
 title = ‘Winner and Count’) +
 coord_flip() + 
 theme_bw()surfaceTitle = ‘Country Winning on All Surfaces’matches %>%
 group_by(winner_ioc) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(winner_ioc = reorder(winner_ioc,Count)) %>%
 head(10) %>%

 ggplot(aes(x = winner_ioc,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”,fill=fillColor) +
 geom_text(aes(x = winner_ioc, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = surfaceTitle, 
 y = ‘Count’, 
 title = surfaceTitle) +
 coord_flip() + 
 theme_bw()****

壳体

硬质表面上的前 10 名获胜者如下所示

********

****surfaceWinners = function(surfaceName)
{
 matches %>%
 filter(surface == surfaceName) %>%
 group_by(winner_name) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(winner_name = reorder(winner_name,Count)) %>%
 head(10) %>%

 ggplot(aes(x = winner_name,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”,fill=fillColor2) +
 geom_text(aes(x = winner_name, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Winner’, 
 y = ‘Count’, 
 title = ‘Winner and Count’) +
 coord_flip() + 
 theme_bw()

}countriesSurface = function(surfaceName,surfaceTitle)
{
 matches %>%
 filter(surface == surfaceName) %>%
 group_by(winner_ioc) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(winner_ioc = reorder(winner_ioc,Count)) %>%
 head(10) %>%

 ggplot(aes(x = winner_ioc,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”,fill=fillColor) +
 geom_text(aes(x = winner_ioc, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = surfaceTitle, 
 y = ‘Count’, 
 title = surfaceTitle) +
 coord_flip() + 
 theme_bw()
}surfaceWinners(‘Hard’)
countriesSurface(‘Hard’,’Country Winning on Hard Surface’)****

粘土表面

粘土表面上的前 10 名获胜者如下所示

********

****surfaceWinners(‘Clay’)
countriesSurface(‘Clay’,’Country Winning on Clay Surface’)****

草地表面

草地表面的前 10 名获胜者如下所示

****surfaceWinners(‘Grass’)
countriesSurface(‘Grass’,’Country Winning on Grass Surface’)****

地毯表面

地毯表面的前 10 名获奖者如下所示

********

****surfaceWinners(‘Carpet’)
countriesSurface(‘Carpet’,’Country Winning on Carpet Surface’)****

锦标赛级别

下面的条形图显示了与每个级别相关的锦标赛数量。

****matches %>%
 filter(!is.na(tourney_level)) %>%
 group_by(tourney_level) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(tourney_level = reorder(tourney_level,Count)) %>%

 ggplot(aes(x = tourney_level,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”,fill=fillColor2) +
 geom_text(aes(x = tourney_level, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Tournament Levels’, 
 y = ‘Count’, 
 title = ‘Tournament Levels and Count’) +
 coord_flip() + 
 theme_bw()tournamnentLevelTournaments = function(tournamnentLevel)
{
 matches %>%
 filter(tourney_level == tournamnentLevel) %>%
 group_by(tourney_name) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(tourney_name = reorder(tourney_name,Count)) %>%
 head(10) %>%

 ggplot(aes(x = tourney_name,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”,fill=fillColor) +
 geom_text(aes(x = tourney_name, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Tournament Name’, 
 y = ‘Count’, 
 title = ‘Tournament Name and Count’) +
 coord_flip() + 
 theme_bw()

}tournamnentLevelWinners = function(tournamnentLevel)
{
 matches %>%
 filter(tourney_level == tournamnentLevel) %>%
 group_by(winner_name) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(winner_name = reorder(winner_name,Count)) %>%
 head(10) %>%

 ggplot(aes(x = winner_name,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”,fill=fillColor2) +
 geom_text(aes(x = winner_name, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = ‘Winner’, 
 y = ‘Count’, 
 title = ‘Winner and Count’) +
 coord_flip() + 
 theme_bw()

}****

我们调查了不同锦标赛级别的顶级赢家

  • 威廉姆斯姐妹和玛丽亚·莎拉波娃占据了大满贯的前三名
  • 伊琳娜·德门蒂耶娃、贾斯汀·海宁和玛蒂娜·辛吉斯占据了 T1 锦标赛的前三名。比赛最多的 T1 锦标赛是迈阿密、印第安维尔斯和罗马
  • 陈月娇·毛瑞斯莫、林德赛·达文波特和吉姆·克里斯特尔斯占据了 T2 锦标赛的前三名。比赛最多的 T2 锦标赛是阿米莉娅岛、洛杉机和悉尼

大满贯中获胜次数最多的

****tournamnentLevelWinners(‘G’)****

T1 锦标赛级别的大多数比赛

****tournamnentLevelTournaments(‘T1’)****

在 T1 锦标赛级别赢得最多

****tournamnentLevelWinners(‘T1’)****

T2 锦标赛级别的大多数比赛

****tournamnentLevelTournaments(‘T2’)****

在 T2 锦标赛中获胜次数最多

****tournamnentLevelWinners(‘T2’)****

T3 锦标赛级别的大多数比赛

****tournamnentLevelTournaments(‘T3’)****

在 T3 锦标赛级别赢得最多

****tournamnentLevelWinners(‘T3’)****

压折

如果赢家排名比输家排名至少高 10 位,我们可以认为是一个冷门。我们绘制了大满贯冠军和失败者之间的排名差异。

在大满贯决赛中造成冷门的球员

我们注意到大满贯决赛中冷门很少。但是他们中的一些在那里,让我们找出他们是什么。

维纳斯·大威廉姆斯在大满贯决赛中创造了两次冷门。2017 年,当斯隆·斯蒂芬斯在半决赛中击败维纳斯·大威廉姆斯,在决赛中击败麦迪逊·凯斯时,美国公开赛出现了逆转。

****grandslamupsets = grandslam %>%
 filter(rankingdiff < -10) %>%
 select(winner_name,loser_name,winner_rank,loser_rank,tourney_name,year)plotUpsets = function(upsetsData,titleName)
{
 upsetsData %>%
 group_by(winner_name) %>%
 summarise(Count = n()) %>%
 arrange(desc(Count)) %>%
 ungroup() %>%
 mutate(winner_name = reorder(winner_name,Count)) %>%
 head(10) %>%

 ggplot(aes(x = winner_name,y = Count)) +
 geom_bar(stat=’identity’,colour=”white”,fill=fillColor2) +
 geom_text(aes(x = winner_name, y = 1, label = paste0(“(“,Count,”)”,sep=””)),
 hjust=0, vjust=.5, size = 4, colour = ‘black’,
 fontface = ‘bold’) +
 labs(x = titleName, 
 y = ‘Count’, 
 title = titleName) +
 coord_flip() + 
 theme_bw()
}

plotUpsets(grandslamupsets,’Upset Winner in Grand Slam Finals’)datatable(grandslamupsets, style=”bootstrap”, class=”table-condensed”, options = list(dom = ‘tp’,scrollX = TRUE))****

大满贯半决赛的冷门

威廉姆斯姐妹再次在大满贯半决赛中制造冷门。

****grandslamSF =getGrandSlamWinners(‘SF’)grandslamupsets = grandslamSF %>%
 filter(rankingdiff < -10) %>%
 select(winner_name,loser_name,winner_rank,loser_rank,tourney_name,year)plotUpsets(grandslamupsets,’Upset Winner in Grand Slam Semi Finals’)datatable(grandslamupsets, style=”bootstrap”, class=”table-condensed”, options = list(dom = ‘tp’,scrollX = TRUE))****

T1 锦标赛中的冷门

****getTournamentWinners = function(tourney_level_name,roundname)
{
 return(
 matches %>%
 filter(tourney_level == tourney_level_name) %>%
 filter(round == roundname) %>%
 mutate(agediff = winner_age — loser_age) %>%
 mutate(rankingdiff = loser_rank — winner_rank)
 )
}T1Winners = getTournamentWinners(‘T1’,’F’)T1upsets = T1Winners %>%
 filter(rankingdiff < -10) %>%
 select(winner_name,loser_name,winner_rank,loser_rank,tourney_name,year)plotUpsets(T1upsets,’Upset Winner in T1 tournament Finals’)datatable(T1upsets, style=”bootstrap”, class=”table-condensed”, options = list(dom = ‘tp’,scrollX = TRUE))****

T2 锦标赛的冷门

****T2Winners = getTournamentWinners(‘T2’,’F’)T2upsets = T2Winners %>%
 filter(rankingdiff < -10) %>%
 select(winner_name,loser_name,winner_rank,loser_rank,tourney_name,year)plotUpsets(T2upsets,’Upset Winner in T2 tournament Finals’)datatable(T2upsets, style=”bootstrap”, class=”table-condensed”, options = list(dom = ‘tp’,scrollX = TRUE))****

你可能也喜欢访问我的网站 http://ambarishg.github.io,了解其他有趣的帖子。

Python 中的音乐特征提取

原文:https://towardsdatascience.com/extract-features-of-music-75a3f9bc265d?source=collection_archive---------2-----------------------

不同类型的音频特征以及如何提取它们。

MFCC feature extraction

特征提取是分析和发现不同事物之间关系的一个非常重要的部分。所提供的音频数据不能被模型直接理解以将它们转换成可理解的格式,使用特征提取。这是一个以可理解的方式解释大部分数据的过程。分类、预测和推荐算法都需要特征提取。

在这个博客中,我们将提取音乐文件的特征,这将有助于我们将音乐文件分类为不同的流派,或者根据您的喜好推荐音乐。我们将学*用于提取音乐特征的不同技术。

音频信号是三维信号,其中三个轴代表时间、振幅和频率。

Audio signal

要使用的包

我们将使用 librosa 来分析和提取音频信号的特征。为了播放音频,我们将使用 pyAudio ,这样我们就可以直接在 jupyter 上播放音乐。

加载音频

import librosa
audio_path = 'audio-path'
x , sr = librosa.load(audio_path)
print(type(x), type(sr))

.load加载一个音频文件,解码成一维数组,一维数组是时间序列xsr是采样率x。默认sr是 22kHz。我们可以通过以下方式覆盖sr

librosa.load(audio_path, sr=44100)

我们可以通过以下方式禁用采样:

librosa.load(audio_path, sr=none)

播放音频

import IPython.display as ipd
ipd.Audio(audio_path)

IPython.display允许我们直接在 jupyter 笔记本上播放音频。它有一个非常简单的界面,有一些基本的按钮。

#display waveform
%matplotlib inline
import matplotlib.pyplot as plt
import librosa.display
plt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)

librosa.display用于显示不同格式的音频文件,如波形图、声谱图或色彩图。波形图让我们知道在给定时间音频的响度。频谱图显示了在特定时间播放的不同频率及其振幅。振幅和频率是声音的重要参数,对于每个音频都是唯一的。librosa.display.waveplot用于绘制振幅对时间的波形,其中第一轴为振幅,第二轴为时间。

频谱图

声谱图是声音频率频谱或其他信号随时间变化的直观表示。它代表了给定音乐信号的频率随时间的变化。

#display Spectrogram
X = librosa.stft(x)
Xdb = librosa.amplitude_to_db(abs(X))
plt.figure(figsize=(14, 5))
librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='hz') 
#If to pring log of frequencies  
#librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='log')
plt.colorbar()

.stft将数据转换成短期傅立叶变换。 STFT 转换信号,这样我们就可以知道给定时间给定频率的幅度。使用 STFT,我们可以确定音频信号在给定时间播放的各种频率的幅度。.specshow用于显示频谱图。

输出如下所示:

spectrum

特征提取

过零率

过零率是信号符号变化的速率,即信号从正变到负或反变的速率。这个特性已经在语音识别和音乐信息检索中大量使用。它通常具有较高的值,适用于像金属和摇滚这样的高敲击声。

x, sr = librosa.load(audio_path)
#Plot the signal:
plt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)

放大:

这里我们将只缩放或打印 100 个阵列列的光谱。

# Zooming in
n0 = 9000
n1 = 9100
plt.figure(figsize=(14, 5))
plt.plot(x[n0:n1])
plt.grid()

情节看起来像:

正如我们所见,在给定的图表中有三个过零点。

我们也可以使用给定代码计算过零事件:

zero_crossings = librosa.zero_crossings(x[n0:n1], pad=False)
print(sum(zero_crossings))

光谱质心

它表示声音的“质量中心”所在的位置,计算方法是声音中频率的加权平均值。如果音乐中的频率始终相同,那么频谱质心将围绕一个中心,如果在声音的末端有高频,那么质心将朝向其末端。

#spectral centroid -- centre of mass -- weighted mean of the frequencies present in the sound
import sklearn
spectral_centroids = librosa.feature.spectral_centroid(x, sr=sr)[0]
spectral_centroids.shape# Computing the time variable for visualization
frames = range(len(spectral_centroids))
t = librosa.frames_to_time(frames)
# Normalising the spectral centroid for visualisation
def normalize(x, axis=0):
    return sklearn.preprocessing.minmax_scale(x, axis=axis)
#Plotting the Spectral Centroid along the waveform
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_centroids), color='r')

.spectral_centroid用于计算每一帧的光谱质心。所以它将返回一个数组,其列数等于样本中的帧数。

.frames_to_time将帧转换为时间。时间[i] ==帧[i]。

我们正在标准化,以便我们可以轻松地可视化数据。

spectral centroid

与过零率类似,在信号开始时,频谱质心会出现杂散上升。这是因为开始时的静音幅度很小,高频成分有机会占主导地位。

光谱衰减

频谱衰减是总频谱能量的指定百分比(例如 85%)低于的频率。

它也给出了每一帧的结果。

spectral_rolloff = librosa.feature.spectral_rolloff(x, sr=sr)[0]
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_rolloff), color='r')

.spectral_rolloff用于计算给定帧的滚降。

Spectral Rolloff

MFCC —梅尔频率倒谱系数

该特征是提取音频信号特征的最重要的方法之一,并且主要在处理音频信号时使用。信号的 mel 频率倒谱系数(MFCCs)是一小组特征(通常约 10–20),它们简明地描述了频谱包络的整体形状。

mfccs = librosa.feature.mfcc(x, sr=sr)
print(mfccs.shape)#Displaying  the MFCCs:
librosa.display.specshow(mfccs, sr=sr, x_axis='time')

.mfcc用于计算信号的 mfccs。

通过打印 MFCC 的形状,你可以得到多少 MFCC 是根据多少帧计算的。第一个值表示计算的 mfccs 的数量,另一个值表示可用的帧数。

MFCC

现在,我们已经提取了音乐信号的特征。我们可以使用在各种用例中提取的这个特征,例如分类成不同的流派。我们将在我们的下一篇博客中实现这一点。

在 Python 中提取和转换数据

原文:https://towardsdatascience.com/extracting-and-transforming-data-in-python-63291f63d350?source=collection_archive---------8-----------------------

(Source)

为了从数据中获得洞察力,你必须对它稍加处理..

重要的是能够从数据帧中提取、过滤和转换数据,以便深入到真正重要的数据中。熊猫图书馆有许多技术使这一过程高效而直观。在今天的文章中,我将列出这些技术,并附有代码示例和一些解释。让我们开始吧。

在这篇文章中,我用随机数创建了一个样本数据帧来玩它。在本文的解释过程中,我们将使用这些数据作为例子。

import pandas as pd
import numpy as np
cols = ['col0', 'col1', 'col2', 'col3', 'col4']
rows = ['row0', 'row1', 'row2', 'row3', 'row4']
data = np.random.randint(0, 100, size=(5, 5))
df = pd.DataFrame(data, columns=cols, index=rows)df.head()**Out[2]: 
      col0  col1  col2  col3  col4
row0    24    78    42     7    96
row1    40     4    80    12    84
row2    83    17    80    26    15
row3    92    68    58    93    33
row4    78    63    35    70    95**

索引数据帧

为了从 pandas 数据帧中提取数据,我们可以使用直接索引或访问器。我们可以使用标签选择必要的行和列:

df['col1']['row1']**Out[3]: 4**

请注意这种索引的顺序:首先指定列标签,然后指定行。但事实是,数据集很少,而且很小,而在现实生活中,我们使用的机器要重得多。使用访问器— 来选择数据要好得多。锁定。iloc 。他们的区别在于。loc 接受标签,而接受标签。iloc —索引。同样,当我们使用访问器时,我们首先指定行,然后指定列。一开始我很难适应它——SQL 背景,你还能说什么..

因此,要使用访问器选择单个值,您需要执行以下操作:

df.loc['row4', 'col2']
**Out[4]: 35** df.iloc[4, 2]
**Out[5]: 35**

使用索引,我们可以从数据帧中选择单个值、系列或数据帧(抱歉,这是同义反复)。上面我已经展示了如何选择一个值。

要再选择几列,只需传递其标签的嵌套列表,DataFrame 将被返回:

df_new = df[['col1','col2']]
df_new.head(3)

**Out[6]: 
      col1  col2
row0    78    42
row1     4    80
row2    17    80**

如果您还想选择特定的行,添加它的索引,您将再次获得一个数据帧。这种技术被称为切片,下面会有更详细的介绍。

df_new = df[['col1','col2']][1:4]
df_new.head(3)

**Out[7]: 
      col1  col2
row1     4    80
row2    17    80
row3    68    58**

要选择一个系列,您必须选择包含所有行或一系列行的单个列。每一行代码都会产生相同的输出:

df['col0']
df.loc[:,'col0']
df.iloc[:, 0]

**Out[8]: 
row0    24
row1    40
row2    83
row3    92
row4    78
Name: col0, dtype: int32**

冒号意味着我们要选择所有行或所有列— df.loc[:,:]df.iloc[:,:] 将返回所有值。慢慢地,我们进入了切片阶段——从数据中选择特定的范围。要对一个系列进行切片,您只需添加要使用其索引选择的一系列行:

df['col3'][2:5]

**Out[12]: 
row2    26
row3    93
row4    70
Name: col3, dtype: int32**

不要忘记 Python 中的范围——第一个元素被包含,第二个被排除。所以上面的代码将返回索引为 5、6、7、8 和 9 的行。索引从 0 开始。

切片数据帧的工作方式相同。只有一个细微的差别。使用时。loc (标签)包括两个边框。例如,选择从标签“行 1”到标签“行 4”的行或从行索引 1 到索引 4 的行以及所有列:

df.loc['row1':'row4', :]
**Out[20]: 
      col0  col1  col2  col3  col4
row1    40     4    80    12    84
row2    83    17    80    26    15
row3    92    68    58    93    33
row4    78    63    35    70    95** df.iloc[1:4, :]
**Out[21]: 
      col0  col1  col2  col3  col4
row1    40     4    80    12    84
row2    83    17    80    26    15
row3    92    68    58    93    33**

上面的第一行代码选择了 row1、row2、row3 和 row4。而第二个—仅行 1、行 2 和行 3。下面再举几个例子。

选择从标签“列 1”到标签“列 4”或从列索引 1 到索引 4 的列以及所有行:

df.loc[:, 'col1':'col4']
**Out[22]: 
      col1  col2  col3  col4
row0    78    42     7    96
row1     4    80    12    84
row2    17    80    26    15
row3    68    58    93    33
row4    63    35    70    95** df.iloc[:, 1:4]
**Out[23]: 
      col1  col2  col3
row0    78    42     7
row1     4    80    12
row2    17    80    26
row3    68    58    93
row4    63    35    70**

选择从标签“行 1”到标签“行 4”或从行索引 1 到索引 4 的行,以及从标签“列 1”到标签“列 4”或从列索引 1 到索引 4 的列:

df.loc['row1':'row4', 'col1':'col4']
**Out[24]: 
      col1  col2  col3  col4
row1     4    80    12    84
row2    17    80    26    15
row3    68    58    93    33
row4    63    35    70    95** df.iloc[1:4,1:4] **Out[25]: 
      col1  col2  col3
row1     4    80    12
row2    17    80    26
row3    68    58    93**

使用列表选择不在范围内的特定列或行。

df.loc['row2':'row4', ['col1','col3']]
**Out[28]: 
      col1  col3
row2    17    26
row3    68    93
row4    63    70** df.iloc[[2,4], 0:4]
**Out[30]: 
      col0  col1  col2  col3
row2    83    17    80    26
row4    78    63    35    70**

过滤数据帧

过滤是一种更通用的工具,它根据数据本身的感兴趣的属性而不是索引或标签来选择数据的一部分。数据帧有几种过滤方法。所有这些方法的基本思想是布尔级数。在这个条件为真的情况下, df['col1'] > 20 (我们假设 col1 的类型是 integer)将返回一个布尔序列。我将在这里输入。head()方法,所以不需要向上滚动来匹配数字。

**Out[2]: 
      col0  col1  col2  col3  col4
row0    24    78    42     7    96
row1    40     4    80    12    84
row2    83    17    80    26    15
row3    92    68    58    93    33
row4    78    63    35    70    95**

因此,要选择数据帧中 col1 的值大于 20 的部分,我们将使用以下代码:

df[df['col1'] > 20]
*# assigning variable also works*
condition = df['col1'] > 20
df[condition]

**Out[31]: 
      col0  col1  col2  col3  col4
row0    24    78    42     7    96
row3    92    68    58    93    33
row4    78    63    35    70    95**

我们可以使用标准的逻辑运算符(and — &,or — |,not — ~)来组合这些过滤器。请注意括号在这些操作中的用法。

df[(df['col1'] > 25) & (df['col3'] < 30)] # logical and
**Out[33]: 
      col0  col1  col2  col3  col4
row0    24    78    42     7    96** df[(df['col1'] > 25) | (df['col3'] < 30)] # logical or
**Out[34]: 
      col0  col1  col2  col3  col4
row0    24    78    42     7    96
row1    40     4    80    12    84
row2    83    17    80    26    15
row3    92    68    58    93    33
row4    78    63    35    70    95** df[~(df['col1'] > 25)] # logical not
**Out[35]: 
      col0  col1  col2  col3  col4
row1    40     4    80    12    84
row2    83    17    80    26    15**

处理 0 和 NaN 值

几乎所有的数据集都有零值或 NaN 值,我们肯定想知道它们在哪里。我们的比较特殊,所以我们会稍微修改一下:

df.iloc[3, 3] = 0
df.iloc[1, 2] = np.nan
df.iloc[4, 0] = np.nan
df['col5'] = 0
df['col6'] = np.NaN
df.head()

**Out[57]: 
      col0  col1  col2  col3  col4  col5  col6
row0  24.0    78  42.0     7    96     0   NaN
row1  40.0     4   NaN    12    84     0   NaN
row2  83.0    17  80.0    26    15     0   NaN
row3  92.0    68  58.0     0    33     0   NaN
row4   NaN    63  35.0    70    95     0   NaN**

要选择没有任何零值的列,我们可以使用。all() 方法(所有数据都存在):

df.loc[:, df.all()] **Out[43]: 
      col0  col1  col2  col4  col6
row0  24.0    78  42.0    96   NaN
row1  40.0     4   NaN    84   NaN
row2  83.0    17  80.0    15   NaN
row3  92.0    68  58.0    33   NaN
row4   NaN    63  35.0    95   NaN**

如果我们希望找到至少有一个非零(任意)值的列,这将有助于:

df.loc[:, df.any()]

**Out[47]: 
      col0  col1  col2  col3  col4
row0  24.0    78  42.0     7    96
row1  40.0     4   NaN    12    84
row2  83.0    17  80.0    26    15
row3  92.0    68  58.0     0    33
row4   NaN    63  35.0    70    95**

要选择具有任何 NaN 的列:

df.loc[:, df.isnull().any()]

**Out[48]: 
      col0  col2  col6
row0  24.0  42.0   NaN
row1  40.0   NaN   NaN
row2  83.0  80.0   NaN
row3  92.0  58.0   NaN
row4   NaN  35.0   NaN**

选择不带 nan 的色谱柱:

df.loc[:, df.notnull().all()]

**Out[49]: 
      col1  col3  col4  col5
row0    78     7    96     0
row1     4    12    84     0
row2    17    26    15     0
row3    68     0    33     0
row4    63    70    95     0**

我们可以删除那些包含 nan 的行,但是这是一个危险的游戏——删除通常不是一个解决方案。您必须理解您的数据,并明智地处理这样的行。我警告过你。

你确定你想知道吗?好..😀

df.dropna(how='all', axis=1) # if all values in a column are NaN it will be dropped
**Out[69]: 
      col0  col1  col2  col3  col4  col5
row0  24.0    78  42.0     7    96     0
row1  40.0     4   NaN    12    84     0
row2  83.0    17  80.0    26    15     0
row3  92.0    68  58.0     0    33     0
row4   NaN    63  35.0    70    95     0** df.dropna(how='any', axis=1) # if any value in a row is NaN it will be dropped
**Out[71]: 
      col1  col3  col4  col5
row0    78     7    96     0
row1     4    12    84     0
row2    17    26    15     0
row3    68     0    33     0
row4    63    70    95     0**

这种方法不会修改原始数据帧,因此要继续处理过滤后的数据,必须将其分配给新的数据帧或重新分配给现有的数据帧

df = df.dropna(how='any', axis=1)

过滤的美妙之处在于,我们实际上可以根据一列的值来选择或修改另一列的值。例如,我们可以从 col1 中选择值,其中 col2 大于 35,并通过给每个值加 5 来更新这些值:

*# Find a column based on another*
df['col1'][df['col2'] > 35]
**Out[74]: 
row0    78
row2    17
row3    68
Name: col1, dtype: int32**

*# Modify a column based on another*
df['col1'][df['col2'] > 35] += 5
df['col1']
**Out[77]: 
row0    83
row1     4
row2    22
row3    73
row4    63
Name: col1, dtype: int32**

这让我们进入下一部分——

转换数据帧

一旦我们选择或过滤了我们的数据,我们想以某种方式转换它。最好的方法是使用继承到 DataFrames 或 numpy universal funcs 的方法,它们按元素方式转换整列数据。熊猫就是例子。floordiv() 函数(来自文档:
‘data frame 和其他元素的整数除法’)或 numpy 的。floor_divide() (doc:'返回小于或等于输入的除法的最大整数。').

如果这些函数不可用,我们可以编写自己的函数并与一起使用。应用()方法。

def some_func(x): 
    return x * 2df.apply(some_func) -- *# update each entry of a DataFrame without any loops**# lambda also works* 
df.apply(lambda n: n*2) -- *# the same*

这些函数不返回转换,所以我们必须显式地存储它:

df['new_col'] = df['col4'].apply(lambda n: n*2)
df.head()

**Out[82]: 
      col0  col1  col2  col3  col4  col5  col6  new_col
row0  24.0    83  42.0     7    96     0   NaN      192
row1  40.0     4   NaN    12    84     0   NaN      168
row2  83.0    22  80.0    26    15     0   NaN       30
row3  92.0    73  58.0     0    33     0   NaN       66
row4   NaN    63  35.0    70    95     0   NaN      190**

如果 index 是一个字符串,它有一个。允许我们一次修改整个索引的访问器:

df.index.str.upper()
**Out[83]: Index(['ROW0', 'ROW1', 'ROW2', 'ROW3', 'ROW4'], dtype='object')**

同样,我们不能使用。对索引应用()方法—它的替代方法是。map()

df.index = df.index.map(str.lower)
**Out[85]: Index(['row0', 'row1', 'row2', 'row3', 'row4'], dtype='object')**

但是。map() 也可以用在列上。例如:

*# Create the dictionary: red_vs_blue*
red_vs_blue = {0:'blue', 12:'red'}

*# Use the dictionary to map the 'col3' column to the new column df['color']*
df['color'] = df['col3'].map(red_vs_blue)
df.head()

**Out[92]: 
      col0  col1  col2  col3  col4  col5  col6  new_col color
row0  24.0    83  42.0     7    96     0   NaN      192   NaN
row1  40.0     4   NaN    12    84     0   NaN      168   red
row2  83.0    22  80.0    26    15     0   NaN       30   NaN
row3  92.0    73  58.0     0    33     0   NaN       66  blue
row4   NaN    63  35.0    70    95     0   NaN      190   NaN**

序列和数据帧上的算术运算直接起作用。下面的表达式将创建一个新列,其中索引为 n 的每个值是来自‘col 3’‘col 7’的索引为 n 的值的总和。

df['col7'] = df['col3'] + df['col4'] 
df.head()

**Out[94]: 
      col0  col1  col2  col3  col4  col5  col6  new_col color  col7
row0  24.0    83  42.0     7    96     0   NaN      192   NaN   103
row1  40.0     4   NaN    12    84     0   NaN      168   red    96
row2  83.0    22  80.0    26    15     0   NaN       30   NaN    41
row3  92.0    73  58.0     0    33     0   NaN       66  blue    33
row4   NaN    63  35.0    70    95     0   NaN      190   NaN   165**

这是文章的第二个版本,因为第一个完全是一团糟——代码中有错误,没有例子,也没有其他东西。感谢反馈,我又看了一遍这篇文章,我觉得现在看起来好多了。我在这里用代码片段和例子讲述了用 Python 转换和提取数据的基础知识,希望对刚开始涉足这一领域的人有用。

同时,热爱数据科学,多笑笑。我们必须乐观,因为我们拥有 21 世纪最性感的工作😀

原载于sergilehkyi.com

利用 k-均值聚类从图像中提取颜色

原文:https://towardsdatascience.com/extracting-colours-from-an-image-using-k-means-clustering-9616348712be?source=collection_archive---------1-----------------------

Photo by @shawnanggg on Unsplash

问题是

我想写一些软件,允许我从图像中提取一组颜色,并以一种似乎自然的方式完成,并考虑人类的感知。一个配色方案通常可以概括整个图像的“氛围”,所以我认为这将是一件有用的事情。

所以……我花了一些时间来思考我能做到这一点的一些方法。我设计了一些相当简单的算法,例如,将图像有规律地分割成块,并输出这些部分的平均颜色。也许可以添加额外的层,将这些块相互比较并组合成组,也许每种颜色可以递归地与另一种颜色组合,直到达到所需的颜色数量。不过,我很快意识到,这个问题在一般情况下已经得到了解决,而且以一种非常好的方式。

解决方案

K 均值聚类是一种方法,通过这种方法可以将一组数据点划分为几个不相交的子集,每个子集中的点被认为彼此“接*”(根据某种度量)。一个常见的度量标准是 bog 标准欧几里德距离函数,至少当这些点可以用几何方法表示时是这样。“k”只是指最终输出中所需的子集数量。事实证明,这种方法正是我们将图像分成一组颜色所需要的。

我们的案子

在我们的例子中,“数据点”是颜色,距离函数是两种颜色“不同程度”的度量。我们的任务是将这些颜色分成给定数量的集合,然后计算每个集合的平均颜色。使用平均值似乎是一个相当明智的选择,因为你可以想象当你看着不同的颜色集群时模糊你的眼睛,并看到每一个的平均颜色。然而,我们可以使用任何其他的统计方法(众数,中位数,或其他任何东西!)并可能得到更好的结果。

让我们用 JavaScript 写这个吧!

数据点

每个数据点都是一种颜色,可以用一个 RGB 颜色空间中的一个点来表示。

在 JavaScript 中,单个数据点可能看起来像这样:

*// An array if we want to be general* let colour = [100,168,92];*// Or an object if we want to be more explicit* let colour = {red: 100, green: 168, blue: 92};

距离函数

因为我们希望能够计算两种颜色有多相似,所以我们需要一个函数。这是我们有许多选择的另一点,但一个简单的方法是使用每种颜色的分量值来计算欧几里德距离。

我们的距离函数可以是这样的:

*// Distance function* function euclideanDistance(a, b) {
    let sum = 0;
    for (let i = 0; i < a.length; i++) {
        sum += Math.pow(b[i] — a[i], 2);
    }
    return Math.sqrt(sum);
}

由于我们没有在函数中指定固定数量的组件,因此它将适用于 n 维数据点(有 n 个组件)。如果我们以后想用不同的方式来表现颜色,这是很有用的。

该算法

k-means 聚类最常用的算法叫做劳氏算法(尽管它通常被简称为k-means 算法)。我们将在这里使用该算法。

我们将创建一组称为“质心”的对象,每个对象定义一个单独的、唯一的簇。

质心有两个相关的东西:

  • 数据集范围内的点(质心位置)
  • 数据集中的一组数据点(质心簇中的点)

该算法有三个主要步骤:

1.初始化。选择质心的初始值。在这种情况下,我们将为每一个随机选择一个点。

2.分配。将每个数据点分配给均值(质心)距离最小的聚类。

3.更新。将每个质心的新平均值设置为与其关联的所有数据点的平均值(在质心的聚类中)。

该算法将执行初始化一次,然后依次重复执行赋值更新,直到算法收敛。

当赋值之间没有变化时,该算法被称为“收敛”。基本上,当这些点决定它们属于哪个集群时,我们可以停止循环。

助手功能

让我们定义一些辅助函数:一个用于计算给定数据集的范围,一个用于生成给定范围内的随机整数。n 维数据集的“范围”只是一组范围——每个维度一个范围。

**// Calculate range of a one-dimensional data set*function rangeOf(data) {
    return {min: Math.min(data), max: Math.max(data)};
}*// Calculate range of an n-dimensional data set* function rangesOf(data) {
    let ranges = []; for (let i = 0; i < data[0].length; i++) {
        ranges.push(rangeOf(data.map(x => x[i])));
    } return ranges;
}*// Generate random integer in a given closed interval* function randomIntBetween(a, b) {
    return Math.floor(Math.random() * (b - a + 1)) + a;
}*

假设我们已经得到了这两个,我们现在可以为算法的三个步骤编写代码。

第一步—初始化

对于所需的质心数量(k),我们在所提供的数据集范围内生成一个随机整数值点,并将其附加到一个数组中。数组中的每个点代表一个质心的位置。当然,质心的维数与数据的维数相同。

*function initialiseCentroidsRandomly(data, k) {
    let ranges = rangesOf(data);
    let centroids = [];
    for (let i = 0; i < k; i++) {
        let centroid = [];
        for (let r in ranges) {
            centroid.push(
            randomIntBetween(ranges[r].min, ranges[r].max));
        } centroids.push(centroid);
    } return centroids;
}*

第二步——分配

这是我们将数据点分配给集群的地方。对于每个点,我们选择距离最小的质心,并将该点附加到关联的聚类中。

我在这里使用了数组的 map 函数和一个 arrow 函数,所以如果你不确定发生了什么,可以快速浏览一下。

*function clusterDataPoints(data, centroids) {
    let clusters = []; centroids.forEach(function() {
        clusters.push([]);
    }); data.forEach(function(point) { let nearestCentroid = Math.min(
    centroids.map(x => euclideanDistance(point, x))); clusters[centroids.indexOf(nearestCentroid)].push(point);
    }); return clusters;
}*

第三步—更新

对于每个聚类,我们计算其包围数据点的平均值,并将其设置为相关质心的位置。然后我们返回新的质心集。

这里实际上使用了另一个函数,叫做均值点。我就不赘述了,因为实现自己是相当明显的。它返回一个点,该点的分量是每个传递点中相应分量值的平均值。

*function getNewCentroids(clusters) {
    let centroids = []; clusters.forEach(function(cluster) {
        centroids.push(meanPoint(cluster));
    });return centroids;
}*

哦,还有一件事!

这种算法有一个问题,就是有时聚类会变空。对于发生这种情况时应该做什么还没有达成共识,但是一些可能的方法是:

  • 移除集群(有点傻)
  • 将随机数据点分配给群集
  • 将最*的数据点分配给聚类
  • 重启算法,希望不会再发生

虽然最后一个选项看起来有点混乱,但是算法(带有随机初始化)是不确定的,所以简单地重启就能很好地工作。毕竟,这种方法很大程度上是一种试探法,而试探法从定义上来说是“一种杂烩”……至少与可靠的算法相比是这样。

齐心协力

现在我们已经定义了基本的功能,剩下的就是编写一些代码,在算法要求时调用每个函数。

我将把它留给你作为一个练*,但是,如果你真的想,你可以在这里看到我作为一个 web 应用程序的实现。🌈

Here’s what it looks like after being fed the cover of a Ryan Hemsworth song.

从短文本中提取关键词

原文:https://towardsdatascience.com/extracting-keywords-from-short-text-fce39157166b?source=collection_archive---------0-----------------------

专业提示:更多关于人工智能和机器学*的文章、故事、代码和研究,请访问我的网站:【www.theapemachine.com】

多年来,我多次遇到提取关键词的问题,尤其是从单句、标题或问题等短文本中提取关键词。

在 NLP 中处理短文本一直是一个众所周知的问题,而识别关键词尤其是很难做到。
这些年来,我尝试了许多方法,从我自己基于一个非常流行的文字游戏非常天真地实现了一个简单的评分算法,到快速自动关键词提取(RAKE ),如果没有大型文档要处理,没有一种方法表现得非常好。

最终,随着我对现代常见的机器学*模型越来越熟悉,我开始将关键词提取视为“简单!翻译问题,在这篇文章中,我们将回顾导致一个伟大的关键字提取器,我们现在可以在生产中使用的旅程。

我第一次需要找到一个短句中最重要的关键词时,我正在为一家心理学家公司开发一些软件,他们正在开发一个平台,其中有一个模块需要从语言挑战数据库中提取相关的句子。

这个想法是要将要检索的句子与前一个句子的关键词进行匹配,由于我当时对机器学*知之甚少,所以我用自己的天真解决方案来计算句子中每个单词的拼字得分,并从这些结果中取出得分最高的第 n 个单词,并假设它们是关键词。

如果不是因为一些在拼字游戏中得分很高的停用词,这实际上非常有效。
当然,你可以在这个方法中部署一个非索引列表,事情就会迎刃而解,这甚至是相当可扩展的,因为任何语言都只包含你想要过滤掉的单词,你只需要定义这个列表一次。

耙子

下一个实现是快速自动关键词提取,它实际上只比前一个方法好一点点,并且仍然使用非索引列表。

如今,RAKE 已经作为即插即用模块在许多编程语言中实现,您应该不用花太多时间来试验它,但是我警告您,不要让它在短文本上欺骗您。大多数时候,它实际上并没有提取任何关键词,只是删除了停用词。因为文本很短,所以没有那么多其他的词可以“搜索”。

发明一种新的语言!

最终,我明白了一些事情:如果像序列到序列神经网络这样的现代翻译方法可以翻译语言,或者给出从序列中学*到的响应,为什么我们不能将关键词视为其自身的“语言”。
一种没有语法的语言,可以翻译成(甚至可能翻译成?).

这似乎是一个很好的想法:简单地训练一个序列,对标有关键词的短句数据集进行神经网络排序,并让网络将新句子“翻译”成我们的关键词“语言”。

所以让我们开始吧!

1.生成数据集

现在我有了新方法,我面临的一个挑战是找到一个数据集进行训练,我相信你会认识到这是一个困难。可能会让你吃惊的是,真的没有任何现成的数据集有短句与文本中实际存在的关键词相匹配。当然,有许多关于关键词提取的数据集,但它们都有较大的文本,这些文本已经被手动标注了关键词。

幸运的是,我身边的一个人给了我一个绝妙的主意:使用博客圈真正的大玩家的博客标题,并使用这些页面上的关键字元标签来找到与标题相关的关键字。事实上,这些博客非常关注 SEO,因此我们可以假设这些数据是经过精心策划的。

剩下唯一要做的事情是确保删除所有实际上不在标题中的关键词,尽管你可能想考虑甚至保留这些关键词,因为一旦你的神经网络训练完毕,你不仅能够从一个句子中提取准确的关键词,甚至能够提取相关的关键词。
不过,我会把这留给未来的实验。

下面的 Ruby 脚本正是我用来在 Lifehacker 和 TechCrunch 上搜索关键词的脚本。

require 'mechanize'

**class** **Scrape**

  **def** initialize
    @mechanize = Mechanize.new
    @visited   = []
    @v_titles  = []

    @csv = File.open('/home/theapemachine/data/keywords-web2.csv', 'a')
  **end**

  **def** run(urls)
    scraped_urls = []

    urls.each **do** |url|
      **if** !@visited.include?(url)
        **begin**
          rawpage = @mechanize.get(url)

          rawpage.links.uniq.each **do** |a|
            scraped_urls << a.href
          **end**

          page_title = ''

          rawpage.search('title').each **do** |title|
            page_title = title.text.downcase.strip
          **end**

          keywords = rawpage.at('head meta[name="keywords"]')['content'].split(', ').delete_if{|k| page_title.scan(k.downcase).empty?}

          **if** !page_title.empty? && !keywords.empty? && !@v_titles.include?(page_title)
            puts
            puts "TITLE:    #{page_title}"
            puts "KEYWORDS: #{keywords.join(',')}"

            @csv << %("#{page_title}","#{keywords.join(',').downcase}"\n)
          **end**

          @v_titles << page_title
        **rescue**
        **end**
      **end**
    **end**

    @visited += urls
    run(scraped_urls.uniq)
  **end**

**end**

@scrape = Scrape.new
@scrape.run([
  'http://lifehacker.com/',
  'http://www.techcrunch.com'
])

2.准备数据

我们现在需要准备收集的数据,这样我们就可以在 Pytorch 序列中使用它来排序我接下来将列出的模型。我使用了下面非常简单的 Ruby 脚本来确保训练数据中的每一行首先有文章标题,然后是制表位,然后是关键字。

require 'csv'

train = File.open('./keywords.train', 'w')

csv_text = File.read('/home/theapemachine/data/keywords-web.csv')
csv      = CSV.parse(csv_text, headers: **false**)

csv.each **do** |row|
  **begin**
    train.puts row[0] + "\t" + row[1]
  **rescue**
  **end**
**end**

3.序列对序列模型

我们现在可以使用 Pytorch 编写我们的序列到序列神经网络,事实上,简单地使用他们的教程部分列出的代码就可以很好地完成这个任务。我在培训周期结束时添加了一个简单的提示,这样我就可以轻松地测试网络。
在以后的版本中,你会想要保存你的模型以备后用,因为在我的笔记本电脑上训练花了很长时间。

由肖恩·罗伯逊(Sean Robertson)的原 Pytorch 源代码翻译而来。

**import** unicodedata
**import** string
**import** re
**import** random
**import** time
**import** math

**import** torch
**import** torch.nn **as** nn
**from** torch.autograd **import** Variable
**from** torch **import** optim
**import** torch.nn.functional **as** F

USE_CUDA  = True
SOS_token = 0
EOS_token = 1

**class** **Lang**:
    **def** __init__(self, name):
        self.name       = name
        self.word2index = {}
        self.word2count = {}
        self.index2word = {0: "SOS", 1: "EOS"}
        self.n_words    = 2

    **def** index_words(self, sentence):
        **for** word in sentence.split(' '):
            self.index_word(word)

    **def** index_word(self, word):
        **if** word not in self.word2index:
            self.word2index[word]          = self.n_words
            self.word2count[word]          = 1
            self.index2word[self.n_words]  = word
            self.n_words                  += 1
        **else**:
            self.word2count[word] += 1

**def** unicode_to_ascii(s):
    **return** ''.join(
        c **for** c in unicodedata.normalize('NFD', u'' + s)
        **if** unicodedata.category(c) != 'Mn'
    )

**def** normalize_string(s):
    s = unicode_to_ascii(s.lower().strip())
    s = re.sub(r"([.!?])", r" \1", s)
    s = re.sub(r"[^a-zA-Z.!?]+", r" ", s)

    **return** s

**def** read_langs(lang1, lang2, reverse=False):
    **print**("Reading lines...")

    lines = open('keywords.train').read().strip().split('\n')
    pairs = [[normalize_string(s) **for** s in l.split('\t')] **for** l in lines]

    **if** reverse:
        pairs       = [list(reversed(p)) **for** p in pairs]
        input_lang  = Lang(lang2)
        output_lang = Lang(lang1)
    **else**:
        input_lang  = Lang(lang1)
        output_lang = Lang(lang2)

    **return** input_lang, output_lang, pairs

MAX_LENGTH = 100

good_prefixes = (
    "i am ", "i m ",
    "he is", "he s ",
    "she is", "she s",
    "you are", "you re "
)

**def** filter_pair(p):
    **return** len(p[0].split(' ')) < MAX_LENGTH and len(p[1].split(' ')) < MAX_LENGTH

**def** filter_pairs(pairs):
    **return** [pair **for** pair in pairs **if** filter_pair(pair)]

**def** prepare_data(lang1_name, lang2_name, reverse=False):
    input_lang, output_lang, pairs = read_langs(lang1_name, lang2_name, reverse)
    **print**("Read %s sentence pairs" % len(pairs))

    pairs = filter_pairs(pairs)
    **print**("Trimmed to %s sentence pairs" % len(pairs))

    **print**("Indexing words...")
    **for** pair in pairs:
        input_lang.index_words(pair[0])
        output_lang.index_words(pair[1])

    **return** input_lang, output_lang, pairs

input_lang, output_lang, pairs = prepare_data('eng', 'fra', False)
**print**(random.choice(pairs))

**def** indexes_from_sentence(lang, sentence):
    **return** [lang.word2index[word] **for** word in sentence.split(' ')]

**def** variable_from_sentence(lang, sentence):
    indexes = indexes_from_sentence(lang, sentence)
    indexes.append(EOS_token)

    var = Variable(torch.LongTensor(indexes).view(-1, 1))

    **if** USE_CUDA:
        var = var.cuda()

    **return** var

**def** variables_from_pair(pair):
    input_variable  = variable_from_sentence(input_lang, pair[0])
    target_variable = variable_from_sentence(output_lang, pair[1])

    **return** (input_variable, target_variable)

**class** **EncoderRNN**(nn.Module):
    **def** __init__(self, input_size, hidden_size, n_layers=1):
        super(EncoderRNN, self).__init__()

        self.input_size  = input_size
        self.hidden_size = hidden_size
        self.n_layers    = n_layers
        self.embedding   = nn.Embedding(input_size, hidden_size)
        self.gru         = nn.GRU(hidden_size, hidden_size, n_layers)

    **def** forward(self, word_inputs, hidden):
        seq_len        = len(word_inputs)
        embedded       = self.embedding(word_inputs).view(seq_len, 1, -1)
        output, hidden = self.gru(embedded, hidden)

        **return** output, hidden

    **def** init_hidden(self):
        hidden = Variable(torch.zeros(self.n_layers, 1, self.hidden_size))

        **if** USE_CUDA:
            hidden = hidden.cuda()

        **return** hidden

**class** **BahdanauAttnDecoderRNN**(nn.Module):
    **def** __init__(self, hidden_size, output_size, n_layers=1, dropout_p=0.1):
        super(AttnDecoderRNN, self).__init__()

        self.hidden_size = hidden_size
        self.output_size = output_size
        self.n_layers    = n_layers
        self.dropout_p   = dropout_p
        self.max_length  = max_length
        self.embedding   = nn.Embedding(output_size, hidden_size)
        self.dropout     = nn.Dropout(dropout_p)
        self.attn        = GeneralAttn(hidden_size)
        self.gru         = nn.GRU(hidden_size * 2, hidden_size, n_layers, dropout=dropout_p)
        self.out         = nn.Linear(hidden_size, output_size)

    **def** forward(self, word_input, last_hidden, encoder_outputs):
        word_embedded  = self.embedding(word_input).view(1, 1, -1)
        word_embedded  = self.dropout(word_embedded)
        attn_weights   = self.attn(last_hidden[-1], encoder_outputs)
        context        = attn_weights.bmm(encoder_outputs.transpose(0, 1))
        rnn_input      = torch.cat((word_embedded, context), 2)
        output, hidden = self.gru(rnn_input, last_hidden)
        output         = output.squeeze(0)
        output         = F.log_softmax(self.out(torch.cat((output, context), 1)))

        **return** output, hidden, attn_weights

**class** **Attn**(nn.Module):
    **def** __init__(self, method, hidden_size, max_length=MAX_LENGTH):
        super(Attn, self).__init__()

        self.method      = method
        self.hidden_size = hidden_size

        **if** self.method == 'general':
            self.attn = nn.Linear(self.hidden_size, hidden_size)

        **elif** self.method == 'concat':
            self.attn  = nn.Linear(self.hidden_size * 2, hidden_size)
            self.other = nn.Parameter(torch.FloatTensor(1, hidden_size))

    **def** forward(self, hidden, encoder_outputs):
        seq_len       = len(encoder_outputs)
        attn_energies = Variable(torch.zeros(seq_len))

        **if** USE_CUDA:
            attn_energies = attn_energies.cuda()

        **for** i in range(seq_len):
            attn_energies[i] = self.score(hidden, encoder_outputs[i])

        **return** F.softmax(attn_energies).unsqueeze(0).unsqueeze(0)

    **def** score(self, hidden, encoder_output):
        **if** self.method == 'dot':
            energy = hidden.dot(encoder_output)
            **return** energy

        **elif** self.method == 'general':
            energy = self.attn(encoder_output)
            energy = hidden.dot(energy)
            **return** energy

        **elif** self.method == 'concat':
            energy = self.attn(torch.cat((hidden, encoder_output), 1))
            energy = self.other.dot(energy)
            **return** energy

**class** **AttnDecoderRNN**(nn.Module):
    **def** __init__(self, attn_model, hidden_size, output_size, n_layers=1, dropout_p=0.1):
        super(AttnDecoderRNN, self).__init__()

        self.attn_model  = attn_model
        self.hidden_size = hidden_size
        self.output_size = output_size
        self.n_layers    = n_layers
        self.dropout_p   = dropout_p
        self.embedding   = nn.Embedding(output_size, hidden_size)
        self.gru         = nn.GRU(hidden_size * 2, hidden_size, n_layers, dropout=dropout_p)
        self.out         = nn.Linear(hidden_size * 2, output_size)

        **if** attn_model != 'none':
            self.attn = Attn(attn_model, hidden_size)

    **def** forward(self, word_input, last_context, last_hidden, encoder_outputs):
        word_embedded      = self.embedding(word_input).view(1, 1, -1)
        rnn_input          = torch.cat((word_embedded, last_context.unsqueeze(0)), 2)
        rnn_output, hidden = self.gru(rnn_input, last_hidden)
        attn_weights       = self.attn(rnn_output.squeeze(0), encoder_outputs)
        context            = attn_weights.bmm(encoder_outputs.transpose(0, 1))
        rnn_output         = rnn_output.squeeze(0)
        context            = context.squeeze(1)
        output             = F.log_softmax(self.out(torch.cat((rnn_output, context), 1)))

        **return** output, context, hidden, attn_weights

encoder_test = EncoderRNN(MAX_LENGTH, MAX_LENGTH, 2 )
decoder_test = AttnDecoderRNN('general', MAX_LENGTH, MAX_LENGTH, 2)

**print**(encoder_test)
**print**(decoder_test)

encoder_hidden = encoder_test.init_hidden()
word_input     = Variable(torch.LongTensor([1, 2, 3]))

**if** USE_CUDA:
    encoder_test.cuda()
    word_input = word_input.cuda()

encoder_outputs, encoder_hidden = encoder_test(word_input, encoder_hidden)

word_inputs     = Variable(torch.LongTensor([1, 2, 3]))
decoder_attns   = torch.zeros(1, 3, 3)
decoder_hidden  = encoder_hidden
decoder_context = Variable(torch.zeros(1, decoder_test.hidden_size))

**if** USE_CUDA:
    decoder_test.cuda()

    word_inputs     = word_inputs.cuda()
    decoder_context = decoder_context.cuda()

**for** i in range(3):
    decoder_output, decoder_context, decoder_hidden, decoder_attn = decoder_test(word_inputs[i], decoder_context, decoder_hidden, encoder_outputs)
    **print**(decoder_output.size(), decoder_hidden.size(), decoder_attn.size())
    decoder_attns[0, i] = decoder_attn.squeeze(0).cpu().data

teacher_forcing_ratio = 0.5
clip                  = 5.0

**def** train(input_variable, target_variable, encoder, decoder, encoder_optimizer, decoder_optimizer, criterion, max_length=MAX_LENGTH):
    encoder_optimizer.zero_grad()
    decoder_optimizer.zero_grad()
    loss = 0

    input_length                    = input_variable.size()[0]
    target_length                   = target_variable.size()[0]
    encoder_hidden                  = encoder.init_hidden()
    encoder_outputs, encoder_hidden = encoder(input_variable, encoder_hidden)
    decoder_input                   = Variable(torch.LongTensor([[SOS_token]]))
    decoder_context                 = Variable(torch.zeros(1, decoder.hidden_size))
    decoder_hidden                  = encoder_hidden

    **if** USE_CUDA:
        decoder_input   = decoder_input.cuda()
        decoder_context = decoder_context.cuda()

    use_teacher_forcing = random.random() < teacher_forcing_ratio

    **if** use_teacher_forcing:
        **for** di in range(target_length):
            decoder_output, decoder_context, decoder_hidden, decoder_attention = decoder(decoder_input, decoder_context, decoder_hidden, encoder_outputs)
            loss += criterion(decoder_output[0], target_variable[di])
            decoder_input = target_variable[di] # Next target is next input

    **else**:
        **for** di in range(target_length):
            decoder_output, decoder_context, decoder_hidden, decoder_attention = decoder(decoder_input, decoder_context, decoder_hidden, encoder_outputs)
            loss += criterion(decoder_output[0], target_variable[di])

            topv, topi = decoder_output.data.topk(1)
            ni         = topi[0][0]

            decoder_input = Variable(torch.LongTensor([[ni]]))

            **if** USE_CUDA:
                decoder_input = decoder_input.cuda()

            **if** ni == EOS_token:
                **break**

    loss.backward()

    torch.nn.utils.clip_grad_norm(encoder.parameters(), clip)
    torch.nn.utils.clip_grad_norm(decoder.parameters(), clip)

    encoder_optimizer.step()
    decoder_optimizer.step()

    **return** loss.data[0] / target_length

**def** as_minutes(s):
    m  = math.floor(s / 60)
    s -= m * 60

    **return** '%dm %ds' % (m, s)

**def** time_since(since, percent):
    now = time.time()
    s   = now - since
    es  = s / (percent)
    rs  = es - s

    **return** '%s (- %s)' % (as_minutes(s), as_minutes(rs))

attn_model  = 'general'
hidden_size = 500
n_layers    = 2
dropout_p   = 0.05

encoder = EncoderRNN(input_lang.n_words, hidden_size, n_layers)
decoder = AttnDecoderRNN(attn_model, hidden_size, output_lang.n_words, n_layers, dropout_p=dropout_p)

**if** USE_CUDA:
    encoder.cuda()
    decoder.cuda()

learning_rate     = 0.0001
encoder_optimizer = optim.Adam(encoder.parameters(), lr=learning_rate)
decoder_optimizer = optim.Adam(decoder.parameters(), lr=learning_rate)
criterion         = nn.NLLLoss()
n_epochs          = 50000
plot_every        = 200
print_every       = 1000
start             = time.time()
plot_losses       = []
print_loss_total  = 0
plot_loss_total   = 0

# Begin!
**for** epoch in range(1, n_epochs + 1):

    # Get training data for this cycle
    training_pair   = variables_from_pair(random.choice(pairs))
    input_variable  = training_pair[0]
    target_variable = training_pair[1]

    # Run the train function
    loss = train(input_variable, target_variable, encoder, decoder, encoder_optimizer, decoder_optimizer, criterion)

    # Keep track of loss
    print_loss_total += loss
    plot_loss_total  += loss

    **if** epoch == 0: **continue**

    **if** epoch % print_every == 0:
        print_loss_avg   = print_loss_total / print_every
        print_loss_total = 0
        print_summary    = '(%d %d%%) %.4f' % (epoch, epoch / n_epochs * 100, print_loss_avg)

        **print**(print_summary)

    **if** epoch % plot_every == 0:
        plot_loss_avg = plot_loss_total / plot_every
        plot_losses.append(plot_loss_avg)
        plot_loss_total = 0

**import** matplotlib.pyplot **as** plt
**import** matplotlib.ticker **as** ticker
**import** numpy **as** np

**def** show_plot(points):
    plt.figure()

    fig, ax = plt.subplots()
    loc     = ticker.MultipleLocator(base=0.2) # put ticks at regular intervals

    ax.yaxis.set_major_locator(loc)
    plt.plot(points)

show_plot(plot_losses)

**def** evaluate(sentence, max_length=MAX_LENGTH):
    input_variable = variable_from_sentence(input_lang, sentence)
    input_length = input_variable.size()[0]

    # Run through encoder
    encoder_hidden = encoder.init_hidden()
    encoder_outputs, encoder_hidden = encoder(input_variable, encoder_hidden)

    # Create starting vectors for decoder
    decoder_input = Variable(torch.LongTensor([[SOS_token]])) # SOS
    decoder_context = Variable(torch.zeros(1, decoder.hidden_size))
    **if** USE_CUDA:
        decoder_input = decoder_input.cuda()
        decoder_context = decoder_context.cuda()

    decoder_hidden = encoder_hidden

    decoded_words = []
    decoder_attentions = torch.zeros(max_length, max_length)

    # Run through decoder
    **for** di in range(max_length):
        decoder_output, decoder_context, decoder_hidden, decoder_attention = decoder(decoder_input, decoder_context, decoder_hidden, encoder_outputs)
        decoder_attentions[di,:decoder_attention.size(2)] += decoder_attention.squeeze(0).squeeze(0).cpu().data

        # Choose top word from output
        topv, topi = decoder_output.data.topk(1)
        ni = topi[0][0]
        **if** ni == EOS_token:
            decoded_words.append('<EOS>')
            **break**
        **else**:
            decoded_words.append(output_lang.index2word[ni])

        # Next input is chosen word
        decoder_input = Variable(torch.LongTensor([[ni]]))
        **if** USE_CUDA:
            decoder_input = decoder_input.cuda()

    **return** decoded_words, decoder_attentions[:di+1, :len(encoder_outputs)]

**def** evaluate_randomly():
    pair = random.choice(pairs)

    output_words, decoder_attn = evaluate(pair[0])
    output_sentence = ' '.join(output_words)

    **print**('>', pair[0])
    **print**('=', pair[1])
    **print**('<', output_sentence)
    **print**('')

evaluate_randomly()

**while** True:
    **try**:
        raw = raw_input(">")
        output_words, attentions = evaluate(raw)
        **print** output_words
    **except**:
        **pass**

**def** show_attention(input_sentence, output_words, attentions):
    # Set up figure with colorbar
    fig = plt.figure()
    ax = fig.add_subplot(111)
    cax = ax.matshow(attentions.numpy(), cmap='bone')
    fig.colorbar(cax)

    # Set up axes
    ax.set_xticklabels([''] + input_sentence.split(' ') + ['<EOS>'], rotation=90)
    ax.set_yticklabels([''] + output_words)

    # Show label at every tick
    ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
    ax.yaxis.set_major_locator(ticker.MultipleLocator(1))

    plt.show()
    plt.close()

**def** evaluate_and_show_attention(input_sentence):
    output_words, attentions = evaluate(input_sentence)
    **print**('input =', input_sentence)
    **print**('output =', ' '.join(output_words))
    show_attention(input_sentence, output_words, attentions)

一旦这段代码完成训练,您将看到一个简单的提示,您可以在这里测试结果。在我的笔记本电脑上训练需要相当长的时间,因为我让我的 scraper 脚本运行了很长时间。你收集的训练数据越多,效果就越好,但是你必须自己试验,看看什么对你来说效果最好。

以下是我在笔记本电脑上进行了两个小时的训练后得出的句子结果:

我需要食物[u ' food],'【T4]']
我在哪里可以找到食物[u ' food],'< EOS > ']
我想要一些食物>我的胃需要食物
你好我需要食物[u ' food],'< EOS > ']
我想要巴黎的免费食物[u ' food],'< EOS > '] < EOS > ']
我要踢一场足球赛
足球赛【u'football】,< EOS > ']
我可以换酒店吗【u'change】,'】
换酒店我可以【u'change】,< EOS > ']
怎么可以

如果根据更多数据进行训练,结果会显著改善。最终,这不是你在笔记本电脑上做的事情,我使用的最终版本是在云中训练的,以便能够在合理的时间框架内完成训练。

幸运的是,那里有几乎无穷无尽的数据供应,您可以向 scraper 脚本添加更多的博客 URL。

我们来实验一下!

这将是一个非常有趣的实验,看看我们是否可以颠倒整个过程,看看我们是否可以得出一个完整的句子,只给关键字作为输入,这肯定是我会尝试的事情,我会很快报告。

原载于

F#降临节日历——圣诞节分类器

原文:https://towardsdatascience.com/f-advent-calendar-a-christmas-classifier-72fb9e9d8f23?source=collection_archive---------18-----------------------

如何使用 F#和 ML 创建图像分类器?网

作为对硅谷和 Jìan-Yáng 的应用程序的赞美,该应用程序可以检测图片中是否包含热狗,我决定实现自己的版本,加入圣诞元素。

Silicon Valley — Hot Dog / Not Hot Dog

我想看看我是否能使用 F#创建一个二进制图像分类器,它能识别一个图像是否包含圣诞老人。

GitHub 上有这方面的代码。

数据采集

为了获得用于训练和评估模型的图像,我使用了 Bing 图像搜索 API

该 API 有助于查询图像,并返回一个 JSON 响应,该响应包括图像元数据和下载它们的 URL。

我使用了 F#数据 Http 实用程序来查询 API 和下载图像。我还使用了 JSON 类型提供者来处理 API 响应。

我总共下载了 1540 张图片——770 张有圣诞老人,770 张没有。

在收集没有圣诞老人的图片时,我搜索了包含可能引起混淆的特征的图片,如“留胡子的老人”和“圣诞精灵”。

下载后,我手动清理了数据集,确保没有图像被错误地标注。

我创建了两个 tsv 文件(train-images.tsvtest-images.tsv),使用 80-20 分割对数据集进行分区。

每个文件都包含图像的相对路径及其标签(santaclausnotsantaclaus)。

F#脚本1DownloadImageSearchResults.fsx2DownloadImages.fsx3CreateImageTsv.fsx记录了查询 Bing 图像搜索 API、下载图像以及标记和划分数据的过程。

ML。网

为了创建分类器,我使用了微软新的机器学*库,ML.NET

它仍处于早期开发阶段(0.7.0 ),所以功能有限,但很高兴看到机器学*在 F#中变得更容易使用。网!

张量流

我希望使用神经网络作为图像分类器,当通读 ML.NET 文档时,我很兴奋地看到它支持 TensorFlow。然而,目前该库仅支持评估预训练模型。

因此,我不能使用 ML.NET 来训练我自己的 TensorFlow 模型,但我可以使用预训练模型的输出作为更传统的机器学*算法的输入。

盗梦空间-第三版

Inception-v3 是在 ImageNet 数据集上训练的卷积神经网络。该网络有 48 层,并试图将图像分类到 ImageNet 中定义的 1000 个类别中的一个。

使用 Netron ,可以查看训练好的模型的结构。这里不能贴全网图片(它有 48 层!)但是对于这个任务,相关部分在网络的输出层。

Inception-v3 Softmax2 Function

上图中的Softmax2节点是一个激活函数,它根据 1000 个类获取图像的最终表示,并将其转换为概率分布。

它为每个类别分配一个小数概率,这样我们就可以确定哪个类别最有可能是图像的类别。

在我的图像分类器中,我可以使用 Inception-v3 模型,将输入输入到Softmax2节点(softmax2_pre_activation),并将其用作 model 算法的图像特征。

Model 模式

该模型在[Program.fs](https://github.com/williamtetlow/ChristmasClassifier/blob/master/ChristmasClassifierConsoleApp/Program.fs)中定义

dataLoader指定了输入数据的模式。

Input Data Schema

然后使用dataLoader加载训练和测试数据视图。

Load Training and Test Data

dataPipeline指定应该应用于输入 tsv 的变换。

因为这是一个二进制分类,所以我使用了一个自定义映射来将这两个类转换成布尔值— santaclaus = truenotsantaclaus = false

Transform Input Data

然后,我使用modelBuilder来描述图像如何加载、预处理和用于训练模型的管道。

管道使用输入 tsv 中定义的相对路径加载图像,调整它们的大小,使它们都具有相同的大小,然后提取像素信息,以便可以将它们传递到 Inception-v3 模型中。

Image Loading and Preprocessing

使用[TensorFlowEstimator](https://docs.microsoft.com/en-us/dotnet/api/microsoft.ml.transforms.tensorflowestimator?view=ml-dotnet),流水线加载预训练的 Inception-v3 模型,并输入从之前阶段提取的像素。

我想使用Softmax2节点的输入来获取我将在 ML.NET 使用的算法的特征。因此,TensorFlowEstimator 的输出是softmax2_pre_activation

TensorFlow Estimator using Inception-v3

最后一级将 TensorFlowEstimator 的输出传递到来自 ML.NET 的[StochasticDualCoordinateAscentBinaryClassifier](https://docs.microsoft.com/en-us/dotnet/api/microsoft.ml.legacy.trainers.stochasticdualcoordinateascentbinaryclassifier?view=ml-dotnet)中,这是一种用于线性二进制分类的算法。

Stochastic Dual Coordinate Ascent Binary Classifier

modelBuilder定义模型后,使用训练数据对其进行训练。

Training the Model

模型只花了几分钟训练。

我用了测试数据和 ML。[BinaryClassifierEvaluator](https://docs.microsoft.com/en-us/dotnet/api/microsoft.ml.runtime.data.binaryclassifierevaluator?view=ml-dotnet)内置网络,用于评估模型性能。

在测试集上,该模型给出了 96.08%的准确率

Model Metrics

这是一个非常好的结果,尤其是对于相对较小的数据集!

为了提高准确性,我可以增加数据集的大小,例如操纵图像的方向和缩放。

我还可以研究调整当前算法参数或使用另一种算法是否会返回更好的结果。

该项目的下一步是添加功能,将训练好的模型加载到应用程序中进行预测,这将在另一篇文章中演示(圣诞节前)。

但希望我已经展示了 F#中的机器学*变得越来越容易!

参考

https://github . com/dot net/machine learning/blob/master/docs/code/mlnet cookbook . MD

https://github.com/dotnet/machinelearning/issues/581

https://github . com/dot net/machine learning-samples/tree/master/samples/cs harp/getting-started/deep learning _ image classification _ tensor flow

https://github . com/dot net/machine learning-samples/tree/master/samples/cs harp/getting-started/deep learning _ image classification _ tensor flow

https://github . com/dot net/machine learning-samples/tree/master/samples/cs harp/getting-started/deep learning _ tensorflow estimator

https://github . com/dot net/machine learning-samples/tree/master/samples/fs harp

F#为勉强连接的人设计的笔记本电脑

原文:https://towardsdatascience.com/f-notebooks-for-the-barely-connected-44de0f5b06eb?source=collection_archive---------7-----------------------

对于很少上网的人来说。

最初发布于:https://devstufwithjpada . com/f-notebooks-for-the-barely-connected/

虽然 Azure notebooks 可能是在 Jupyter 笔记本上进行 F#数据科学实验的最快和最简单的方法,但这只在你总是在线的情况下才有效。如果你在一个第三世界国家(像我一样),只有断断续续的互联网连接怎么办?你如何在 Jupyter 笔记本上使用 F#?

我们有一个解决方案。但是当然,你需要先上网。之后,您可以随时离线,但仍然可以在您最喜欢的 Jupyter 笔记本上使用您喜欢的 F#进行工作。

码头工人来救援了

F#背后的人已经想到了这一点,并为在 Docker 中运行 F#笔记本的构建了一个 Dockerfile

过程的成本

[## 在 Docker 上设置 F#笔记本

这里发生了什么事?首先,IfSharp 回购被克隆。然后我们进入 IfSharp 目录。然后我们建造…

asciinema.org](https://asciinema.org/a/AGdxx2ROXS20smWMbH809rgFu)

那么我们如何做到这一点呢?

  1. 首先, IfSharp repo 克隆。
  2. 然后我们进入IfSharp目录。
  3. 然后我们用docker build -t ifsharp:3.0.0-alpha .Dockerfile构建 Docker 映像
  4. 然后,我们使用docker run -d -v your_local_notebooks_dir:/notebooks -p your_port:8888 ifsharp:3.0.0-alpha运行映像。更改端口和笔记本位置。
  5. 之后,我们使用docker ps来查看运行的容器。我们复制正在运行的容器的 id。
  6. 我们用docker exec -it the-container-id /bin/bash打开运行容器内的 bash shell。用我们复制的容器 id 替换“the-container-id”。
  7. 运行jupyter notebook list查看运行中的笔记本。将令牌复制到 URL 的?token=部分之后。
  8. localhost中打开笔记本,粘贴令牌以访问笔记本。

打开笔记本后,我们看到了这个:

Jupyter Authentication Page

这是我们粘贴之前复制的令牌的位置。将其粘贴在顶部并按下Log in

恭喜你!您现在可以像这样创建 F#笔记本:

Some F# code I wrote on the local F# Jupyter notebook.

现在,即使离线,你也可以在 Jupyter 笔记本上做 F#实验!耶!

使用 GANs 的人脸属性操作

原文:https://towardsdatascience.com/face-attribute-manipulation-using-gans-9fae92e9f1c3?source=collection_archive---------8-----------------------

添加面部属性,如胡须,小胡子,性别变化等。由于所涉及的复杂性,在图像编辑中是一项具有挑战性的任务。像生成式广告串行网络这样的现代深度学*算法有助于解决这个问题,而不需要人工编辑。

进场

我们的目标是根据给定的属性值修改人脸图像。我们建议学*相应的残差图像,而不是处理整个图像,残差图像被定义为处理前后图像之间的差异。

在这里,您可以看到由变换网络 G0 和 G1 生成的残差图像,它与原始图像相加以获得输出。

这种方法的动机是面部属性操作通常只需要适度修改特定于属性的面部区域,而其他部分保持不变。

图像变换网络

给定 x0 =具有负属性值的人脸图像和 x1 =具有正属性值的人脸图像,学*网络 G0 和 G1 应用操作变换以产生残差图像 r0 和 r1

然后将残差图像添加到输入图像中作为最终输出。

输出=输入+残差。

区别网络

判别网络是一个三类分类器,它将图像从不同类别中分类出来:

  1. 从 G0 和 G1 生成的图像(变换图像),
  2. 具有正属性标签的图像(真实图像),
  3. 以及带有负属性标签的图像(实像)。

给定已知属性标签 0 和标签 1实像 x0 和 x1 ,我们将变换后的图像视为标签为 2 的额外类别。

双重学*

双重学*的机制可以看作是一个两人的交流游戏。

对于给定的具有负属性值的图像 x0,我们通过 G0 传递它。获得的图像然后被馈送到 G1 。由于 G0 和 G1 分别是原始任务和双重任务,来自 G1** 的输出预期具有与 x0 相同的属性值。**类似的过程也适用于 x1。****

产生的图像 G1(G0(x0)) = x0

产生的图像 G1(G0(x1)) = x1

双重学*的有效性在于

1)从两个生成器生成的图像增加了训练样本的数量。

2)在双重学*阶段,G1(G0(x0))和 G0(G1(x1))的地面真实图像是已知的,这简化了两个生成器的训练。

参考

学*残差图像进行人脸属性操作—https://arxiv.org/abs/1612.05363

面向初学者的人脸检测

原文:https://towardsdatascience.com/face-detection-for-beginners-e58e8f21aad9?source=collection_archive---------0-----------------------

Multiple face detection in an image

在过去的几年里,人脸识别被认为是图像分析领域最有前途的应用之一。人脸检测可以考虑人脸识别操作的实质部分。根据其强度将计算资源集中在图像中包含人脸的部分。图片中的人脸检测方法是复杂的,因为人脸之间存在可变性,例如姿势、表情、位置和方向、肤色、眼镜或胡须的存在、相机增益的差异、光照条件和图像分辨率。

目标检测是计算机技术的一种,它与图像处理和计算机视觉相结合,它与检测目标的实例如人脸、建筑物、树木、汽车等相互作用。人脸检测算法的主要目的是确定图像中是否有人脸。

*年来,在人脸识别和人脸检测领域提出了许多研究工作,以使其更加先进和准确,但 Viola-Jones 推出的实时人脸检测器使这一领域发生了一场革命,它能够以高精度实时检测人脸。

人脸检测是人脸识别的首要步骤,用于检测图像中的人脸。它是目标检测的一部分,可用于许多领域,如安全、生物计量、执法、娱乐、个人安全等。

它用于实时检测人脸,以监视和跟踪人或物体。它被广泛应用于相机中,以识别移动相机和 DSLR 相机中的多个画面。脸书还使用人脸检测算法来检测图像中的人脸并进行识别。

人脸检测方法:-

Yan,Kriegman 和 Ahuja 提出了人脸检测方法的分类。这些方法分为四类,人脸检测算法可以属于两类或更多类。这些类别如下-

Different types of Face Detection Methods

1。知识型:-

基于知识的方法依赖于规则集,并且它基于人类的知识来检测人脸。一张脸必须有一个鼻子、眼睛和嘴巴,它们之间的距离和位置一定。这些方法的最大问题是难以建立一套合适的规则。如果规则太笼统或太详细,可能会有许多误报。这种方法本身是不够的,并且不能在多幅图像中找到许多人脸。

2。基于特征:-

基于特征的方法是通过提取人脸的结构特征来定位人脸。它首先被训练为分类器,然后用于区分面部和非面部区域。这个想法是为了克服我们对面孔的本能认识的局限性。这种方法分为几个步骤,甚至许多人的照片,他们报告的成功率为 94%。

3。模板匹配:-

模板匹配方法使用预定义或参数化的人脸模板,通过模板和输入图像之间的相关性来定位或检测人脸。人脸可以分为眼睛、面部轮廓、鼻子和嘴巴。此外,通过使用边缘检测方法,可以由边缘建立人脸模型。这种方法实现起来很简单,但是对于人脸检测来说是不够的。然而,已经提出了可变形模板来处理这些问题。

Template Matching

4。基于外观:-

基于外观的方法依赖于一组代表性的训练人脸图像来找出人脸模型。基于外观的方法优于其他表现方式。一般来说,基于外观的方法依赖于来自统计分析和机器学*的技术来寻找人脸图像的相关特征。这种方法也用于人脸识别的特征提取。

基于外观的模型进一步划分为用于面部检测的子方法,如下所述

4.1 .基于特征脸:-

用于人脸识别的基于特征脸的算法,是一种使用主成分分析有效表示人脸的方法。

4.2 .基于分配:-

像 PCA 和 Fisher 判别式这样的算法可以用来定义表示面部模式的子空间。有一个经过训练的分类器,它从背景图像模式中正确地识别目标模式类的实例。

4.3 .神经网络:-

许多检测问题,如物体检测、人脸检测、情感检测和人脸识别等。已经被神经网络成功地解决了。

4.4 .支持向量机:-

支持向量机是线性分类器,可以最大化决策超平面和训练集中的样本之间的差距。Osuna 等人首先将该分类器应用于人脸检测。

4.5 .稀疏网络的风选:-

他们定义了两个线性单元或目标节点的稀疏网络;一个代表人脸图案,另一个代表非人脸图案。它耗时少,效率高。

4.6 .朴素贝叶斯分类器:-

他们通过计算一系列模式在训练图像中出现的频率,计算出一张脸出现在照片中的概率。分类器捕获人脸的局部外观和位置的联合统计。

4.7 .隐马尔可夫模型:-

模型的状态是面部特征,通常被描述为像素带。HMM 通常与其他方法一起用于构建检测算法。

4.8 .信息论方法:-

马尔可夫随机场(MRF)可以用于人脸模式和相关特征。马尔可夫过程使用 Kullback-Leibler 散度来最大化类别之间的区分。因此,该方法可用于人脸检测。

4.9 .归纳学*:-

这种方法已经被用于检测人脸。像 Quinlan 的 C4.5 或 Mitchell 的 FIND-S 这样的算法用于此目的。

人脸检测的工作原理

检测人脸的技术有很多,借助这些技术,我们可以以更高的准确率识别人脸。这些技术对于人脸检测有着几乎相同的步骤,如 OpenCV、神经网络、Matlab 等。面部检测工作就像检测图像中多个面部一样。我们在 OpenCV 上进行人脸检测,人脸检测的操作步骤如下-

首先,通过提供图像的位置来导入图像。然后将图片从 RGB 转换为灰度,因为在灰度中很容易检测到人脸。

Converting RGB image to Grayscale

之后,使用图像处理,如果需要的话,对图像进行尺寸调整、裁剪、模糊和锐化。下一步是图像分割,用于轮廓检测或分割单幅图像中的多个对象,以便分类器可以快速检测图片中的对象和人脸。

下一步是使用由 Voila 和 Jones 提出的 Haar-Like 特征算法进行人脸检测。这种算法用于在帧或图像中寻找人脸的位置。所有人脸都具有人脸的一些普遍属性,如眼睛区域比其相邻像素暗,鼻子区域比眼睛区域亮。

Haar-like features for face detection

借助于边缘检测、线检测、用于检测眼睛、鼻子、嘴等的中心检测,haar-like 算法也用于图像中对象的特征选择或特征提取。图中。它用于选择图像中的基本特征,并提取这些特征用于人脸检测。

下一步是给出 x,y,w,h 的坐标,这在图片中形成一个矩形框来显示人脸的位置,或者我们可以说是显示图像中感兴趣的区域。在此之后,它可以在感兴趣的检测人脸的区域制作一个矩形框。还有许多其他检测技术一起用于检测,例如微笑检测、眼睛检测、眨眼检测等。

Successfully detect the face in an image

如何实时运行人脸检测器(网络摄像头):-

运行代码的要求- Python,OpenCV,网络摄像头,Numpy。

***#import libraries*** import cv2
import numpy as np**#import classifier for face and eye detection**
face_classifier = cv2.CascadeClassifier(‘Haarcascades/haarcascade_frontalface_default.xml’)***# Import Classifier for Face and Eye Detection*** face_classifier = cv2.CascadeClassifier(‘Haarcascades/haarcascade_frontalface_default.xml’)
eye_classifier = cv2.CascadeClassifier (‘Haarcascades/haarcascade_eye.xml’)
def face_detector (img, size=0.5):***# Convert Image to Grayscale*** gray = cv2.cvtColor (img, cv2.COLOR_BGR2GRAY)
faces = face_classifier.detectMultiScale (gray, 1.3, 5)
If faces is ():
return img***# Given coordinates to detect face and eyes location from ROI*** for (x, y, w, h) in faces
x = x — 100
w = w + 100
y = y — 100
h = h + 100
cv2.rectangle (img, (x, y), (x+w, y+h), (255, 0, 0), 2)
roi_gray = gray[y: y+h, x: x+w]
roi_color = img[y: y+h, x: x+w]
eyes = eye_classifier.detectMultiScale (roi_gray)
for (ex, ey, ew, eh) in eyes:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,0,255),2)
roi_color = cv2.flip (roi_color, 1)
return roi_color***# Webcam setup for Face Detection*** cap = cv2.VideoCapture (0)
while True:
ret, frame = cap.read ()
cv2.imshow (‘Our Face Extractor’, face_detector (frame))
if cv2.waitKey (1) == 13: #13 is the Enter Key
break***# When everything done, release the capture*** cap.release ()
cv2.destroyAllWindows ()

这个博客是为那些想通过学*什么是人脸检测,它的类型,以及它是如何工作的来开始他们在计算机视觉或人工智能领域的事业的初学者准备的。

人脸检测神经网络是什么样子的?

原文:https://towardsdatascience.com/face-detection-neural-network-structure-257b8f6f85d1?source=collection_archive---------2-----------------------

在我的上一篇文章中,我探索了多任务级联卷积网络(MTCNN)模型,用它来通过我的网络摄像头检测人脸。在这篇文章中,我将研究神经网络的结构。

MTCNN 模型由 3 个独立的网络组成:P 网、R 网和 O 网:

Image 1: MTCNN Structure // Source

对于我们传入的每个图像,网络都会创建一个图像金字塔:也就是说,它会创建该图像的多个不同大小的副本。

Image 2: Image Pyramid // Source

在 P-Net 中,对于每个缩放的图像,一个 12×12 的内核在图像中运行,以搜索人脸。在下图中,红色方块代表内核,它缓慢地在图像中上下移动,搜索人脸。

Image 3: 12x12 kernel in the top right corner. After scanning this corner, it shifts sideways (or downwards) by 1 pixel, and continues doing that until it has gone through the entire image.

在这些 12x12 内核的每一个中,3 个卷积与 3x3 内核一起运行(如果你不知道卷积是什么,请查看我的另一篇文章本网站)。在每一个卷积层之后,一个预层被执行(当你把每一个负像素乘以一个特定的数字‘alpha’。“α”将通过训练来确定)。此外,maxpool 层放在第一个 prelu 层之后(maxpool 每隔一个像素取出一个像素,只留下附*最大的像素)。

Image 4: Max-pool // Source

在第三卷积层之后,网络分裂成两层。来自第三层的激活被传递到两个单独的卷积层,以及其中一个卷积层之后的 softmax 层(softmax 为每个结果分配十进制概率,并且概率总计为 1。在这种情况下,它输出两个概率:在该区域中有人脸的概率和有不是人脸的概率)。

Image 5: P-Net

卷积 4–1 输出一个面在每个边界框中的概率,卷积 4–2 输出边界框的坐标。

看一看 mtcnn.py 会给你展示 P-Net 的结构:

class PNet(Network):def _config(self):layer_factory = LayerFactory(self)layer_factory.new_feed(name='data', layer_shape=(None, None, None, 3))layer_factory.new_conv(name='conv1', kernel_size=(3, 3), channels_output=10, stride_size=(1, 1),padding='VALID', relu=False)layer_factory.new_prelu(name='prelu1')layer_factory.new_max_pool(name='pool1', kernel_size=(2, 2), stride_size=(2, 2))layer_factory.new_conv(name='conv2', kernel_size=(3, 3), channels_output=16, stride_size=(1, 1),padding='VALID', relu=False)layer_factory.new_prelu(name='prelu2')layer_factory.new_conv(name='conv3', kernel_size=(3, 3), channels_output=32, stride_size=(1, 1),padding='VALID', relu=False)layer_factory.new_prelu(name='prelu3')layer_factory.new_conv(name='conv4-1', kernel_size=(1, 1), channels_output=2, stride_size=(1, 1), relu=False)layer_factory.new_softmax(name='prob1', axis=3)layer_factory.new_conv(name='conv4-2', kernel_size=(1, 1), channels_output=4, stride_size=(1, 1),input_layer_name='prelu3', relu=False)

R-Net 具有类似的结构,但是具有更多的层。它以 P-网包围盒作为其输入,并改进其坐标。

Image 6: R-Net

类似地,R-Net 最终分成两层,给出两个输出:新边界框的坐标和机器对每个边界框的置信度。同样,mtcnn.py 包括 R-Net 的结构:

class RNet(Network):def _config(self):layer_factory = LayerFactory(self)layer_factory.new_feed(name='data', layer_shape=(None, 24, 24, 3))layer_factory.new_conv(name='conv1', kernel_size=(3, 3), channels_output=28, stride_size=(1, 1),padding='VALID', relu=False)layer_factory.new_prelu(name='prelu1')layer_factory.new_max_pool(name='pool1', kernel_size=(3, 3), stride_size=(2, 2))layer_factory.new_conv(name='conv2', kernel_size=(3, 3), channels_output=48, stride_size=(1, 1),padding='VALID', relu=False)layer_factory.new_prelu(name='prelu2')layer_factory.new_max_pool(name='pool2', kernel_size=(3, 3), stride_size=(2, 2), padding='VALID')layer_factory.new_conv(name='conv3', kernel_size=(2, 2), channels_output=64, stride_size=(1, 1),padding='VALID', relu=False)layer_factory.new_prelu(name='prelu3')layer_factory.new_fully_connected(name='fc1', output_count=128, relu=False) layer_factory.new_prelu(name='prelu4')layer_factory.new_fully_connected(name='fc2-1', output_count=2, relu=False) layer_factory.new_softmax(name='prob1', axis=1)layer_factory.new_fully_connected(name='fc2-2', output_count=4, relu=False, input_layer_name='prelu4')

最后,O-Net 将 R-Net 包围盒作为输入,并记下面部标志的坐标。

Image 7: O-Net

O-Net 最终分成 3 层,给出 3 种不同的输出:人脸在框中的概率、边界框的坐标和面部标志的坐标(眼睛、鼻子和嘴的位置)。以下是 O-Net 的代码:

class ONet(Network):def _config(self):layer_factory = LayerFactory(self)layer_factory.new_feed(name='data', layer_shape=(None, 48, 48, 3))layer_factory.new_conv(name='conv1', kernel_size=(3, 3), channels_output=32, stride_size=(1, 1),padding='VALID', relu=False)layer_factory.new_prelu(name='prelu1')layer_factory.new_max_pool(name='pool1', kernel_size=(3, 3), stride_size=(2, 2))layer_factory.new_conv(name='conv2', kernel_size=(3, 3), channels_output=64, stride_size=(1, 1),padding='VALID', relu=False)layer_factory.new_prelu(name='prelu2')layer_factory.new_max_pool(name='pool2', kernel_size=(3, 3), stride_size=(2, 2), padding='VALID')layer_factory.new_conv(name='conv3', kernel_size=(3, 3), channels_output=64, stride_size=(1, 1),padding='VALID', relu=False)layer_factory.new_prelu(name='prelu3')layer_factory.new_max_pool(name='pool3', kernel_size=(2, 2), stride_size=(2, 2))layer_factory.new_conv(name='conv4', kernel_size=(2, 2), channels_output=128, stride_size=(1, 1),padding='VALID', relu=False)layer_factory.new_prelu(name='prelu4')layer_factory.new_fully_connected(name='fc1', output_count=256, relu=False)layer_factory.new_prelu(name='prelu5')layer_factory.new_fully_connected(name='fc2-1', output_count=2, relu=False)layer_factory.new_softmax(name='prob1', axis=1)layer_factory.new_fully_connected(name='fc2-2', output_count=4, relu=False, input_layer_name='prelu5')layer_factory.new_fully_connected(name='fc2-3', output_count=10, relu=False, input_layer_name='prelu5')

注意,P-Net、R-Net 和 O-Net 的所有代码都导入了一个名为“LayerFactory”的类。本质上,LayerFactory 是一个类,由该模型的制作者创建,用于生成具有特定设置的层。有关更多信息,您可以查看 layer_factory.py。

点击此处阅读实现 MTCNN 模型!

点击此处阅读 MTCNN 模式如何运作!

点击此处下载 MTCNN 论文和资源:

Github 下载:【https://github.com/ipazc/mtcnn

研究文章:http://arxiv.org/abs/1604.02878

面向初学者的人脸识别

原文:https://towardsdatascience.com/face-recognition-for-beginners-a7a9bd5eb5c2?source=collection_archive---------0-----------------------

ace 识别是一种识别技术,用于检测其图像保存在数据集中的个人的面部。尽管其他身份识别方法可能更准确,但人脸识别一直是研究的一个重要焦点,因为它的非干涉性质,因为它是人们进行个人身份识别的简便方法。

人脸识别方法:-

人脸识别有以下几种不同的方法

1。几何基础/模板基础:-

人脸识别算法分为基于几何或基于模板的算法。基于模板的方法可以使用统计工具来构建,如 SVM[支持向量机]、PCA[主成分分析]、LDA[线性判别分析]、核方法或迹变换。基于几何特征的方法分析局部面部特征及其几何关系。它也被称为基于特征的方法。

2。零碎/整体:-

元素之间的关系或功能的连接与整个面部没有经历到的数量,许多研究人员遵循这种方法,试图推导出最相关的特征。一些方法试图使用眼睛、特征的组合等等。一些隐马尔可夫模型方法也属于这一类,特征处理在人脸识别中非常有名。

3。基于外观/基于模型:-

基于外观的方法显示关于几幅图像的人脸。被认为是高维向量的图像。这种技术通常用于从图像分割中导出特征空间。与训练集比较的样本图像。另一方面,基于模型的方法试图对人脸建模。对模型实现的新样本和用于识别图像的模型参数。

基于外观的方法可以分为线性或非线性。Ex- PCA、LDA、IDA 用于直接方法,而核 PCA 用于非线性方法。另一方面,在基于模型的方法可以归类为 2D 或三维弹性束图匹配使用。

4。基于模板/统计/神经网络:-

4.1 .模板匹配:-

在模板匹配中,模式由样本、模型、像素、纹理等表示。识别函数通常是相关性或距离度量。

4.2 .统计方法:-

在统计学方法中,用特征表示的模式。判别函数中的识别函数。每个图像都代表了三维特征。因此,目标是选择和应用正确的统计工具进行提取和分析。

用于人脸识别的统计工具有很多。这些分析工具用在两个或多个组或分类方法中。这些工具如下-

4.2.1 .主成分分析【PCA】:-

使用和引用最多的统计方法之一是主成分分析。数学过程通过提取多维数据的主成分来执行维度缩减。

Dimension reduction from 3D to 2D image

T5 4 . 2 . 2 .离散余弦变换【DCT】:-

它表示关于不同振荡频率的余弦函数和的一系列数据点。离散余弦变换基于傅立叶离散变换,因此,通过压缩变化,它可以用于变换图像,并允许有效的维数减少。

4.2.3 .线性判别分析【LDA】:-

LDA 广泛用于寻找特征的线性组合,同时保持类的可分性。与 PCA 不同,LDA 试图对级别之间的差异进行建模。对于每个级别,LDA 获得多个投影向量的差值。

PCA vs LDA

4.2.4 .局部保持投影【LPP】:-

他和代代木介绍了 LPP。它是保持局部结构和设计的 PCA 的最佳替代方案。模式识别算法通常搜索最*的模式或邻居。因此,维护 LLP 质量的地方可以加快认识。

4.2.5.Gabor 小波:-

在这种算法中,它表明来自哺乳动物大脑视觉皮层的神经生理学数据证据表明,视觉皮层中的简单细胞可以视为一族自相似的 2D Gabor 小波。Daugman 提出的 Gabor 函数是局部空间带通滤波器,其实现了 2D 空间和 2D 傅立叶域中信息的联合分辨率的理论极限。

Gabor Wavelet in different magnitude

4.2.6 .独立分量分析【ICA】:-

ICA 旨在将数据转换为统计上独立的数据点的线性组合。因此,其目标是提供独立而非不相关的图像表示。ICA 是 PCA 替代方案,它给出了更强大的数据表示。这是一种判别分析准则,可用于增强 PCA。

4.2.7 .内核主成分分析:-

Scholkopf 等人介绍了使用核函数来执行非线性 PCA。其基本方法是对输入应用非线性映射,然后在得到的特征子空间中求解线性 PCA。

4.3 .神经网络:-

神经网络继续使用模式识别和分类。Kohonen 是第一个证明神经元网络可以用来识别对齐和标准化的面孔的人。存在使用神经网络执行特征提取的方法。有很多方法可以结合 PCA 或 LCA 等工具,组成混合分类器用于人脸识别。这些如具有附加偏差前馈神经网络、具有 PCA 的自组织映射和具有多层感知的卷积神经网络等。这些可以提高模型的效率。

Deep Neural Network for Face Recognition

4.3.1 .具有 Gabor 滤波器的神经网络:-

该算法通过使用反向传播算法实现多层感知器来实现人脸识别。首先,有一个预处理步骤。每幅图像在对比度和光照阶段进行标准化。然后,通过 Gabor 滤波器处理每幅图像。伽柏滤波器有五个方向参数和三个空间频率,因此有 15 个伽柏波长。

Neural Networks with Gabor filters

4.3.2 .神经网络和隐马尔可夫模型:-

隐马尔可夫模型是一种用于人脸识别的统计工具。它们与神经网络一起使用。它在训练伪 2D HMM 的神经网络中生成。这个 2D HMM 过程的输入是 ANN 的输出,它为算法提供适当的维数缩减。

4.3.3 .模糊神经网络:-

用于人脸识别的模糊神经网络于 2009 年推出。这是一个使用多层感知器的人脸识别系统。这种方法背后的概念是捕捉非线性流形中的决策面,这是一个简单的 MLP 很难完成的任务。使用 Gabor 波长变换获得特征向量。

Fuzzy Neural Network

人脸识别的工作原理

人脸识别有很多种方法。这里我们使用 OpenCV 进行人脸识别。在人脸识别中,首先对图像进行预处理,然后训练人脸识别器来识别人脸。教完识别器后,我们测试识别器看看结果。OpenCV 人脸识别器有以下三种类型

1。特征脸人脸识别器

EigenFaces 人脸识别器将所有字符的所有训练图像视为一个复合体,并尝试推断其组成部分。这些成分是必要的和有帮助的(抓住最大变化/改变的部分),并丢弃图像的其余部分,这样它不仅从训练数据中提取必要的元素,而且通过拒绝不太重要的片段来节省存储器。

2。鱼脸识别器

Fisherfaces 算法不是获得代表所有人的所有面部的有用特征,而是移除区分一个人和其他人的有价值的特征。一个人的这种特征并不支配其他人,你有区别一个人和其他人的特征。

3。局部二元模式直方图

我们知道本征脸和鱼脸都受光线影响,在现实生活中也是如此;我们不能保证完美的光线条件。LBPH 人脸识别器是克服这一缺点的改进。这个想法不是找到图像的局部特征。LBPH 算法试图找到图像的局部结构,它是通过将每个像素与其相邻像素进行比较来实现的。

如何运行人脸识别:-

**#import OpenCV module**
import cv2
import os
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline**#function to detect face**
def detect_face (img):**#convert the test image to gray image**
gray = cv2.cvtColor (img, cv2.COLOR_BGR2GRAY)**#load OpenCV face detector**
face_cas = cv2.CascadeClassifier ('-File name.xml-')
faces = face_cas.detectMultiScale (gray, scaleFactor=1.3, minNeighbors=4);**#if no faces are detected then return image**
if (len (faces) == 0):
return None, None**#extract the face**
faces [0]=(x, y, w, h)**#return only the face part**
return gray[y: y+w, x: x+h], faces [0]**#this function will read all persons' training images, detect face #from each image
#and will return two lists of exactly same size, one list** def prepare_training_data(data_folder_path):**#------STEP-1--------
#get the directories (one directory for each subject) in data folder** dirs = os.listdir(data_folder_path)
faces = []
labels = []
for dir_name in dirs:**#our subject directories start with letter 's' so
#ignore any non-relevant directories if any** if not dir_name.startswith("s"):
continue;**#------STEP-2--------
#extract label number of subject from dir_name
#format of dir name = slabel
#, so removing letter 's' from dir_name will give us label** label = int(dir_name.replace("s", ""))**#build path of directory containin images for current subject subject
#sample subject_dir_path = "training-data/s1"** subject_dir_path = data_folder_path + "/" + dir_name**#get the images names that are inside the given subject directory** subject_images_names = os.listdir(subject_dir_path)**#------STEP-3--------
#go through each image name, read image,
#detect face and add face to list of faces** for image_name in subject_images_names:**#ignore system files like .DS_Store** if image_name.startswith("."):
continue;**#build image path
#sample image path = training-data/s1/1.pgm** image_path = subject_dir_path + "/" + image_name**#read image** image = cv2.imread(image_path)**#display an image window to show the image** cv2.imshow("Training on image...", image)
cv2.waitKey(100)**#detect face** face, rect = detect_face(image)**#------STEP-4--------
#we will ignore faces that are not detected** if face is not None:**#add face to list of faces** faces.append(face)**#add label for this face** labels.append(label)
cv2.destroyAllWindows()
cv2.waitKey(1)
cv2.destroyAllWindows()
return faces, labels**#let's first prepare our training data
#data will be in two lists of same size
#one list will contain all the faces
#and other list will contain respective labels for each face** print("Preparing data...")
faces, labels = prepare_training_data("training-data")
print("Data prepared")**#print total faces and labels** print("Total faces: ", len(faces))
print("Total labels: ", len(labels))**#create our LBPH face recognizer** face_recognizer = cv2.face.createLBPHFaceRecognizer()**#train our face recognizer of our training faces** face_recognizer.train(faces, np.array(labels))**#function to draw rectangle on image
#according to given (x, y) coordinates and
#given width and heigh** def draw_rectangle(img, rect):
(x, y, w, h) = rect
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)**#function to draw text on give image starting from
#passed (x, y) coordinates.** def draw_text(img, text, x, y):
cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0), 2)**#this function recognizes the person in image passed
#and draws a rectangle around detected face with name of the subject** def predict(test_img):**#make a copy of the image as we don't want to chang original image** img = test_img.copy()**#detect face from the image** face, rect = detect_face(img)**#predict the image using our face recognizer** label= face_recognizer.predict(face)**#get name of respective label returned by face recognizer** label_text = subjects[label]**#draw a rectangle around face detected** draw_rectangle(img, rect)**#draw name of predicted person** draw_text(img, label_text, rect[0], rect[1]-5)
return img**#load test images** test_img1 = cv2.imread("test-data/test1.jpg")
test_img2 = cv2.imread("test-data/test2.jpg")**#perform a prediction** predicted_img1 = predict(test_img1)
predicted_img2 = predict(test_img2)
print("Prediction complete")**#create a figure of 2 plots (one for each test image)** f, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))**#display test image1 result** ax1.imshow(cv2.cvtColor(predicted_img1, cv2.COLOR_BGR2RGB))**#display test image2 result** ax2.imshow(cv2.cvtColor(predicted_img2, cv2.COLOR_BGR2RGB))**#display both images** cv2.imshow("Tom cruise test", predicted_img1)
cv2.imshow("Shahrukh Khan test", predicted_img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.waitKey(1)
cv2.destroyAllWindows()

这个博客是为那些想通过学*什么是人脸识别,它的类型以及它是如何工作的来开始他们在计算机视觉或人工智能领域的载体的初学者而写的。

人脸识别:理解 LBPH 算法

原文:https://towardsdatascience.com/face-recognition-how-lbph-works-90ec258c3d6b?source=collection_archive---------0-----------------------

人类每天都在自动进行人脸识别,几乎不费吹灰之力。

虽然这听起来对我们来说是一个非常简单的任务,但对计算机来说却是一个复杂的任务,因为它有许多变量会影响方法的准确性,例如:光照变化、低分辨率、遮挡等。

在计算机科学中,人脸识别基本上是根据人脸图像识别一个人的任务。在过去的二十年里,它变得非常流行,主要是因为新方法的发展和当前视频/摄像机的高质量。

注意人脸识别不同于人脸检测:

  • 人脸检测:它的目的是找到图像中的人脸(位置和大小),并可能提取它们以供人脸识别算法使用。
  • 面部识别:面部图像已经被提取、裁剪、调整大小并通常转换为灰度,面部识别算法负责寻找最能描述图像的特征。

面部识别系统基本上可以在两种模式下运行:

  • 面部图像的验证或认证:基本上是将输入的面部图像与要求认证的用户相关的面部图像进行比较。基本上就是 1x1 的对比。
  • 身份识别或面部识别:它主要将输入的面部图像与数据集中的所有面部图像进行比较,目的是找到与该面部相匹配的用户。基本上是 1xN 的对比。

有不同类型的人脸识别算法,例如:

每种方法都有不同的方法来提取图像信息并执行与输入图像的匹配。然而,特征面和鱼面方法以及 SIFT 和 SURF 方法具有类似的方法。

今天我们要讨论一种最古老(不是最古老)也是最流行的人脸识别算法:局部二值模式直方图(LBPH)

目标

这篇文章的目的是尽可能简单地解释 LBPH ,一步一步地展示这个方法。

由于这是一种比较简单的人脸识别算法,我想每个人都可以理解它,没有大的困难。

介绍

局部二进制模式 (LBP)是一个简单但非常有效的纹理算子,它通过对每个像素的邻域进行阈值处理来标记图像的像素,并将结果视为二进制数。

它在 1994 年首次被描述(LBP ),并且已经被发现是纹理分类的强大特征。已经进一步确定,当 LBP 与方向梯度直方图(HOG)描述符结合时,它在一些数据集上显著提高了检测性能。

使用 LBP 结合直方图,我们可以用简单的数据向量来表示人脸图像。

因为 LBP 是视觉描述符,所以它也可以用于面部识别任务,正如在下面的逐步解释中可以看到的。

:你可以在这里阅读更多关于 LBPH:http://www.scholarpedia.org/article/Local_Binary_Patterns

循序渐进

现在,我们对人脸识别和 LBPH 有了更多的了解,让我们更进一步,看看算法的步骤:

  1. 参数:LBPH 使用 4 个参数:
  • 半径:半径用于构建圆形局部二值模式,代表中心像素周围的半径。它通常设置为 1。
  • 邻居:构建圆形局部二值模式的样本点数。请记住:包含的样本点越多,计算成本就越高。通常设置为 8。
  • 网格 X :水平方向的单元格个数。单元越多,网格越细,得到的特征向量的维度越高。通常设置为 8。
  • 网格 Y :垂直方向的单元格个数。单元越多,网格越细,得到的特征向量的维度越高。通常设置为 8。

现在不用担心参数,看完后面的步骤你就明白了。

2。 训练算法:首先,我们需要训练算法。为此,我们需要使用一个包含我们想要识别的人的面部图像的数据集。我们还需要为每张图像设置一个 ID(它可能是一个数字或人名),因此算法将使用这些信息来识别输入图像并给你一个输出。同一个人的图像必须有相同的 ID。训练集已经构建好了,让我们看看 LBPH 的计算步骤。

3。应用 LBP 操作:LBPH 的第一个计算步骤是创建一个中间图像,通过突出面部特征,以更好的方式描述原始图像。为此,该算法使用滑动窗口的概念,基于参数半径邻居。****

下图显示了此过程:

根据上面的图片,让我们把它分成几个小步骤,这样我们就可以很容易地理解它:

  • 假设我们有一张灰度的面部图像。
  • 我们可以得到这个图像的一部分,作为一个 3x3 像素的窗口。
  • 也可以表示为包含每个像素(0~255)强度的 3x3 矩阵。
  • 然后,我们需要取矩阵的中心值作为阈值。
  • 该值将用于定义来自 8 个邻居的新值。
  • 对于中心值(阈值)的每个邻居,我们设置一个新的二进制值。我们将等于或高于阈值的值设置为 1,将低于阈值的值设置为 0。
  • 现在,矩阵将只包含二进制值(忽略中心值)。我们需要将矩阵中每个位置的每个二进制值逐行连接成一个新的二进制值(例如 10001101)。注意:一些作者使用其他方法连接二进制值(例如顺时针方向),但最终结果将是相同的。
  • 然后,我们将这个二进制值转换为十进制值,并将其设置为矩阵的中心值,这实际上是原始图像的一个像素。
  • 在这个过程(LBP 过程)的最后,我们有一个新的图像,它更好地代表了原始图像的特征。
  • :LBP 程序被扩展为使用不同数量的半径和邻居,它被称为圆形 LBP。

可以通过使用双线性插值来完成。如果某个数据点在像素之间,它将使用最*的 4 个像素(2x2)的值来估计新数据点的值。

4。提取直方图:现在,使用上一步生成的图像,我们可以使用网格 X网格 Y 参数将图像分成多个网格,如下图所示:****

根据上面的图像,我们可以提取每个区域的直方图如下:

  • 由于我们有一个灰度图像,每个直方图(来自每个网格)将只包含 256 个位置(0~255 ),代表每个像素强度的出现。
  • 然后,我们需要连接每个直方图来创建一个新的更大的直方图。假设我们有 8×8 的网格,在最终的直方图中我们将有 8×8×256 = 16.384 个位置。最终的直方图表示图像原始图像的特征。

LBPH 算法差不多就是这样。

5。执行面部识别:在这个步骤中,算法已经被训练。创建的每个直方图用于表示来自训练数据集的每个图像。因此,给定一个输入图像,我们对这个新图像再次执行这些步骤,并创建一个代表该图像的直方图。

  • 因此,要找到与输入图像匹配的图像,我们只需比较两个直方图,并返回直方图最接*的图像。
  • 我们可以使用各种方法来比较直方图(计算两个直方图之间的距离),例如:欧氏距离卡方绝对值等。在本例中,我们可以根据以下公式使用欧几里德距离(这是众所周知的):

  • 因此,算法输出是直方图最接*的图像的 ID。该算法还应返回计算出的距离,该距离可用作'置信度'度量。注意:不要被“置信度”这个名称所迷惑,因为置信度越低越好,因为这意味着两个直方图之间的距离越*。
  • 然后,我们可以使用阈值和“置信度”来自动估计算法是否正确识别了图像。我们可以假设该算法已经成功识别了置信度是否低于定义的阈值。

结论

  • LBPH 是最简单的人脸识别算法之一。
  • 它可以表示图像中的局部特征。
  • 有可能获得很大的成果(主要是在可控的环境下)。
  • 它对单调的灰度变换是鲁棒的。
  • OpenCV 库(开源计算机视觉库)提供。

LBPH 算法

我正在用 Go 编程语言实现 LBPH 算法。项目可在 Github 上获得,并在 MIT 许可 下发布,因此请随意为该项目做出贡献(欢迎任何贡献)。
链接到项目:https://github.com/kelvins/lbph

:结论中提到的 LBPH 也是由 OpenCV 库 提供的。OpenCV 库可以被许多编程语言使用(例如 C++、Python、Ruby、Matlab)。

如果你喜欢这个故事,请鼓掌。这激励我写更多关于人脸识别的故事。

参考

我看起来像布拉德·皮特吗?

原文:https://towardsdatascience.com/face-recognition-with-deep-learning-767a1e6f4974?source=collection_archive---------10-----------------------

我们来问一个深度学*模型

Face recognition with deep learning

在另一篇文章中,我查看了数据准备来从图像中提取一张脸,并将其对齐,这样不管脸的旋转,面部特征总是对齐在中心。

在这篇文章中,我将准备一些我自己和布拉德·皮特的照片。目标将是在这些图像上训练一个深度学*模型,看看当呈现新图像时,它是否能检测出我们之间的差异。

这有点像第二十二条军规。如果一切顺利的话,模特将会成功地认出我或者布拉德·皮特。另一方面,如果它可以轻松做到这一点,这可能意味着我看起来一点也不像布拉德·皮特!

深度学*——它是什么?

机器学*和深度学*是相当超载的术语。他们被认为是不需要太多努力就能轻松解决任何问题的灵丹妙药。然而,事情并不总是这么简单。为了建立一个模型,你需要了解你在找什么,有什么参数,有多少训练数据,它有多可靠等等。

深度学*是一种专注于神经网络的机器学*。那就是编程和建立一个受人脑启发的模型。亚当·盖特基有一篇很棒的文章,他会比我更好地解释神经网络。

对于这篇文章,深度学*将用于产生称为嵌入的点(稍后解释)。这些点描述了面部的图像。在我们的例子中,给定两组人的图像,它的目标是确保它产生的点(嵌入)对于同一个人的面部非常相似,但是对于另一个人的面部非常不同。

  1. 确保为布拉德·皮特的脸的图像产生的所有点是相似的。
  2. 确保为我的脸部图像生成的所有点都是相似的。
  3. 确保为布拉德·皮特的图像生成的点与为我的脸的图像生成的点尽可能不同。

这将允许我们训练一个分类模型来区分两组图像。

建立一些训练数据

第一步是获得更多的数据。我不想花太多时间去挖掘和下载图片,所以我最初用 3 张布拉德的图片和 3 张我自己的图片来验证这个概念。

我通过我在上一篇文章中写的face_skew.py python 应用程序运行每张图片。这给了我总共 6 个对齐的图像。

我将这些图像存储在一个名为 aligned_faces 的文件夹中,每个图像都有自己的子目录。

./aligned_faces/me/ ./aligned_faces/bradp/

建筑嵌入

现在我已经准备好了数据,是时候构建嵌入了。

请记住,这些嵌入是由神经网络产生的一组 128 个点。这些点对于相同的人脸是相似的,而对于其他人的人脸是不同的。128 点嵌入过程是从谷歌的一些研究中发展出来的。建立一个深度学*模型来做到这一点非常耗时,并且需要一些强大的显卡。为了克服这一点,我使用了来自 Openface 的预训练模型。

他们提供了一些帮助代码以及帮助我生成嵌入的模型。你需要确保你已经用 sklearn 和 pandas 库安装了 Python,同时还安装了 DlibOpenCV 和 open face(https://github . com/cmusatyalab/open face)。

一旦你安装了所有这些,进入 Openface 的基本目录,然后进入一个名为batch-recognise的文件夹。

在这里,我运行以下命令来为我对齐的面构建嵌入。

./main.lua -outDir ~/facerecognition/embeddings/ -data ~/facerecognition/aligned_faces/

outDir中,这应该产生 2 个文件:labels.csvreps.csv。它们分别包含输入图像的图像路径和每个图像的一行 128 个点。

成功了!我已经用深度学*模型运行了我的图像,并产生了一些输出

在处理机器学*应用时,你可能会注意到一个趋势。大部分工作是在数据准备和将数据转换成机器可读的格式。在我们的例子中,它获取图像数据并将其转换成数字表示。在分类文本数据进行情感分析之前,我们必须做同样的事情。

一旦完成,剩下的就是构建一个简单的分类器来进行“识别”。

识别面孔——我看起来像布拉德·皮特吗?

如果您想要更高级的方法来完成这一步,您可以训练自己的分类模型来对嵌入进行分类。然而,在 Openface 目录中,他们友好地提供了一个使用支持向量机算法的示例 python 分类器。

从 Openface 基本目录,进入名为demos的目录。

为了训练分类器,我运行了以下内容:

$ python classifier.py train ~/facerecognition/embeddings

现在,在您的嵌入文件中,您应该有一个 pickle 文件,其中包含您生成的 SVM。

为了测试它,我简单地获得了两个额外的图像,它们不同于我用来训练模型的图像。一张是我的,另一张是布拉德·皮特的。

我对它们进行了测试,得到了以下结果:

$ python classifier.py infer ~/facerecognition/embeddings/classifier.pkl /media/sf_Shared/test_image_me.jpg === /media/sf_Shared/test_image_me.jpg === Predict me with 0.86 confidence. $ python classifier.py infer ~/facerecognition/embeddings/classifier.pkl /media/sf_Shared/test_image_bradp.jpeg === /media/sf_Shared/test_image_bradp.jpeg === Predict bradp with 0.73 confidence.

包裹

总之,不幸的是,即使只有 3 张图片的训练数据集,这个模型也能很容易地区分我和布拉德·皮特!我真的应该看到它的到来。

然而,它似乎只对小样本数据有效。这是一个很好的介绍,让我开始理解深度学*的力量及其工作原理。尽管只是复制粘贴命令,但阅读这个主题的内容是很重要的,至少可以对模型的工作原理有所了解。

在未来,我将试图从头开始建立自己的深度学*模型。

face 2 face——模仿德国总理面部表情的 Pix2Pix 演示

原文:https://towardsdatascience.com/face2face-a-pix2pix-demo-that-mimics-the-facial-expression-of-the-german-chancellor-b6771d65bf66?source=collection_archive---------0-----------------------

受吉恩·科岗工作室的启发,我制作了自己的 face2face 演示,可以在 2017 年德国总理发表新年演讲时将我的网络摄像头图像翻译成她的样子。它还不完美,因为这个模型还有一个问题,例如,学*德国国旗的位置。然而,这个模特已经很好地模仿了她的面部表情,考虑到我在这个项目上的有限时间,我对结果很满意。

这就是了😃

Face2face demo with the original video input.

这也是另一个版本,它把我的面部标志作为输入。

Face2face demo with the detected facial landmarks.

如果你有兴趣创建自己的演示或者只是自己运行它, Github repositor y 包含了你需要的一切。当然,你应该继续阅读!😁

动机

几周前,我参加了在柏林艺术博物馆举行的吉恩·科岗关于 pix2pix 和深度生成模型的研讨会。在那里,他展示了几个利用生成模型的艺术项目。他展示的其中一个项目是他自己的,他使用面部追踪器创建了一个能够模仿特朗普的生成模型:

这种演示真的让我耳目一新,因为我在工作中通常不会接触这类项目。在这次研讨会后,我决定创建自己的项目,类似于 Gene 用面部追踪器做的项目,但用的是不同的人。

生成培训数据

我要做的第一件事是创建数据集。为此,我使用了 Dlib 的姿势估计器,它可以检测一张脸上的 68 个标志(嘴、眉毛、眼睛等……)以及 OpenCV 来处理视频文件:

  • 检测面部标志是两个阶段的过程。首先,使用面部检测器来检测面部,然后对检测到的面部应用姿态估计器。
  • 姿势估计器是论文的一个实现:一毫秒人脸对齐与回归树集合由瓦希德·卡泽米和约瑟芬·苏利文于 2014 年在 CVPR 发表
  • 我遇到的一个问题是,在我第一次实现时,面部标志检测器非常滞后(非常低的每秒帧数-fps)。我发现输入框太大了。将帧的大小缩小到四分之一会大大提高 fps。在 Satya Mallick 的另一篇博客文章中,他也建议跳过帧,但我没有这样做,因为 fps 现在已经足够好了。但是,我可以在以后尝试这种方法来进一步提高性能。
  • 我在 YouTube 上查找了几个潜在的视频,我可以用它们来创建从采访到名人演讲的数据。最后,我决定用安格拉·默克尔(德国总理)的 2017 年新年致辞。这个视频特别适合,因为相机的位置是静态的,所以我可以用她的脸和背景的相同位置得到很多图像。

One sample of the training data.

训练模型

幸运的是,在研讨会上,Gene 还指出了一些现有的生成模型的代码库,如 pix2pix。所以我不需要做很多研究。对于模型的训练,我使用了 Daniel Hesse 令人惊奇的 pix2pix TensorFlow (TF) 实现,这是有据可查的。丹尼尔也在他自己的博客上对 pix2pix 做了很好的介绍。如果你没看过,你应该看看!剧透:还利用了 hello kitty!🐱

备注:

  • pix2pix 的最初实现实际上在 Torch 中,但我更喜欢 TensorFlow。

  • 此外,如果你不知道 pix2pix 是什么或者一般的生成模型,你可以考虑 PCA 或自动编码器,它们的主要目标是重建。不过,与这些模型的主要区别在于,生成模型中的“重建”在生成输出数据时会涉及一些随机性。例如,如果您已经了解自动编码器的基本知识,那么variable auto encoder是一个易于理解的生成模型。

  • Gene 也在为 Pix2Pix 编写教程。我认为它还没有完成,但在他的页面上你可以找到很多其他的展示案例,例如贾斯帕·范·洛宁的神经城也很酷。

  • 我发现的另一个很酷的应用是 Arthur Juliani 做的,他用 pix2pix 在 TensorFlow 中翻拍经典电影。这是我从他的文章中截取的电影后窗的一个经过重新制作的短片:

Top: input video. Middle: pix2pix output. Bottom: original remastered version.

因此,在我克隆了 Daniel 的 repo 并用他的助手脚本处理数据后,主要的挑战是实际的训练本身,因为训练模型可能需要 1-8 个小时,这取决于 GPU 和实际设置,如时期数、图像等..关于 CPU 的培训马上被排除,因为这可能需要几个小时。和往常一样,由于我家里没有带 GPU 的机器(我知道是时候投资这样的 machine^^了),我不得不依赖云服务。

Pix2Pix model graph in TensorFlow.

通常,我的第一选择是 AWS 和它的 G2 实例,但是这次我使用了 FloydHub 来代替。我必须承认,这很酷。我在《黑客新闻》上读到过,想尝试一下。好的一面是,目前当你在那里注册一个账户,你将获得 100 小时的免费 GPU,这是相当可怕的。他们也有一个非常好的 CLI 工具,比起 GUI 我更喜欢它(但是他们也有一个)。训练包含一个命令行的模型也非常容易。到目前为止,我唯一的批评是,在培训结束后,你不能像在 AWS 上那样 ssh 到容器中。有时候,你只需要改变一件事,而不需要重新上传所有的文件,如果你的文件很大,这尤其令人讨厌。不管怎样,从另一方面来说,你省钱了,但是总有好处和坏处。

然后,我终于对我生成的 400 张图片进行了实际的训练。就此而言,320 用于训练,其余用于验证。而且我用不同的历元数(5*,200,400)对模型进行了训练。训练时间因设置而异,从 6 分钟到 7 小时以上不等。

*这更多是出于测试目的。在低位,安格拉·默克尔生成的输出非常像素化和模糊,但你已经可以很好地看到她的表情轮廓。

这是我做的一个实验的一些结果(纪元 200)。如您所见,鉴别器和生成器的学*过程非常嘈杂:

Plot for the discriminator and generator loss.

如果我们查看不同步骤的输出摘要,我们可以看到这可能是由标志引起的:

Output summary for different steps.

增加时期的数量有助于减少一点点的像素化,但是旗帜的问题仍然存在。

Detected facial landmarks and the generated output for epoch 400.

有趣的是,我注意到,根据我旋转头部的方式,旗子的位置也会发生变化。我想为了提高我的成绩,我可能需要用更多的数据来训练它。

为模型服务

训练完模型后,是时候在此基础上用 OpenCV 构建应用程序了。最大的挑战实际上是如何在应用程序中集成这个模型,因为 Daniel 的实现并不真正适合这个。他的实现对于训练来说是高度优化的,例如他使用队列读入数据。这对训练真的很好,但我在为模特服务时没有看到这种必要性。此外,如您所知,在 TF 中保存模型时,会创建很多文件,如检查点、图本身的权重和元数据。但是在生产中,我们不需要任何这些元数据文件,因为我们只是希望我们的模型和它的权重很好地打包在一个文件中(如果你想知道如何做到这一点, Morgan Giraud 写了一个关于这个的很好的教程)。因此,我不得不做了相当多的逆向工程,使它更适用于应用程序。

注:从 TF 1.0 开始,我们也可以使用[tf.saved_model](https://www.tensorflow.org/api_docs/python/tf/saved_model)保存模型。这是使用 TensorFlow 服务时的首选方式。但是,这种方法也会创建多个文件。通常,您会得到一个包含模型的图形定义的save_model.pb和一个保存其权重的variables文件夹。

如果你喜欢这个职位给我一个❤️.这是我第一个将深度学*用于艺术的项目。我还有一些想法想要解决。敬请关注。在 Medium Dat Tran 或 twitter @datitran 上关注我,了解我的最新作品。

脸书研究中心刚刚发表了一篇关于学*层级表征的精彩论文

原文:https://towardsdatascience.com/facebook-research-just-published-an-awesome-paper-on-learning-hierarchical-representations-34e3d829ede7?source=collection_archive---------3-----------------------

学*分层表示的庞加莱嵌入

Arxiv 链接:https://arxiv.org/abs/1705.08039

在初步阅读后,我的一位教授说:

这个想法很有趣,结果好得令人难以置信。

这是我给很多人看结果时他们的反应。

首先,我将向你展示我在 WordNet 的一部分上得到的结果,这样上面的不可行性图片就淡化了一点:

WordNet embeddings for Mammal (only three levels)

我只用过三级:

  • 黑色一号在 0 级
  • 红色的在第一层
  • 绿色的在第二层。

我觉得结果不错。

在我以前的一篇文章中,跨语言单词嵌入是什么?,我解释了单词嵌入。它们可以用于不同的任务,如信息检索、情感分析和无数其他任务。

类似地,我们可以嵌入图,并有像 node2vec 这样的方法,潜在空间嵌入可以帮助我们表示图,并随后进行社区检测和链接预测。
让我们从最初的 node2vec 论文开始研究这个问题→

在 node2vec 中,我们学*了节点到低维特征空间的映射,该映射最大化了保存节点的网络邻域的可能性。

像 word2vec 嵌入一样,我们可以使用 node2vec 嵌入来预测新的链接。假设我们有一个社交网络的数据,现在当我们嵌入节点时,通过一些距离度量,我们看到两个节点(用户)有一个小的距离,然后我们可以建议用户成为社交网络上的朋友。可能发生这种情况的一种情况是,当用户 2 是社交网络的新用户,并且获得与用户 1 相似的朋友时,给定重叠的朋友(图中的边),用户 2 和用户 1 彼此认识的机会增加。

node2vec 嵌入有两个主要方面:

能够学*将来自相同网络社区的节点紧密嵌入在一起的表示,以及学*共享相似角色的节点具有相似嵌入的表示

Source: Google Images

现在考虑表示分层数据的情况,分层数据的结构像树一样

基于直觉,我们可以把它比作双曲线。
根居中,叶向外展开。

Source: Google Images

这一事实被报纸所利用:

为了利用这种结构特性来学*更有效的表示,我们建议不在欧几里得空间中而是在双曲空间中计算嵌入,即具有恒定负曲率的空间。非正式地,双曲空间可以被认为是树的连续版本,因此它自然地被装备来建模分层结构。

他们使用庞加莱球模型作为双曲空间的模型,因为它非常适合基于梯度的优化,因此也适合反向传播。

当然,当你谈论一个不同的空间时,距离的度量是不同的。在庞加莱球模型的情况下,两点uv之间的双曲线距离由下式给出:

Source: Original paper

其中||x||是欧几里德范数。如果你看到维基百科给出的公式,你可能会注意到1已经取代了|r|,因为作者只取了一个半径为1的球。

现在,为了训练模型,我们基于这个距离创建一个优化函数,类似于 Mikolov 等人使用的负采样。

Source: Original paper

然后反向传播我们的方法来更新嵌入。

∇e =(∂l(θ)/∂d(θ,x))*(∂d(θ,x)/∂d(θ)

第一部分已经知道了,他们已经给出了第二部分的公式:

Source: Original Paper

他们使用了一个小技巧,这样在更新后嵌入的内容不会比模型大。为此他们部署了以下投影:

Source: Original Paper

然后,它们通过以下规则更新嵌入:

Source: Original Paper

结果

这是最有趣的部分

Source: Original Paper

我们可以看到,该模型在 5 维空间中实现的效果优于欧几里德模型在 200 维空间中实现的效果。

我希望你对结果感到敬畏。

TL;博士

他们使用双曲空间来嵌入分层数据的节点,并取得了一些超级棒的结果。

你可以在 twitter 上关注我,地址是 @nishantiam ,我在 github 上的地址是 @nishnik

脸书,告诉我该怎么做!

原文:https://towardsdatascience.com/facebook-tell-me-what-to-do-168b1e028880?source=collection_archive---------10-----------------------

在围绕侵犯隐私和#deleteFacebook 运动的丑闻中,我发现自己感到兴奋,而不是不安。

Mirror mirror on the wall

我相信真理和意义——只是我还没能识别它们。这就是为什么十几岁的时候,我梦想成为一名物理学家,提出一个描述一切事物的公式。我已经放弃了这个想法。)当围绕大数据的讨论让我从艺术转向 IT 和数据科学时,我对自己的能力产生了怀疑。大数据的承诺是,我们可以知道一切,即使我们可能永远也不会理解它。

多年后,我们在这里用数据销售产品,寻找爱人,赢得选举。数据就是力量。而大权力是可怕的。因此,我们努力限制这种权力,声明数据应该受到保护,并将隐私视为一项基本人权。

(我的祖父母更关心食物和其他东西。)

Google n-gram

当我们不知道这种力量为谁服务的时候,或者有时我们太了解它的时候,这种力量就特别可怕。如果你不是付费的顾客,那么你可能就是产品。当谈到脸书时,我认为不应该是这样。可以为用户提供真正的价值,从而使个人成为客户——挑战将是设计最好的以用户为中心的数据产品。

作为又一个困惑的千禧一代,我真的需要一些见解。我已经知道我会在霍格沃茨的哪个房间,哪个性别,哪个城市角色和死去的天才,但是我发现这些信息很难应用到现实生活的决定中。你为什么不给我一些更有说服力的证据?是的,我会为此付出代价。(我的意思是,我曾经付钱给一位名叫劳拉的在线占星家,她在自己的网站上使用漫画。有满月折扣或 smth。# no regets)

大数据可以成为更好地了解自我和个人成长的工具。没有人比像脸书这样的大型互联网公司更适合提供这种服务,这些公司已经收集个人数据十多年了。所以不用感谢你的“下载数据”按钮。我宁愿你以对我有利的方式使用我的数据,如果你搞砸了,就去找下一个提供商。

脸书的开源强化学*平台——深度探索

原文:https://towardsdatascience.com/facebooks-open-source-reinforcement-learning-platform-a-deep-dive-313a3d9d528?source=collection_archive---------13-----------------------

脸书决定开源他们创建的平台,以解决他们正在研究的规模的端到端强化学*问题。所以我当然要试试这个。)让我们一起来看看他们是如何安装的,以及您自己应该做些什么来让它工作。

我开始创建一个全新的 Ubuntu 18.10 安装

还测试并验证了在 Linux 的 Windows 子系统上工作

安装 Anaconda

让我们从安装 Anaconda 开始,这很容易通过导航到位于https://conda.io/docs/user-guide/install/index.html的文档来完成,然后我们可以找到到 Linux 安装程序https://www.anaconda.com/download/#linux的链接,这将为我们提供安装程序脚本:https://repo . Anaconda . com/archive/Anaconda 3-5 . 3 . 0-Linux-x86 _ 64 . sh .

我们可以通过运行以下命令来下载并运行它:

curl https://repo.anaconda.com/archive/Anaconda3-5.3.0-Linux-x86_64.sh -o conda.sh
bash conda.sh

然后按照安装程序的步骤安装 Anaconda

完成后,通过以下方式将 conda 安装添加到您的PATH变量:

echo 'export PATH="$PATH":/home/<YOUR_USER>/anaconda3/bin' >> ~/.bashrc
. ~/.bashrc

注意:对于 Python 3 版本,anaconda 的默认安装是/home/ubuntu/anaconda3

为我们的 Horizon 安装配置 Anaconda

脸书地平线需要几个特定软件的通道,我们可以很容易地将它们添加到 anaconda 中:

conda config --add channels conda-forge # ONNX/tensorboardX
conda config --add channels pytorch

安装 Horizon

要深入了解如何安装 Horizon,请查看 Git repo:https://github . com/Facebook research/Horizon/blob/master/docs/installation . MD

git clone https://github.com/facebookresearch/Horizon.git
cd Horizon/
conda install `cat docker/requirements.txt` # wait till it solved the environment, then select y
source activate base # Activate the base conda environmentpip install onnx # Install ONNX
export JAVA_HOME="$(dirname $(dirname -- `which conda`))" # Set JAVA_HOME to anaconda installation
cd # Go back to root# Install Spark 2.3.1
wget http://www-eu.apache.org/dist/spark/spark-2.3.1/spark-2.3.1-bin-hadoop2.7.tgz
tar -xzf spark-2.3.1-bin-hadoop2.7.tgz
sudo mv spark-2.3.1-bin-hadoop2.7 /usr/local/sparkexport PATH=$PATH:/usr/local/spark/bin # add to PATH so we can find spark-submit# Install OpenAI Gym
pip install "gym[classic_control,box2d,atari]"# Build Thrift Classes
cd Horizon/
thrift --gen py --out . ml/rl/thrift/core.thrift# Build Horizon
pip install -e . # we use "-e" for "ephemral package" which will instantly reflect changes in the package

地平线(全球概览)

介绍

Horizon 是一个端到端平台,其中“包括模拟环境的工作流,以及用于预处理、培训和导出生产模型的分布式平台。”——(消息来源)

从阅读文件中,我们可以了解到该平台是基于以下考虑而创建的:

  • 高效处理大型数据集的能力
  • 能够自动高效地预处理数据
  • 竞争算法性能
  • 发布前的算法性能评估
  • 服务于生产的柔性模型
  • 平台可靠性

这听起来对我来说太棒了,所以让我们从如何利用这个平台开始,然后我们可以更深入地了解它的工作原理。

对于强化学*中用到的一些术语,可以随时查看我之前的 博文 了解一下。

入门指南

开始使用 Horizon 就像检查他们编写的用法文档一样简单。这包括以下步骤

  1. 创建培训数据
  2. 将数据转换为时间线格式
  3. 创建标准化参数
  4. 训练模型
  5. 评估模型

地平线—批量 RL(深潜)

现在,我们知道了 Horizon 平台的总体概念,让我们按照使用文档中所写的那样运行不同的步骤,并深入了解它们,发现幕后发生的事情。让我们从创建训练数据开始。

1.创建培训数据

我们的使用文档列出了我们应该通过以下命令创建训练数据:

# Create a directory where we will put the training data
mkdir cartpole_discrete# Generate training data
python ml/rl/test/gym/run_gym.py -p ml/rl/test/gym/discrete_dqn_cartpole_v0_100_eps.json -f cartpole_discrete/training_data.json

但是这实际上是做什么的呢?打开位于ml/rl/test/gym/中的run_gym.py文件,在main()方法中向我们展示了以下内容:

def main(args):
    parser = argparse.ArgumentParser(
        description="Train a RL net to play in an OpenAI Gym environment."
    )
    parser.add_argument("-p", "--parameters", help="Path to JSON parameters file.")

这向我们展示了当运行命令python ml/rl/test/gym/run_gym.py时,我们能够在控制台中看到我们的脚本的使用情况,运行该命令会导致:

Traceback (most recent call last):
  File "ml/rl/test/gym/run_gym.py", line 611, in <module>
    + " [-s <score_bar>] [-g <gpu_id>] [-l <log_level>] [-f <filename>]"
Exception: Usage: python run_gym.py -p <parameters_file> [-s <score_bar>] [-g <gpu_id>] [-l <log_level>] [-f <filename>]

向我们解释,如果我们给出由我们的-p参数定义的参数文件,它将加载这个 JSON 文件并将其加载到一个名为params的变量中,而如果我们添加-f参数,我们将能够将收集的样本作为一个 RLDataSet 保存到提供的文件中。

main()方法

main 方法现在将继续做几件事情:

# Load our parameters from the json
with open(args.parameters, "r") as f:
    params = json.load(f)# Initialize a dataset variable of type `RLDataset` if the `file_path` parameter is set
#    `file_path`: If set, save all collected samples as an RLDataset to this file.
dataset = RLDataset(args.file_path) if args.file_path else None# Call the method `run_gym` with the parameters and arguments provided
reward_history, timestep_history, trainer, predictor = run_gym(
    params, args.score_bar, args.gpu_id, dataset, args.start_saving_from_episode
)# Save our dataset if provided through the -f parameter
if dataset:
    dataset.save()#  Save the results to a csv if the `results_file_path` parameter is set
if args.results_file_path:
    write_lists_to_csv(args.results_file_path, reward_history, timestep_history)# Return our reward history
return reward_history

运行使用文档python ml/rl/test/gym/run_gym.py -p ml/rl/test/gym/discrete_dqn_cartpole_v0_100_eps.json -f cartpole_discrete/training_data.json中显示的命令后,我们可以在由-f参数定义的training_data.json文件中看到以下结构。

{
    "ds": "2019-01-01",
    "mdp_id": "0",
    "sequence_number": 10,
    "state_features": {
        "0": -0.032091656679586175,
        "1": -0.016310561477682117,
        "2": -0.01312794549150956,
        "3": -0.04438365281404494
    },
    "action": "1",
    "reward": 1.0,
    "action_probability": 1.0,
    "possible_actions": [
        "0",
        "1"
    ],
    "metrics": {
        "reward": 1.0
    }
}

RLDataset 类

这是由-f参数生成的,它将以RLDataset类提供的格式将结果保存到提供的文件中。检查位于ml/rl/training/rl_dataset.py的这个类向我们显示:

"""
Holds a collection of RL samples in the "pre-timeline" format.:param file_path: String Load/save the dataset from/to this file.
"""# === LINES REMOVED ===self.rows.append(
{
    "ds": "2019-01-01",  # Fix ds for simplicity in open source examples
    "mdp_id": str(mdp_id),
    "sequence_number": int(sequence_number),
    "state_features": state_features,
    "action": action,
    "reward": reward,
    "action_probability": action_probability,
    "possible_actions": possible_actions,
    "metrics": {"reward": reward},
}

run_gym()方法

现在我们可以看到这些行被创建并保存在内存中的RLDataset类中。但是实际上是什么在使用它并填充它呢?让我们先来看看我们的run_gym()方法的总体情况:

env_type = params["env"]# Initialize the OpenAI Gym Environment
env = OpenAIGymEnvironment(
    env_type,
    rl_parameters.epsilon,
    rl_parameters.softmax_policy,
    rl_parameters.gamma,
)
replay_buffer = OpenAIGymMemoryPool(params["max_replay_memory_size"])
model_type = params["model_type"]use_gpu = gpu_id != USE_CPU# Use the "training" {} parameters and "model_type": "<MODEL>" model_type
# to create a trainer as the ones listed in /ml/rl/training/*_trainer.py
# The model_type is defined in /ml/rl/test/gym/open_ai_gym_environment.py
trainer = create_trainer(params["model_type"], params, rl_parameters, use_gpu, env)# Create a GymDQNPredictor based on the ModelType and Trainer above
# This is located in /ml/rl/test/gym/gym_predictor.py
predictor = create_predictor(trainer, model_type, use_gpu)c2_device = core.DeviceOption(
    caffe2_pb2.CUDA if use_gpu else caffe2_pb2.CPU, int(gpu_id)
)# Train using SGD (stochastic gradient descent)
# This just passess the parameters given towards a method called train_gym_online_rl which will train our algorithm
return train_sgd(
    c2_device,
    env,
    replay_buffer,
    model_type,
    trainer,
    predictor,
    "{} test run".format(env_type),
    score_bar,
    **params["run_details"],
    save_timesteps_to_dataset=save_timesteps_to_dataset,
    start_saving_from_episode=start_saving_from_episode,
)

run_gym方法似乎在使用我们从 JSON 文件中加载的参数来初始化 OpenAI Gym 环境。因此,让我们打开一个 JSON 文件,运行一个快速的cat ml/rl/test/gym/discrete_dqn_cartpole_v0_100_eps.json向我们展示:

{
  "env": "CartPole-v0",
  "model_type": "pytorch_discrete_dqn",
  "max_replay_memory_size": 10000,
  "use_gpu": false,
  "rl": {
    "gamma": 0.99,
    "target_update_rate": 0.2,
    "reward_burnin": 1,
    "maxq_learning": 1,
    "epsilon": 1,
    "temperature": 0.35,
    "softmax_policy": 0
  },
  "rainbow": {
    "double_q_learning": false,
    "dueling_architecture": false
  },
  "training": {
    "layers": [
      -1,
      128,
      64,
      -1
    ],
    "activations": [
      "relu",
      "relu",
      "linear"
    ],
    "minibatch_size": 64,
    "learning_rate": 0.001,
    "optimizer": "ADAM",
    "lr_decay": 0.999,
    "use_noisy_linear_layers": false
  },
  "run_details": {
    "num_episodes": 100,
    "max_steps": 200,
    "train_every_ts": 1,
    "train_after_ts": 1,
    "test_every_ts": 2000,
    "test_after_ts": 1,
    "num_train_batches": 1,
    "avg_over_num_episodes": 100
  }
}

其中显示了EnvironmentEpsilonSoftmax PolicyGamma parameters都用于启动OpenAIGymEnvironment,其余参数传递给训练器。接下来,run_gym方法还将初始化一个 replay_buffer,创建训练器和预测器。此后它将运行train_sgd方法。

既然我们现在知道了我们的run_gym()方法,让我们进一步看看我们的dataset变量是如何进一步传递的:

  • run_gym()将获取由main()方法传递的方法作为save_timesteps_to_dataset参数
  • run_gym()将把它传递给train_sgd()方法
  • train_sgd()将它传递给train_gym_online_rl()方法。

train_gym_online_rl()方法

现在定义了这个参数后,train_gym_online_rl()方法将通过RLDataset类中定义的insert()方法保存几个变量:

记住 *RLDataset* 类是在文件中定义的:*ml/rl/training/rl_dataset.py**insert*方法定义为:* *RLDataset::insert(mdp_id, sequence_number, state, action, reward, terminal, possible_actions, time_diff, action_probability)**

来源: run_gym.py#L208

来源变量来自run_gym.py输出变量类型描述 i mdp_id string情节(例如游戏的整个播放过程)的唯一 ID EP _ time steps-1 sequence _ numberinteger定义 mdp(例如事件的时间戳)状态中状态的排序。action_to_log 动作string选择的动作名称奖励奖励float此状态下的奖励/动作终端终端bool未使用可能的动作可能的动作list<string>此状态下所有可能的动作列表。请注意,所采取的行动必须出现在此列表中。1.0 action_probability float如果策略是随机的,则采取此操作的概率,否则为空。请注意,我们强烈鼓励使用随机策略,而不是在每个时间步选择最佳行动。这种探索将改善评价,并最终导致更好地了解政策。1 time_diff integer未 Ised?ds string这个数据集的唯一 ID

我们的run_gym.py现在将运行-p文件(例如ml/rl/test/gym/discrete_dqn_cartpole_v0_100_eps.json)中指定的一定数量的剧集,其中它将(当它能够)使用train_gym_online_rl()方法来:

  • 获取可能的操作
  • 采取行动(基于它是否是离散行动类型)
  • 浏览健身房环境并检索next_staterewardterminal变量
  • 基于gym_env.policy变量中的policy定义要采取的 next_action
  • 增加获得的奖励
  • 将观察到的行为插入重放缓冲区
  • 每个train_every_tsreplay_buffer上取下num_train_batches并用这些训练trainer
  • 注意:这个训练器是在[create_trainer()](https://github.com/facebookresearch/Horizon/blob/bbea36948bd409f03ec449be4539bd6bd9006418/ml/rl/test/gym/run_gym.py#L208)方法中创建的,该方法将创建一个 DDPGTrainer、SACTrainer、ParametericDQNTrainer 或 DQNTrainer
  • 每个test_every_ts记录我们的模型在loggeravg_reward_historytimestep_history的表现
  • 记录剧集结束的时间

2.将我们的训练数据转换为时间线格式

在第 2 步中,我们将转换之前以以下格式保存的培训数据:

*{
    "ds": "2019-01-01",
    "mdp_id": "0",
    "sequence_number": 10,
    "state_features": {
        "0": -0.032091656679586175,
        "1": -0.016310561477682117,
        "2": -0.01312794549150956,
        "3": -0.04438365281404494
    },
    "action": "1",
    "reward": 1.0,
    "action_probability": 1.0,
    "possible_actions": [
        "0",
        "1"
    ],
    "metrics": {
        "reward": 1.0
    }
}*

对于他们所谓的timeline格式,这是一种给定一个表(state,action,mdp_id,sequence_number,reward,possible_next_actions)返回强化学*所需的表(mdp_id,state_features,action,reward,next_state_features,next_action,sequence_number,sequence_number_ordinal,time_diff,possible_next_actions)的格式,在 Timeline.scala 中定义,我们可以表示为:

这将执行一个 Spark 作业,通过 Hive 运行一个查询,并将结果返回到一个不同的文件中。

*# Build timeline package (only need to do this first time)
mvn -f preprocessing/pom.xml clean package# Clear last run's spark data (in case of interruption)
rm -Rf spark-warehouse derby.log metastore_db preprocessing/spark-warehouse preprocessing/metastore_db preprocessing/derby.log# Run timelime on pre-timeline data
/usr/local/spark/bin/spark-submit \
  --class com.facebook.spark.rl.Preprocessor preprocessing/target/rl-preprocessing-1.1.jar \
  "`cat ml/rl/workflow/sample_configs/discrete_action/timeline.json`"# Merge output data to single file
mkdir training_data
mv cartpole_discrete_timeline/part* training_data/cartpole_training_data.json# Remove the output data folder
rm -Rf cartpole_discrete_timeline*

执行之后,我们现在可以通过运行head -n1 training_data/cartpole_training_data.json来查看创建的文件:

*{
	"mdp_id": "31",
	"sequence_number": 5,
	"propensity": 1.0,
	"state_features": {
		"0": -0.029825548651835395,
		"1": 0.19730168855281788,
		"2": 0.013065490574540607,
		"3": -0.29148843030554333
	},
	"action": 0,
	"reward": 1.0,
	"next_state_features": {
		"0": -0.02587951488077904,
		"1": 0.0019959027899765502,
		"2": 0.00723572196842974,
		"3": 0.005286388581067669
	},
	"time_diff": 1,
	"possible_next_actions": [1, 1],
	"metrics": {
		"reward": 1.0
	}
}*

有趣的是,Spark 引擎将允许我们利用完全由 CPU 操作运行的分布式集群。GPU 操作将在稍后阶段进行。允许我们完全利用 HDFS 上的一个集群和纯粹用于 GPU 计算的一个集群。

3.正常化

为了减少噪音和更快地训练我们的神经网络,我们使用了“标准化”。Horizon 包含一个工具,该工具可自动分析训练数据集,并为每个要素确定最佳变换函数和相应的归一化参数。

要运行它,可以使用以下命令:

*python ml/rl/workflow/create_normalization_metadata.py -p ml/rl/workflow/sample_configs/discrete_action/dqn_example.json*

打开/ml/rl/workflow/sample_configs/discrete_action/dqn_example.json文件,我们可以看到一个类似的配置文件被传递给我们的健身房环境的主函数:

*{
	"training_data_path": "training_data/cartpole_training_data.json",
	"state_norm_data_path": "training_data/state_features_norm.json",
	"model_output_path": "outputs/",
	"use_gpu": true,
	"use_all_avail_gpus": true,
	"norm_params": {
		"output_dir": "training_data/",
		"cols_to_norm": [
			"state_features"
		],
		"num_samples": 1000
	},
	"actions": [
		"0",
		"1"
	],
	"epochs": 100,
	"rl": {
		"gamma": 0.99,
		"target_update_rate": 0.2,
		"reward_burnin": 1,
		"maxq_learning": 1,
		"epsilon": 0.2,
		"temperature": 0.35,
		"softmax_policy": 0
	},
	"rainbow": {
		"double_q_learning": true,
		"dueling_architecture": false
	},
	"training": {
		"layers": [-1,
			128,
			64, -1
		],
		"activations": [
			"relu",
			"relu",
			"linear"
		],
		"minibatch_size": 256,
		"learning_rate": 0.001,
		"optimizer": "ADAM",
		"lr_decay": 0.999,
		"warm_start_model_path": null,
		"l2_decay": 0,
		"use_noisy_linear_layers": false
	},
	"in_training_cpe": null
}*

因此,让我们打开ml/rl/workflow/create_normalization_metadata.py文件,在这里我们可以立即看到它的 main 方法以一个名为create_norm_table的函数开始。

create_norm_table()方法将接受参数(上面的 json)并利用norm_paramstraining_data_pathcols_to_normoutput_dir配置来创建规范化表。

这个规范化表是通过检查要规范化的列(在上面的 json 中是列state_features)构建的,它将通过get_norm_metadata()函数获取元数据。该函数将开始从我们的数据集中读取数据,并开始对要素及其值进行采样。一旦它收集到足够的样本(如norm_params["num_samples]配置所定义的),它将继续。

4.训练模型

由于现在一切都经过预处理,数据也标准化了,我们准备开始训练我们的模型。为此,我们可以运行以下命令:

*python ml/rl/workflow/dqn_workflow.py -p ml/rl/workflow/sample_configs/discrete_action/dqn_example.json*

它将利用 dqn_workflow.py 文件选择正确的教练来训练它的模型。运行此命令将导致:

*INFO:__main__:CPE evaluation took 0.23067665100097656 seconds.
INFO:__main__:Training finished. Processed ~3961 examples / s.
INFO:ml.rl.workflow.helpers:Saving PyTorch trainer to outputs/trainer_1543773299.pt
INFO:ml.rl.workflow.helpers:Saving Caffe2 predictor to outputs/predictor_1543773299.c2
INFO:ml.rl.caffe_utils:INPUT BLOB: input.1\. OUTPUT BLOB:11
INFO:ml.rl.training.dqn_predictor:Generated ONNX predict net:
INFO:ml.rl.training.dqn_predictor:name: "torch-jit-export_predict"
op {
  input: "input.1"
  input: "1"
  input: "2"
  output: "7"
  name: ""
  type: "FC"
}
op {
  input: "7"
  output: "8"
  name: ""
  type: "Relu"
}
op {
  input: "8"
  input: "3"
  input: "4"
  output: "9"
  name: ""
  type: "FC"
}
op {
  input: "9"
  output: "10"
  name: ""
  type: "Relu"
}
op {
  input: "10"
  input: "5"
  input: "6"
  output: "11"
  name: ""
  type: "FC"
}
device_option {
  device_type: 0
  device_id: 0
}
external_input: "input.1"
external_input: "1"
external_input: "2"
external_input: "3"
external_input: "4"
external_input: "5"
external_input: "6"
external_output: "11"INFO:ml.rl.preprocessing.preprocessor_net:Processed split (0, 4) for feature type CONTINUOUS
INFO:ml.rl.preprocessing.preprocessor_net:input# 0: preprocessor_net.py:287:Where_output0*

5.评估模型

模型是训练出来的,但是我们怎么测试呢?这可以通过附带的 cartpole 实验评估脚本来完成:

*python ml/rl/test/workflow/eval_cartpole.py -m outputs/predictor_<number>.c2def main(model_path):
    predictor = DQNPredictor.load(model_path, "minidb", int_features=False) env = OpenAIGymEnvironment(gymenv=ENV) avg_rewards, avg_discounted_rewards = env.run_ep_n_times(
        AVG_OVER_NUM_EPS, predictor, test=True
    ) logger.info(
        "Achieved an average reward score of {} over {} evaluations.".format(
            avg_rewards, AVG_OVER_NUM_EPS
        )
    ) def parse_args(args):
    if len(args) != 3:
        raise Exception("Usage: python <file.py> -m <parameters_file>") parser = argparse.ArgumentParser(description="Read command line parameters.")
    parser.add_argument("-m", "--model", help="Path to Caffe2 model.")
    args = parser.parse_args(args[1:])
    return args.model*

这将使用给定的模型运行我们的健身房环境,并以对数线的形式返回 x 评估的奖励分数。

这方面的一个例子是:

*INFO:__main__:Achieved an average reward score of 9.34 over 100 evaluations.*

6.通过 Tensorboard 可视化

现在,最后一步是通过 Tensorboard 可视化一切,我们可以这样开始:

*tensorboard --logdir outputs/*

这将产生一个绑定到 https://localhost:6006 的进程。

渲染我们训练过的模型

一旦我们训练了我们的模型,我们就能够通过 Tensorboard 可视化它。然而,我们也希望能够在评估模型的同时查看模型的运行情况。为了能够从这开始,首先安装先决条件+依赖项,如下所示:如何在 Windows 上用 Javascript 运行 open ai Gym

我们现在要做的另一件事是更改eval_cartpole.py文件,并在run_ep_n_times()方法中添加render=True,使其看起来像这样:

*avg_rewards, avg_discounted_rewards = env.run_ep_n_times(
    AVG_OVER_NUM_EPS, predictor, test=True, render=True
)*

当我们现在通过以下方式重新推出评估工具时:

*python ml/rl/test/workflow/eval_cartpole.py -m outputs/predictor_<number>.c2*

我们将能够看到我们的流程产生:

faced:使用深度学*的 CPU 实时人脸检测

原文:https://towardsdatascience.com/faced-cpu-real-time-face-detection-using-deep-learning-1488681c1602?source=collection_archive---------4-----------------------

在没有 GPU 的情况下,有可能实现具有实时性能的对象检测模型吗? faced是一个概念证明,可以为 CPU 上运行于实时 的单个类对象(在本例中为人脸)构建自定义对象检测模型。

Face detection task

有什么问题?

在许多情况下,需要进行单个类对象检测。这意味着我们想要检测图像中属于特定类别的所有对象的位置。例如,我们可以为人脸识别系统检测人脸,或者为行人跟踪检测人。

此外,大多数时候我们希望实时运行这些模型为了实现这一点,我们有一个以速率 x 提供样本的图像馈送,我们需要一个模型以小于速率 x 运行每个样本。然后,一旦图像可用,我们就可以对其进行处理。

如今,解决这一任务(以及计算机视觉中的许多其他任务)最容易获得和使用的解决方案是对先前训练的模型执行(在大型数据集上训练的一般标准模型,如在 Tensorflow HubTF 对象检测 API 中找到的数据集)

有许多经过训练的对象检测架构(例如 FasterRCNN、SSD 或 YOLO)在运行于 GPU 上的实时性能内实现了令人印象深刻的准确性。

Extracted from SSD paper here

GPU 很贵,但在训练阶段是必须的。然而,据推断用专用 GPU 来实现实时性能是不可行的。如果没有 GPU,所有通用对象检测模型(如上所述)都无法实时运行。

那么,如何重新审视单类对象的对象检测问题,以达到实时性能但在 CPU 上?

主要观点:简单的任务需要较少的可学*的特征

上面提到的所有架构都是为检测多个对象类而设计的(在 COCOPASCAL VOC 数据集上训练)。为了能够将每个边界框分类到其适当的类别,这些架构需要大量的特征提取。这意味着大量的可学*参数,大量的过滤器,大量的层。换句话说,这个网络很大。

如果我们定义更简单的任务(而不是多类包围盒分类),那么我们可以认为网络需要学*更少的特征来执行任务。检测图像中的人脸显然比检测汽车、人、交通标志和狗(都在同一模型内)更简单。深度学*模型为了识别人脸(或任何单个类对象)所需的特征量将少于同时检测几十个类所需的特征量。执行第一项任务所需的信息少于后一项任务。

单一类别对象检测模型将需要较少的可学*特征。参数越少意味着网络会越小。较小的网络运行速度更快,因为它需要更少的计算。

那么,问题是:在保持准确性的情况下,我们可以在 CPU 上实现多小的实时性能?

这是faced的主要概念:建立尽可能小的网络,在保持准确性的同时(希望)在 CPU 中实时运行。

建筑

faced是两个神经网络的集合,都是使用 Tensorflow 实现的。

主网络

faced主建筑大量基于 YOLO 的建筑。基本上,它是一个完全卷积的网络(FCN ),通过一系列卷积层和池层(不涉及其他层类型)运行 288x288 输入图像。

卷积层负责提取空间感知特征。汇集层增加了后续卷积层的感受域。

该架构的输出是一个 9x9 的网格(相对于 YOLO 的 13x13 网格)。每个网格单元负责预测该单元内是否有人脸(相对于 YOLO,每个单元可以检测多达 5 个不同的对象)。

每个网格单元有 5 个关联值。第一个是包含面部中心的单元的概率 p 。另外 4 个值是被检测人脸的( x_center,y_center,width,height) (相对于单元格)。

Main architecture

确切的架构定义如下:

  • 2x[288 x288 图像上的 8 个过滤卷积层]
  • 最大池(288x288 到 144x144 功能图)
  • 2x[144 x144 特征图上的 16 个过滤卷积层]
  • 最大池(144x144 到 72x72 功能图)
  • 2x[72x 72 特征图上的 32 个过滤卷积层]
  • 最大池(72x72 到 36x36 功能图)
  • 2x[36x 36 特征图上的 64 个过滤卷积层]
  • 最大池(36x36 到 18x18 功能图)
  • 2x[18x 18 特征图上的 128 过滤卷积层]
  • 最大池(18x18 到 9x9 功能图)
  • 4x[9x 9 特征图上的 192 滤波卷积层]
  • 5 在 9x9 特征图上过滤卷积层,以形成最终网格

所有激活功能都是leaky_relu

faced has 6993517 个参数。YOLOv2 有 51,000,657 个参数。它的大小是 YOLO 大小的 13%!

辅助网络

( x_center,y_center,width,height) 主网络的输出不如预期的准确。因此,实现了一个小的 CNN 网络,将包含人脸的小图像(用主架构输出裁剪)作为输入,并输出人脸的地面真实边界框的回归。

The network takes a crop containing a face and predicts the correct bounding box

它唯一的任务是补充和改进主架构的输出坐标。

该网络的具体架构无关紧要。

资料组

两个网络都是在宽脸数据集上训练的。

WIDER FACE multiple scenarios

“更宽的人脸数据集是人脸检测基准数据集[…]。我们选择了 32,203 张图像,并标记了 393,703 张在比例、姿态和遮挡方面具有高度可变性的人脸,如样本图像中所描绘的那样。”

培养

训练是在 Nvidia Titan XP GPU 上进行的。培训时间大约花了 20 个小时。使用批量标准化技术来帮助收敛,并使用漏失(40%比率)作为正则化方法来避免过拟合。

推理和非最大抑制

当使用faced进行推理时,首先将图像尺寸调整为 288x288,以便输入网络。该图像位于 FCN 下方,给出了上面描述的 9x9 网格输出。

每个单元格有一个包含图像的概率 p 。通过可配置的阈值过滤单元格(即仅保留具有 p > t 的单元格)。对于那些保留的单元格,使用单元格的( x_center,y_center,width,height)定位人脸。

在某些情况下,多个细胞可以竞争同一张脸。让我们假设一个面部中心位于 4 个细胞相交的精确位置。这 4 个单元可能具有高的 p (在单元内包含面中心的概率)。如果我们保留所有的单元并投影每个单元的面坐标,那么我们将会看到相同的面周围有 4 个相似的边界框。这个问题是通过一种叫做 非最大抑制 的技术解决的。结果如下图所示:

Non max suppression example.

表演

faced在推论上能够达到以下速度:

考虑到 YOLOv2 在 i5 2015 MBP 上甚至不能达到 1FPS,这已经很不错了。

结果

来看看成果吧!

**

faced on images

现在我们来看一下facedHaar Cascades 的对比,Haar Cascades 是一种不使用深度学*的计算机视觉传统方法。这两种方法在相似的速度性能下运行。faced显示出显著的更高的准确性。

**

Haar Cascade [left] vs faced [right]

如何使用 faced?

faced是一个非常简单的程序,既可以嵌入 Python 代码,也可以作为命令行程序使用。

请访问 github repo 获取更多说明:

* [## iitzco/faced

🚀 😏使用深度学*的*实时 CPU 人脸检测- iitzco/faced

github.com](https://github.com/iitzco/faced)

喜欢这个项目?在项目的回购上留下⭐!

结论

faced是一个概念证明,在这些模型对您的问题来说是多余的并且涉及到性能问题的场景中,您不需要总是依赖通用训练模型。不要高估花时间设计专门针对你的问题的定制神经网络架构的能力。这些特定的网络将是比一般网络更好的解决方案。*

使用人工智能的面部情感检测:用例

原文:https://towardsdatascience.com/facial-emotion-detection-using-ai-use-cases-248b932200d6?source=collection_archive---------7-----------------------

不同的公司已经广泛使用情绪分析来衡量消费者在数字世界中对其产品或品牌的情绪。然而,在离线世界中,用户也与零售店、陈列室等中的品牌和产品进行交互。并且在这种设置下自动测量用户反应的解决方案仍然是一项具有挑战性的任务。使用人工智能从面部表情进行情感检测可以成为自动测量消费者对其内容和品牌的参与度的可行替代方法。

ParallelDots ,我们结合了心理学、人类表情和人工智能科学,自动识别每个人脸上的不同情绪。我们的面部情绪检测算法可以实时识别七种不同类型的情绪状态。

在本帖中,我们将讨论如何使用这样的技术来有效地解决各种现实世界的用例。

1.让汽车更加安全和个性化

世界各地的汽车制造商越来越注重让汽车更加个性化,让我们驾驶起来更加安全。在追求构建更多智能汽车功能的过程中,制造商使用人工智能来帮助他们理解人类情感是有意义的。使用面部情绪检测的智能汽车可以在司机昏昏欲睡时提醒他。

美国交通部声称,大约 95%的致命交通事故都是由驾驶失误造成的。面部情绪检测可以发现困倦之前面部微表情的微妙变化,并向司机发送个性化警报,要求他停下来喝杯咖啡,改变音乐或温度。

2.面试中的面部情绪检测

候选人和面试官的互动容易受到多种判断和主观性的影响。这种主观性使得很难确定候选人的个性是否适合这份工作。识别候选人想说什么是我们力所不及的,因为有多层的语言解释、认知偏差和介于其间的语境。这就是人工智能的用武之地,它可以测量候选人的面部表情,以捕捉他们的情绪,并进一步评估他们的性格特征。

值得注意的是,联合利华已经开始将这项技术纳入他们的招聘流程。有了这项技术,招聘人员将能够知道,比如说,被面试者的总体信心水平,并决定这个候选人是否能够在面对客户的工作中表现出色。同样,通过测量候选人在回答过程中的情绪变化,并将其与该领域的大量可用知识相关联,可以发现候选人是否诚实地回答了所有问题。

员工的士气也可以通过这项技术在工作中保持和记录互动来感知。作为一种人力资源工具,它不仅可以帮助设计招聘策略,还可以帮助设计人力资源政策,使员工发挥最佳绩效。

3.视频游戏测试

电子游戏是针对特定的目标受众而设计的。每个视频游戏都旨在唤起用户的特定行为和情绪。在测试阶段,用户被要求在给定的时间内玩游戏,他们的反馈被整合到最终产品中。使用面部情绪检测可以帮助了解用户在玩游戏时的实时情绪,而无需手动分析整个视频。

这种产品反馈可以通过分析用户的实时反馈并检测他的面部情绪来获得。虽然沮丧和愤怒的感觉在高级视频游戏中很常见,但利用面部情绪检测将有助于了解在游戏中的什么时候体验了哪些情绪。也有可能是在游戏过程中观察到了一些意想不到的或者不良的情绪。从体验过游戏的用户那里获取反馈可能是低效的。这是因为通常很难用语言来表达一段经历。此外,用户可能不记得他们在游戏的不同部分到底经历了什么。面部情绪检测是一种超越口头或书面反馈并欣赏用户体验的实用方法。当反馈以这种形式出现时,就用户体验而言,它变得真正无干扰。同时,这样的反馈比其他形式更可靠。

4.市场调查

传统上,市场研究公司采用口头方法,如调查,来发现消费者的需求。然而,这种方法假设消费者可以口头表达他们的偏好,并且所陈述的偏好对应于可能不总是正确的未来行为。

市场研究行业的另一种流行方法是采用行为方法,在与品牌或产品互动时观察用户的反应。这种方法被认为比口头方法更客观。行为方法使用用户与产品互动的视频,然后人工分析这些视频,观察用户的反应和情绪。然而,随着样本量的增加,这种技术会很快变得非常耗费人力。面部情绪识别可以通过允许市场研究公司自动测量每时每刻的面部表情(面部编码)并汇总结果来拯救人类。

用技术检测情绪是一项具有挑战性的任务,但机器学*算法已经显示出巨大的前景。使用 ParallelDots 的面部情绪检测 API,客户可以实时处理图像和视频,以监控视频馈送或自动进行视频分析,从而节省成本并改善用户的生活。这种 API 的定价基于一种现收现付的模式,允许您在扩大规模之前测试该技术。

面部情绪检测只是视觉智能自动分析视频和图像的一部分。点击此处查看图片中的面部表情。

点击此处了解更多关于病毒检测 API 的不同使用案例,可用于增强图像质量。

我们希望你喜欢这篇文章。请注册一个免费的 ParallelDots 账户,开始你的 AI 之旅。你也可以在这里查看 parallel dots API的演示。

此处阅读原文

教程:使用深度学*和 OpenCV(面部标志检测)的自拍滤镜

原文:https://towardsdatascience.com/facial-keypoints-detection-deep-learning-737547f73515?source=collection_archive---------4-----------------------

这是一个关于如何构建一个 python 应用程序的教程,该应用程序可以通过找到面部关键点(15 个独特的点)在检测到的脸上放置各种太阳镜(我称它们为“自拍过滤器”)。这些关键点标记了面部的重要区域——眼睛、嘴角、鼻子等。

项目描述

OpenCV 经常在实践中与其他机器学*和深度学*库一起使用,以产生有趣的结果。在 Keras 中使用卷积神经网络(CNN)和 OpenCV——我建立了几个自拍过滤器(非常无聊的)。

面部关键点可用于各种机器学*应用,从面部和情感识别到商业应用,如 Snapchat 推广的图像过滤器。

您可以在此访问完整的项目代码:

[## acl21/Selfie_Filters_OpenCV

更新]:我将不再关注与回购相关的问题或邮件,因为我目前非常忙…

github.com](https://github.com/acl21/Selfie_Filters_OpenCV)

工作示例

代码要求

代码在 Python 版本中,使用 OpenCV 和 Keras 库。

跟随这篇中帖在 Python 3 中安装 OpenCV 和 Keras。

数据描述

Kaggle 上的这个数据集允许我们训练一个模型,在给定一张有脸的图像的情况下检测面部关键点。

它是由蒙特利尔大学的 Yoshua Bengio 博士提供的。

数据集中的每个数据点包含按顺序的图像的空间分隔的像素值,并且数据点的最后 30 个值表示面上关键点的 15 对坐标。

所以我们只需要训练一个 CNN 模型来解决一个经典的深度学*回归问题。点击查看回归问题的损失函数列表。

代码解释

步骤 1:训练卷积神经网络模型

1.1 定义模型

为了方便起见,我们首先在一个单独的 python 文件中定义模型架构—my _ CNN _ model . py

我们编写一个创建网络架构的方法。

1.2 编译、保存、适配和加载

我们现在编写方法来编译、保存、拟合和加载模型

1.3 模型构建器(包装器)

我们现在编写一个模型构建器,它加载数据并调用上述方法。

第二步:初始化东西

我们现在创建一个新的 python 文件— shades.py ,我们在其中编写代码来读取网络摄像头输入,检测人脸,使用我们构建的 CNN 模型,等等。

步骤 3:检测输入中的人脸

一旦您开始从网络摄像头读取输入,使用我们之前初始化的级联分类器对象检测输入中的人脸。

步骤 4:创建过滤器开关触发器

在这里,我使用了一个蓝色的瓶盖作为过滤器开关。为了检测蓝帽,我们编写代码来寻找图像中的蓝色轮廓。我们传递我们在步骤 2 中定义的 blueLower blue upperHSV 范围。

一旦我们创建了 blueMask ,即应该在视频中找到蓝色的东西,我们使用 OpenCV 的cv2 . find contours()方法来找到轮廓。

上面的代码检查框架中是否有轮廓(蓝色瓶盖),一旦发现,它检查轮廓的中心是否接触到我们在这一步中创建的“下一个过滤器”按钮。如果被触摸,我们更改过滤器(将 过滤器索引 增加 1)

步骤 5:使用模型检测面部关键点

我们使用之前初始化的面部层叠来定位帧中的面部。然后,我们对每一张脸进行循环,以预测面部关键点。

在我们将检测到的人脸传递给模型之前,我们有必要对输入进行归一化,因为归一化的图像是我们的模型所训练的图像,将其大小调整为 96 x 96 图像,因为这是我们的模型所期望的。上面的代码也是如此。

第六步:使用面部关键点在脸上添加阴影

一旦我们检测到面部关键点,我们就可以用它们来做各种很酷的事情。例如,您可以使用鼻子关键点来添加小胡子,嘴唇关键点来添加颜色,等等。

这里,我们使用了 4 个关键点来配置脸部阴影的宽度和高度。并且,face _ resized _ color有阴影并贴图回 face _ resized _ color 2有关键点并贴图回 帧 2 。然后我们把它们都展示出来。

最后,我们只是清理东西。

您可以在此访问完整的项目代码:

[## acl21/Selfie_Filters_OpenCV

更新]:我将不再关注与回购相关的问题或邮件,因为我目前非常忙…

github.com](https://github.com/acl21/Selfie_Filters_OpenCV)

执行

1。下载数据

这里下载数据,并把它放在项目目录中名为‘data’的文件夹中。确保“数据”文件夹包含— training.csvtest.csv

2。建立 CNN 模型

> python model_builder.py

这将调用my _ CNN _ model . py,因此请确保您的项目目录中有该文件。

4。运行引擎文件

> python shades.py

5。抓起一个蓝色瓶盖

玩得开心点。

结论

在本教程中,我们建立了一个深度卷积神经网络模型,对面部关键点数据进行训练。然后,我们使用该模型来预测在输入网络摄像头数据中检测到的面部的面部关键点。我们还使用轮廓创建了一个开关,它允许我们通过手势迭代其他过滤器。我鼓励您调整模型架构,亲自看看它是如何影响关键点检测的。

这个数据只有 15 个关键点,还有其他几个数据集在面部标注了超过 30 个关键点。

Awesome right?

面部关键点检测的应用:

  • 面部特征检测改善了面部识别
  • 男性/女性区别
  • 面部表情区分
  • 头部姿态估计
  • 面部变形
  • 虚拟改造
  • 面部置换

希望这个教程是有趣的。谢谢你阅读它。

活也让别人活!

使用 Dlib + python 绘制面部地图(地标)

原文:https://towardsdatascience.com/facial-mapping-landmarks-with-dlib-python-160abcf7d672?source=collection_archive---------5-----------------------

在照片或视频中识别人脸非常酷,但这不足以创建强大的应用程序,我们需要更多关于人脸的信息,如位置,嘴是张开还是闭合,眼睛是睁开还是闭合,抬头等等。在这篇文章中,我将(以一种快速而客观的方式)向你展示 Dlib,一个能够给你 68 分(landkmarks)的人脸库。

什么是 Dlib?

这是一个具有预训练模型的地标面部检测器,dlib 用于估计 68 个坐标(x,y)的位置,这些坐标映射了一个人脸上的面部点,如下图所示。

这些点是从使用了 iBUG300-W 数据集的预训练模型中确定的。

给我看看代码!

在这个“Hello World”中,我们将使用:

在本教程中,我将用 dlib 编写一个简单的例子。我们正在识别和绘制图像上的人脸点,在以后的文章中,我会详细介绍这个漂亮的库的使用。

正在安装依赖项。

pip install numpy opencv-python dlib imutils

从我们将要处理的图像捕获开始,我们将使用 OpenCV 在一个“无限”循环中捕获图像的网络摄像头,从而给人一种观看视频的感觉。

运行您的脚本,并确保您的网络摄像头的图像被捕获(它会为您打开一个窗口,显示网络摄像头的图像)。

拿到照片后,让我们来创造奇迹吧。

提醒:我们正在使用已经训练好的模型,我们将需要下载文件 shape _ predictor _ 68 _ face _ landmarks . dat,你可以在这里找到它。

之后,只需运行脚本,您就可以在 Dlib 中运行“hello_world ”,在以后的文章中,我将详细介绍如何提取图像中人脸的更多信息。

所有代码都在我的 github 上。

TKS。

面部识别和对抗性攻击

原文:https://towardsdatascience.com/facial-recognition-adversarial-attack-analytics-applied-on-wordpress-com-32b7622b8fb1?source=collection_archive---------3-----------------------

面部识别系统已经成为主流技术。最*,苹果三星都推出了具有面部识别功能的手机。上周,美国运输安全管理局启动了一项名为的试点项目,允许美国公民基于面部识别作为主要验证系统快速通过机场。中国在使用面部识别进行身份认证方面处于世界领先地位。《经济学家》杂志估计,数百万中国人已经在智能手机上刷脸授权支付。随着使用面部识别进行身份验证的想法变得越来越流行,攻击这种系统的想法也越来越流行。

由于深度神经网络(DNNs)的使用,今天的面部识别系统非常接*人类的表现。DNN 的一个弱点是对抗性攻击。

什么是对抗性攻击?

对抗性攻击试图误导网络来预测错误的类别。开创性的论文(赛格迪等。艾尔。2014 arXiv:1312.6199v4)展示了人眼察觉不到的看似微小的扰动如何扰乱神经网络的例子。

All Images to the right are classified as Ostrich. (IC: https://arxiv.org/pdf/1312.6199.pdf))

在上述示例中,DNN 能够成功识别左侧面板图像中的物体。然而,如果引入了精心选择的扰动(中图),则新图像(右图)被错误分类。扰动非常小,以至于左面板和右面板用肉眼看起来完全一样。

如果一个人试图用别人的护照进入一个国家,他只需要稍微改变一下他的面部特征,DNN 的面部识别系统就会让他通过。

为什么世界级的 dnn 那么容易被忽悠?

首先让我确认以上结果不是来自低精度的低容量神经网络。即使是最复杂的模型也容易受到这种攻击。这里引用的论文使用了 2014 年的 GoogLeNet,从那时起,这些测试在其他 dnn 上重复进行。

如果模型和他们得到的一样好,那么深度学*模型更容易受到这种攻击吗?RBF 网络等一些模型不太容易受到对抗性攻击 (Goodfellow et al 2016,arXiv:1412.6572)。但是 RBF 网络的召回率要低得多。RBF 网络为了更高的精度牺牲了大量的召回率。在 DNS 的情况下,对抗性的例子是足够普遍的。伊恩·古德费勒(Goodfellow et al 2016,arXiv:1412.6572)已经向展示了对于大多数 dnn 来说,找到对立的例子是可能的。这意味着,即使有一个训练有素的系统,一个坚定的黑客总是可以找到敌对的例子来欺骗面部识别系统。并且对立的例子对于人眼来说是绝对无法察觉的,这使得冒充的威胁变得非常真实。

我们如何产生一个对立的例子?

在面部识别的背景下,我们希望我们的对立示例能够成功建立两项任务——

  1. 躲闪——主体避免被面部识别系统识别。
  2. 模仿——受术者模仿他人。

在这两个任务中,转换应该是可行的,例如,化浓妆或戴面具是行不通的,因为这种转换在真实情况下会引起注意。

马哈茂德·谢里夫等人。艾尔。(谢里夫等人。al 2015) ( 论文)使用了一种优化方法来进行躲闪和模仿。为了躲避,他们优化

其中“r”是应用于图像的扰动。使用这种技术,他们能够成功地避开预先训练的 DNN。

Small Imperceptible Changes Lead to successful Dodging (IC: https://www.cs.cmu.edu/~sbhagava/papers/face-rec-ccs16.pdf))

在上面的例子中,左边的图像被正确分类,但是中间的图像没有。如右图所示,这两幅图像仅有小的扰动。

使用类似的技术,作者展示了一个非常可信的模仿。DNN 非常自信地成功认出了瑞茜·威瑟斯彭和拉塞尔·克罗。但同一网络将戴眼镜的里斯(中间部分)归类为拉塞尔。

Reese Witherspoon (left) wearing glasses (middle) impersonating Russel Crowe (Right) (IC: https://www.cs.cmu.edu/~sbhagava/papers/face-rec-ccs16.pdf))

我们如何防止这种攻击?

在这一点上,让我提醒一下,这些想法中有许多还不够实际。当 DNN 权重已知时,最好的对抗生成器工作。然而,对于我们只能访问响应的黑盒人脸识别系统,这样的攻击并不奏效。然而,识别系统和攻击每天都在变得更好。

生成对抗网络(GANs)可以通过使 DNNs 对对抗示例更健壮来很好地防御对抗攻击。虽然关于这个主题的研究还远未完成,但似乎创建高容量网络 ( Madry 等人 2017,arXiv:1706.06083)并使用 GAN 生成的示例进行训练,可以帮助创建对敌对图像鲁棒的面部识别系统。另一种方法是使用一种完全不同的网络,称为胶囊网络,Geoffrey Hinton 在题为“卷积神经网络有什么问题?”(YouTube 链接——https://www.youtube.com/watch?v=rTawFwUvnLE)

在过去的几年里,我们在 DNN 和面部识别系统领域取得了长足的进步。现在,随着面部识别成为主流,我们将看到从身份验证到监控的众多应用。新的想法可能伴随着未知的挑战。诸如躲避和冒充之类的攻击将会越来越频繁和复杂。但是,我确信我们将通过人类的聪明才智和一点技术来克服这些挑战。

原载于 2017 年 11 月 16 日e4c5blog.wordpress.com

使用深度学*的面部识别

原文:https://towardsdatascience.com/facial-recognition-using-deep-learning-a74e9059a150?source=collection_archive---------0-----------------------

卷积神经网络允许我们从图像中提取广泛的特征。事实证明,我们也可以将这种特征提取的想法用于人脸识别!这就是我们在本教程中要探索的,使用深度 conv 网进行人脸识别。注:这是人脸 识别 (即实际告知是谁的脸) 不是 只是检测(即识别一张图片中的人脸)。

如果你不知道什么是深度学*(或者什么是神经网络),请阅读我的帖子初学者的深度学*。如果你想尝试一个使用卷积神经网络进行图像分类的基础教程,你可以尝试这个教程。请记住,本教程假设您有基本的编程经验(最好是 Python),并且您了解深度学*和神经网络的基本思想。

我们将要使用的人脸识别方法相当简单。这里的关键是让一个深度神经网络产生一串描述一张脸的数字(称为人脸编码)。当您传入同一个人的两个不同图像时,网络应该为这两个图像返回相似的输出(即更接*的数字),而当您传入两个不同人的图像时,网络应该为这两个图像返回非常不同的输出。这意味着需要训练神经网络来自动识别面部的不同特征,并基于此计算数字。神经网络的输出可以被认为是特定人脸的标识符——如果你传入同一个人的不同图像,神经网络的输出将非常相似/接*,而如果你传入不同人的图像,输出将非常不同。

谢天谢地,我们不必经历训练或建立自己的神经网络的麻烦。我们可以通过我们可以使用的 dlib 访问一个经过训练的模型。它确实做了我们需要它做的事情——当我们传入某人的面部图像时,它输出一串数字(面部编码);比较来自不同图像的人脸编码将告诉我们某人的脸是否与我们有图像的任何人相匹配。以下是我们将采取的步骤:

  1. 检测/识别图像中的人脸(使用人脸检测模型)——为了简单起见,本教程将只使用包含一个人脸/人的图像,而不是更多/更少
  2. 预测面部姿态/ 界标(针对步骤 1 中识别的面部)
  3. 使用来自步骤 2 的数据和实际图像,计算面部编码(描述面部的数字)
  4. 比较已知人脸的人脸编码和测试图像中的人脸编码,判断照片中的人是谁

希望你对这将如何工作有一个基本的概念(当然上面的描述是非常简化的)。现在是时候开始建设了!

准备图像

首先,创建一个项目文件夹(只是一个保存代码和图片的文件夹)。对我来说它叫做face_recognition,但是你可以随便叫它什么。在该文件夹中,创建另一个名为images的文件夹。这是一个文件夹,将保存您要对其运行人脸识别的不同人的图像。从脸书下载一些你朋友的图片(每人一张),将图片重新命名为你朋友的名字(如taus.jpgjohn.jpg,并将它们全部保存在你刚刚创建的这个images文件夹中。需要记住的一件重要事情是:请确保所有这些图像中只有一张脸(即它们不能是组图),并且它们都是 JPEG 格式,文件名以.jpg结尾。

接下来,在您的项目文件夹中创建另一个文件夹(对我来说是face_recognition文件夹),并将其命名为test。该文件夹将包含您在images文件夹中存储的同一个人的不同的图像。再次,确保每张照片只有一个人在里面。在test文件夹中,您可以随意命名图像文件,并且您可以拥有每个人的多张照片(因为我们将对test文件夹中的所有照片运行人脸识别)。

安装依赖项

这个项目最重要的依赖项是 Python 2.7 和 pip。您可以使用 Anaconda 2(这只是一个预打包了 pip 的 Python 发行版)通过点击链接来安装这两个版本(如果您还没有安装的话)。注意:请 确保Anaconda 2 添加到您的PATH中,并注册为您的系统 Python 2.7(安装过程中会有提示;只需按“是”或勾选复选框)。

如果您已经完成了 Anaconda 2 的设置,或者您已经预先在机器上安装了 Python 2.7 和 pip,那么您可以继续安装 dlib (我们将使用的机器学*库)和其他依赖项。为此,请在终端(Mac OS 或 Linux)或命令提示符(Windows)中键入以下命令:

pip install --user numpy scipy dlib

如果您是 Mac 或 Linux 用户,并且在使用上述命令时遇到问题,请尝试以下命令:

sudo pip install --user numpy scipy dlib

如果上述过程对您不起作用,您可能需要手动下载、编译和安装 dlib 及其 Python API。为此,你必须读一些关于 http://dlib.net/的书。不幸的是,这超出了这篇博文的范围,因此我不会在这里讨论。

你需要做的最后一件事是下载预先训练好的人脸识别模型。你需要两种型号。一个模型预测一张脸的形状/姿势(基本上给你形状在图像中如何定位的数字)。另一个模型,获取人脸并给你人脸编码(基本上是描述那个特定人的脸的数字)。以下是关于如何下载、提取和准备它们的说明:

  1. 这个链接下载dlib_face_recognition_resnet_model_v1.dat.bz2,从这个链接下载shape_predictor_68_face_landmarks.dat.bz2
  2. 一旦下载了这两个文件,就需要解压它们(它们以 bz2 格式压缩)。在 Windows 上,您可以使用 Easy 7-zip 来完成此操作。在 Mac 或 Linux 上,您应该能够双击文件并提取它们。如果这不起作用,只需在您的终端中输入这两个文件:bzip2 **{PATH_TO_FILE}** --decompress(用您试图提取的文件的实际路径替换{PATH_TO_FILE};对我来说,命令应该是bzip2 ~/Downloads/dlib_face_recognition_resnet_model_v1.dat.bz2 --decompressbzip2 ~/Downloads/shape_predictor_68_face_landmarks.dat.bz2 --decompress
  3. 一旦你提取它们,你应该有两个名为dlib_face_recognition_resnet_model_v1.datshape_predictor_68_face_landmarks.dat的文件。将这两个文件复制到您的项目文件夹中(对我来说,这是我为这个项目创建的face_recognition文件夹)。

代码!

现在,你已经设置好了一切,在一个文本编辑器(最好是 AtomSublime Text )中打开你的项目文件夹(我称之为face_recognition)。在名为recognize.py的文件夹中创建一个新文件。这是我们将添加代码来匹配你的朋友的脸。注意,这个过程有两个主要部分:首先,在images文件夹中加载已知人脸的人脸编码;完成后,从存储在test文件夹中的人脸/图像中获取人脸编码,并将它们与我们所有已知的人脸一一匹配。我们将逐步完成这一部分。如果您想看到它运行,您可以将该部分中的所有代码一个接一个地复制粘贴到您的文件中(即,按照下面列出的相同顺序合并所有单独的代码部分)。仔细阅读每个代码块中的注释,了解它的作用。

第 1 部分:初始化和设置— 在这里,我们导入所需的库,并设置人脸识别所需的对象/参数。

import dlib
import scipy.misc
import numpy as np
import os# Get Face Detector from dlib
# This allows us to detect faces in images
face_detector = dlib.get_frontal_face_detector()# Get Pose Predictor from dlib
# This allows us to detect landmark points in faces and understand the pose/angle of the face
shape_predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')# Get the face recognition model
# This is what gives us the face encodings (numbers that identify the face of a particular person)
face_recognition_model = dlib.face_recognition_model_v1('dlib_face_recognition_resnet_model_v1.dat')# This is the tolerance for face comparisons
# The lower the number - the stricter the comparison
# To avoid false matches, use lower value
# To avoid false negatives (i.e. faces of the same person doesn't match), use higher value
# 0.5-0.6 works well
TOLERANCE = 0.6

第 2 部分:从图像中获取人脸编码— 这里我们编写一个函数,它将获取一个图像文件名,并为我们提供该图像的人脸编码。

# This function will take an image and return its face encodings using the neural network
def get_face_encodings(path_to_image):
    # Load image using scipy
    image = scipy.misc.imread(path_to_image) # Detect faces using the face detector
    detected_faces = face_detector(image, 1) # Get pose/landmarks of those faces
    # Will be used as an input to the function that computes face encodings
    # This allows the neural network to be able to produce similar numbers for faces of the same people, regardless of camera angle and/or face positioning in the image
    shapes_faces = [shape_predictor(image, face) for face in detected_faces] # For every face detected, compute the face encodings
    return [np.array(face_recognition_model.compute_face_descriptor(image, face_pose, 1)) for face_pose in shapes_faces]

第 3a 部分:比较人脸— 我们在这里编写一个函数,它将给定的人脸编码与一系列已知的人脸编码进行比较。它将返回一个布尔值(真/假)数组,指示是否存在匹配。

# This function takes a list of known faces
def compare_face_encodings(known_faces, face):
    # Finds the difference between each known face and the given face (that we are comparing)
    # Calculate norm for the differences with each known face
    # Return an array with True/Face values based on whether or not a known face matched with the given face
    # A match occurs when the (norm) difference between a known face and the given face is less than or equal to the TOLERANCE value
    return (np.linalg.norm(known_faces - face, axis=1) <= TOLERANCE)

第 3b 部分:查找匹配— 这里我们编写了一个函数,它将接受一个已知人脸编码列表、一个人名列表(对应于已知人脸编码列表)和一个要查找匹配的人脸。它将调用 3a 中的函数,并返回与给定人脸匹配的人的姓名。

# This function returns the name of the person whose image matches with the given face (or 'Not Found')
# known_faces is a list of face encodings
# names is a list of the names of people (in the same order as the face encodings - to match the name with an encoding)
# face is the face we are looking for
def find_match(known_faces, names, face):
    # Call compare_face_encodings to get a list of True/False values indicating whether or not there's a match
    matches = compare_face_encodings(known_faces, face) # Return the name of the first match
    count = 0
    for match in matches:
        if match:
            return names[count]
        count += 1 # Return not found if no match found
    return 'Not Found'

至此,我们拥有了运行程序所需的函数。是时候编写应用程序的最后一部分了(我将把它分成两个独立的部分)。

第 4a 部分:获取 images 文件夹中所有人脸的人脸编码

# Get path to all the known images
# Filtering on .jpg extension - so this will only work with JPEG images ending with .jpg
image_filenames = filter(lambda x: x.endswith('.jpg'), os.listdir('images/'))# Sort in alphabetical order
image_filenames = sorted(image_filenames)# Get full paths to images
paths_to_images = ['images/' + x for x in image_filenames]# List of face encodings we have
face_encodings = []# Loop over images to get the encoding one by one
for path_to_image in paths_to_images:
    # Get face encodings from the image
    face_encodings_in_image = get_face_encodings(path_to_image) # Make sure there's exactly one face in the image
    if len(face_encodings_in_image) != 1:
        print("Please change image: " + path_to_image + " - it has " + str(len(face_encodings_in_image)) + " faces; it can only have one")
        exit() # Append the face encoding found in that image to the list of face encodings we have
    face_encodings.append(get_face_encodings(path_to_image)[0])

部分 4b:将 test 文件夹中的每张图像与已知人脸进行匹配(逐个)

# Get path to all the test images
# Filtering on .jpg extension - so this will only work with JPEG images ending with .jpg
test_filenames = filter(lambda x: x.endswith('.jpg'), os.listdir('test/'))# Get full paths to test images
paths_to_test_images = ['test/' + x for x in test_filenames]# Get list of names of people by eliminating the .JPG extension from image filenames
names = [x[:-4] for x in image_filenames]# Iterate over test images to find match one by one
for path_to_image in paths_to_test_images:
    # Get face encodings from the test image
    face_encodings_in_image = get_face_encodings(path_to_image) # Make sure there's exactly one face in the image
    if len(face_encodings_in_image) != 1:
        print("Please change image: " + path_to_image + " - it has " + str(len(face_encodings_in_image)) + " faces; it can only have one")
        exit() # Find match for the face encoding found in this test image
    match = find_match(face_encodings, names, face_encodings_in_image[0]) # Print the path of test image and the corresponding match
    print(path_to_image, match)

就是这样!一旦你将第 1 部分到第 4b 部分的所有代码复制粘贴到recognize.py文件中(一个接一个——按照我写它们的顺序),你应该能够使用你的终端(Mac OS 或者 Linux)或者命令提示符(Windows)通过输入这些命令来运行它(用你的项目文件夹的完整路径替换**{PROJECT_FOLDER_PATH}**;对我来说是/Users/taus/face_recognition):

cd **{PROJECT_FOLDER_PATH}** python recognize.py

这将为您提供类似如下的输出:

('test/1.jpg', 'Shihab')
('test/2.jpg', 'Not Found')
('test/3.jpg', 'Taus')
('test/4.jpg', 'Mifrah')
('test/5.jpg', 'Mubin')

文件名旁边的名称显示与给定人脸匹配的人的姓名。请注意,这可能并不适用于所有图像。为了获得此代码的最佳性能,请尝试使用人脸清晰可见的图像。当然,还有其他方法可以使它准确(比如通过实际修改我们的代码来检查多个图像或者使用抖动,等等)。)但这只是为了让你对人脸识别的工作原理有一个基本的了解。

这篇文章的灵感来自于亚当·盖特基(Adam Geitgey)的博客文章(T3)和(T4)关于人脸识别的 Github 报告(T5)。此外,我们正在使用 dlib 网站上提供的一些预先训练好的模型——所以向他们致敬,让他们可以公开访问。我的主要目标是介绍和解释人脸识别的基本深度学*解决方案。当然,有更简单的方法来做同样的事情,但我认为我应该使用 dlib 来一部分一部分地(详细地)做这件事,这样你就能真正理解不同的运动部件。还有其他运行人脸识别的方法(非深度学*),请随意研究它们。这种方法很酷的一点是,你可以用每个人/对象的一两张图像来运行它(假设该模型在实际区分两张脸方面做得很好)。

不管怎样,我希望你喜欢这篇文章。请随意发表评论。

基于事实的人工智能。知识图的改进

原文:https://towardsdatascience.com/fact-based-ai-improving-on-a-knowledge-graph-12c37481cce6?source=collection_archive---------8-----------------------

我的公司 Viev(2022 10 13:now Fact engine:www . Fact engine . ai)生产基于事实的建模软件 Boston(FBM)。我们认为,基于事实的建模将在下一波对话式用户界面(CUI)、语音用户界面(VUI)和人工智能(AI)中产生影响。

Cui 和 vui 在相对较短的时间内变得流行起来。苹果 Siri VUI 的推出预示着苹果、微软、谷歌和亚马逊之间在各自的计算机操作系统和智能扬声器中生产 VUI 的竞赛的开始,我提供的这类产品是自引入面向对象编程和关系数据库以来在信息产业中从未见过的[1]。竞争似乎很激烈,就实用性而言,vui 正迅速变得更加智能。这些技术被认为很快会在家用电器甚至汽车中变得普遍[2][3][15]。

在研究和应用方面,聊天机器人形式的 Cui 也处于快速增长的领域。脸书的 Messenger 应用程序和微软的 Skype 中的聊天机器人已经有了相当大的发展,据报道仅在 Messenger 平台上就有超过 100,000 个聊天机器人[16]。据报道,早期的消费者体验令人失望[16]。然而,似乎至少有一家企业报告其 chatbot 实施的月收入超过 100 万美元[16],并且不断有关于其成功应用的报告即将发布[14]。我个人对聊天机器人的分析让我觉得缺失的元素是对对话语境的深刻理解和自然的对话流程。

所有 Cui/vui 的基本前提是,人们交谈和使用自然语言比用其他形式交流要容易得多。举例来说,我最*购买了一部基于 Android 的手机,现在很少通过连续按下虚拟按钮来打电话或发送短信,而是我只是对着手机说话,它就知道我想做什么。要给某人发短信,我只需简单地说,“好的,谷歌,给彼得发个短信”。谷歌助手用自然语言问我想说什么。我的语音信息被转换成文本。Google Assistant 问我是否愿意发送该消息。回答,“发送”,谷歌助手尽职尽责地发送短信。所有这些都不需要按我手机上的任何一个按钮。难以置信,除了因为这种技术现在如此之好,它是可信的。我觉得这项技术会一直存在下去。随着时间的推移,我觉得这项技术只会变得越来越好,甚至更容易使用,越来越成为那些接触到这项技术的人日常生活的一部分。

对于那些作为消费者非常熟悉该技术的人,尤其是开发该技术的人来说,这样的例子将很快变得不起眼。即使在今天,我仍然认为,因为这种技术是如此容易获得和令人满意,它不仅已经成为一种产品的区别特征,而且还是一种预期的技术。我相信消费者对 CUIs/VUIs 的需求将推动人工智能的快速采用,并且在很大程度上,已经做到了。

从计算机时代开始,人类就在思考用自然语言与机器对话的能力,甚至通过机器用自然语言对话的能力(即图灵测试)来判断机器的智能。最*一篇有趣的文章重申了这一观点,并旨在巩固'会话认知'作为人工智能的基准[5]。

图灵测试在人工智能领域如此普遍,以至于它催生了一年一度的罗布纳奖(Loebner Prize ),当评委们根本无法区分他们是在与机器对话还是与另一个人对话时,这项比赛就会结束。

如果我们认为人类提供了智能的最终基准,那么用这个基准来评判人工智能似乎是自然和公平的。

然而,当今 Cui 和 vui 的相对迅速崛起,只是表面上,并没有反映出为使这些技术可用而进行的长期研究和开发。从消费者的角度来看,这种技术相对较新,但从研究的角度来看,它是几十年研究的累积成果。

但这是我们感兴趣的研究的未来。技术领先在哪里?最佳技术将采用何种外形规格?这些是我将在这里提出的问题,并提供一个前进的方向。

如果我们接受所有 Cui 和 vui 代表某种形式的人工智能和不同程度的实际智能,那么我们可以将我们的讨论限制在谈论一般的人工智能。这一点,尤其是如果我们接受会话认知作为我们讨论中的价值基准的话。也就是说,我们不是在谈论关于计算机视觉或诸如此类的人工智能,而是那些管理与人对话的人工智能。

对人工智能的研究大体上有两个主流,一个是算法,另一个是基于我称之为直觉的。第一种是确定性的,在这种情况下,我们可以窥视人工智能的工作方式,并根据它的推理得出问题的答案;第二个问题的结构如此复杂,以至于我们可能永远不知道它是如何推导出解决方案的,只知道它确实(正确或错误地)[7][8]。

我在确定性人工智能中包括那些不仅包含某种描述的知识库,而且包含一组逻辑规则和算法的人工智能,这两者对于对人工智能的工作感兴趣的外部观察者来说是完全透明的。默认情况下,我包括所有那些对一阶逻辑(FOL)有算法感知的人工智能系统。这样的人工智能很少被媒体报道,如果有一个通用术语来代表它们,我也想不起来。

我在直觉人工智能中包括那些人工智能内部工作如此复杂的问题,以至于准确确定一个答案是如何得出的可能是耗时的,以至于更容易接受人工智能要么产生要么不产生想要的结果。这并不是说一个人不能在人工智能中分解一个事务的内部工作,而是说它会如此复杂以至于期望有人去尝试是不合理的。这些类型的人工智能确实有可识别的名称,如神经网络和那些结合了深度学*和机器学*的人工智能。为了简单起见,在这里我将它们都归入神经网络这个术语。

一个对这两种类型的人工智能漫不经心和因果关系的观察者很可能会说,神经网络的内部工作方式当然是众所周知的,否则它们是如何建立起来的。不过,更详细地说,这里我们只考虑令人生畏的复杂性,即分析一个适当复杂的基于神经网络的人工智能采取什么步骤来得出一个单一的答案。当然,有了无限的时间和资源,人们可以分析任何事情,然而,似乎我们只是根据神经网络的数据模型是否返回有利的结果来接受或拒绝神经网络。如果结果是有利的,我们可能不太倾向于分析为什么,每次迭代的问题解决。

例如,当谷歌发布一篇论文,宣布他们基于 AlphaZero 神经网络的人工智能在国际象棋的自动化游戏中取得“突破”时,世界级的玩家称这一结果是显著的[9]。其他人评论了“直觉”是如何与确定性游戏相抗衡的[10]。据我所知,没有人准确分析过 AlphaZero 的每一步棋是如何做出决定的。

在这方面,确定性人工智能和随机人工智能之间的区别是明显的。

对在线文献的粗略搜索很容易表明,目前在人工智能中解决确定性和随机系统的组合以产生更智能的整体方面有很多活动。

如果我们重新将我们的讨论集中在那些与人交谈的人工智能上,以及它们将如何模仿人类的话语能力,那么看看你自己的内心并思考人类需要多少能力来产生演讲和回答外部世界的问题是合理的,这是基于应用逻辑而不是依靠训练有素的思维路径。

例如,用合适的“嗨”来回应“你好”的问候可能在大脑的神经路径中根深蒂固,以至于很容易推断出这些功能是在神经网络人工智能中训练出来的。

更重要的是构建一个神经网络来思考“我今天需要一把伞吗?”、“外面下雨了”、“好的,是的,你今天需要一把伞”扩展了这种能力,以提供需要遍历数十或数百个条件谓词才能得到合适结果的问题的答案。

这并不是说神经网络不能处理需要某种形式的谓词逻辑的问题,而是说无论人工智能如何处理自然语言的分析,如果人工智能在对话中具有适当的智能,它将需要与数据相关联的丰富语义信息的数据,包括合并了谓词逻辑的某种表达的数据。

一切都与数据有关

我最*在一篇关于艾的文章中强调了一句话,内容是:

人工智能方法大致有三个部分:产生数据、解释数据和对数据做出判断

我们到达这篇文章的核心,并讨论为什么我相信一些描述的基于事实的建模将是未来掌握对话认知的人工智能的核心,以及我个人将如何使用该方法来改进 Google 的知识图。

在他们的核心,每个人工智能都依赖于数据。正是语义信息在基于事实的模型中的丰富嵌入,包括一阶逻辑谓词的表达,使得基于事实的建模成为一种有吸引力的产品,以一种可以存储、分析和判断的方式来定义数据的结构。

从这一点开始,我们不再考虑如何对数据做出(确定性的或随机的)决策,而是关注什么是数据,包括存储为数据的逻辑谓词。

基于事实的建模

基于事实的建模是概念建模的一种形式,它捕捉作为“事实”呈现的信息结构。事实可以写成“人‘巴拉克·奥巴马’身高‘1.85’米”的形式,事实类型从该形式中捕获结构,“人身高(以米为单位)”。“人”可以被分析为一种实体类型。

我们将“高度(以米为单位)”表示为一种特殊类型的实体类型,表示单位度量值。然而,通常值是作为值类型来分析的,而“人‘巴拉克·奥巴马’的名字是‘巴拉克’”会将姓名表示为值类型。

在一种被称为对象-角色建模 (ORM)的基于事实的建模中,上述信息在概念上被捕获在下图中:

基于事实的建模和 ORM 与其他更简单的概念建模语言(例如,实体关系图和 UML 类图)的区别在于,ORM 在语义上丰富了它在事实类型中捕获的关于事实的信息。在相应的事实类型中捕获用自然语言重建事实的完整信息。

当考虑连接的对象类型(人、身高)时,“…是…高”谓词读数(上图)允许其事实类型推断为“人是身高(米)高”,样本人口/数据允许我们推断“巴拉克·奥巴马是 1.85 米高”这一事实。

ORM 允许我们用自然语言查询一个模型,并提出类似这样的问题:“巴拉克·奥巴马身高 1.85 米吗?”,相对容易,因为随模型一起捕获了丰富的语义信息。

同一个概念模型的实体关系图所能捕获的信息量是有限的,如下所示:

在所示类型的 ERD 中,没有捕获关于每个实体属性(例如,Person Height)对的底层谓词的额外语义信息。例如,使用那种类型的 ER 图,我们不知道身高是以米为单位的,并且我们没有额外的信息来形成自然语言中的“巴拉克·奥巴马身高 1.85 米”这一事实。

我觉得实体关系图和 UML 图有它们的位置,然而我们在这里寻求的是如何捕捉丰富的语义信息来创建一个具有对话认知的 AI。我觉得为了做到这一点,我们不仅需要捕获数据,还需要关于将数据绑定在一起的底层谓词的信息。

观察力敏锐的读者可能会思考图表在实现数据方面有什么价值。在这里,我们认识到,以图形(如 ORM 图)表示的基于事实的模型在数据存储级别上实现了有效的知识图形。让我们进一步检查基于事实的建模的效用。

如果我们在模型中加入一组有身高的人是活着的人的子集(例如,火化后的人当然没有我们通常理解的“身高”),那么我们的例子就变成了需要谓词逻辑的例子。在 ORM 中,子集约束表示如下:

用问题“巴拉克·奥巴马有多高?”,应该回“巴拉克·奥巴马身高 1.85 米”。质疑“巴拉克·奥巴马身高 1 米 85 吗?”应回,“是”。但是用“拿破仑·波拿巴有 1.69 米高吗?”来询问同样型号的智能人工智能应该回敬,“不,因为拿破仑·波拿巴已经不在人世了”。

NB 如果我们接受 ORM 只迎合开放世界语义,并且不记录某人活着并不一定意味着他们不活着,我们至少可以通过在实践中采用封闭世界语义来迎合相同的结果。或者干脆修改模型,反映一个人可能没死,有身高。

拥有语义丰富的数据加上逻辑谓词,允许人工智能使用自然语言中作为问题提出的语义查询来探索底层模型[12]。如何实现这一点是当前研究的主题,然而,研究和开发的环境扫描表明,如果要实现语义查询,就需要在数据存储内或数据存储上有语义知识,这一概念几乎没有阻力[11]。

展望未来的知识图谱

如果我们接受对话认知包括回答人工智能提出的问题的能力,那么我们可以检查现实世界中实现这种人工智能的尝试。

谷歌搜索有一个功能叫“知识图”(微软的 Bing 实现了类似的东西),指的是底层技术。知识图是收集的关于各种感兴趣的主题的知识的集合;出于兴趣,‘名人’。知识图大概被概念化并存储为数据图。然而,我们知道数据的来源(T0)以一种更相关的方式(T3)存储(T2)。对我们来说,谷歌如何将收集到的数据存储到知识图中并不重要,重要的是它存储了什么

例如,我们知道知识图表捕捉关于名人及其身高的信息。

让这些信息有些用处的是,你可以在谷歌上搜索“巴拉克·奥巴马有多高?”并且返回 1.85 米的合适结果。因为关于巴拉克·奥巴马的信息存储在知识图中,所以在搜索结果页面上会显示一个关于巴拉克·奥巴马的额外信息框。这样的搜索结果如下所示。

如果我们在谷歌上搜索“巴拉克·奥巴马身高 1.85 米吗?”我们分析的问题就变得很明显了。不显示知识图信息(如下)。如果我们期待一个确认,“是”,我们在写这篇文章的时候运气不好,伴随着我们对艺术水平的失望。

如果我们在谷歌上搜索“拿破仑有多高?”这个问题会变得更加复杂。一个搜索结果(至少在我的 iPad 上)显示了知识图谱信息,可能表明拿破仑还活着!(下图)需要进一步挖掘,点击“报价和概览”按钮来揭示死亡日期。显然,拿破仑仍然有 1.69 米高。可能发生,但是在这里我们寻找一个用自然语言提供的结果,来回答用自然语言提出的问题。

因此,我们知道,在 2018 年的前几个月,知识图不包含合适的谓词逻辑规则,这些规则允许我们在与实现价值对话认知的人工智能对话时找到合适的智能问答水平。

有些人可能会认为知识图表并不代表对话认知的尝试,但如果是这样,为什么要回答一个问题,“巴拉克·奥巴马有多高?”,一点都没有?人们已经在会话认知方面做了一些尝试。公平地说,微软的必应搜索引擎也好不到哪里去。“当今的技术水平”根本不能反映这种潜力。

需要改变什么?

我的感觉是,我们正处于分析和实施对话认知的早期阶段。我感觉用不了多久 Google/Bing 搜索就会返回“拿破仑没有 1.69 米高,因为他已经不在人世了”这样的答案。在我看来非常清楚的是,在当前的竞争环境下,如果微软必应返回这样的结果,毫无疑问,谷歌将很快效仿,反之亦然。当那发生时,我会第一个从椅子上摔下来;似乎不可避免。

我们需要一个支持语义查询和对话认知的架构。

会话认知的架构

现在你可能已经看到我的论文了。语义查询需要一个语义数据存储,其中数据和关于该数据的丰富语义信息都存储在一个逻辑数据存储中,包括一阶逻辑的条件谓词。为了实现对话式的价值认知,语义数据存储需要能够解析自然语言谓词以及底层数据的逻辑约束。

该架构最简单的形式如下图所示:

目前开发语义数据存储(SDS)的研究正在进行中。例如,波尔扎诺自由大学的“知识表示数据库研究中心”致力于开发他们所谓的知识表示数据库(KRDB)。

基于事实的建模,如对象-角色建模,是 SDS 的天然选择。事实类型读数可能包括“反向读数”;其中“零件在仓库的储箱中”,例如,有补充读数,“仓库在储箱中存储零件”和“储箱在仓库中存放零件”。更简单的事实建模形式只存储一个读数,甚至试图截断谓词,如“Person isFriendOf Person”。我不相信这种简单的谓词表示的价值。

我觉得重要的是,如何存储自然语言中的完整谓词(作为图形、关系或数据层次)并不重要,因为如果我们采用基于事实的建模的元模型来存储谓词的语义,当涉及到数据库时,基于事实的建模是实现不可知的。

同样重要的是,可以在 SDS 上进行两种形式的查询,一种是对数据的语义查询,另一种是对丰富语义数据的语义分析查询(SAQ ),它定义并管理底层数据,以便于语义查询。SAQ 返回逻辑谓词,帮助人工智能细化语义查询和结果。

例如,语义查询“Bin '1 '是否在仓库'主仓库'中存储零件' 456 '?”在它的执行中,可能需要通过基于事实的模型上的语义分析查询的解决方案,即初始查询涉及事实类型“Bin stores Part in Warehouse”及其底层数据。类似的 saq 可以解决这个问题,“哪个零件存储在仓库‘主仓库’的哪个箱中?”通过首先识别存储数据的适当谓词,返回满足请求的数据列表。

因为使用解析和自然语言处理的组合来解决这样的查询需要算法体操,所以实现这样的技术不是一件容易的事,但是我很清楚,如果不存储事实类型、事实类型读数和以谓词逻辑表示的条件规则,智能对话认知的目标将无法实现。我们的第一个目标是在 AI 底层的数据模型中存储适当的谓词。

实现语义数据存储的目标并不新鲜([13]),在我看来,这种数据库在人工智能领域的最终发展和流行是不可避免的。

一个开放的研究领域是如何最好地让人工智能更新其 SDS 的语义层。在我看来,如果我们要发展人工通用智能,这个要求是不可或缺的。

Viev 正在开发工具来帮助构建语义数据存储的语义层,我们将与人工智能社区合作,帮助实现对话式认知。

感谢您的阅读。我希望这篇文章对你有所帮助。如果时间允许,我将提供更多关于基于事实的建模和对象角色建模的信息。

— — — — — — — — — — — — — — — —

参考

  1. 沃勒顿,m .,“语音战争:Siri vs. Alexa vs. Google Assistant”,【www.cnet.com】T2,https://www . CNET . com/news/Voice-wars-Siri-vs-Alexa-vs-Google-Assistant/,2018 年 2 月 24 日访问
  2. Westlake,“智能家居和联网汽车——语音激活”,www.gearbrain.com,2018 年 2 月 24 日访问
  3. “市场上创新的语音控制设备”,www.globalme.com,https://www . global me . net/blog/best-Voice-Controlled-Devices-Market,于 2018 年 2 月 24 日访问
  4. “图灵测试”,www.wikipedia.orghttps://en.wikipedia.org/wiki/Turing_test,于 2008 年 2 月 25 日访问
  5. Perez,c .,“对话式认知:人工通用智能的新衡量标准”,www.medium.comhttps://medium . com/intuition machine/conversation-Cognition-A-New-approach-to-agi-95486 FFE 581 f,于 2018 年 2 月 25 日获取
  6. “罗布纳奖”,www.wikipedia.orghttps://en.wikipedia.org/wiki/Loebner_Prize,于 2018 年 2 月 25 日获得
  7. Rankin K .,“人工智能核心的黑暗秘密”,《麻省理工技术评论》,https://www . Technology Review . com/s/604087/The-Dark-Secret-at-The-Heart-of-AI/,于 2018 年 2 月 23 日查阅
  8. Perez,c .,“深度学*是非平衡信息动力学”,www.medium.comhttps://medium . com/intuition machine/Deep-Learning-is-Non-balanced-Information-Dynamics-b 00 baa 16 b 135,2018 年 2 月 25 日访问
  9. “AlphaZero:来自顶级 GMs,Stockfish 作者的反应”,www.chess.comhttps://www . chess . com/news/view/alpha zero-Reactions-From-Top-GMs-stock fish-Author,于 2018 年 2 月 25 日访问
  10. 佩雷斯,c .,“AlphaZero:直觉如何摧毁逻辑”,www.medium.comhttps://medium . com/Intuition machine/alpha zero-How-Intuition-disrupted-Logic-66a 4841 e 6810,于 2018 年 2 月 25 日访问
  11. 林琳,王宏,王敏,“实例语义查询”,谷歌研究,
  12. “语义查询”,www.wikipedia.org,https://en.wikipedia.org/wiki/Semantic_query,2018-02-25 访问
  13. 日期,C.J .,“约束和谓词:简要教程(第一部分)”,www.brcommunity.com,http://www.brcommunity.com/articles.php?id=b065a
  14. 案例研究:一个房地产机器人如何在 10 天内卖出 3 套公寓。,www.medium.com
  15. “语音助手正在使智能手机变得多余”,《二元地区杂志》,https://then extweb . com/syndication/2018/02/24/Voice-assistants-making-smart phone-redundant/
  16. Mai,m .,“从阴郁到迷人:Facebook Messenger 聊天机器人的演变”,《福布斯》,
    https://www . Forbes . com/sites/mariyayao/2017/10/12/From-droom-To-Glam-The-Evolution-Of-Facebook-Messenger-Chatbots/# 3b 3869263 Abd,于 2018 年 2 月 25 日查阅

事实/仿真陈述;数据/数据驱动?当媒体变戏法却忘了戳破科学泡沫时

原文:https://towardsdatascience.com/fact-factoid-data-data-driven-when-media-conjure-but-forget-to-burst-the-science-bubbles-df1967530dd?source=collection_archive---------2-----------------------

Photo by Diana Orey on Unsplash

我不知道你是否注意到了,但是最*伦敦到处都张贴着“安东尼·诺兰治愈血癌”的海报。

乍一看,你可能会认为这是另一项科学突破。然而,如果你仔细阅读,你会发现一个较小的印刷字体,上面写着“每天,我们将干细胞捐赠者与急需救命移植的血癌和血液疾病患者相匹配”。

如果你有额外的时间在谷歌上快速搜索一下,你会发现安东尼·诺兰是一个慈善组织,为需要骨髓移植的病人和可能的捐赠者牵线搭桥。

我对这个组织没有任何不满。事实上,我认为他们在提高公众意识方面做得很好。随着骨髓治疗变得更加普遍,迫切需要更大的供体库,以便找到更接*的供体-患者匹配。对黑人、亚洲人、少数民族(BAME)和混血儿的捐献者也有强烈的吸引力,因为目前他们的代表性严重不足,这反过来影响了来自这些背景的患者的存活率。

然而,这些重要的信息都没有通过这些标志传达出来。因此,我不满意的是,该组织设计海报的方式。

具体来说,你说的“治愈血癌”是什么意思?

如果个人不小心,他们可能会带着已经有治疗血癌的药物的知识离开,并且只要他们接*“安东尼·诺兰”,患病的人就会康复。

老实说,真的是这样吗?

首先,我们需要知道没有“血癌”这种东西,因为正确的说法应该是“血液、骨髓或淋巴系统的癌症”。其中,病情可以进一步细分为白血病、骨髓瘤和淋巴瘤,每种都有自己的变异形式,可以是急性或慢性的。

从“抗抑郁药”、“基因”到“科学方法”,某些医学、科学和技术术语经常被媒体和大众以一种极其松散的方式使用。尽管这些外行术语旨在弥合新手和专家之间的差距,但它们从未有助于构建我们的知识。

接下来,骨髓或干细胞移植只是治疗方案之一。其他包括化疗和放疗,根据患者的健康状况、年龄和严重程度,可以选择任何一种。

最后,骨髓捐献是无痛的,因为捐献者将在大约一小时的过程中处于全身麻醉状态。此外,捐赠者也可以选择通过外周血干细胞方法进行非手术捐赠。在这里,将对捐赠者进行连续四天的注射,然后要求他们耐心等待五到七个小时的捐赠程序,在此过程中,他们的血液被抽取,通过一台分离和收集干细胞的机器,然后返回体内。

我不确定公众是否会费心去发现这些“安东尼·诺兰治愈血癌”海报背后的真正含义,但我确信这不是科学第一次被媒体歪曲。

《苍蝇》,一部 20 世纪 80 年代的电影,由杰夫·高布伦主演,他发明了一种传送装置,但这种装置对生物不起作用。在他心烦意乱和喝醉时对机器进行的一次实验中,戈德布卢姆完全与一只家蝇融为一体,导致他逐渐转变为一种半家蝇半人的生物。

这部电影在特殊的化妆、效果和现实方面做得很好,我们不应该在不清醒的时候做任何实验。除此之外,这部电影的核心思想根本就是荒谬的。

完全融合意味着家蝇现在是人类的一部分,反之亦然。家蝇的平均体重约为 0.0003 公斤,一个成年人的平均体重为 80 公斤。一只家蝇大约有 2000 万个细胞,一个人大约有 10 万亿到 100 万亿个细胞。家蝇的基因组(即生物体内的遗传信息)拷贝数约为 4000 万,而人类至少有 12 万亿。

总之,这意味着人类太大而不能与家蝇完全结合,因为没有足够的家蝇基因组与人类共享(在这种情况下,只有大约 300,000 个人类细胞中的 1 个会接受家蝇基因组)。

蜘蛛侠有着相似的情节,除了蜘蛛现在是人类的一部分。电影中最令人质疑的一句台词是“…转移 RNA 来编码整个新的基因组,将所有三种蜘蛛的遗传信息结合到这 15 种遗传设计的超级蜘蛛中…”

因为你可能想通过重读两遍来理解这句话的意思,所以请注意没有必要这样做,因为这句话是无意义的。

人类体内的遗传物质是 DNA(脱氧核糖核酸),而不是 RNA(核糖核酸)。虽然“转移 RNA”是一种现有的方法,但它并不用于在两个不同物种之间转移遗传物质。我相信生成这条线的人混淆了 DNA 和 RNA 的作用,把“转移 RNA”错当成了“RNA 的转移”。

有人可能会说,科幻小说不必如此认真,但这并不能证明向观众提供不正确信息的行为也是正当的。

接下来,媒体似乎不能让自己正确,即使他们不处理电影。看看面筋是如何被妖魔化的,而超级食品却被美化了。

许多人选择了无麸质饮食,却不知道麸质是什么。面筋在拉丁语中的意思是“胶”,是一种储存在普通谷类植物如小麦和大麦种子中的蛋白质。这种蛋白质为植物生长提供能量,但也导致了它们的粘性。这就是为什么我们的面包和比萨饼面团不会轻易从我们手中脱落,并且有足够的弹性可以塑造成不同的形状。

妖魔化麸质的历史可以追溯到畅销书,如“小麦肚”系列或“谷物大脑”,以及倡导无麸质饮食的名人(如格温妮丝·帕特洛、史蒂夫·纳什和麦莉·塞勒斯)。由于可能的权威/名人效应,麸质现在被认为是导致肥胖、糖尿病和疲劳的罪魁祸首。

与此同时,还有超级食物。超级食物是巴西莓、巴西莓、藜麦、花椰菜、菠菜、鲑鱼、杏仁等的总称。据信它们含有更高含量的抗氧化剂和更丰富的营养。定期食用超级食物被认为可以减缓身体组织的磨损,保护我们免受癌症和其他疾病的侵害。

然而,没有一个科学家完全确定去除或添加某些食物对健康的确切益处,因为仍然需要考虑个人的身体吸收和适应性。因此,仍然大力提倡均衡饮食和经常锻炼。

排除麸质和偏爱超级食物都是虚假的、不可靠的信息的例子,这些信息在重复足够多次后会变成事实。就像我们牙齿上的牙结石一样,虚假的事实是日积月累的,很难清除,其后果往往是不利的,但不容易观察到。

如果苍蝇、蜘蛛侠、无麸质饮食和超级食物是媒体不承认其低科学素养的老掉牙的例子,也许数据会更时尚。

有些人可能会认为媒体对数据的使用以及将调查、数据和新闻都放在一个屋檐下的需要是当前的话题。然而,事实并非完全如此,因为它的历史可以追溯到几十年前,当时菲利普·迈耶率先在报道中采用社会科学研究方法,当时被称为“精确新闻”。

像所有其他科学一样,大多数社会科学研究从假设(A)开始,之后,研究人员将不得不从相关样本中收集信息,以接受或拒绝这些假设(B)。

同样,Meyer 的第一份报纸报道涉及为学校建筑购买火灾和风暴保险的超支,这发生在保险代理人根据赔偿金额获得佣金份额的计划下。这意味着保险费用越高,代理人赚的钱就越多。

于是,迈耶做了三个简单的假设(A ),然后去寻找支持或不支持它们的证据(B)。

詹姆斯·斯蒂尔和唐纳德·巴莱特在 20 世纪 70 年代通过使用计算机分析将这种方法提高到了一个新的水平。他们的普利策奖获奖作品旨在发现费城法院是否行使真正的正义(A)。带着这个问题,两人费力地选择了 1034 个涉及暴力的案例,并科学地比较了它们与使用 IBM 电脑的关系(B)。

这两起事件显示了科学和新闻之间的巨大合作,不幸的是,精确新闻或现在被称为数据新闻的东西,*惯性地与数据驱动的新闻相混淆。

“数据驱动新闻”这个术语可能是在 2000 年代末发明的,它颠覆了精确新闻的顺序。现在,记者们不再从 A 地走到 B 地,而是使用编程语言或数据库管理系统从公开的在线资源中搜索所谓的“数据”(B),在得出结论(A)之前,对它们进行清理。

数据驱动新闻作为一种新闻采集工具并没有错,但通常情况下,数据新闻和数据驱动新闻是以这样一种可互换的方式使用的,记者们并不确切知道他们喜欢使用或正在使用哪种技术。

此外,大多数记者不知道数据通常以四种不同的方式衡量。

  1. 名义上的,作为标签的数据,很少带有数字属性,如姓名、性别、种族和身体特征。

  2. 序数,无法量化孰优孰劣的数据。比如一个调查中给出的“很开心,很开心,中性,不开心,很不开心”的想法。除非我们接着问其他问题,但只看这个问题本身,我们无法推断出选择“快乐”的人比选择“中立”或“不快乐”的人快乐多少,反之亦然。

  3. 区间,这些数据让我们既知道顺序又知道每个类别之间的数量差异。比如温度。我知道 30 摄氏度比 10 摄氏度要热 20 摄氏度,因为这 20 摄氏度的差异不仅使我能够根据它们的温暖程度来排列这两个温度,而且还能从数量上解释它们的差异。

  4. 比率,类似于区间,只是比率刻度的基数为零。像身高和体重一样,它们都有确定的零,因为没有负的身高和体重(而温度可以降到零度以下,因此它是一个区间,而不是比例)。

某些数据比其他数据更容易受到其他数据的影响。与测量 2)一样,很可能一个人在进行调查时会选择“非常不开心”,这不是因为他/她真的不开心,而是因为他/她在调查前遇到了不愉快的事情,这反过来影响了他/她的情绪。

这些嘈杂的数据被称为混杂因素,是科学家在分析过程中必须控制的因素。尽管如此,从测量 3)和 4)中得到的数据是相对理想的,因为可以应用更强大的分析技术来确定它们的真实值,并且使我们能够跟踪可能的异常。

此外,大多数记者没有意识到只玩一个数据池的危险。例如,如果我是一个健康作家,对写伦敦的药物或合法药物使用感兴趣。

使用 A-B 方法(即精确新闻),我可能会以这样一个推测开始— “人们死于过量非处方药比药物滥用更普遍”

从这里,我将从药剂师的处方、公众通常购买的药物种类以及客户档案中收集数据,并与从警方或医院收集的数据进行比较,以说明死于用药过量或药物滥用的人数、这些受害者的病史以及哪种药物/人最易受影响等。

与 B-A 方法(即数据驱动的新闻)相比,我使用 A-B 方法检查和交叉引用各种数据来源的倾向可能更高,我可能会废弃英国的处方数据库,对我能找到的任何东西进行排名或列表,希望能找到一个有趣的模式。

尽管记者们处理的数据库的数量不会影响一个故事最终变得多么激动人心或有新闻价值,但预防可能发生的【Sokal 事件】 仍然是值得的。

索卡尔事件之所以成功,是因为《社会文本》在审查艾伦·索卡尔的手稿时,没有从其他来源或专家那里寻求证实。随着越来越多的人冒险进入数据使用领域,我们不能否认出现另一个艾伦·索卡尔(Alan Sokal)或不可靠的告密者的可能性,他们玷污了让我们更接*真相的可能性。

通常,媒体用他们自己对科学的定义制造泡沫,而不给公众足够的机会或信心去打破它们,导致我们都生活在看似真实但本质上错误的茧中。那么,在对科学的理解和展示中,我们到底做错了什么?

首先,我们大多数人不区分相关性和因果关系。相关性意味着两个或更多的事情可能是相关的,但我们不确定是否一个因素预测另一个因素,或者是否有其他潜在的方面促成了相关性。

另一方面,因果关系更直接,它意味着某件事是另一件事的结果。尽管假设存在可能的相关性或因果关系,但仍然需要确保这种关系是显著的,而不是偶然的混杂结果。

接下来,我们需要知道,在对科学的理解上,没有所谓的“正确”。大多数科学实验追逐黑天鹅;一只黑天鹅的存在颠覆了天鹅池全是白色的整个观念。所以,没有错的不代表就是正确的;它仅仅意味着它不能被反对。

第三,永远质疑,永远不要一概而论。大多数实验都是以受控的方式进行的,在某些情况下,使用动物样本。因此,我们决不能把这些实验的结果应用到生活在自然环境中的人或动物身上。同样,当一组数据整齐地呈现在你眼前时,不要高兴得太早,很可能它并不能公平地代表总体。

有趣的是,媒体对政治家如此挑剔,而对研究人员或科学家却不是这样。和记者一样,科学家也面临着时间的压力。科学家需要尽快发表新的发现,以击败同行,获得下一笔资助。对以前做过的事情的确认很少被重视,因为没有人喜欢同样的事情被说两次。因此,就p-hacking而言,科学家也会犯错。**

回到“安东尼·诺兰治愈血癌”的海报,如果广告的内容是“你不知道什么是骨髓捐赠”,“你害怕骨髓捐赠”,或“你从未接受过骨髓捐赠”等,可能会更合适。媒体需要利用公众的好奇心,而不是他们的感受。

如果科学让我们偏离神话,数据和研究方法是我们的工具,媒体应该大声告诉我们这一点。

FADL2 L8:“神经”艺术风格转移

原文:https://towardsdatascience.com/fadl2-l8-neural-artistic-style-transfer-a2e6780ab17b?source=collection_archive---------7-----------------------

最*完成了杰瑞米·霍华德实用深度学*的第八课(beta 版第二部分)。在这里,我将回顾一下重建本课 Jupyter 笔记本的一些工作和结果。< 这是 非常 粗糙 >

[ 注意:think part 2 已更名为“前沿深度学*”——应该很快就会公开发布。 亦作TL;dr: 滚动到底部观看视频

我对笔记本的解读可以跟着这里:https://github . com/WNoxchi/kauka SOS/blob/master/fai 02/L8 _ NeuralArtTrsfr _ code along . ipynb

在回顾了库导入和指定limit_mem()以便 TensorFlow 不会吃掉你的 GPU 所提供的一切之后,我必须学* Python 中的‘picking’是什么。结果,多亏了 YouTube 上的 sentdex,这只是 Python 中的序列化。什么连载?显然,它是一个接一个地发送数据流…显然,当你进行大量的磁盘访问时,它是有用的(比如为 ML 读取数据),尽管它不提供安全性,所以要小心网络流。

我试着写了一本小型拉丁语字典:

Learning to Pickle in Python (data serialization)

原来如此。我还没有看过 sentdex 更新的“酸洗和缩放——用 Python p.6 进行实用机器学*”视频,但如果我觉得有必要,我可能会看。

1。内容重建

神经风格转移

NST 正在创建一个新的图像,它保留了一个图像的“风格”和另一个图像的形式。例如,使用两幅输入图片创建一幅文森特·梵高风格的猫的图片:一幅猫的图片,另一幅代表梵高的绘画风格。

这里有几件事很重要。该算法并没有将梵高的风格应用到猫图像本身:它从一幅新图像(像一堆随机的像素)开始,并将其构建成所需的复合图像。

它需要一个已经足够好的模型来辨别两个输入图像的特征。所以,“眼睛在哪里”,“这是一张脸”,“这笔触是一个东西”等等。

第一步是初始化模型(这里是使用平均池并减去 FC 层的顶部块的修改的 VGG16 CNN):

instantiating a VGG16 model using Average-Pooling instead of Max, and excluding the end-block of Fully-Connected layers (we want convolutional features, not classification here)

接下来,我们在 Keras 中定义一个计算图。一个计算图,就我目前的理解,是定义一系列对数据替身的操作。还没有数据传入,但一旦传入,程序就会知道该怎么做。我们这样做是为了定义目标图像

targ isn’t any ‘thing’ yet, but more of an operational placeholder for when this bit of computation occurs.

可以看到,targimg_arrlayer_model的输出(预测)。layer_model是一个Model(keras.models.Model:Keras Functional API),由从其输入到layermodel层组成,我们将其定义为 VGG16 模型的第五个 Conv 块的第一个卷积层。img_arr是经过预处理的原始图像,其预处理方式与 VGG 作者在训练其模型时预处理其 ImageNet 数据的方式相同。

注意 : layer是卷积子模型结束时的输出激活。layer_model是从原模型开始到layer定义的子模型。targ是目标激活。损失函数试图使layertarg尽可能靠*。

这种措辞可能会令人困惑,但是当你在代码中浏览它时,它更有意义。我们在整个笔记本中使用 Keras 定义了几个这样的图形。

为了让算法衡量它做得有多好,它需要以某种方式量化它的进展:一个损失/目标函数。

为此,我们将损失定义为输出层和目标图像之间的均方误差

evaluator是一个自定义的Evaluator类,允许程序单独访问损失函数和梯度,因为 Keras 一起返回它们,但优化器需要单独查看它们。

这个evaluator,连同迭代次数,以及随机图像x,进入solve_image(•),完成优化损失的工作。

所有这些都是通过将原始图像的 conv 特征应用于随机生成的图像并更新损失函数来从原始图像中重建图像。

基本思想是:我们通过子模型运行原始图像和新的随机图像,并使用我们的损失函数来确定它们的匹配程度。我们使用来自scipy.optimize.fmin_l_bgfs_b线搜索算法作为优化器来最小化损失。当我们下一步从一个样式图像中合并样式时,我们将使用权重来平衡我们想要在多大程度上重新创建原始图像,而不是应用样式图像的样式。

loss is the sum of style_loss-es for all layers & targets. style_loss is the mean-squared-error between the gramian matrix of the layer, and the gramian matrix of the target. The Gram Matrix is the dot-product of a matrix with its own transpose. ~ I think I remember in lecture, Howard saying no one really knows why it works … but it works.

所以我们最终得到的,用我的猫 Terek 作为原始图像:

Terek.

以及生成随机像素的图像:

并通过solve_image(•)进行 10 次迭代:

我们得到了这个不虔诚的怪物:

How cats actually see

Here’s an animation of it (the videos in this post were all first taken on Instagram as I was coding)

尽管这看起来很糟糕,但实际上非常有趣。请记住,这种算法是采用马赛克或随机像素,通过我们上面定义的 CNN 来重建猫的图片,并根据新(目标)图像和网络中原始激活之间的均方误差来优化网络的权重和激活。这意味着将根据卷积网络中表达的特征来构建目标图像。所以这个模型必须能够区分眼睛和背景等等。较低的卷积块将为我们提供更精细的特征,而稍后的卷积块将为我们提供模型中更多的宏特征。因此,我们可以通过使用更早的卷积层来获得看起来更像原始图像的输出。

2。风格重构

为了重塑风格,我们必须做更多的事情。我们通过计算多层的损失函数来改变它。引用原始笔记本:

在我们计算原始卷积输出的 MSE 之前,我们先将它们转换为信道的“格拉米矩阵”(即矩阵与其转置矩阵的乘积),然后再计算它们的 MSE。目前还不清楚为什么这有助于我们实现目标,但它确实有效。一种想法是 Gramian 显示了我们在卷积层的特征是如何相互关联的,并且完全删除了所有的位置信息。所以匹配通道的 Gram 矩阵只能匹配某种类型的纹理信息,而不能匹配位置信息。

style_arr is the preprocessed style image. shp is the shape of style_arr. Note the major difference from before being that we’re building arrays from layers. Specifically 3 layers: for the 3 color-channels.

loss is the sum of style_loss-es for all layers & targets. style_loss is the mean-squared-error between the gramian matrix of the layer, and the gramian matrix of the target. The Gram Matrix is the dot-product of a matrix with its own transpose. ~ I think I remember in lecture, Howard saying no one really knows why it works … but it works.

这样做,我们就可以了解梵高这幅画的风格:

并将该样式应用于这个随机生成的目标图像:

要在 10 次迭代后获得梵高风格的随机像素图像:

3。风格转移

最后是风格转移。我们得到了 1。投入再创造。2.风格休闲。现在把它放在一起:

这是以(最终)直观的方式完成的:通过加权和添加两个损失函数来组合这两种方法。和以前一样,我们获取一系列层输出来计算风格损失。计算内容损失只需要一个图层输出。层越低:内容重建越精确。当我们将内容重建与样式合并时:更早的层/更松散的重建将为样式留出更多空间,反之亦然。

这里我们有代码使style_layers成为块 1 到 5 的第二卷积层;以及content_layer块 4 conv 层 2 的输出(激活):

The style and content models become submodels of the full model’s input to the respective style and content outputs. NOTE: the style target outputs/activations correspond to their multiple layers. The style targets ultimate take in the style array (preprocessed style image) and likewise content target takes in the preprocessed source image (src).

这创建了三个独立的输出类型:原始图像,风格图像,以及我们正在训练的像素的随机图像。

最后,创建一个应用于样式输出激活的权重数组。这调整了图像重建和风格转换这两个层面的组合。注意:这是内容丢失的一个因素。系数越小(分母越大),样式对最终图像的影响就越大,直到它完全掩盖了任何原始内容。

必须在全风格全商务之间找到最佳平衡点。

This does the thing

以下是一些结果:

我偶然得到了一幅电源插头的印象派画作:

卷积神经网络需要固定的输入大小,因此内容、风格和输出图像必须具有相同的维度。因此,当我对我的猫的图片进行适当的裁剪时,我忘记了调整它,得到了左上角,和我用来设计风格的一幅小鸟画的尺寸一样。

Artistic inspiration brought to you by Snapchat…

最后,确保我做的事情是正确的:看看我是否能在相同的输入图像上得到与杰瑞米·霍华德相同的结果:

肯定有些不同,当然也有相似之处,我喜欢这是第一次运行。我肯定对做好风格转移感到兴奋,就像你将在这里找到的一样:https://github.com/titu1994/Neural-Style-Transfer

足够幸运的是,看起来像“蒙版”等技术将在第 9 课中涉及,所以我甚至不需要额外学*。

所以,最后一点:这不是一个从头学*的帖子。为此:你必须浏览课文和原始笔记本。但是如果你正在做这个并且想要一些额外的想法,那么希望这是有帮助的。

我喜欢人工智能的另一点是它提供了粗略但精确的文件夹名称:

非常感谢杰瑞米·霍华德瑞秋·托马斯将 fast.ai 组装在一起

发射失败:IT,我们有一个(自助服务)问题!

原文:https://towardsdatascience.com/failure-to-launch-it-we-have-a-self-service-problem-ced1e4f7980?source=collection_archive---------4-----------------------

虽然现代自助服务正在为消费者服务,但 IT 自助服务门户却停滞不前。然而,IT 向客户提供世界范围的服务是一项非常重要的任务,不能放弃。相反,我们必须对我们的现状进行诚实的评估,并规划一条新的前进道路。

在我与 IT 领导者的交谈中,我经常听到一些轶事,如“亚马逊、优步和 AirBnB 等公司对自助服务设定了不切实际的期望”或“人们就是不喜欢自助服务”。虽然这种说法可能会起到暂时缓解的作用,但它们正在让 IT 接受平庸。事实上,人们越来越多地接受(如果不是期望的话)利用自助服务来处理我们个人生活中的大量日常任务,例如安排约会、购物和在线支付账单,而无需与客户服务代表直接联系。

IT 自助服务的采用停滞不前并不是因为缺乏需求。事实上,根据 Forrester Research 的调查,72%的客户更喜欢通过自助服务来解决他们的支持问题,而不是打电话或发电子邮件。同样,越来越多的员工希望在工作中获得与消费者相同的便捷和简单的服务体验。

自 It 服务目录在 ITIL 第 3 版中首次推出以来,已经过去了多年,但大多数 IT 组织仍在努力有效地管理 IT 自助服务的实施、推广和利用。平心而论,现代消费者自助服务产品在“诞生于云中”以及能够利用社交和大数据进步方面肯定具有优势。然而,IT 自助服务门户必须应对问题和认知,这些问题和认知通常是遗留工具和不太完善的流程的产物。

例如,IT 自助服务主要关注 IT 的优势,而不是客户体验。许多首席信息官从 IT 效率和员工数量的角度来看待自助服务,服务台经理寻求减少呼叫量的灵丹妙药,IT 分析师则想象空票队列。自助服务最重要的地方——用户体验——就是今天所提供的服务被打破的地方。用户发现当前的门户令人沮丧、复杂且效率低下。

大多数 IT 自助服务门户都是使用静态服务目录构建的,这些目录要求用户手动搜索详尽的技术列表,以找到他们需要的资源。一旦用户选择了一个项目,他们通常会获得一个表单链接,或者需要致电服务台提交请求。客户需要的是一个可操作的服务门户,它提供符合其工作职能、位置和角色的 IT 服务产品的个性化视图,并以有限的摩擦快速交付请求的服务。

缺乏个性化和自动化,加上服务门户的复杂性,让用户感到沮丧,并最终迫使他们回到传统的支持渠道,如语音和电子邮件。以用户为中心设计门户体验是推动自助服务采用的必要条件。这需要超越实现一个闪亮的 UI。IT 必须确定将激励员工利用自助服务的业务目标,然后将这些目标与服务门户中可用的适当 IT 资源相关联。

随着业务增长对创新技术的依赖,将业务用户与即时 IT 服务结合起来将需要一种迭代方法,包括持续的客户输入。但是,它还可以访问服务目录、CMDBs 以及财务和人力资源系统等中的大量用户相关数据。有效地聚合和呈现这些有价值的信息需要 IT 部门重新思考服务的交付方式,并使用数据来持续监控和提高自助服务的可用性。向前向上!

公平的警告:女人、财产和预算的孤岛

原文:https://towardsdatascience.com/fair-warning-islands-of-women-property-and-budgets-88d5128ac7b9?source=collection_archive---------7-----------------------

你好!如果上周的简讯严重缺乏和低能量(悲伤),那么本周的又回到了正轨!

如果你没见过猫敲钟觅食,你可能应该去看看。

报名每周日收件箱收到公平预警

在国内

我真的很喜欢《卫报》的这篇文章——投票支持英国退出欧盟的英国地区的情况会更糟。我真正喜欢的是以如此简单的方式显示数据的图形。这些地图清晰易懂,并能产生立竿见影的效果。

伦敦的豪宅业主似乎无法转移他们的房产(有人感到惊讶吗),所以他们转向 AirBnB

英国大部分地区(57.9%)没有本地报纸——这是来自这张本地新闻地图的令人震惊的统计数据,它显示了(或缺乏!)当地新闻来源。安德鲁·布莱特韦尔

在池塘那边

美国人对唐纳德·特朗普的看法简史。

CNN 制作了一张今年在美国成为目标的清真寺的地图。

很好的互动展示了蒙特利尔的建筑有多古老。

NPR 的《一张图中的美国工作日》很不错,尽管我不知道四处点击看看不同的行业有多吸引人。他们自己对数据进行了一些探索,这很好,因为我不确定我是否会寻找午餐时间的差异,或者将建筑工人与厨师进行比较。

《华盛顿邮报》查看了过去 40 年的预算,以比较不断变化的国家优先事项。同样在川普的预算上,美联社创造了一个尺度来平衡预算的削减和增加。只有五家机构将获得更多资金;其他一切都被削减了。

这是一张美国每平方英尺房产价格的地图(H/TCharles Arthur)——在 3D 环境下使用有点奇怪,但你可以通过拖动和使用鼠标滚轮放大和缩小来操纵它。

在别处

《卫报》的全球发展网络关注了千年发展目标的成功程度。2100 万额外的生命被挽救,4.71 亿人摆脱了贫困,但这是一幅复杂的画面。

根据饥荒预警系统网络,今年将有 7000 万人需要粮食援助。《经济学人》研究了非洲和也门即将发生的饥荒是如何有政治原因的。

《印度斯坦时报》选择了一种非常有趣的方式来形象化政治中的性别差距——去掉所有没有女性候选人的地理区域,剩下的就是女性孤岛。

零碎东西

泰坦尼克号上的生死。

这是查尔斯·密纳德的一个很棒的简介,他以拿破仑三月的形象化而闻名(这很特别)——但是他实际上做的远不止这些!同样值得一读的是——寻找画有密纳德画作的艺术品。

交互式图形的问题是没有人真正使用它们。这引发了我长久以来的思考,也是一个棘手的问题——你如何在图形设计和交互性方面拓展边界,同时确保用户从中获得最大收益?关键是个性化。

Steve Wexler 写了他如何在看到一个很棒的图表示例后,学会了喜欢 Marimekko 图表并理解它的用例。我不得不同意艾玛·威特版本的图表确实让任何其他的想象都相形见绌。

本周最差图表

啊,不:

这星期就这些了!感谢阅读。如果你喜欢这篇时事通讯,把它转发给别人,鼓励你的朋友注册,或者请我喝杯咖啡以示感谢。评论?回复这封邮件。如果你认为我们可以一起工作——让我们聊聊吧!在 Twitter 上找到我@ soviewernes

假新闻和数据科学家的责任

原文:https://towardsdatascience.com/fake-news-and-the-responsibility-of-data-scientists-b74d176d7bd1?source=collection_archive---------3-----------------------

Photo by Bank Phrom on Unsplash

95%的统计数据都是编造的。

关于事实与真相的讨论最*出现了很多,特别是随着“假新闻”的泛滥和新闻媒体对某些事实(以及非事实)的报道。我们听到到处都是人们提起热点问题并声称“90%的人同意我的事实!”“我有证据证明 X 发生了——这是事实!”像 snopes.com、politifact.com 和 factcheck.org 这样的网站的存在是为了消除这些“事实”中的政治偏见和解释,但是我们为什么需要这样的东西呢?是因为记者主动编造信息,故意骗观众吗?或者,他们只是简单地调整了一些确凿的事实,使之符合他们偏好的叙述?

Credit: National Review

在上图中,国家评论(通过 Twitter)显示,从 1880 年到大约 2015 年,全球平均气温几乎没有变化。这里要问的重要问题是:

  1. y 轴是怎么回事?为什么有这么大的空间?
  2. 如果我们垂直放大会看到什么?在这(极其)广阔的数据视野中,是否隐藏着某些趋势或周期?
  3. 全球年平均气温的显著变化是什么?50 度?. 5 度?

Credit: NASA

美国宇航局公布了相同的数据,但垂直轴更紧。当我们放大时,很明显,自 20 世纪初以来,全球平均气温一直呈上升趋势。此图中要问的重要问题是:

  1. 1900 年之前发生了什么?毕竟,地球已经存在了一段时间。我们有可能在寻找另一个局部最大值吗?我们应该期待这种循环自然逆转吗?
  2. 同样,随着时间的推移,什么会被认为是平均温度的显著上升或下降?

亲爱的读者,我知道你在想什么,我保证不会把一些伪装成假新闻的情绪化/错误的政治宣言扔给你,但重要的是要注意,在更广泛的背景下,你从新闻评论员那里听到的东西并不总是事实,同时也不一定是彻头彻尾的谎言。

它们是事实——或者换句话说,它们是通过报道者的视角呈现给消费者的事实。诚然,在政治背景下,这经常被用来满足党派议程或引导消费者相信一个人而不是另一个人,但这不是我真正想讨论的。

事实与真相,在上下文中

我们在党派新闻报道中看到的同样的偏见无处不在——存在于我们依赖某人(或某事)来吸收事实并代表他人解释它们的所有地方。

对于我们关于数据科学的讨论,请允许我将事实和真相分别归结为数据和数据的表示。更深一层来看,数据只是。。。嗯,数据。列和行的原始信息通常完全不受解释偏差的影响(尽管对于任何实验,数据科学家都应该意识到人类天生倾向于通过糟糕的实验设计来偏差数据,但我们现在不去管研究偏差)。

另一方面,真相是从数据的解释中得出的结果。正如生活中人们需要提取原始数据的其他地方一样,作为消费者,我们看到的是对原始事实的有偏见的表示,强调对解释者产生最大影响的东西。换句话说,真相有可能有多种有效版本,所有版本都基于同一组事实。

对此的第一反应是思考“为什么我们不跳过中间人,向消费者提供原始的、不带偏见的事实,而不是一些扭曲的事实?”这是一个公平的观点,但通常消费者要么不知道如何解析原始信息,要么根本不在乎;这非常耗时,需要大量的主题知识和专业技能,并且在现代应用程序的环境中,会严重破坏愉快的用户体验。想象一下,你不得不查询网飞的数据库来决定接下来该看哪部蒸汽吸血鬼动作惊悚僵尸恐怖喜剧(不,谢谢)。

因此,如果向消费者提供原始事实是无效的,并且提供一个更简单、更精炼的事实会受到解释偏差的影响,那么我们还有什么选择呢?这就是数据科学专家的道德和义务所在。

数据科学家的责任

在让数据自己说话和提供平台(肥皂盒?)数据的最重要特征对消费者来说是最明显的。在实践中,构成“重要功能”的标准是高度个案化的,基于用户是谁,用户需要完成什么,以及知道用户能够影响什么过程(参见:用户体验研究)。

更简洁地说:通过数据科学家吸引用户的信息传递来实现对事实的最佳呈现,同时非常小心地确保所呈现的数据不会

以下是实现这一点的几种方法:

  • 了解你的用户:了解他们的需求、技术能力、可用性/交互/体验偏好,以及最终什么样的信息将帮助他们做出最佳决策。数据科学家通常会忽略这一步,直接进入数据,但请记住,回到基础,问一些“愚蠢”的问题,并确保不做不切实际的假设总是没问题的。这很重要。
  • 保持透明:教育是数据科学家最大的盟友!商业用户变得越来越复杂,通常不再认同“神奇的黑匣子”的概念:他们想知道引擎盖下是什么,是什么在驱动引擎。以我的经验来看,它有助于指导用户(在高层次上)完成你所进行的不同类型的实验,为什么某些模型比其他模型更好,并突出你在数据中发现的有趣信息——它让他们继续投入到探索过程中,并让他们对最终产品有更大的欣赏力。
  • 注意而不是提供领先内容(未经消费者同意):提供行动号召是没问题的(事实上,这通常是首先进行数据科学的原因),但重要的是要知道,无论你的分析产生什么样的行动号召,都不是在“欺骗”用户。例如,显示一个带有暗红色指示器的图表可能会让消费者认为他们正在查看的数据是负面的或不受欢迎的;再加上不相称的坐标轴(正如我们从《国家评论》中得到的数据),你就得到一份相当误导性的分析报告(这个词我在本文中用得很不严谨)。如果你不确定你的可视化、统计等等的含义,那么和你公司的 UX 专家一起工作;根据我的经验,他们在数据科学中的角色被严重低估了。

假新闻分类器(使用 LSTMs)

原文:https://towardsdatascience.com/fake-news-classifier-e061b339ad6c?source=collection_archive---------3-----------------------

本课是 DeepSchool.io 提供的课程的一部分,我们使用深度学*(递归神经网络)将一组文章分为‘假’和‘真’新闻类。

参见下面的视频或在https://github.com/sachinruk/deepschool.io(第 18 课)获得的代码,了解所用模型的解释。

我们拥有的数据集是一组围绕 2016 年美国大选期间撰写的新闻文章。在第二个模型中,我们利用预先训练好的手套向量来进行迁移学*。如果不使用这些方法,就存在过度拟合的实际风险,如第一个被训练的模型所示。

真的是在学*什么是假新闻吗?不会。如果一个好记者写的内容和假新闻一样,他很可能会把假新闻归类为真新闻。请记住,模型不知道世界的实际状态。事实上,“特朗普总统是有史以来最伟大的总统。”根据我的模型(wtf),有 73%的概率是一篇真实的新闻文章。

这可能是学*功能,如希拉里被提到了多少次,或者 CNN(电视网络,而不是神经网络类型)被提到了太多。也许网络会询问作者是否来自“信息战争”(由极右翼疯子/精神病患者/讨厌同性恋青蛙的人经营)。

请看这里关于如何在 scikit learn 中使用 TfIDf 解决相同问题集的博文。它实际上在 93%的准确率上做得更好(RNN 模型大约是 87%的准确率)。虽然 scikit learn 确实比深度学*表现得更好,但重要的是要理解,你必须在“正常”的机器学*方面进行特征工程。

外卖食品

总之,深度学*是避开机器学*的特征工程方面的一个很好的方法。与单词袋方法相比,我们可以通过使用 RNN 来保持句子结构。手套向量的使用是减少我们必须训练的参数数量的重要一步,因此减少了过度拟合的风险。

如果你喜欢我的教程/博客帖子,可以考虑在https://www.patreon.com/deepschoolio支持我,或者订阅我的 YouTube 频道https://www.youtube.com/user/sachinabey(或者两者都支持!).哦还有拍手!😃

生成假卫星图像—训练 GAN

原文:https://towardsdatascience.com/fake-satellite-images-training-a-gan-437424d3cb6b?source=collection_archive---------4-----------------------

学* 39 种不同的技巧,让 GAN 走向成功

除了在 Coursera 上学*吴恩达的 ML 课程之外,我以前从未做过神经网络。发誓!那真是一门课程!转行。不是吗?

通常,每当我感到技术转向的威胁时,我就会提出一些结合了许多未知因素的宠物项目。它帮助我探索空间并获得一些舒适的感觉。正是在这条线上,我开始了我的宠物项目,训练一个甘生成航空卫星图像。所有涉及的技术—神经网络、CNN、GAN、Tensorflow、Python 等。对我来说都有些陌生。所以,从我的角度来看,这是一个有价值的项目。

第一步是获得一些低分辨率的卫星图像。我在网上找到的图片都很大。23000x12000 左右的样子。每当我打开 PIL 的 Python 图像处理库来调整它们的大小时,它都会崩溃。无论如何,将如此高分辨率的图像调整到 64x64 会破坏所有的细节。这似乎不是一个好主意。那时我发现了“通用地图下载器”软件,它可以从你选择的地理区域下载 256x256 的图像。免费版本只下载了 50 厘米低分辨率的卫星图像,这对于我的实验目的来说是可以的。

Courtesy: Screenshot of the Universal maps downloaded taken by me

这是一个干净的软件,做它承诺要做的事情。下面是软件下载的一些真实图片。对于寻找真实卫星图像的从业者来说,“亚马逊地球”是一个非常有前途的资源。我相信它是从美国政府的地球资源卫星项目获得图像的。

Map images downloaded by Universal maps downloader — Screenshot taken by me

我兼职工作了 5 个月,让这个项目运行。如果我有一些先验知识,并且全职使用 GPU 的话,花费的时间会少得多。我从头开始开发所有代码,没有重用任何存储库中的任何代码(除了来自 OpenAI 的 RelU 函数)。所以这给了我一个犯很多错误的机会,我把这些都记录在这里供你参考。希望这有所帮助。

本文档分为以下几个部分

  1. 如何不训练一个甘
  2. 云 GPU 提供商之间的快速比较:Crestle 与 FloydHub
  3. 生成的图像
  4. 图灵检定
  5. 图灵测试答案

如何不训练一个甘

我将这一部分组织成 4 个部分,每个部分讨论潜在的“错误”

  1. 一般准则
    —未遵循标准架构
    —低估计算需求
    —未对 GPU 进行培训
    —未使用内存中的图像进行云 GPU 培训
    —未维护观察日志
    —未初始播种 RNG
    —混合单色/彩色图像,输入不佳
    —未标准化输入
    —未进行中间模型检查点
    —未转储生成的图像以检查学*情况
  2. TensorFlow 相关指南
    —不使用图像格式
    —缺少来自 API 的隐式规范化
    —使用 TF 读取/写入图像
    —创建孤立张量
    —在同一个调用中同时运行 opt 和 loss
  3. 神经网络相关指南
    —未保持生成器/Discr 对称
    —未对最终生成器使用 TANH
    —未对偏差使用零初始化器
    —未使用 Xavier Init
    —未使用正确数量的滤波器组
    —未使用步进卷积代替汇集
    —未使用泄漏 Relu
    —未使用批处理归一化来加速计算
    —未使用正则化器
    —未选择正确的正则化器常数
    —在批处理中进行归一化
  4. 培训相关指南
    —将所有 CPU 内核专用于培训
    —不将输入图像转换为-1 和+1
    —运行较少的迭代
    —非常高的学*率
    —重用 Adam 优化器对象
    —不使用历史图像进行培训
    —为历史目的生成单独的图像
    —不执行历史图像转换
    —将生成器置于鉴别器之上
    —强大的 Discr/强大的 Gen
    —具有批处理规范的 Net arch
    —取消

通用指南

错误 1

不遵循标准网络架构

DCGAN 是一个很好的架构,它们适用于 64x64 图像。Github 中有一些例子——open ai 和 Carpedm20 的 DCGAN Tensorflow 实现。

不要尝试任何新颖的架构。只要实现基本的 DCGAN 正常工作。这本身会帮助你正确理解许多基础知识。

在没有完全实现 DCGAN 架构的情况下,我开始对网络进行随机更改。我有更少的层,每层有不同数量的滤波器组,等等。我想很快看到我得到的输出…但你在 GAN 中很快得到的只是 BS。你不会希望这样的。

错误 2

低估计算需求

深度学*需要大量的计算。不要低估这一点。

如果你的笔记本电脑/台式机有发热问题,我不建议运行深度学*。你会把它融化的。不要把发热的笔记本电脑放在床上或易燃的地方。Table mate 是远程连接笔记本电脑的好选择。它由纤维制成,不会受热。

对于计算,如果你有机会的话,GPU 无疑是最好的选择。

如果你受到笔记本电脑/台式机 CPU 或类似设备的限制,从一个适中的目标开始(比如说较低的图像分辨率),一旦你清楚如何解决这个问题,就选择基于云的 GPU。

我从 256x256 的图像生成开始,并不知道我在做什么。在我的笔记本电脑上训练它需要一年的时间。糟糕的选择。

错误 3

不在 GPU 上训练

如果你不在 GPU 上训练你的 GAN,你可能哪里也去不了。初始形状的出现需要将* 1000 次迭代。

20000 次迭代的训练很常见。

如果你在 CPU 上运行,这些训练可以一起运行几天,在你决定取消一个模式崩溃(或)一个不稳定的训练路径之前,需要几个小时。

超参数调谐也非常困难。它会耗掉你所有的时间。不值得。

错误 4

在云上使用 GPU 驱动的笔记本电脑进行培训时,不在内存中保存图像

FloydHub / Crestle 这样的云 GPU Jupyter 笔记本提供商往往有一个缓慢的 IO 子系统。他们可能使用亚马逊 S3 或某种 Blob 存储或一个新颖的文件系统来存储你的文件。这意味着,每次迭代从这些存储器中读取图像会非常慢。

如果没有足够的内存,在处理当前批处理时,使用异步 IO 读取下一个批处理。将 GPU 计算与 IO 重叠也是一个好主意!

错误 5

没有维护观察日志

保持一个观察日志,记录你所做的所有改变,你所看到的效果等等。这确实有助于避免一次又一次地犯同样的错误。

你也可以把“待定清单”放在另一张纸上,这样你就不会错过你的想法。

错误 6

未初始播种的 RNG

在开始时用一个常数作为 RNG 的种子是很重要的,这样你就可以理解你的超参数变化实际上是如何影响学*的。

tf.set_random_seed(1234) *#Lets inspire some Determinism*

通过将连续运行的中间输出与配置变化进行比较,您可以看到学*是进行得更快了(还是变慢了(还是退化了)等等。

不确定 RNG,你不能对你的超参数变化做出任何推断。观察日志将不会有用。

错误 7

在输入图像中混合单色和彩色图像(或)输入图像中的不良特征

保持输入的一致性和丰富的特性

有时,我们可能会在输入中混合单色和彩色图像。由于单色只有一个通道,而彩色图像有三个通道,混合它们会在处理时导致错误。有时,当你创建一个有几千幅图像的数据集时,你的处理会在某一批中失败,你需要一段时间来解决这个问题。这是真的,尤其是如果你没有在初始化期间一次读取所有的图像。

错误 8

未标准化输入

标准化输入将避免大的 logit 值,这反过来会破坏梯度和学*过程。这是我学到的第一件事。如果您使用的图像值在 0 到 255 之间,请在 0 到 1 之间转换它们。

如果你想一想神经网络是如何工作的,图像值乘以权重,相加,并用于 sigmoid/Relu 激活。当结果值很大时,曲线在这些区域或多或少是平坦的,因此梯度很小,并且它不会推进学*。梯度是学问。如果没有梯度,那么就没有学*

错误 9

不检查模型,仅在所有迭代完成后保存

任何可能出错的事情都会出错——墨菲定律。

为了确保故障恢复,总是每 500 次迭代左右检查一次模型。很容易从离开的地方恢复。Tensorflow 支持此操作的简单 API。模型保存会导致创建共享相同模型名称前缀的多个文件。您可以简单地单独使用 model-name 前缀来加载和保存模型。

确保在获得最终输出后,手动清除所有检查点。GAN 型号会留下巨大的磁盘空间。

saver = tf.train.Saver()
savePath = saver.save(session, 
                 outputFolder + "/" + thisRunTime + "." + str(step))....SavedModelCheckpoint = "/home/nbuser/output/1510295650.2870145.4000"
restorer = tf.train.Saver()
        restorer.restore(session, SavedModelCheckpoint)

错误 10

不转储生成的图像以检查学*情况

这相当简单明了。每 10 次迭代,总是转储一个随机生成的图像。你会知道训练的方向。

注意:生成的图像是一个“噪声”向量的函数。根据“噪声”矢量的不同,生成的图像可能看起来很好(也可能很差)。所以,如果你看到生成器有时生成愚蠢的图像,并不意味着它已经退化了。只是随机噪声向量可能是一个不太可能的向量。不要试图过多解读被甩的形象。

TensorFlow 相关指南

错误 11

在 TensorFlow 中没有使用正确的图像格式

大多数与 NN 相关的图像操作,如 tf.nn.conv2dtf.nn.conv2d_transpose 接受 4 维张量。4D 通常用于 RGB 图像阵列。

Tensorflow APIs 支持两种图像格式——NHWC 和 NCHW。

NHWC 布局——【批次、高度、宽度、通道】

NCHW 布局——【批次、通道、高度、宽度】

根据您阅读输入文件的方式选择相关的选项。默认值是 NHWC,应该没问题。但是如果您的图像不同,请确保在 API 调用中指定了格式。

错误 12

缺少 API 完成的“隐式”规范化

Tensorflow 提供了TF . image . convert _ image _ dtypeAPI,当您将“数据类型”从“uint8”转换为“float”时, 会自动在 0 和 1 之间缩放图像。0–255 Int image 映射到 0–1 float image,反之亦然。如果你再把图像除以 255。,那你就要承受一些无声的痛苦了。

这是我在文档中没有正确阅读的内容。转储正在传送到网络的图像。这将给出一个好主意,如果事情按你认为的方式运行。

错误 13

使用 Tensorflow APIs 读取/写入图像

是的。不要用 TF 看图像。在 Tensorflow 中将图像读取为 Numpy 数组并不简单。至少,不像我希望的那样简单。一些文档谈到队列管理器(为了什么?和做其他体操——对于做一件简单的事情来说,这太复杂了。在这方面,我可以理解“张量流很烂”的家伙。

使用“matplotlib”将文件读取为 Numpy 数组。这是一个干净的选择。参见下面的代码片段,这是一个很好的例子。

**import** **matplotlib.pyplot** **as** **plt**
**import** **matplotlib.image****def** listFolder(folder) :
    f = []
    **for** (dirpath, dirnames, filenames) **in** walk(folder):
        jpgfiles = list(filter(**lambda** x : x.split(".")[-1] == "jpg" **or** x.split(".")[-1] == "jpeg", filenames))
        f.extend(jpgfiles)
    **return** f**class** **originalDistribution** :
    **def** __init__(self, imageInputFolder):
        self.srcFolder = imageInputFolder
        self.listOfFiles = listFolder(self.srcFolder)
        np.random.shuffle(self.listOfFiles) *#Inplace shuffling*
        **if** floydRun **or** crestleRun:
            self.imagesInMemory = np.asarray(list(map(**lambda** x : matplotlib.image.imread(self.srcFolder+"/"+x), self.listOfFiles)))/255.
        **else**:
            self.imagesInMemory = np.asarray(list(map(**lambda** x : matplotlib.image.imread(self.srcFolder+"**\\**"+x), self.listOfFiles)))/255.*And so on.......*

使用 matplotlib API 保存生成的图像,该图像是一个 numpy 数组

**import** **matplotlib.pyplot** **as** **plt**
**import** **matplotlib.image**plt.imsave(tempImages + "**\\**GEN_STEP_" + '**{:05d}**'.format(step) + ".png", genMap[0], format='png', vmin=-1, vmax=1)

使用 Tensorflow 占位符将读取的图像提供给 TF 图

inputTensorPlaceholder   = tf.placeholder(tf.float32, shape=(nSamples, inputheight, inputwidth, inputchannels)) ....._ = session.run([d_opt_1], feed_dict={ 
                        inputTensorPlaceholder: inputNumPy,
                        realBenchmarksPlaceholder:benchmarkones 
                                    })

错误 14

创建孤立张量。

这将导致你的程序内存泄漏,从而导致“应用程序失败”和一些“窗口冲击”。嘿!为什么 windows 不能直接运行它?Linux 将震撼它。不是吗?没有。孤儿张量吸内存!

下面是孤立张量的一个例子。我使用下面的函数为每次迭代从文件系统中读取“小批量”。从磁盘读取本身是一个坏主意,我们稍后会看到。但重要的一点是,这些张量只是呆在外面,没有被清理,等待会话结束。这将逐渐耗尽您的系统内存,尤其是当您运行 1000 次迭代时。这会毁了你的周末跑步。

# 
# DON'T USE THIS FUNCTION
# MEMORY LEAK AHEAD
# YOU HAVE BEEN WARNED!!
#**def** makeImageTensor(filename):
    fileTensor = tf.read_file(tf.convert_to_tensor(filename))
    intImage = tf.image.decode_jpeg(fileTensor, channels=inputchannels)
    floatImage = tf.image.convert_image_dtype(intImage, tf.float32)
    **return** floatImage .............#
# Repeatedly calling the code below will cause memory leak
#*inputImageTensorList = [makeImageTensor(x) for x in imageFiles]*
*inputImagesTensor = tf.stack(inputImageTensorList)*
*inputNumPy = inputImagesTensor.eval()
session.run([some list], 
            feed_dict={inputImageTensor: inputNumPy and so on...})*

错误 15

在一次运行中同时运行优化器和损耗

下面的代码是不确定的,因为 TensorFlow 没有指定其操作的执行顺序。因此,无法确定“d_opt_1”是在“d_real_loss”之前还是之后运行。那么,上报的“d_real_loss”是优化前的还是优化后的呢?

#
# This code below is NOT deterministic
#_, l, dregloss, dt1 = session.run([d_opt_1, d_real_loss, d_reg_loss, DiscriminatorGraph], 
                     feed_dict={  
                        inputTensorPlaceholder: inputNumPy, 
                        realBenchmarksPlaceholder:benchmarkones,
                               })

运行优化器后,始终在单独的 session.run()调用中运行“loss”。这样,你就可以确定,打印出来的损耗是经过优化的

神经网络相关指南

错误 16

未保持发电机和鉴别器对称

DCGAN 论文没有全面讨论鉴频器架构(或者)可能只是一个参考。选择对称的架构。如果在生成器中有 7 层,确保在鉴别器中有相同的层。

这也可能与鉴别器和发生器的等功率配置有关。

错误 17

最终发电机输出不使用 TANH】

TANH 激活返回-1 到+1。这是 DCGAN 中建议的,在 OpenAI 代码中也可以看到。不知道为什么。用一样的,开心就好。

错误 18

用非常数、非零初始值设定项初始化偏差

所有的偏差变量必须用一个“常数”初始化器初始化,初始值为“0”。

这将允许算法学*它自己的偏差。在没有任何显著原因的情况下,最初保持较大的偏差会使训练过程极其缓慢,因为偏差会对成本产生如此大的影响,以至于其他变量将不会正确地看到它们的效果(以及梯度)。

gb1 = tf.get_variable("gb1", shape=[SecondChannels], dtype=tf.float32, initializer=tf.constant_initializer(0.0),
                              regularizer = g_reg)

错误 19

不使用类似 Xavier / Glorot-Bengio 初始化的细微初始化

批处理规范化确实可以弥补糟糕的初始化的影响。但是一个好的初始化,像 Xavier init 总是受欢迎的举措。所以,不要忽视。

Xavier init 的简单直观的解释可以在 Andy Jones 的博客中找到。

g_dc1_fanin = 5*5*FirstChannelsg_dc1_fanout = 5*5*ThirdChannelsg_dc1_scale = np.sqrt(6./(g_dc1_fanin + g_dc1_fanout))dc1filter   = tf.get_variable("dc1filter", shape=[5,5,SecondChannels, FirstChannels], dtype=tf.float32, initializer=tf.random_uniform_initializer(minval=-g_dc1_scale,maxval=g_dc1_scale), regularizer = g_reg)

错误 20

未使用足够数量的滤波器组

DCGAN 从 4×4 分辨率开始,发生器中有 1024 个滤波器组,逐渐减少滤波器组的数量,同时提高分辨率。

在鉴频器端,由于对称性,也需要类似数量的滤波器组。

我认为滤波器组的数量与所用滤波器的尺寸成正比。这在鉴别器上下文(或)图像分类上下文中是真实的。如果您为 5x5 选择 1024 个存储体,那么您将不得不为 11x11 滤波器选择 4096 个存储体。11x11 可以捕获比 5x5 更多的模式,因此我们需要更多数量的滤波器组来捕获所有变化。这是我的想法。

错误 21

不使用交错卷积,而是使用合并层

DCGAN 论文明显不鼓励使用池层,而是提出使用“步长卷积和“分数步长转置卷积分别用于下采样和上采样。

错误 22

鉴别器中未使用泄漏 Relu

泄漏的 RelU 导致一个强大的鉴别器。不要在鉴别器中错过这个。

根据 DCGAN 论文,这在发电机中是不需要的。但是我的观察日志显示 LRelu 在生成器中确实产生了非常好的结果。但是,由于某种原因,最后成功运行的人从来没有使用它。所以,也可以用发电机来测试泄漏的 Relu!

错误 23

不使用批量标准化来加速计算

DCGAN 建议对生成器和鉴别器都进行批处理规范化。

批处理规范化有助于克服错误的初始化,并可以加速训练过程。

从学*模型生成图像时使用相同的批量很重要(训练后阶段)。如果您使用不同的批量大小,批量统计将会不同,学*的批量标准相关参数将而不是适用

(或)您必须在训练时保存批量统计数据,并对这些统计数据进行加权平均,在生成非标准批量图像时使用这些参数进行批量标准化。

(或)使用 OpenAI 引入的虚拟批处理规范化,而规范化总是针对外部预配置的批处理

错误 24

不使用正则化子

Tensorflow 不强制设置正则项。这取决于你去找一个正则化。

当您运行数千次迭代时,不执行正则化会破坏训练过程的稳定性。

出于某种原因,我找不到关于如何在 TensorFlow 中应用正则化的像样的文档。所以,我只是参考资料来理解它是如何做到的。下面我也总结了一下。

#
# Declare a Regularizer. 
# d_reg is a function which can be called with weights. 
# It returns a Graph that computes L2 regularization. 
# Choose the Constant wisely according to the number of parameters
# to be optimized.
#d_reg = **tf.contrib.layers.l2_regularizer**(scale=DREG_SCALE, scope="REG-DISCR")#
# Pass the declared regularizer when creating Variables. 
# Depending on which scope the variables are created, Regularizer
# will also be associated with the same call
#c1filterVar = tf.get_variable("c1Filter", shape=[5,5,inputchannels,c1Banks], dtype=tf.float32, initializer=tf.random_uniform_initializer(minval=-c1scale, maxval=c1scale), **regularizer=d_reg**)#
# get_reg_loss: Uses TF API to get all regularization related 
# losses corresponding to the "scope" and then add them up using
# tf.add_n() API
# NOTE: The "add_n" is what ties all the loose L2 regularizer graphs
# together into 1 meaningful
#**def** get_reg_loss(regscope):
    **return tf.add_n**(**tf.losses.get_regularization_losses**(scope=regscope))#
# Call the get_reg_loss() with the scope of the variables 
# that you want to regularize.
# d_reg_loss = get_reg_loss(regscope="DISCR")#
# Add the loss to the regular loss
#
d_loss = d_real_loss + d_fake_loss + d_reg_loss

错误 25

没有选择好的正则化常数

使用正则化时,始终打印最终损失分解。这将告诉我们正则化损失占总损失的比例。如果正则化损失在训练开始时很大,您可能需要减少常数

以下是我的配置

Number of Generator Parameters     = 19,154,627
Number of Discriminator Parameters = 19,616,609
Discriminator Regularizer Scaling Constant = 0.0001
Generator     Regularizer Scaling Constant = 0.0001

错误 26

在生成器的最后一层/鉴别器的第一层进行批量归一化

对发生器末端的单个双曲正切单元的输入进行批量归一化将确保输入到双曲正切单元的输入具有 0 的平均值和有限的方差。这一点也不理想,因为我们希望激活在-1 和+1 之间展开。所以,不要批量归一化生成器中的最后一层。

dc5relu = tf.nn.relu(batchNormalize(tf.nn.bias_add(dc5, gb5), "BN_DC5Filter"))#Contrast the above with the belowdc6relu = tf.nn.tanh(tf.nn.bias_add(dc6, gb6))

这同样适用于第一层鉴别器。这将确保生成的图像中的差异传播到下游的所有层。

错误 27

没有做足够的工作来减轻棋盘效应

在生成器管道的末端,TANH 层之前,运行几个卷积转置层,步长为 1x1,分辨率不变,以消除 2x2 和其他步长卷积引入的棋盘效应。我多跑了一层。但是如果你有很好计算能力,你可以多运行几次。确保在鉴别器层中反射相同的光线以保持对称性。我记得在 OpenAI 代码中看到过这个。

培训相关指南

错误 28

将所有 CPU 内核专用于训练

如果你使用 CPU 进行训练,不要为训练分配所有的核心。张量流可以配置。请参见下面的片段。

#
# My laptop has 4 cores. The code below provides the context for the # main training loop.
# Leaving 1 core free for OS and other apps.
# This will ensure machine is interactive despite GAN training
#**with** tf.Session(config=tf.ConfigProto(intra_op_parallelism_threads=2, inter_op_parallelism_threads=1)) **as** session:

错误 29

不将输入图像变换到-1 到+1 范围

认识到生成的图像来自-1 和+1 是很重要的。输入图像归一化后通常从 0 到 1。你还需要 1 级转换才能将它移动到-1 到+1。见下文。

inputImagesTensor = (inputTensorPlaceholder * 2.) - 1.

错误 30

运行较少的迭代次数

看看别人都发表了什么。20,000 次迭代是常见的。即使在你的笔记本电脑上运行了 12 个小时,你也不会在 500 或 700 次迭代中得到任何东西。

学*任何有意义的东西都需要大量的迭代。

错误 31

使用非常高的学*率

非常高的学*率会破坏训练过程的稳定性。

即使您使用了批量标准化和良好的初始化,使用像 0.001 这样的学*率也会使整个训练过程不稳定,这取决于您的批量大小。

可以注意到,较高的“批量”通常可以支持较高的训练速率。后来,我发现这一点在“高效背景”文件中也有讨论。

如果您使用 512 作为您的批量大小,0.001 可以是一个很好的学*率。如果你的批量大小是 64,坚持使用 0.0002 (DCGAN 推荐)

Image Resolution = 64 x 64
Mini Batch size  = 64
Generator Learning Rate     = 0.0002
Discriminator Learning Rate = 0.00015

错误 32

重用 Adam 优化器对象

Adam 优化器是一种状态优化器,与梯度下降优化器相比,建议用于 GAN 训练。但是,重用 Adam Optimizer 对象可能会导致无意义的行为,因为它具有有状态的性质。

Adam optimizer 将梯度计算为过去梯度的指数衰减加权平均值。这个想法是为了加速学*最小值,更快地穿越平坦区域等等。

为每个损失最小化使用单独的 Adam 优化器对象。例如,在我使用的方案中,我使用了 4 个优化器对象。一个用于 D_REAL_LOSS,另一个用于 D_FAKE_LOSS,另一个用于 D_REAL_LOSS + D_FAKE_LOSS,另一个用于 GEN_LOSS。

错误 33

不使用历史图像训练鉴别器

这是我从 Soumith Chintala 的 GAN 提示和技巧博客中学到的。也是 AIDL·脸书集团的史蒂夫·梅西纳建议的。

偶尔向鉴别器提供历史图像有助于打破鉴别器和生成器之间的重复循环,并稳定整个训练过程。

这个在学*过程中绝对有价值。我在主训练循环中花了 30%的时间进行这种训练。只有在包括这一步之后,学*的最初症状才开始出现。

错误 34

生成用于历史目的的单独图像

确保保存用于历史记录的图像在您已经生成的批次中重复使用。

如果您正在为历史目的生成一个单独的图像,那么它将不会像预期的那样工作,因为批处理规范化是有效的。因此,谨慎的做法是从生成的批处理中选择一个图像并使用它。

错误 35

将生成图像的历史记录输入鉴别器时不转换图像

训练过程有时会从缓存生成的历史图像中向鉴别器馈送样本(并非总是如此,因为这是有条件运行的)。当我们这样做时,我们需要注意“图形”路径 可能 期望一个从 0 到 1 值的图像。这个看你的训练逻辑了。因此,如果您的逻辑需要,在将生成的图像存储到历史缓存之前,将其转换为 0 到 1 之间的值。

hc = np.random.randint(0, nSamples) *#history candidate*
candidateForHistory = genMap[hc]
candidateForHistory = candidateForHistory + 1.
candidateForHistory = candidateForHistory / 2.
GCache.addImage(candidateForHistory, step)

错误 36

优先考虑发生器而不是鉴别器

最初,人们更多地关注优化生成器,而不是鉴别器。这是错误的,因为鉴别器是 GAN 中最重要的部分。鉴别器带路,通过提供健康的梯度来教导生成器。

在 GAN 训练结束时,鉴别器滤波器组也可以用于对象检测和开发有效的分类器。由于他已经被大量的虚假图像轰炸,他也不太容易受到对抗性攻击,我想是这样的。

错误 37

强力鉴别器/强力发生器

可以通过增加更多层或增加滤波器组的数量来增加鉴频器的功率。这可能导致模式崩溃,因为鉴别器可能会快速通过并将发电机推到非常糟糕的区域(梯度差),发电机无法从这些区域出来。

同样强大的发电机将没有鉴别器来引导他。歧视者,谁必须领导的方式和教学,现在被制服。这个配置也不好。

稳定的 GAN 训练的理想设置是鉴别器和发生器功能相同,并反复相互学*。

Losses seen in a Successful GAN training. Gen is trained Twice

在上面的图中,我们可以看到发电机总是被训练两次。鉴别器有时分别针对纯 1 损耗和纯 0 损耗进行优化,有时针对 1 和 0 的总损耗进行优化。这个想法是根据损失的进展在两者之间交替,并在训练中保持平衡。更多关于“自由训练”下的精确策略

错误 38

使用批量标准化时选择了错误的张量图架构

Image courtesy: Self made PPT

如果我们在鉴别器中使用批量规范化,上面的架构将会爆炸。为什么?

考虑送入鉴别器的 3 个批次。3 个批次的“批量”和“统计”不同。同意吗?它们的μ适马将影响鉴别器网络内部执行的批量归一化。每批将被不同地标准化。

因此,您会看到,所报告的 D_LOSS 并不表明“Discriminator”能够很好地阻挡 0。所以,你会预计 G_LOSS 是巨大的。但是…然后你会看到 G_LOSS 报告也少了。这是因为批次统计的差异。

与包含“0”和“1”图像的批次相比,完全相同的“0”图像在单独馈送到鉴别器时具有不同的批次统计。这个架构将 而不是 设置鉴频器和发生器之间的战斗。训练将会退化,什么也学不到。啊!

Image courtesy: Self made PPT

上述架构不易受批量定额相关问题的影响,因为批量统计数据不会改变。看一看!

错误 39

自由训练

Goodfellow 博士在 GAN 的原始论文中描述的训练过程谈到在每一步中训练鉴别器“k”次,而在每一步中只训练发生器一次。这是为了确保鉴别器在学*曲线中领先。然而,这种技术依赖于鉴别器和发生器的相对强度。此外,随着训练的进行,鉴别器或发生器很可能变得过于强大,主训练循环不能适应这些动态变化。

在我的训练计划中,我选择了一个动态的计划。我不确定它如何适用于不同的图像数据集。所以,不保证!

在我的设置中,我选择两种不同的路径来训练鉴别器。一条路径使得鉴别器对生成器非常强。让我们称这条路径为-A。另一条路径可能会也可能不会使鉴别器对生成器更强。当 50%的阳性标记被识别为“阴性”或 50%的阴性标记被识别为“阳性”或两者都有时,我选择路径 A。如果没有,我继续更轻的路径-B,为发电机提供呼吸空间。这确保了没有一个变得非常强大,在鉴别器和生成器之间总是有一个平衡,并且它们的学*是交织在一起的。下图显示了确切的逻辑。

此方案的 Adam 优化器的“Beta1”比率必须设置为较小的值,而不是 0.9。这是因为当我们在训练期间在路径 A 和路径 B 之间切换时,连续的运行可能在迭代方面相距很远。我把它设置为 0.5,它工作得很好。

Image courtesy: Self made PPT

快速对比 Crestle 和 Floyd Hub

如果你是一名实验开发者,就去 www.crestle.com。

如果您是一家企业,正在寻求支持、各种平台和专用 GPU 实例,请选择 www.floydhub.com。

两者都以“秒”为单位计算使用量。太好了!

Crestle 提供 GPU (K80)驱动的笔记本电脑,价格仅为竞争对手的一小部分,如 FloydHub ( 0.34 美元(现在为 0.59 美元)对1.14 美元)。Crestle 在你的浏览器中提供了一个 unix 命令行(称为 Jupyter 控制台),可以用来创建你需要的目录,压缩输出文件,解压输入文件,安装你需要的包等等。这叫灵活性,亲爱的。你可以使用 Jupyter 笔记本界面上传你的输入,它只是“干净”。你可以在几分钟内开始。但是使用 Crestle,你需要知道你在一个 Amazon Spot 实例内部。尽管您的文件在 Crestle 中跨运行持久化(这本身就是一个很好的特性),但是您的运行可能会突然中断。哎呀!

与“Floyd Hub”相比,它提供了名为 floyd-CLI 的 Python 包,这是“加载”数据和代码所需要的。这在一开始看起来很傻……但是……Floyd 支持下载/上传的恢复,如果你使用的是不稳定的互联网连接或者你没有备用电源,这将非常有用!Floyd CLI 也在服务器端处理文件的压缩和解压缩。Floyd hub 还以更高的价格提供更好的支持和专用实例。

Floyd Hub 支持使用“装载”将一个作业的输出重新用作另一个作业的输入。与“Crestle”提供的界面相比,这确实是一个复杂的界面。Crestle 只是为你打开了文件系统,你可以按照自己喜欢的方式来读/写。没有挂载,没有命名空间混淆等等。对于像我这样懒惰的简单开发人员来说,Crestle 是一个明显的赢家。

我为我的 GAN 作品选择了 Crestle。我的公司(www.tavant.com)报销所有这些费用。但是,少即是多。不是吗?

生成的图像

Image courtesy: Screenshot of generated images taken by me

想参加图灵测试吗?

Screenshot of images taken by me

图灵测试答案

请稍微滚动一下……

答:假像排列成 N 的图案

假阳性和假阴性

原文:https://towardsdatascience.com/false-positive-and-false-negative-b29df2c60aca?source=collection_archive---------4-----------------------

当你学*假设检验时,有两种错误经常出现—— 技术上分别称为第一类错误第二类错误

起初,我并不热衷于这些概念,我不明白它们怎么会有用。然而,这些年来,我开始改变想法。我对这些错误理解得越多,遇到得越多,它们就越让我兴奋和感兴趣。看到它们在现实世界中的应用和用途帮助我从一个不感兴趣的学生变成了一个热情的老师。

你知道那些疯狂地谈论一个没人理解或想理解的主题的老师吗?对,现在就是我了!这很棒,所以我想通过这篇文章向你展示这两个错误是如何在不同的和有趣的现实生活环境中产生实际影响的,从而让你达到我的兴奋程度。那么希望,看完之后,你会跃跃欲试地把所有关于 和**假***负** 的事情告诉你爱的人。他们真幸运!*

惊呼者:本文不是来教你如何区分两者的。如果你想了解如何做到这一点,我在这里 做了一个关于这个主题的讲解视频。

让错误成为你的朋友。

你认为哪个错误更严重?

一个假阳性(I 型错误)* —当你拒绝一个零假设——或者一个假阴性(II 型错误)——当你接受一个零假设?*

我在很多地方看到这个问题的答案是:一个误报。我不相信这是 100%真实的。

正确的科学方法是形成一个无效假设,让你试图拒绝它,给我一个积极的结果。所以,假设我想看看这篇特定的文章是否比我发布的其他文章的平均表现更好。

考虑到这一点,我会选择零假设:

“我的文章被阅读的次数将与我发布的类似文章的次数相差减去* *

如果我拒绝零假设,这意味着两件事之一。

1。 这篇文章表现中等偏上——太棒了!这是我的正面结果。

2。 我犯了一个 I 型错误。我拒绝了一个为真的无效假设。我的测试显示我的表现高于平均水平,但事实上,我没有。我得到一个假阳性。

是的,在这里我的假阳性有一个坏的结果,我会不可避免地认为我的文章比它是更好的,从那时起,我所有的文章都以同样的风格写,最终伤害了我的博客流量。这无疑会对我的职业生涯和自尊心产生负面影响。

假** 呢?**

如果说这篇文章是博客写作的杰作,但我的测试表明它并不平庸,这种情况就会发生。当然,短期内我不会尝试用这种风格写文章。然而,我是一个有动力的人,会从他的“错误”中学*,所以尝试不同的技巧,有可能创造出更好的作品。

这不是最好的结果,我可能错过了一个机会,但这绝不像假阳性那样具有毁灭性。****

现在,这是一个最坏的情况是假阳性的情况,然而,一个关键的事实是以一种特定的方式陈述了零假设。如果我交换了无效假设和替代假设,错误也会被交换。

让我展示给你看。

我的新无效假设:

“我的文章被阅读的次数将会比我发表的类似文章的次数多”

假** 的情况下,我会拒绝一个为真的零假设。所以,测试会显示我的杰作实际上是平庸或更糟。还记得这句话吗?这就是上一个例子中的 。**

这表明这两种误差是可以互换的。所以,都是关于你书房的设计;你可以改变一些事情来帮助你避免更大的问题。

在积极中寻找积极。

在申请数据科学行业的工作时,一个经常出现的面试问题是:

“你能提供一个假** 负的结果更好的例子吗?(反之亦然)**

当然,你可以使用上面的例子,然而,一些学者不太喜欢听到交换假设的想法。我只是想证明一个观点,当涉及到这个概念时,一切都不是那么非黑即白。

另外,我有更多的例子给你,你可以向你的潜在雇主展示你真的很了解自己。你很快就会赢得他们的支持!

这些例子都有因科学或法律而无法切换的假设(见,没那么非黑即白)。然而,它们确实给我们带来了假阴性不理想的情况。当然,我们仍然有点叛逆,但这样做是在科学和法律的范围内,所以,谁能阻止我们!

对宝宝还是不对宝宝?

当你做验孕测试时,你是在问:“我怀孕了吗?”

然而,在假设检验中,你有你的零假设:

“我没有怀孕”

拒绝假设给你一个“+”祝贺!你怀孕了!

接受假设会给你一个“对不起,祝你下次好运!”

生物学决定了这一点,所以恐怕不能切换。虽然测试可能会出现故障,而且假** 确实会发生;在这种情况下,一个假阳性就是你实际上没有怀孕时的那个小“+”。一个 负,过程会是“–”当你肚子里有个小宝宝在成长。******

这是一个很好的例子,因为更好的情况完全取决于你的情况!

想象一下,有人为了一个孩子努力了很长时间,然后奇迹般地怀孕测试呈阳性。他们在心理上为生孩子做好准备,在短暂的狂喜之后,以某种方式,他们发现他们实际上并没有怀孕!

这是一个可怕的结果!

对于那些真的不想要孩子、没有准备好要孩子的人来说是假阴性,当他们用阴性结果向自己保证时,饮酒和吸烟会对她、她的家庭和她的孩子造成难以置信的伤害。

然而,交换一下这些女性的情况,你会得到尽管不理想,但好得多的结果。

琐事时间!

怀孕测试已经发展到最小化假阴性的可能性。这确实改善了测试,因为虽然你不太可能去看医生来确认阴性结果,但对阳性结果来说是明智的。有许多医学原因导致假阳性,但假阴性只出现在测试的错误执行中。

艾滋病测试

这里有一个更明确的例子。

想象一下,一个病人正在接受艾滋病毒测试。

无效假设是:

“病人没有感染艾滋病毒。”

一个 阳性的结果起初会让病人心碎;不得不面对这一消息并告诉家人和朋友的创伤不是你希望发生在任何人身上的情况,但在接受治疗后,医生会发现她没有病毒。再说一次,这不会是一次特别愉快的经历。但是没有艾滋病毒最终是一件好事。

另一方面,假阴性意味着患者携带艾滋病毒,但检测结果显示为阴性。这种情况的影响是可怕的,患者将错过重要的治疗,并有很高的风险将病毒传播给他人

毫无疑问,这里的 才是更大的问题。对个人和社会都是如此。

琐事:

许多医生称艾滋病结果为“反应性”,而不是阳性,因为存在假阳性。在患者被确定为 HIV 阳性之前,会进行一系列的检测。这并不全是基于一份血液样本。

阳性,直到证明为阴性

在许多国家,法律规定刑事案件中的嫌疑人是:“在被证明有罪之前是无辜的”。

这来自拉丁语

**‘我有遗嘱,有判决,无否定;无效遗嘱检验的性质。

也就是说:“证据在于肯定的人,而不是否定的人;因为,根据事物的本质,否认事实的人不能提供任何证据。”*

因此,零假设是:

“嫌疑人是无辜的。”

很简单,一个假阳性会导致一个无辜的一方被判有罪,而一个假阴性会产生一个无罪的有罪判决。

如果缺乏证据,接受零假设比拒绝零假设更有可能发生。因此,如果法律规定嫌疑人是“有罪的,直到被证明是无辜的。”假设是“嫌疑人有罪”接受虚假的零假设会导致许多无辜的人被监禁。

因此,对许多人来说,冒着(可能)让五名罪犯逍遥法外的风险保护一名无辜者似乎是值得的。

就法律这么回事,普遍的共识是,假的正的会是更大的问题。将一个无辜的人投入监狱的想法令人不安,因为一旦被定罪,证明他们事实上是无辜的并不简单。虽然假阴性会导致有罪的一方逍遥法外,但它可能会导致案件重新审理,或者如果这个人是一个惯犯,他将在以后被定罪。****

琐事:

直到最*,墨西哥还在使用“除非证明无罪,否则有罪”的制度。结果,法官甚至不愿审理大多数刑事案件,因为他们害怕将太多无辜的人投入监狱。自 2008 年以来,墨西哥的刑事司法系统一直在向“无罪,除非被证明有罪”过渡。

你的每一次呼吸,我都会看着你。

酒精测试是必要的麻烦。没人想被拦下做酒精测试,但也没人想被醉酒司机撞死。秋千和回旋处。

无效假设:“你低于酒精限度。”

再一次,很简单,一个假阳性将表明你甚至没有碰过酒精饮料就已经超过了限度。当你喝醉了,或者至少超过限度时,假阴性结果会显示你是清醒的。****

这两个问题都是由于影响呼吸酒精样本的各种因素造成的。为了抵消假阳性(失去执照,接受罚款或坐牢)的问题,法律规定,一个人可以提供血液或尿液样本来证明自己的清白(如果他们是无辜的)。****

考虑到这一点,假阴性显然是更大的问题。允许酒后驾车的人在假设他们清醒的情况下继续开车,显然对他们和周围的人都是危险的。虽然损失几个小时的时间是很小的代价,如果这有助于让更多的人不上路的话。

琐事:

人们被视为合法驾车受损的常见酒精水平范围为 0.00%至 0.08%。世界上最常见的基准是 0.00%,也称为零容差,和 0.05%。开曼群岛的限额最高,为 0.1%。这并不意味着对酒后驾车有更高的容忍度,所以在喝完一瓶杰克·丹尼尔酒上路之前,请记住,当地警察确实是通过频繁检查来执行法律的。

一个人的垃圾是另一个人的财富。

最后我想说的是垃圾邮件。

许多网站会告诉你类似这样的话:“请检查你的垃圾邮件文件夹。我们刚刚发送给您的电子邮件可能会在那里结束。”

电子邮件提供商越来越多地使用数据挖掘算法来过滤垃圾邮件。这是一个值得单独写一篇文章的话题。然而,我们讨论的是电子邮件放错地方的情况。

几周前,我给我妹妹发了一封邮件,她的邮件提供商把它标为垃圾邮件,这让我大吃一惊。他们怎么敢!我能想到的唯一解释是,我用我的个人邮箱给我姐姐的公司邮箱发了邮件。所以,算法看不到我妹妹想要我的邮件的证据(也许它知道一些我不知道的东西……)。因此,它接受了零假设:

"这封邮件是垃圾邮件。"

如果算法拒绝零假设,电子邮件就会通过。一个假阳性将意味着你的收件箱里有来自尼日利亚王子的奇怪的电子邮件,他们想要娶你,或者久违的亲戚询问你的银行细节,这样他们就可以把你曾祖母的表姐的继女的猫的大笔遗产寄给你。****

假阴性很可能是更大的问题。你可能会错过你兄弟姐妹的面试邀请或假日快照,只是因为它们被淹没在大量的垃圾邮件中——你在删除之前半心半意地浏览了一下。

不过这取决于个人偏好,有些人对手机上的通知非常恼火,只看到一封毫无意义的邮件,以至于几封放错地方的私人邮件只是小小的代价。

花絮:

你在脸书上发送的好友请求超过 95%都会被接受,因为你通常会联系你认识的人。这是不正确的垃圾邮件帐户,这是脸书检测他们的方式之一。然而,最*机器人采取了一种策略,他们假装是有吸引力的女性,并将男性用户作为他们的受害者。因为男性用户平均来说会接受这些好友邀请,所以检测机器人需要更长的时间。

这是一些常见的假阳性和假阴性的例子。正如你所看到的,更可取的错误实际上取决于情况本身、你的个人偏好或研究是如何设计的(如果需要,你可以改变假设)。所以,我希望你不要遵循一般的假设,即假阳性会导致更大的问题,并且现在更好地准备产生可靠的例子来支持它。****

现在,我敢打赌,读完这篇文章后,你对假阳性和假阴性的兴趣已经从 0%上升到 100%。如果你想了解这方面的一些科学知识,你可以查看我们的视频I 型误差与 II 型误差**

祝您愉快!

如果你喜欢这篇文章,请随意看看我的其他文章。“起步的好处”听起来是个不错的起点!

参考资料:

南·瓦格纳(1917 年 6 月 1 日)。【瓦格纳法律语录网页】 。Wagonerlaw.com。检索到2010–10–13**

deepfakes 的家庭乐趣。或者我是怎么让我妻子上《今夜秀》的

原文:https://towardsdatascience.com/family-fun-with-deepfakes-or-how-i-got-my-wife-onto-the-tonight-show-a4454775c011?source=collection_archive---------2-----------------------

【2018 年 2 月 3 日更新: 在本帖底部新增两个创作。最后一个结果很好

(图片可能需要一段时间加载!)

我第一次听说 deepfakes 是在一周前。感谢推特。谢谢蒂姆·索雷特。

是的,这是相当该死的赛博朋克。但是从表面来看, /r/deepfakes (极其 NSFW!你已经被警告)由使用用户“deepfakes”创建的应用程序来创建假名人色情的人组成。

这在互联网上引起了一场轩然大波,媒体讨论这一切的合法性,网站撤下了 deepfake 的作品,人们恐慌地意识到人工智能会毁了我们所有人。与此同时,尼古拉斯·凯奇正在接管好莱坞。

当每个人都在争论这是好是坏的时候,我不得不发现更多。我首先想到的是什么?我怎样才能把这个应用到我认识的每个人身上(以一种非色情的方式,如果你想知道的话)。

它是如何工作的?

deepfakes 应用程序是一种深度学*算法,可以学*如何重建人脸。给它一堆图片,让它运行几个小时,它就会吐出这些图像的模糊副本。请注意,它不会创建副本。它学*一张脸在不同表情下的样子,并能够仅基于此输出那张脸。Reddit 上有详细的解释,但让我试着简单解释一下。

想象一下,如果你可以盯着一个人看 12 个小时,观察他们所有的表情并吸收到你的大脑中。然后那个人让你在纸上画出他的脸,微笑,哭泣,任何你观察到的表情。你是做什么的?你立即在纸上生成一个摄影质量的草图,从脑海中!(用铅笔)

太疯狂了。

虽然这很酷,但只会变得更好。看到“编码器”那部分了吗?FakeApp 对所有人脸使用一个编码器。是解码器保持了人脸的特异性。最酷的部分来了。让它学会两张脸,事情就变得更有趣了。

好了,现在看看这是怎么回事。编码器获取一张人脸图像,让它通过它的“大脑”,解码器再把它吐出来。在上面的例子中,它可以通过安妮·海瑟薇和我妻子埃尔克的脸来实现。好的,到目前为止还不错。但是现在让我们给它一张安妮的照片,但是使用生成埃尔克的脸的解码器!

你刚给埃尔克拍了张新照片。一张从未存在过的照片,和安妮一样的角度,一样的表情!太神奇了!

家庭乐趣

当然,把名人的脸放在你最喜欢的色情明星身上是一个有趣的用例。但是我们可以利用这些名人做其他事情,比如把你的朋友和家人插入大片和节目中!

为了获得最佳效果,您必须首先找到一个与您希望插入的人的头型相似的男演员/女演员。至于 Elke(我的妻子),我在看《黑暗骑士崛起》的时候偶然发现安妮·海瑟薇可能是个不错的选择。我猜你认识安妮,所以这是埃尔克:

我只需要 850 张埃尔克的照片,1000 张安妮的照片,大量的计算时间,瞧,埃尔克在吉米·法伦主演的《今夜秀》上。

额外效果:现在我们知道短发的:D 看起来像什么了

这里有一个小小的对比 gif:

**

我个人认为这很有趣,可以是无辜的,甚至是一个不错的惊喜/礼物。记住,任何工具都可以用来作恶。只要我们不禁止枪支,这不应该是一个高度优先事项,阿米利特?

有了这项技术,你可以做很多事情。你知道人们发的那些愚蠢的邮件吗?他们用自己的,甚至更糟的,你的脑袋替换了跳舞的精灵的脑袋?好吧,现在你可以把你最好的朋友放进他最喜欢的电影里:让她和帕特里克·斯威兹跳舞,享受她一生的时光,或者让一个外星人从他的肚子里蹦出来。现在一切都触手可及!

除了纯粹的乐趣,我只能想象人们将如何开始把这项技术变成商业创意。时尚将是巨大的(这种发型,这种裙子我会是什么样子……),健身可能会很有趣(我肌肉发达好看吗,我瘦了真的会更好看吗),旅行(这是你站在沙滩上会很有说服力)。它会把广告业带到一个全新的水平。不需要想象如果,他们会告诉你你的“更好”的生活会是什么样子!那幅画面很难从你的脑海中抹去…

与此同时,我又创造了两个。埃尔克是史蒂夫·卡瑞尔的超级粉丝,我突然意识到安妮·海瑟薇和他一起出演了《T2 变聪明》。第一次尝试还可以:

然后我就想试试这个(原视频):

我认为结果很棒:

最初发表于 斯文

在高速公路上挨饿:可视化,映射洛杉矶餐馆检查

原文:https://towardsdatascience.com/famished-on-the-freeway-visualizing-mapping-la-restaurant-inspections-cb6bc8338111?source=collection_archive---------11-----------------------

使用 Python,Matplotlib,Plotly 分析,查看地图上的分级餐厅

“pizza and nachos chip” by Roberto Nickson (@g) on Unsplash

你好。我使用 Python,matplotlib,Plotly 来分析加州洛杉矶县餐馆检查结果数据集,并通过绘制 C 级餐馆来可视化。也许你可以在高速公路上(或者更有可能的是,在堵车时:)仔细阅读这些信息。以下是一个概述:

  • 从 ka ggle-inspections,violations 文件导入数据集
  • 创建数据框架
  • 按违规数量、类型等进行分析、排序。
  • 分组、按等级计数、风险并以图形方式显示
  • 提取低等级(C)的餐馆及其地址
  • 从谷歌地图中获取他们的地理坐标(纬度,经度)以在地图中使用,将它们存储到[创建]地图
  • 在地图上标出那些餐馆的位置

开始之前:

  • 确保您有 Python 编辑器或笔记本可用于分析
  • 拥有一个谷歌地图 API 令牌(获取餐馆位置的坐标)
  • 有一个地图框令牌(将坐标映射到地图上)
Start a new notebook file:**#TSB - Hari Santanam, 2018**
***#import tools required to run the code***
from mpl_toolkits.mplot3d import Axes3D
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import numpy as np 
import os
import pandas as pd 
import requests
import logging
import time
import seaborn as sns

读取两个数据集文件:

  • 检查文件是所有被检查的餐厅、菜场的清单
  • 违规文件是发现的所有违规和相应设施的列表(一个设施可能有多个违规)
***#read in file with all inspections and put in dataframe***
df1 = pd.read_csv('../input/restaurant-and-market-health-inspections.csv', delimiter=',')
nRow, nCol = df1.shape
***#print number of rows and columns***
print({nRow}, {nCol})***#read in file with all health VIOLATIONS and put in dataframe***
df2 = pd.read_csv('../input/restaurant-and-market-health-violations.csv')

Output of file rows x columns

用原始检查分数创建一个数据框架,并绘制在直方图上:

***#Put these two lines before each plot/graph, otherwise it sometimes #re-draws over the same graph or does other odd things***from matplotlib import reload
reload(plt)
%matplotlib notebook
***#draw the histogram for scores***
df2['score'].hist().plot()

Histogram for score distribution — x-axis is score value bins, y-axis is count for each value bin

为标签描述键入以下内容:

***#search for missing grade, i.e, that is not A or B or C***
df1[~df1['grade'].isin(['A','B','C'])]
***#one record (record # 49492) popped up, so we fix it by assigning it a grade C***
df1.loc[49492,['grade']] = 'C'***#find out the distribution of the grades, i.e, how many records in each grade******#basically, group dataframe column grade by grade letter, then count and index on that, and print it***
grade_distribution = df1.groupby('grade').size()
pd.DataFrame({'Count of restaurant grade totals':grade_distribution.values}, index=grade_distribution.index)

注意,上面的总数加起来是 58,872,这是文件中的总行数,这意味着没有没有等级的行。

按餐厅类型(座位类型)分组,并计数和绘制图表

***#group by restaurant type and count # in each category
#then sort from highest # to lowest, then create a bar graph***
temp = df1.groupby('pe_description').size()
description_distribution = pd.DataFrame({'Count':temp.values}, index=temp.index)
description_distribution = description_distribution.sort_values(by=['Count'], ascending=True)
df2['pe_description'].hist().plot()

Grouped by pe_description field (ex: “Restaurant (seats 31–60, high risk”)

用原始检查分数创建一个数据框架,并绘制在直方图上:

***#the previous charts and graphs show breakdown of various types food restaurants with risk
#broken down to high, medium, low.
#This procedure use the split function to break the pe_description field into the sub-string
#after the 2nd space from the end - ex: string x = "Aa Bb Cc", when split applied like this: x.split(' ')[-2] ->sub-string after(not before) 2nd space '=>Bb'***def sub_risk(x):
    return x.split(' ')[-2]
***#apply function to get only high, medium, low*** df2['risk'] = df2['pe_description'].astype(str).apply(sub_risk)***#group, count by risk level***
temp = df2.groupby('risk').size()                                       ** *#plot the histogram for the 3 levels of risk***
df2['risk'].hist().plot()

Count by Risk type (High, Medium, Low) , extracted from restaurant type field string

用原始检查分数创建一个数据框架,并绘制在直方图上:

***#show first 10 rows of the violations file dataframe*** 
df2.head(10)
***#groupb by violation_description, count and sort them from largest violation by count to smallest***
violation_description = df2.groupby('violation_description').size()
pd.DataFrame({'Count':violation_description.values},index = violation_description.index).sort_values(by = 'Count',ascending=False)

Screen shot — Counts for each type of violation

创建一个函数,将字符串定义的值转换为数字,并制作一个热图:

***#create a simple proc for heat map for risk - low, moderate, high***
def convert_risk_value(x):
    if x == 'LOW':
        return 10
    elif x == 'MODERATE':
        return 5
    else:
        return 0
***#create simple proc to map grade to value* **   
def convert_grade_value(x):
    if x == 'A':
        return 10
    elif x == 'B':
        return 5
    else:
        return 0
***#call (apply) procs created above*** 
df2['risk_value']=df2['risk'].apply(convert_risk_value)
df2['grade_value']=df2['grade'].apply(convert_grade_value)
df3 = df2.loc[:,['score', 'grade_value', 'risk_value']]
corr = df3.corr()
corr = (corr)
reload(plt)
%matplotlib notebook
sns.heatmap(corr, xticklabels = corr.columns.values, yticklabels=corr.columns.values, cmap="Purples", center=0)

Screen shot — Heat map — score, grade_value and risk_value

从最常见的违规开始按降序显示违规计数:

***#violations listing from most common, descending - violation description, violation code, counts***
violation_desc=df2.groupby(['violation_description','violation_code']).size()
pd.DataFrame({'Count':violation_desc.values}, index=violation_desc.index).sort_values(by = 'Count', ascending=False)

Screen shot — Violation count by description and code

显示违规最多的设施点:

***#list facilities with most violations and type of violation
#create a dataframe with facility and violation columns, aggregate by size, then count and sort them***
violation_desc2 = df2.groupby(['facility_name','violation_description']).size()
pd.DataFrame({'Count':violation_desc2.values}, index=violation_desc2.index).sort_values(by='Count', ascending=False)

Screen shot — Facilities with the most violations and type of violation

分离并提取等级为“C”的餐厅进行映射。使用 loc 函数,然后删除重复项,这样每个餐馆名称只出现一次。我们稍后将在地图中使用它。

***#get a list of all the restaurants with grade C***
df4 = df2.loc[(df2['grade'] == 'C'),['facility_name','facility_address','facility_zip']]***#only want each restaurant listed once, since many of them have multiple violations, or may be listed more than once for multiple inspections or other reasons***
df4=df4.drop_duplicates(['facility_name'])***#print***
df4

Screen shot — list of restaurants with grade C

下面,我们列出上面的地址(C 级餐馆)并添加城市和州(所有地址都相同)作为完整地址(位置#、街道、城市、州)。这是必需的,因为在国家和世界的其他地区可能有同名的街道和城镇,作为调用 google maps api 的参数,它将为我们提供地理坐标(纬度、经度),然后我们将这些坐标叠加在加利福尼亚州洛杉矶县的地图上。

***#visualize bad restaurants (grade C)on a map, so that if you are in that area, you can avoid them :)***
***#some of them might have remediated their violations, or may be operating under "new management" or maybe even turned over a new leaf - we just don't know***
addresses_to_avoid = df4['facility_address'].tolist()
addresses_to_avoid = (df4['facility_name'] + ',' + df4['facility_address'] + ',' + 'LOS ANGELES' + ',CA').tolist()

添加一些控制台处理,一些常数:

***#some logging and console handling system items***
logger = logging.getLogger("root")
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()      #console handler
ch.setLevel(logging.DEBUG)
logger.addHandler(ch)***#some constants for our upcoming function***
address_column_name = 'facility_address'
restaurant_name = 'facility_name'
RETURN_FULL_RESULTS = False
BACKOFF_TIME = 30                 ***#for when you hit the query limit******#api key needed for the call to google maps -if you are wondering #what this is, you missed the 1st couple of paragraphs, please go #back and re-read***API_KEY = 'your api key here'
output_filename = '../output-2018.csv'     
***#output file stores lat,lon***

创建一个函数,从上面的列表中调用每个地址,并通过调用 google maps 来获取将用于叠加在加利福尼亚州洛杉矶地图上的坐标。

logger = logging.getLogger("root")
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()      #console handler
ch.setLevel(logging.DEBUG)
logger.addHandler(ch)address_column_name = 'facility_address'
restaurant_name = 'facility_name'
RETURN_FULL_RESULTS = False
BACKOFF_TIME = 30API_KEY = 'Your API key here'
output_filename = '../output-2018.csv'
#print(addresses)***#adapted from Shane Lynn - thanks***
def get_google_results(address, api_key=None, return_full_response=False):
    geocode_url = "[https://maps.googleapis.com/maps/api/geocode/json?address={](https://maps.googleapis.com/maps/api/geocode/json?address={)}".format(address)
    if api_key is not None:
        geocode_url = geocode_url + "&key={}".format(api_key)

        #ping google for the results:
        results = requests.get(geocode_url)
        results = results.json()             

        if len(results['results']) == 0:
            output = {
                "formatted_address" : None,
                "latitude": None,
                "longitude": None,
                "accuracy": None,
                "google_place_id": None,
                "type": None,
                "postcode": None
            }
        else:
            answer = results['results'][0]
            output = {
                "formatted_address" : answer.get('formatted_address'),
                "latitude": answer.get('geometry').get('location').get('lat'),
                "longitude": answer.get('geometry').get('location').get('lng'),
                "accuracy": answer.get('geometry').get('location_type'),
                "google_place_id": answer.get("place_id"),
                "type": ",".join(answer.get('types')),
                "postcode": ",".join([x['long_name'] for x in answer.get('address_components') 
                                  if 'postal_code' in x.get('types')])
            }

        #append some other details
        output['input_string'] = address
        output['number_of_results'] = len(results['results'])
        output['status'] = results.get('status')
        if return_full_response is True:
            output['response'] = results

        return output

调用这个函数,如果一切顺利,它将把结果写到指定的文件中。注意:这个调用经常会遇到 Google 强加的“查询限制”,所以您要么必须手动调用它们(从文件中过滤后),要么从输出文件中删除它们。

***#for each address in the addresses-to-avoid list, call the function we just created above, to get the coordinates, and add to a new list called results2***
results2=[]
for address in addresses_to_avoid:
    geocode_result = get_google_results(address, API_KEY, return_full_response=RETURN_FULL_RESULTS)
    results2.append(geocode_result)***#now, convert the list with our geo coordinates into a csv file that will be called by another program to overlay on a map.***pd.DataFrame(results2).to_csv('/Users/hsantanam/datascience-projects/LA-restaurant-analysis/restaurants_to_avoid.csv', encoding='utf8')

我们差不多完成了。我本可以用相同的代码创建一个函数,但是为了便于阅读和理解,我用一个新的程序创建了这个函数,这个程序为地图设置配置,从输出文件中调用我们刚才创建的地址坐标数据,并在浏览器选项卡上绘制它。这是它的输出:

这是最后的结果——上面代码的可视化地图输出。

Restaurants with C grade — mapped out for LA county, CA — opens in default browser, new tab

Popups with name, coordinates, address appear when you hover over any location dot

感谢您耐心通读此文:)。你现在可能饿了——如果你碰巧在这个地区,找一家餐馆吃饭,只是不要在那些等级不好的餐馆里!

github 到这里的链接是这里是

如果你感兴趣,可以看看我的其他文章:

[## 使用 Google Datalab 和 BigQuery 进行图像分类比较

样本数据,简单用法

medium.com](https://medium.com/google-cloud/using-google-datalab-and-bigquery-for-image-classification-comparison-13b2ffb26e67) [## 使用 Google Cloud ML 引擎训练回归模型

在 Google Cloud Datalab 中提交一个培训模型作业

medium.com](https://medium.com/google-cloud/using-google-cloud-ml-engine-to-train-a-regression-model-e2a582de389e) [## 使用 Keras 预测时尚数据集并查看机器学*使用的图像

人工智能使用图像识别学*过程来处理成千上万的图像,并“学*”哪些图像属于哪个…

medium.com](https://medium.com/@hari.santanam/using-keras-to-predict-fashion-dataset-and-see-images-used-by-machine-learning-5f4a889fb1b0) [## 人工智能对 IT 的价值主张

人工智能对于公司内部的大多数业务领域来说都很棒。它有望带来新的洞察力、预测和分析,这使得…

medium.com](https://medium.com/@hari.santanam/value-proposition-of-ai-for-it-1c8903c0ec25)

神奇的模型和如何训练他们

原文:https://towardsdatascience.com/fantastic-models-and-how-to-train-them-experimenting-with-software-development-pipelines-in-7051b9d930f7?source=collection_archive---------7-----------------------

在机器学*项目中试验软件开发管道。

在我多年的软件工程师生涯中,我参与过不同规模和应用领域的软件项目。到目前为止,我很幸运有机会尝试不同的技术堆栈,使我的专业技能始终保持最新,并与当今技术领域不断发展的节奏保持一致。不过,直到最*,我才开始尝试和积累机器学*相关技术的技能,一部分是出于日常工作的需要,一部分是出于个人兴趣(我承认,我算是个极客)。因此,在恢复我的数学理论并学*了一两个主要软件库的基础知识后,我开始尝试复制一些在网上找到的最有趣的例子。

首先,当你开始使用一个全新的技术堆栈时,你可能会很容易记下一些实现 web 教程的随机脚本,或者尝试一些没有特定顺序的变体,只是为了体验一下它的感觉…

不过,我很快意识到,为了能够在更专业的环境中开发我的新技能,我需要以一种更有条理的方式进行。因此,我考虑将这些新技术和工具与我迄今为止通过设计和开发“经典”企业级应用程序所学到的东西相结合,通过将通常的软件开发管道和工具适应于涉及机器学*模型的特定情况。我计划在这里记录我的努力和实验,并把它们作为指南提供给像我一样开始在这个迷人的技术领域前进的人。

首先,我开始从鸟瞰的角度考虑整个软件开发和发布过程。

最佳实践和模式在这个问题上提供了一个有用的视角:举个例子,其中一些实践建议在软件开发和发布生命周期中严格分离构建、发布和运行的三个阶段。构建阶段处理用我们最喜欢的编程语言为我们的应用或服务实际编写源代码,处理源代码版本等方面,通常会产生一个二进制可执行文件包,称为“构建”。接下来的发布(也称为部署)阶段采用这个二进制包,并将其与严格依赖于目标部署环境的特定配置数据相结合(开发、测试和质量保证、试运行、生产等)。这种配置数据可以包括外部数据库或其他类似服务(所谓的“后台服务”)的连接和凭证,部署特定的设置,例如部署的规范主机名等。因此,这个阶段产生的东西是可以立即执行的。作为最后一个阶段,运行阶段在目标环境中执行应用程序或服务的主进程。

这种严格的阶段分离意味着,例如,禁止在运行时环境中直接改变应用程序代码,但是必须启动新的发布周期来改变源代码,产生新的包,并在目标运行时上将其作为新版本执行。这保证了许多好的属性,比如过程的可追溯性、可再现性等等。

因此,所有这些导致建立分离的(至少在概念上)运行时环境,其中不同的阶段由不同的特定环境支持,每个环境配备有最适合支持与所讨论的阶段相关的特定活动的资源级别、软件基础设施工具。

开发环境将需要一些 IDE(如 Eclipse、Visual Studio 或 PyCharm)和语言运行时,以允许开发人员生成他们的代码,持续集成(CI)环境将包含共享、版本化和管理源代码和编译的组件二进制文件(如 GIT、Maven、Jenkins 等)的工具。),最后,目标运行时环境应该配备一些可靠的运行时基础设施,允许软件组件的执行,同时管理诸如分布、负载平衡、容错等问题(最*我对 Kubernetes 很感兴趣)。

现在,当考虑机器学*项目时,首先想到的一个方面是构建阶段在概念上变得稍微复杂一些。开发人员不只是编写一个构建然后执行的程序源代码,而是这个第一个源代码是一个构建然后在某个地方执行的程序以产生另一个“程序”(即 ML 模型),最终将在其他地方执行以服务于客户的请求。

明确地说,CI 和 train 环境之间的实际“物理”分离基本上是由从源代码构建应用程序二进制文件的不同任务与训练 ML 模型相比产生的根本不同的需求所强加的。后者应该比前者需要更高的计算能力和资源,可能需要 GPU、TPUs 等等的支持……我意识到,对于有经验的 ML 实践者来说,这一切听起来可能微不足道,但是我承认,一开始我花了一些时间来正确地关注这个问题,导致了一些最初的困惑,我认为模型训练只是最终可执行工件构建过程中的一个进一步阶段。

类似地,训练环境和目标执行环境的需求可能会有很大的不同,其中最终目标甚至可能只是运行训练模型的某个移动设备,作为某个“人工智能驱动的”移动应用程序的一部分。

在接下来的文章中,我打算研究在设置和操作上述难题的任何部分时可能出现的任何问题,主要关注企业级环境中的相关解决方案,其中可能涉及不止一个开发人员的团队,设计大规模模型或(最重要的)使用大数据集,以及运行时性能、高可伸缩性或弹性等考虑因素很重要。就基于机器学*的软件而言,所有这些都是从一个初学者的角度来看的,就像我正在进行的这项探索工作的“日记”一样。与此同时,我的意图不是提供一些关于如何制作东西的深入的逐步指导,而是对可能出现的问题、您面临的选择或可用选项(最佳实践、软件工具、服务等)采取高层次的观点。)这可能有助于找到所需的解决方案。

我希望这是一个能让一些人感兴趣的主题,也希望收到关于如何改进这一系列帖子的好的反馈和有用的建议。

参考文献和注释

[1] 参见所谓的“12 因素”方法,这是一套最*非常流行的模式和建议,最初是由 Heroku(众所周知的 PaaS 平台)的工程师设计的。这些旨在为构建可移植、高可伸缩和弹性的应用程序提供指导,特别关注基于 web(软件即服务)或基于云的服务,正如大多数现代软件应用程序所期望的那样。https://12factor.net/T2

FAQ:使用 TensorFlow 构建手写文本识别系统

原文:https://towardsdatascience.com/faq-build-a-handwritten-text-recognition-system-using-tensorflow-27648fb18519?source=collection_archive---------2-----------------------

本文是关于如何使用 TensorFlow 实现一个文本识别模型的文章的后续。它基于 SimpleHTR 库的一个旧代码版本

有些问题我想在这里讨论一下。我们来看看以下三个一:

  1. 如何识别图像/数据集中的文本?
  2. 如何识别包含在行或整页中的文本?
  3. 如何计算识别文本的置信度得分?

1 如何识别图像/数据集中的文本?

在 IAM 数据集上训练预训练模型。来自 IAM 的一个样本如图 1 所示。该模型不仅学*如何阅读文本,还学*数据集样本的外观。如果您浏览 IAM 单词图像,您会注意到这些模式:

  • 图像具有高对比度
  • 单词被紧凑地裁剪
  • 大胆的写作风格

Fig. 1: A sample from the IAM dataset.

如果你给一个图像输入一个非常不同的风格,你可能会得到一个不好的结果。让我们看一下图 2 所示的图像。

Fig. 2: A sample for which the model recognizes the text “.”.

该模型识别文本“”在这张图片中。原因是模型从未见过这样的图像:

  • 低对比度
  • 单词周围有很多空间
  • 线条非常细

让我们来看两种改善识别结果的方法。

1.1 预处理图像

让我们从一个简单的方法开始,让图像看起来更像来自 IAM 数据集的样本。我们将使用上面的图像来尝试这一点(见图 3)。首先,让我们来修剪它。该模型仍然识别“.”。然后,我们增加对比度。现在,模型给出了一个好得多的结果:“tello”。这几乎是正确的。如果我们通过应用形态学操作来加粗线条,模型最终能够识别正确的文本:“Hello”。

Fig. 3: Preprocessing steps and the recognized text for each of them.

这种裁剪可以用一种分词算法来完成。增加对比度和应用形态学操作是通过以下 Python 代码实现的。

1.2 创建 IAM 兼容的数据集和训练模型

获得良好读取结果的最佳方法当然是根据您的数据重新训练模型。虽然创建数据集可能相当费力,但绝对值得。您需要将图像-文本对转换成 IAM 兼容的格式。下面的代码显示了如何进行这种转换。DataProvider 类的 getNext()方法在每次调用时返回一个样本(文本和图像)。createIAMCompatibleDataset()函数创建文件 words.txt 和目录 sub,所有图像都放在这个目录中。如果您想要转换数据集,您必须修改 getNext()方法(目前它只是为所提供的单词创建机器打印的文本,以显示示例用法)。

转换后,将文件 words.txt 和目录 sub 复制到 SimpleHTR 项目的数据目录中。然后可以通过执行 python main.py - train 来训练模型。

2 如何识别成行或整页的文字?

该型号可输入 128×32 的图像,最多可输出 32 个字符。所以,用那个模型识别一个或者两个单词是可能的。但是,更长的句子甚至整页都无法直接阅读:

  • 行:要么将行分割成单词,要么将文本识别模型放大,以便它可以处理整行
  • 整页:将页面分割成单个的单词,然后分别阅读每一页

我们先来看看预处理,它既可以用于行级文本处理,也可以用于页面级文本处理。

2.1 预处理图像

如果该行的单词容易分割(单词之间的间隙大,单词的字符之间的间隙小),那么可以使用类似于 R. Manmatha 和 N. Srimal 提出的简单的单词分割方法(参见图 4 的例子)。然后,将分割后的单词分别输入文本识别模型。对于更复杂的文档,可以使用基于深度学*的分词方法。

Fig. 4: Word-segmentation on page-level.

2.2 扩展模型以适合完整的文本行

如果在行级别上工作,您可以轻松地扩展模型,以便输入更大的图像和输出更长的字符串。

表 1 显示了我用于文本行识别的架构。它允许更大的输入图像(800×64 ),并且能够输出更大的字符串(长度可达 100)。此外,它包含更多的 CNN 层(7),并在两层中使用批量标准化。

Table 1: Architecture for reading on line-level. Use option 1 (LSTM) for the recurrent network. Abbreviations: bidirectional (bidir), batch normalization (BN), convolutional layer (Conv).

3 如何计算识别文本的置信度得分?

获得被识别文本的概率的最简单的方法是使用 CTC 损失函数。损失函数将字符概率矩阵和文本作为输入,并输出损失值 L。损失值 L 是看到给定文本的负对数可能性,即 L=-log(P)。如果我们将字符概率矩阵和识别的文本提供给损失函数,然后取消对数和减号,我们得到识别文本的概率 P:P = exp(-L)。

以下代码显示了如何为一个玩具示例计算识别文本的概率。

结论

这篇文章展示了如何处理不同的数据集以及行级甚至页面级的读取。此外,还讨论了计算置信度得分的简单方法。

参考

最后,概述一下我的其他媒体文章

奇异明天的迷人故事

原文:https://towardsdatascience.com/fascinating-tales-of-a-strange-tomorrow-72048639e754?source=collection_archive---------4-----------------------

人工智能:科学与小说

我们的旅行始于 1956 年 3 月“禁忌星球”电影的上映,这部电影的主角是机器人罗比,他是公认的第一个出现在银幕上的科幻机器人。几个月后,由【1】领导的一小组计算机科学家在新罕布什尔州的达特茅斯学院举办了为期 6 周的研讨会。

******

John McCarthy (Turing Award 1971) & Robbie the Robot**

这次研讨会的主题是“人工智能”,这是麦卡锡自己创造的一个术语,他是这样定义的:

“学*的每一个方面或智力的任何其他特征,原则上都可以如此精确地描述,以至于可以制造一台机器来模拟它”。

如果达特茅斯的工作室实际上是由约翰·麦卡锡看了《禁忌星球》然后回家想:“让我们来建造罗比”而引发的,那不是很棒吗?不过,这可能根本不是真的。哦好吧。

不管怎样,这个小组开始工作,为我们所知的人工智能奠定了基础。事实上,大多数参与者将他们的整个职业生涯都奉献给了推动人工智能的发展,在这个过程中获得了不下四个图灵奖:1969 年的马文·明斯基【3】,1971 年的约翰·麦卡锡,希尔伯特·西蒙【4】&艾伦·纽厄尔【5】1975 年。

******

Herbert Simon (Turing Award 1975, Nobel Prize in Economics 1978) ad Allen Newell (Turing Award 1975)**

在人工智能的早期,这些聪明的科学家做出了一些预测,比如:

1958 年,希尔伯特·西蒙和艾伦·纽厄尔:“10 年内数字计算机将是世界象棋冠军。****

1965 年,希尔伯特·西蒙:“20 年内,机器将能做任何人能做的工作。****

1967 年马文·明斯基: 在一代人之内,创造‘人工智能’的问题将得到实质性解决

1970 年马文·明斯基:“ 在 3 到 8 年的时间里,我们将拥有一台拥有普通人一般智力的机器。

哎呀。

人工智能的冬天来了

预测未来总是有风险的事情,但这仍然提出了一个令人生畏的问题:对于人工智能在合理的时间框架内会(或不会)实现什么,如此聪明的头脑怎么会如此大错特错?不要担心,我们稍后会回答这个问题。

不幸的是,多次未能取得重大进展成为了人工智能的商标。

期望很高,结果很少或根本没有,资金被削减,项目被放弃。不出所料,这些多重的 AI winters 让除了最铁杆支持者之外的所有人望而却步。

这种幻灭最明显的象征来自马文·明斯基本人。2001 年,他做了一个名为“的报告:现在是 2001 年:哈尔在哪里?当然指的是斯坦利·库布里克电影《2001:太空漫游》中的哈尔电脑。更重要的是,早在 1968 年,明斯基就在电影制作期间给库布里克提了建议。在这次演讲中,他明确地提出了“常识问题”😗“今天没有任何程序可以区分狗和猫,或者识别典型房间中的物体,或者回答 4 岁儿童可以回答的问题!”*****

****

Marvin Minsky (Turing Award 1969) & HAL 9000

一句话:在实验室环境中玩人工智能很酷,但在现实世界中它永远不会有所成就。结案了。

与此同时,在美国西海岸…

当人工智能研究人员在实验室里绝望的时候,一些初创公司正在重塑世界:亚马逊、谷歌、雅虎,后来脸书和其他几家公司加入进来,它们正在以疯狂的速度发展自己的网络平台。在这个过程中,他们获得了数以百万计的用户,积累了大量的数据。很快就清楚了,这些数据是一座金矿,如果真的可以开采的话

使用商用硬件,这些公司的工程师开始寻求设计和构建数据处理平台,使他们能够处理原始数据并提取商业价值,这些价值可以转化为收入** …这始终是快速增长的初创公司的一个关键目标!**

2004 年 12 月达到了一个重要的里程碑,当时 Google 发布了著名的 Map Reduce 论文【6】,其中他们描述了一个编程模型和一个用于处理和生成大型数据集的相关实现。不甘示弱的雅虎实现了本文描述的想法,并于 2006 年 4 月发布了他们项目的第一个版本:Hadoop【7】诞生了。

等待火柴的汽油:机器学*爆炸发生了,剩下的,正如他们所说,是历史。

快进几年

2010 年左右:机器学*现在是商品。客户有广泛的选择,从 DIY 到机器学*即服务。数据世界一切都很棒。但真的是这样吗?是的,机器学*帮助我们让很多应用程序变得“更聪明”,但是我们在人工智能方面取得重大进展了吗?换句话说,我们离“建设哈尔”更*了吗?嗯……不。让我们试着理解为什么。

构建机器学*应用的第一步被称为“特征提取”。简而言之,这是数据科学家探索数据集的一个步骤,以找出哪些变量对预测或分类数据有意义,哪些没有意义。虽然这仍然主要是一个冗长的手动过程,但现在已经很好地理解了它,并且可以很好地处理结构化或半结构化数据,如 web 日志或销售数据。

然而,对于复杂的人工智能问题如计算机视觉或计算机语音并不适用,原因很简单,因为要正式定义的特征是什么:例如,是什么让猫成为猫?猫和狗有什么不同?还是来自狮子?

简单来说,传统的机器学*并不能解决这类问题,这就是为什么需要新的工具。进入神经网络!

回到未来

新工具?几乎没有!1957 年,Frank Rosenblatt 设计了一个机电神经网络,感知器【8】,他训练它识别图像(20x20“像素”)。1975 年,Paul Werbos 发表了一篇描述“反向传播”【9】的文章,这是一种允许更好更快地训练神经网络的算法。

因此,如果神经网络已经存在了这么长时间,那么它们肯定要对失败的人工智能尝试负部分责任,对吗?他们真的应该复活吗?为什么他们会突然成功?

确实是非常合理的问题。让我们首先快速了解一下神经网络是如何工作的。一个神经元是一个简单的构造,它将多个加权输入相加产生一个输出。神经元被组织在中,其中层‘n’中每个神经元的输出作为层‘n+1’中每个神经元的输入。第一层称为输入层,输入数据,比如图像的像素值。最后一层称为输出层并产生结果,比如图像的类别号(“这是一只狗”)。

******

The basic structure of a neural network (Source: “Deep Learning”, Goodfellow & Bengio, 2016)**

神经网络的美妙之处在于它们能够自我组织:给定足够大的数据集(比如,图像作为输入,类别标签作为输出),神经网络能够自动学*如何产生正确的答案****

由于一个迭代训练过程,它能够发现允许图像被分类的特征,并反复调整权重以达到最佳结果,即具有最小错误率的结果。

训练阶段及其自动特征发现非常适合解决非正式问题,但这里有一个问题:它们涉及许多数学运算,随着数据大小的增加(想想高分辨率图片)以及随着层数的增加,这些运算往往会呈指数增长。这个问题被称为“维数灾难”,这也是神经网络几十年来停滞不前的主要原因之一:根本没有足够的计算能力来大规模运行它们。

也没有足够的数据可用。神经网络需要大量数据才能正确学*。数据越多越好!直到最*,收集和存储大量的数字数据还是不可能的。你记得穿孔卡片或软盘吗?

一项重大突破发生在 1998 年,当时 Yann Le Cun 发明了卷积神经网络【10】,这是一种新型的多层网络(因此被称为“深度学*”)。

简而言之,CNN 能够有效地提取特征,同时减少输入数据的大小:这允许更小的网络用于分类,这大大降低了网络训练的计算成本。

这种方法非常成功,以至于银行采用 CNN 驱动的系统来实现支票手写识别的自动化。对于神经网络来说,这是一个令人鼓舞的成就…但是最好的还在后面!

Architecture of a Convolutional Neural Network (Source: NVIDIA blog)

神经帝国反击了

到 2000 年代末,三个几乎同时发生的事件使得大规模神经网络成为可能。

首先,大型数据集变得广泛可用。文本、图片、电影、音乐:一切都突然数字化了,可以用来训练神经网络。今天,ImageNet【11】数据库拥有超过 1400 万张带标签的图像,世界各地的研究人员每年都用它来竞争建立最成功的图像检测和分类网络(稍后将详细介绍)。

然后,研究人员能够利用图形处理单元(GPU)的惊人的并行处理能力来训练大型神经网络。你能相信赢得 2015 年和 2016 年 ImageNet 竞赛的分别有 152 层和 269 层吗?

最后但同样重要的是,云计算为开发人员和研究人员带来了弹性可扩展性,允许他们根据培训需要使用尽可能多的基础设施……而不必长期构建、运行或支付费用。

这三个因素的结合有助于神经网络实现其 60 年的承诺。

最先进的网络现在能够比任何人更快和更准确分类图像(误差小于 3%,而人类为 5%)。像亚马逊 Echo 这样的设备能够理解自然语言并和我们交流。自动驾驶汽车正在成为现实。人工智能应用的列表每天都在增长。********

你不想添加你的吗?

Number of layers and error rate of ILSVRC winners

AWS 如何帮助您构建深度学*应用程序

AWS 提供了您开始构建深度学*应用程序所需的一切:

种类繁多的亚马逊 EC2 实例来构建和训练你的模型,随你选择CPU【13】GPU【15】甚至FPGA【16】

深度学*亚马逊机器映像【17】,预装工具和库集合:mxnet【18】(AWS 官方支持),Theano,Caffe,TensorFlow,Torch,Anaconda 等等。

高级别的人工智能服务【19】用于图像识别(亚马逊识别)、语音转文本(亚马逊 Polly )和聊天机器人(亚马逊 Lex )。

选择权在你,开始吧帮助科学赶上小说!

新的希望?

人工智能每天都在进步。人们只能想知道接下来会发生什么!

机器会学*如何理解人类——而不是相反吗?

它们会帮助人类相互理解吗?

他们最终会统治世界吗?

谁知道呢?

无论发生什么,这些都将是奇妙明天的迷人故事。

注:这是我最*一次主题演讲的编辑稿。原始幻灯片可用 此处

时尚 DNA:零售世界中的结构特征映射

原文:https://towardsdatascience.com/fashion-dna-structural-feature-mapping-in-the-world-of-retail-fdba4f1c4070?source=collection_archive---------5-----------------------

Image source: Zalando Research

当将人工智能应用于时尚世界时,其中涉及的服装和其他物品具有许多不同的个体属性,必须定义有意义的结构。

根据项目的相似性来定义它似乎是很自然的:每个项目在抽象空间中都有其明确的位置,相似的项目就在附*。在 Zalando Research ,他们创造了时尚 DNA ,通过收集目录中杂乱无章的信息并将其映射到一个抽象的数学空间——“时尚空间”,使他们的产品属性更容易理解。在那里,物品由一个向量,或者它的“DNA”来表示,并被用来给混乱的时尚产品集合带来秩序。

Zalando Research 的研究负责人 Roland Vollgraf 将参加在阿姆斯特丹举行的机器智能峰会,分享这一领域的专业知识。在 6 月 28 日至 29 日的峰会之前,我与他进行了交谈,以了解更多信息。

你能简单介绍一下你在 Zalando 的工作吗?

我是 Zalando 研究中心的首席研究员。我在机器学*和人工智能领域领导着一个由 15 名科学家组成的研究团队。

你认为是什么主导因素推动了机器学*在时尚行业的最新发展和应用?

很明显,在线零售业务中产生了大量的数据,再加上不断增长的计算能力(目前主要由现代图形处理器提供)。

时尚 DNA 现在或未来潜在的哪些应用最让你兴奋?

我们的时尚 DNA 是将时尚物品映射到数学上方便的欧几里得空间。因此,它为搜索或推荐等各种应用程序的分类提供了一个通用索引。然而,映射并不一致。我个人认为看到特征空间中的白点是最令人兴奋的,也就是说,在我们当前的文章都没有直接映射到的点上。在那里可以找到哪些假设的新鞋或裙子?

总体而言,您认为未来哪些行业会受到机器学*的最大干扰?

在我看来,在不久的将来,自动驾驶汽车将是最具颠覆性的人工智能技术。结果,这可能会让自己开车和拥有一辆车完全过时——我相信这种情况会彻底改变我们城市的面貌。

未来 5 年,我们可以期待看到时尚行业的哪些发展?

其中,将会有全新的面向客户的在线零售应用。想想更好、更智能的搜索体验,比如对话式搜索,允许在与系统对话时询问灵感。计算机视觉和图像处理技术深度学*的进步将允许虚拟试穿应用程序,用户拍摄的自拍可以用她在网上购买的任何类型的服装进行逼真的增强。

Roland Vollgraf 将在 6 月 28 日至 29 日在阿姆斯特丹举行的机器智能峰会上发表演讲,同时还有 自动驾驶汽车机器智能峰会 。会见领先的专家并向他们学*人工智能将如何影响交通、制造、医疗保健、零售等领域。

这项活动的门票有限。立即注册参加。

本次采访中表达的观点可能不代表 RE WORK 的观点。因此,有些观点甚至可能与 RE WORK 的观点相左,但发布这些观点是为了鼓励辩论和全面的知识共享,并允许不同的观点呈现给我们的社区。

时尚 MNIST 分类与 TensorFlow 特色 Deepmind 十四行诗

原文:https://towardsdatascience.com/fashion-mnist-classification-with-tensorflow-featuring-deepmind-sonnet-aeb3987d826e?source=collection_archive---------5-----------------------

在这篇文章中,我们将看看如何使用 TensorFlow (TF)和 Deepmind 的十四行诗库在时尚 MNIST 数据集上执行一个简单的分类任务。

这篇文章也可以作为合作笔记本使用。请随意将笔记本复制到您的驱动器上,并修改代码。

Run in Colab

我写这篇文章的目的有两个:

  1. 展示如何在一个简单的机器学*(ML)任务中使用 TF 提供的附加功能。
  2. 作为 Deepmind 的十四行诗库的一个简单入门示例。

大部分解释都是以代码中注释的形式出现的,所以可以考虑和文章一起阅读代码。这篇文章是在假设读者对 ML 和 TF 框架有基本了解的情况下撰写的。也就是说,我试图提供外部链接到所使用的技术术语。

首先让我们安装 sonnet。通过命令行进行简单的 pip 安装就可以了,但是要确保安装了 TensorFlow 并且版本> = 1.5

$ pip install dm-sonnet

假设安装了其他库,我们将导入所需的 python 库。

**[Out]**
Tensorflow version: 1.10.0-rc1

时尚 MNIST 数据集

更传统的 MNIST 数据集已经被过度使用到了一定程度(99%以上的准确率),不再是一个有价值的分类问题。 Zalando Research 为机器学*研究提供了一个新起点,在 28x28 的图像中捕捉 10 种不同的服装,而不是 10 个数字。这 10 种服装的各种变化构成了时尚 MNIST 数据集。

A Sample from the Fashion MNIST dataset (Credit: Zalando, MIT License)

使用Keras(tensor flow 的高级 API)我们可以通过一个函数调用直接下载时尚 MNIST。由于它相对较小(70K 记录),我们将把它直接加载到内存中。

预处理数据集

由于数据集是为 ML 研究手工制作的,我们不需要进行数据争论。我们需要的唯一预处理是均值居中和方差归一化。所得的数据分布将具有球形结构,导致梯度下降收敛的步骤数量较少。参考 LeCun,Yann A .等人的第 5.3 节“有效反推”关于为什么我们需要进行居中和归一化以实现梯度下降的更快收敛的精确解释。

**[Out]** Downloading data from [https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz](https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz)
32768/29515 [=================================] - 0s 0us/step Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz 
26427392/26421880 [==============================] - 1s 0us/step Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz 
8192/5148 [===============================================] - 0s 0us/step 
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz 
4423680/4422102 [==============================] - 0s 0us/step Training Data ::: Images Shape: (60000, 28, 28), Labels Shape: (60000,) 
Test Data ::: Images Shape: (10000, 28, 28), Labels Shape: (10000,) Random 25 Images from the Training Data:

构建模型

使用 Deepmind 的十四行诗库,我们将建立两个模型,一个是简单的多层感知器(MLP),另一个是卷积网络。然后,我们将设置训练设备,以便在两个模型之间切换是一个简单的配置参数。

顺便说一下, Keras 是另一个高级 API,从 TF v1.9 开始,它就紧密集成到 TF 中。快速原型对于任何 ML 研究项目都是有用的,Keras 和 Sonnet 在这方面都非常有用。诚然,Keras 是一个更加成熟的项目,并且有 TF 团队的官方支持。此外,互联网上有大量的 Keras 教程和项目,再增加一个没有任何意义。另一方面,十四行诗很少在 Deepmind 之外使用,但对于任何跟踪他们的研究的人来说都是必须知道的。

深度思维十四行诗

Sonnet 是来自 Deepmind 的 TensorFlow 库,它抽象出了建模的过程。sonnet 的宗旨是将模型的组件封装为 python 对象(模块),然后可以在需要时插入到 TF 图中,从而为代码重用提供无缝机制。这样的设计让我们不必担心内部配置,如变量重用、重量共享等。有关详细指南,请参考他们的官方文档。此外,它们的源代码有很好的文档记录,值得一读,尤其是在尝试实现某些东西时。

在我们的例子中,我们将创建两个模块:FMNISTMLPClassifierFMNISTConvClassifier。顾名思义FMNISTMLPClassifier用的是 MLP,FMNISTConvClassifier用的是卷积神经网络。然后,我们将在 TensorFlow 中设置训练设备,然后插入我们想要训练的模型。

组装训练器材。

训练器械包含以下部件:

  1. 数据通过输入管道输入到模型中
  2. 执行梯度下降的优化算法。
  3. 将由优化器优化的损失函数。
  4. 正在接受训练的模型。

输入管道

在 TensorFlow 中,向模型提供数据的首选方式是使用[tf.data](https://www.tensorflow.org/api_docs/python/tf/data)模块。它允许我们以简单和可重用的方式对输入数据进行转换。tf.data模块允许我们设计输入管道,比如聚合来自多个来源的数据,以可插拔的方式添加复杂的数据操作任务等。在这个例子中,我们展示了它的基本功能,鼓励读者浏览官方的指南

我们希望输入管道具有以下三个属性:

  1. 能够在训练和测试数据集之间无缝切换,允许我们在每个时期后执行评估。
  2. 打乱数据集,以避免从磁盘上的数据排序中了解到意外的关联。
  3. 对随机梯度下降的数据集进行批处理。

在单个时期中,训练循环将包含覆盖整个数据集的多个小批量训练,然后是对测试数据集的准确度评估。

【计算机】优化程序

Adam(自适应矩估计)优化器是随机梯度下降的变体。在许多其他技术中,Adam 对每个参数使用自适应学*率。这允许与不常见的特征相关联的参数具有积极的学*率,而与常见特征相关联的参数具有低学*率。有关不同 SGD 优化器的详细说明,请阅读这篇精彩的帖子

损失函数

对模型的输出执行 softmax 后,评估交叉熵损失。更多详情此处

模型

这里我们将使用我们用 Sonnet 构建的模型。我们将设置培训,以便根据配置参数值交换两种型号(MLP 和康文网络)。

让我们把所有的组件放在一起。

**[Out]**
Epoch 1 ::: Training Time: 27.48s, Training Loss: 0.35541, Training Accuracy: 0.82533, Test Accuracy: 0.86060 
Epoch 2 ::: Training Time: 26.22s, Training Loss: 0.27885, Training Accuracy: 0.88165, Test Accuracy: 0.88280 
Epoch 3 ::: Training Time: 25.68s, Training Loss: 0.25212, Training Accuracy: 0.89918, Test Accuracy: 0.88710 
Epoch 4 ::: Training Time: 25.82s, Training Loss: 0.21601, Training Accuracy: 0.91033, Test Accuracy: 0.89750 
Epoch 5 ::: Training Time: 26.27s, Training Loss: 0.18370, Training Accuracy: 0.91778, Test Accuracy: 0.90500 
Epoch 6 ::: Training Time: 25.84s, Training Loss: 0.19794, Training Accuracy: 0.92612, Test Accuracy: 0.89190 
Epoch 7 ::: Training Time: 26.45s, Training Loss: 0.15230, Training Accuracy: 0.93163, Test Accuracy: 0.90500 
Epoch 8 ::: Training Time: 25.84s, Training Loss: 0.15200, Training Accuracy: 0.93763, Test Accuracy: 0.90360 
Epoch 9 ::: Training Time: 25.85s, Training Loss: 0.12375, Training Accuracy: 0.94403, Test Accuracy: 0.90550 
Epoch 10 ::: Training Time: 26.06s, Training Loss: 0.11385, Training Accuracy: 0.95010, Test Accuracy: 0.91050

就是这样,我们训练了一个卷积神经网络模型,对时尚 MNIST 数据集进行分类,测试准确率 91.050% 。要训练基于 MLP 的模型,只需在train函数调用中将'conv'改为'mlp'

这篇文章的完整代码可以在 GitHub 上找到:

View on GitHub

参考

  1. LeCun,Yann A .等人《有效的反向投影》
  2. Deepmind 十四行诗
  3. 时尚 MNIST
  4. 来自 TF 指南的基本分类
  5. CS231n 斯坦福课程笔记
  6. ML 备忘单损失函数
  7. TF 指标

最初发布于https://www . surajx . in/2018/08/fashion-mnist-class ification-with-tensor flow-featured-deep mind-sonnet/

时尚-MNIST 与深度学*工作室:一种不墨守成规的方法走向深度学*

原文:https://towardsdatascience.com/fashion-mnist-with-deep-learning-studio-a-nonconformist-approach-towards-deep-learning-52dbe3c0f703?source=collection_archive---------2-----------------------

随着你成为深度学*或机器学*的实践者,你会看到由 1998 年 Yann LeCun 引入的 10 类手写数字组成的 MNIST 数据集在科学论文、博客帖子等中反复出现。

MNIST 如此受欢迎的原因与其规模有关,它允许深度学*和机器学*从业者快速检查和原型化他们的算法。所有机器学*库(例如 scikit-learn)和深度学*框架(例如 TensorFlowPytorch )都提供了开箱即用的 MNIST 助手函数和便利示例,这也是对这一点的补充。

MNIST Dataset

但是,现在扎兰多研究正在谈论用时尚-MNIST 取代 MNIST。原因如下所列:

让我们更多地谈论时尚-MNIST。时尚-MNIST 是 Zalando 文章图像的数据集——由 60,000 个样本的训练集和 10,000 个样本的测试集组成。每个示例都是 28x28 灰度图像,与 10 个类别的标签相关联。Zalando 打算将时尚 MNIST 作为原始 MNIST 数据集的直接替代,用于机器学*算法的基准测试。它共享训练和测试分割的相同图像大小和结构。

下面是数据的一个例子(每个类有三行):

Fashion-MNIST Dataset

关于时尚 MNIST 的背景历史已经讲得够多了,是时候从理论跳到实践了。在这篇文章中,我将向整个深度学*社区演示如何使用时尚-MNIST 数据集和 深度学*工作室 ,一个由深度认知(从根本上改变了深度学*的完成方式)创建的深度学*平台。我很快就能够上传时尚-MNIST 数据集、训练卷积神经网络模型和使用 WEBAPP 部署模型。

"信息:我根据深度学*工作室准备的时尚-MNIST 数据集在我的 GitHub 存储库中可用,所以你们也可以从那里下载数据集"

步骤 1:项目创建

当我登录到运行在云中的 Deep Learning Studio 后,我点击了+按钮来创建一个新项目。

步骤 2:数据集分割

我将不同服装的 70,000 幅图像的整个数据集分别分成 80%、10%、10%的训练集、验证集和测试集,并将内存中的加载数据集设置为“完整数据集”。相同的图像如下所示。

70,000 个示例被分配到以下标签之一:

步骤 3:创建卷积神经网络

然后,我创建了一个卷积神经网络,如下图所示,只需简单地拖放层。

信息:如果你们中的任何人对模型背后的代码感兴趣,可以在我的 GitHub 库中找到,相同的链接可以在参考资料部分找到。

步骤 4:超参数调整

我保持纪元编号=100,批量=512,损失函数为分类交叉熵

步骤 5:训练模型

在调整超参数之后,我开始训练我的模型,并且在训练我的 CNN 模型之后,我得到了 0.9513 的训练精度、0.9272 的验证精度、0.1357 的训练损失和 0.2025 的验证损失

训练损失、训练准确度、验证损失和验证准确度的单独图表如下所示:

第六步:推理

推断是使用训练模型来推断/预测测试样本的阶段,包括与预测值的训练类似的正向传递。与训练不同,它不包括反向传递来计算误差和更新权重。这通常是一个生产阶段,在此阶段,您部署模型来预测真实世界的数据。而深度学*工作室只需点击一下,就可以轻松完成这一切推理阶段。

Inference

步骤 7:部署模型

Deep Learning Studio 的这一特性是独一无二的,因为它允许我以 WEBAPP 的形式访问我部署的模型。

Deploying Model as WEBAPP

在我单击 Deploy 并向实例提供服务名之后,就会生成一个 URL。然后,我看到我的模型通过预测不同的时尚服装图片发挥作用。

1. choose file

2. giving the prediction

所以,这就是如何使用时尚 MNIST 和深度学*工作室,我能够在我的 CNN 模型上获得 95%的准确率。既然现在你们都知道我是如何从上到下执行这个项目的每一个步骤,因此通过这篇文章,我想鼓励我所有的读者、深度学*/机器学*实践者和爱好者提出自己的模型或使用相同的模型,并在其上发布 LinkedIn 或 twitter 帖子(** 但不要忘记标记我:)或 深度认知 **),甚至写一篇关于它的文章来分享你的结果,与整个人工智能社区分享。我将急切地等待你的帖子。

感恩时间:如果没有来自 Mahesh Kashyapdeepcognition.ai 社区的持续和智力支持,这一切都是不可能的。因此,向 Deep Cognition 团队致敬,他们付出了巨大的努力来创建一个改变游戏规则的最简单的深度学*平台。

参考资料:

  1. 代码和时尚 MNIST 数据集可以从我的 repo 这里获取。
  2. 要通过视频教程了解更多关于深度学*工作室的信息,请查看此处的。
  3. 如果你想阅读更多关于深度学*工作室的文章,作者不是别人,正是法维奥·巴斯克斯点击这里
  4. 如果你有兴趣阅读 Zalando 时尚研究-MNIST 发表的论文,请点击这里查看。

感谢您的关注

你利用你的时间阅读我的作品对我来说意味着一切。我完全是这个意思。

如果你喜欢这个故事,那就疯狂鼓掌吧👏 ) 按钮!这将有助于其他人找到我的工作。

还有,跟我上 Linkedin如果你想!我很乐意。****

Fast.ai 深度学*课程 Part1 个人学*笔记分享

原文:https://towardsdatascience.com/fast-ai-deep-learning-course-part1-personal-learning-notes-sharing-5b4cdb5efa82?source=collection_archive---------7-----------------------

我想向大家推荐由杰瑞米·霍华德教授的深度学*课程 fast . ai(Kaggle 连续两年的头号竞争对手,Enlitic 的创始人)。了解如何在不需要研究生水平的数学知识的情况下构建最先进的模型——但也不降低任何东西的质量。哦,还有一件事…它是完全免费的!

可以查一下网址: www.fast.ai

我已经花了大约 7 周的时间学* fastai 课程第一部分,每当我完成一课,我都写下学*笔记,以巩固该课的知识,正如杰里米所说,学*一课的最佳方式是教别人理解该课。这样你就要搞清楚一个概念,确定自己的理解是正确的。另一方面,学*笔记对那些准备学*这一课的人来说是一个完美的建议,告诉他们可能会陷入的困境,或者帮助他们澄清一些令人困惑的概念。

这就是为什么我想与大家分享我的学*经验,告诉他们你将在这一课中学到什么,解释一些困惑,帮助他们开始。

学*笔记由四部分组成:
1 .简报:你要学的东西;
2。任务:你在编码实践中要做什么;
3:重要概念解释:用直白的话解释一些容易混淆的概念。
4。核心代码演示:我实现了 nbs 课程中的代码,并从头重写了它们,修复了一些小错误,并解释了一些重要的代码。我实现了 nbs(笔记本的简称)几乎 90%的代码,因为最初 nbs 的某些部分只是为了解释。

非常抱歉,我用中文写了这些笔记。
我用我的母语写笔记——中文会快得多,也许有一天我会把它们翻译成英文,但 python 是国际化的,如果你忽略中文单词,只关注代码,也许你会知道我想说什么(好吧,那是废话,用谷歌翻译就行了)。

表:
1。第 2 课——猫 vs 狗,使用 vgg16 模型 12。第 3 课—避免过度装配和装配不足的一些技巧
3。第 4 课—第一部分—关于 CNN 的更多细节,在 keras
4 中从头开始构建 CNN。第四课——第二部分——协同过滤和推荐系统
5。第 5 课— NLP 任务,单词嵌入
6。第六课——RNNs 和 LSTM,简单的 RNN 在第
第七课。第 7 课——图像分类中的核武器(ResNet、InceptionV3 和 FCN)1

第 7 课对我来说是最激动人心的一课,这是我见过的最酷的东西,我等不及要学*第 2 部分了!

如果你对我的笔记有什么建议,请告诉我,我很乐意听到,希望你们喜欢!

原文链接: 学*笔记分享自 forums.fast.ai

天空中的眼睛——使用迁移学*和数据增强的图像分类

原文:https://towardsdatascience.com/fast-ai-deep-learnings-part-i-eye-in-the-sky-417e97c3e6bb?source=collection_archive---------13-----------------------

很快。人工智能深度学*第一部分

“Side shot of a fighter jet speeing through the air.” by Dan on Unsplash

成为一名战斗机飞行员是我童年的梦想,看着飞机直到它们离开我的视线仍然是一件令人兴奋的事情。当我在考虑一个数据集,开始应用我从 fast.ai 学到的计算机视觉知识时,这就是我玩它们的动机。

这是我的系列的第一部分快。艾深学 。对于那些不知道的人来说, fast.ai 是一门关于深度学*的在线课程,由前 Kaggle 总裁和#1 竞争对手 Jeremey Howard 教授。在我完成了 Andrew NG 在 Coursera 上的深度学*专业化之后,我觉得他自上而下的方法是一个完美的补充。

我将给出飞机与直升机分类的端到端实现,让我们看看 CNN 架构如何区分机翼与桨叶。完整的执行代码可以在 github 上找到

1.数据准备

我想到不使用任何现有的数据集,所以我自己从谷歌上下载了图片。我用过火狐的谷歌图片下载器,这是一个下载图片的便捷扩展工具。我还发现这个 python 包对于自动处理多个标签非常有用。总共有 216 架飞机和 350 架直升机,让我们看看数据集中的样本图片。

我们的数据集看起来足够多样化(至少飞机),图片范围从常规客运航班、螺旋桨、战斗机、玩具飞机、战斗直升机和巨大的搬家工人。让我们看看我们的 NN 如何对付他们。

2.带 ResNet34 的快速模型

我们将使用 ResNet34 预训练模型,它赢得了 2015 年的 ImageNet 竞赛。由于 ImageNet 包含多样化的点击图片,这种架构将很好地适合这个问题。你可以通过这篇优秀的文章来解码 ResNet 架构,其基本理念是使用更深层次的网络,而不会经历收敛方面的退化。

“你不应该使用较小的网络,因为你害怕过度适应。相反,你应该在你的计算预算允许的情况下使用尽可能大的神经网络,并使用其他正则化技术来控制过拟合”

利用 5 个时期、8 的批量大小和 0.01 的学*率,我们能够实现大约 90%的准确度。

Accuracy after training for five epochs

2a。分析结果

Most correctly classified planes

Most correctly classified helicopters

Most incorrectly classified planes

Most incorrectly classified helicopters

Most uncertain predictions

虽然有些飞机很难辨认(着火的那架和‘希思罗’那架),但分类错误的直升机似乎和正确的没什么区别。

3.学*率探测器

学*率决定了您希望更新权重的快慢。虽然对于像我们这样的小数据集(~500 张图像),这没有多大关系,但是学*速率会显著影响模型性能/收敛。

我们将使用论文中开发的技术,用于训练神经网络的循环学*率,其中我们简单地从最小值开始增加学*率,直到损失停止减少。根据下面的图,我们将使用 1e-2 的 LR。

Left: Increasing learning rate every iteration. Right: Identifying the learning rate where there is still a decreasing loss

4.数据扩充

如果我们为更多的时期训练模型,它将开始过度拟合(训练损失变得更少,而验证损失不会)。该模型将开始学*特定于这些数据点的特征,而不是进行归纳。为了克服这一点,我们将使用数据扩充来创建更多的数据。对于这个问题,我们将使用水平翻转和缩放(高达 1.1 倍)。确保你做了相关的增强——对于字母/数字,任何翻转都没有意义,而对于卫星图像,我们可以根据需要翻转和旋转图像。

Augmenting through horizontal flipping and zooming

我们可以看到,通过这个增广数据后,准确率提高到了 92.3%。请注意,我们仍然使用预训练的权重,并且只训练最终的 FC 层。

Accuracy after 5 epochs with augmentation

5.微调以及差分学*速率退火

学*速率退火:虽然我们发现 1e-2 是理想的学*速率,但我们实际上已经开始使用它,并随着训练的进行逐渐降低它。这是因为,随着我们越来越接*最佳体重,我们应该迈出更小的步伐。

带重启的随机梯度下降:使用上述技术一个历元周期,我们将从 10e-2 再次重启学*速率并继续该过程。这背后的想法是鼓励我们的模型跳出这个最优空间,找到(如果有的话)一个稳定准确的最优空间。将这两者结合起来,学*率就像这样增长—

SGDR: Each cycle corresponds to one epoch

解冻预训练层:现在,由于我们已经训练了足够多的最终层,我们将解冻预训练的 ResNet 层并对其进行微调。由于这些层已经在 imageNet 照片上进行了训练,并且初始层将具有更多通用功能,因此我们将使用不同的学*速率来仔细调整它们。因此,初始层将像以前一样使用 1e-4,中间层使用 1e-3,FC 层使用 1e-2。

Final Accuracy after 3 cycles with 1 epoch, 2 epoch and 4 epoch each

我们看到准确率没有太大变化,但提高到了 93%。我们仍然看到验证损失是 0.21,而训练损失是 0.12,我觉得还有改进模型的空间,但我们现在就到此为止。我认为有更多种类的飞机,但没有足够的例子来学*这些特征(这就是为什么我认为我们看到下面很多飞机被错误分类)。

测试时间增加:这是在验证/测试时使用增加功能的一个很好的方法。TTA 不仅对你的验证集中的图像进行预测,还对它们的几个随机增强版本进行预测。然后,它从这些图像中提取平均预测值,并加以利用。我们实现了 94.4%的准确率,考虑到这种简单而有效的技术,这是一个相当不错的进步。

6.分析最终结果

查看混淆矩阵,有 7 架飞机被预测为直升机(这些似乎是初始模型本身之后不正确的),我们在预测直升机方面做得很好。也许有了更多的飞机图像,我们可能会达到更高的精度。

Final most incorrect aeroplanes

Final incorrect helicopter

非常感谢你一直读到最后。我们已经使用迁移学*、数据增强和差分学*速率退火对飞机和直升机进行了分类,在一个小数据集(~500 张图像)的情况下,达到了 94.4%的相当不错的准确度。如果你喜欢,请鼓掌并分享,如果有任何不清楚或可以改进的地方,也请在评论中告诉我。

代号:https://github.com/murali-munna/deep-learning-fastai

要了解数据科学初学者的实用技巧,请查看这篇文章。

[## 数据科学初学者实用技巧。揭穿几个神话!

当我开始我的旅程和我现在的位置时,我通过职业经历学到了很多东西…

towardsdatascience.com](/practical-tips-for-beginners-in-data-science-debunking-few-myths-30537117a4e4)

LinkedIn上联系我

Google Colab 上的 Fast.ai 第一课(免费 GPU)

原文:https://towardsdatascience.com/fast-ai-lesson-1-on-google-colab-free-gpu-d2af89f53604?source=collection_archive---------3-----------------------

在这篇文章中,我将演示如何为 fastai 使用 google colab。

关于谷歌可乐的一点…(https://colab.research.google.com/)

Google colab 是 Google 内部的数据科学研究工具,已经有一段时间了。他们早些时候向公众发布了该工具,其崇高目标是传播机器学*教育和研究。虽然已经有一段时间了,但有一个新功能会引起很多人的兴趣。

一次可以免费使用 GPU 作为后端 12 个小时。

GPU 计算免费?你在开玩笑吗?

这些是我脑海中立即闪现的问题,我试了一下。事实上,它工作得很好,非常有用。请仔细阅读本次讨论,了解关于此次发布的更多细节。讨论中的几个要点。

  1. 后端使用的 GPU 是 K80(此时此刻)。
  2. 12 小时的限制适用于 VM 的连续分配。这意味着我们可以通过连接到不同的虚拟机来使用 GPU 计算,即使在 12 小时结束后也是如此。

Google Colab 有很多不错的功能,协作是其中一个主要功能。我不打算在这里介绍这些特性,但这是一个很好的探索,尤其是当你和一群人一起工作的时候。

因此,让我们开始使用 fastai 和这项服务。

入门指南

  1. 你需要注册并申请访问权限,才能开始使用 google colab。
  2. 获得访问权限后,您可以使用“文件”->“上传笔记本”来上传笔记本。我已经上传了第一课的笔记本。请访问本笔记本以供参考。设置单元格将在共享笔记本中可用。
  3. 为您的笔记本电脑启用 GPU 后端。运行时->更改运行时类型->硬件加速器->GPU。
  4. 要交叉检查是否启用了 GPU,您可以运行共享笔记本中的第一个单元。

Cross Check to see if GPU is enabled

安装 Pytorch

由于默认环境没有 Pytorch,我们必须自己安装它。请记住,每次连接到新虚拟机时都必须这样做。所以不要删除单元格。

Installing Pytorch

安装 fastai

fastai 也一样。我们将使用 pip 来安装 fastai。

Installing fastai

除此之外,还有一个缺失的库 libSM,所以我们必须安装它。

下载数据

我们可以下载猫和狗的数据集,并使用几个 bash 命令对其进行解压缩

Downloading Data

完成这些步骤后,我们就可以在 Google Colab 上学*第一课了。在我们庆祝之前让我们讨论一些问题。

过程顺利吗???

目前还没有。但这是意料之中的。我们来看一些小问题。

  1. 当试图连接到 GPU 运行时,它有时会抛出一个错误,说它不能连接。这是由于大量的人试图使用这项服务,而不是 GPU 机器的数量。根据之前分享的 kaggle 讨论,他们计划添加更多的 GPU 机器。
  2. 有时,运行时只是间歇性地死亡。这可能有许多潜在的原因。
  3. 可用的内存容量大约是 13GB,这对于空闲的内存来说太好了。但是对于像第 1 课中的 resnet 这样的大型网络,大多数时候都会出现内存警告。当用解冻和不同的学*率尝试最终的完整网络时,我几乎总是遇到问题,我怀疑是由于内存。

结论:

谷歌确实在帮助降低深度学*的准入门槛。而像这样的工具,会帮助很多买不起 GPU 资源的人。我真的希望这将是一个全面的服务很快,并保持免费。

我会继续更新这个帖子,因为我想出了如何处理这些小问题,并使这个过程顺利。如果有人能够解决这些小问题,请在评论中告诉我。

!!!DOGS VS CATS 图像分类器!!!

原文:https://towardsdatascience.com/fast-ai-season-1-episode-2-1-e9cc80d81a9d?source=collection_archive---------8-----------------------

建立一个最先进的图像分类器

几个月来我一直在浏览 fast.ai。我不得不承认在这个过程中我学到了很多东西和很棒的技术。我会确保更新我博客中的所有内容。感谢瑞秋·托马斯 为 AI 民主化所做的努力。感谢牛逼的 fast.ai 社区的所有快速帮助。

下图描绘了我到目前为止的旅程,这使它成为一个有趣的旅程。

Image

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分

  1. 狗 Vs 猫图像分类
  2. 犬种图像分类
  3. 多标签图像分类
  4. 使用神经网络的时间序列分析
  5. IMDB 电影数据集上的自然语言处理情感分析
  6. 电影推荐系统的基础
  7. 从零开始协同过滤
  8. 使用神经网络的协同过滤
  9. 像尼采一样写哲学
  10. 不同神经网络在 Cifar-10 数据集上的性能
  11. 检测图像中最大物体的 ML 模型 Part-1
  12. 检测图像中最大物体的 ML 模型 Part-2

所以,振作起来,专注于 Fastai 课程的第一部分第二课。

狗 VS 猫分类器:

这篇博文讨论了狗和猫的分类模型。这是杰瑞米·霍华德在 FastAI 课程第一部分第二课中讲授的。

导入将在此模型中使用的如下所有库。

!pip install fastai==0.7.0
!pip install torchtext==0.2.3!pip3 install http://download.pytorch.org/whl/cu80/torch-0.3.0.post4-cp36-cp36m-linux_x86_64.whl 
!pip3 install torchvisionimport fastai
from matplotlib import pyplot as plt# Put these at the top of every notebook, to get automatic reloading # and inline plotting
%reload_ext autoreload
%autoreload 2
%matplotlib inline# This file contains all the main external libs we'll use
# from fastai.imports import *from fastai.transforms import *
from fastai.conv_learner import *
from fastai.model import *
from fastai.dataset import *
from fastai.sgdr import *
from fastai.plots import *

使用以下命令检查 GPU 是否已启用:-

上述命令的输出应该返回 True。

在深入研究之前,我想提几个可能有用 Linux 命令。

使用前缀为“!”的命令马克。

  1. !ls是一个列出当前目录中文件的命令。
  2. !pwd代表打印工作目录。将打印工作目录的路径
  3. !cd 代表变更目录。

以上三个命令有助于在目录间导航。

使用以下命令下载了狗和猫的图像。

<< !wget http://files.fast.ai/data/dogscats.zip>>

文件夹的结构应该如下所示

设置存储数据的路径

PATH = "data/dogscats/"
sz=224

使用以下命令检查文件是否已经下载

****

上面的f ’ 代表 f 弦。这是一种在 Python 中格式化字符串的新方法。想了解更多关于 f 弦的信息,请点击 realpython.com 的链接。

分类任务将利用预训练模型。预训练模型是已经由其他人对类似类型的数据进行了训练的模型。因此,不是从头开始训练模型,而是使用已经在 ImageNet 上训练过的模型。ImageNet 是由 120 万幅图像和 1000 个类组成的数据集。ResNet34 是将要使用的模型版本。这是一种特殊类型的卷积神经网络。ResNet34 获得 2015 年 ImageNet 大赛冠军。ResNet 的细节将在即将发布的博文中讨论。

下面几行代码显示了如何使用 fastai 训练模型。

使用的架构resnet34 已经保存在 arch 变量中。数据保存在数据变量中,因为它在前面指定的路径中查找数据。tfms 是数据扩充的一部分,稍后将详细讨论。

pre-trained方法从 arch 模型(resnet34)创建新的神经网络。拟合方法使用学*率和指定的时期数来训练模型。并且已经获得了0.9895的精度。

梯度下降

我来解释一下上面的图像。最初选择的参数是随机的。此时的损失很大。高损失表明在训练期间,“结果/预测值”和“目标值/标签”之间的差异更大。因此,应该遵循一种方法,使用这种方法应该使这种差异最小。收敛或达到局部最小值意味着此时损失最小,因此结果和目标值/标签之间的差异最小。这个过程被称为梯度下降。****

学*率:-

上述拟合函数中的学*率(LR)** 是最重要的参数之一,应仔细选择,以使模型快速有效地达到最优解。基本上说的是如何快速到达函数中的最优点。如果 LR 很低,则过程很慢,如果 LR 太高,则很有可能超过最小值。因此,必须仔细选择 LR,以确保收敛(达到局部最小值)以有效的方式发生。下图描述了上述概念。**

如何选择最佳学*率?

!!!别担心,杰瑞米·霍华德会支持你的。杰里米提到了一个很好的方法来计算学*率,它被称为

学*率查找器。

请检查下面的代码。

****

使用lr_find()可以获得最佳学*率。如学*率与迭代图所示,LR 在每次小批量后增加,并呈指数增加。在第二个图中,即损耗对学*率,观察到损耗随着学*率的增加而减少一段时间,当学*率为 0.1 时,损耗处于最小值,之后它开始再次上升(这意味着 LR 如此之高,以至于它已经超过最小值,损耗变得更糟)。

****选择最佳学*率,步骤如下:-

  1. 确定上面损失与学*率图表中的最低点(即 0.1)
  2. 后退 1 级(即 0.01),选择该值作为学*率。

后退 1 级背后的概念:-

虽然在这一点上损失最小,但是在这一点上选择的学*速率太高,并且继续使用这一学*速率将不会收敛。请查看下图进行解释。

注意:- 学*率查找器是最重要的超参数之一,如果调整/选择得当,将会产生最佳效果。

改进模型

改进模型的一个方法是给它更多的数据。因此,我们使用数据增强。等等,但是** 为什么要数据增强?**

我们的模型通常有几百万个参数,当训练更多的数时,有很大的可能性,它可能开始过度拟合。过度拟合意味着模型过度学*训练数据集中图像的特定细节,并且它可能无法在验证数据集或测试数据集上很好地概括。换句话说,当验证数据集的精度小于训练数据集的精度时(或者在训练数据集上计算的损失远小于在验证数据集上计算的损失),就发生了过拟合。因此过度拟合可以通过向模型提供更多数据来避免,因此使用数据扩充。

注意:- 数据增强并不是创造新的数据,而是让卷积神经网络从一个非常不同的角度学*如何识别狗或猫。

对于数据扩充,我们在tfms_from_model()函数中将transforms_side_on传递给aug_tfmstransforms_side_on 通过水平翻转将给出不同版本的图像。它让神经网络看到图像,就好像它是从侧面角度拍摄的一样,少量旋转它们,稍微改变它们的对比度、亮度,稍微放大一点,移动一点。这些变化可以在下图中看到。

要进行数据扩充,请编写以下代码

tfms = tfms_from_model(resnet34, sz, aug_tfms=transforms_side_on, max_zoom=1.1)
data = ImageClassifierData.from_paths(PATH, tfms=tfms)

虽然为数据扩充创造了空间,但是数据扩充不起作用,因为它最初被设置为precompute=True .

让我详细解释以下代码及其与上述语句的关系:-

data = ImageClassifierData.from_paths(PATH, tfms=tfms)
learn = ConvLearner.pretrained(arch, data, precompute=True)
learn.fit(1e-2, 1)

当使用ConvLearner.pretrained(…) 声明架构时,预计算被设置为真,这表示实现来自预训练网络的激活。预训练网络是已经学会识别某些事物的网络。对于我们的狗与猫的研究,使用的预训练网络已经学会了对 ImageNet 数据集中 120 万张图像的 1000 个类别进行分类。因此,采取倒数第二层(因为这是一层,有所有必要的信息来计算出图像是什么),并保存这些激活。为每个图像保存这些激活,这些被称为预计算激活。**现在,当创建新的分类器时,利用这些预先计算的激活,并基于这些激活快速训练模型。因此要实现这个 set precompute=True。**

注意:-**precompute=True** 时,数据扩充不起作用,因为它当前使用的是特定版本的扩充 cat,或者换句话说,即使每次显示的是不同版本的 cat,特定版本 cat 的激活已经预先计算好了。第一次运行时,预计算激活需要一两分钟。

当使用预计算激活训练时,精确度是98.8% :-

要进行数据扩充,设置**precompute=False** 并检查准确性。在下面的代码中**cycle_len** 是一个重要的参数,将在本文后面详细讨论。

精确度增加了一点到99.1% ,好消息是,它没有过度拟合,训练损失进一步减少。为了进一步改进模型,让我们关注:-

SGDR(重启随机梯度下降)

SGDR 说,当我们越来越接*最小值时,让我们降低学*率。随着我们的训练(即更多的迭代次数)降低学*率的想法被称为学*率退火。有步进式和余弦退火。在这个过程中,杰瑞米·霍华德使用余弦退火。

****

在余弦退火中,当不在最小值附*时,我们使用较高的学*率进行训练。当接*局部最小值时,切换到较低的学*速率,并在此基础上进行几次迭代。

上图显示了一个简单的损失函数。实际上,数据集是在一个非常高维的空间中表示的,有许多相当平坦的点,这些点不是局部极小值。假设我们的表面看起来像下面的图表

从 1 号红点开始,达到了 2 号红点所示的全局最小值,但是这里不能很好地概括。如果使用这种解决方案,在稍微不同的数据集的情况下,它不会导致好的结果。另一方面,红点 3 将在稍微不同的数据集的情况下很好地概括。我们的标准学*率退火方法将下降到一个点,在高维度中有很大的机会陷入尖峰区域,在那里它不会更好地概括,因此不是一个好的解决方案。相反,可以部署一个学*速率调度器,它将重置并执行余弦退火,然后再次跳转,这样它将从点 2 跳转到点 3,以此类推,直到它到达一个泛化能力非常好的点。

每次学*率被重置,它将再次增加学*率,这将导致离开表面的讨厌的尖峰部分,并最终跳到一个漂亮光滑的碗,这将更好地概括。

上述过程被称为 SGDR (重启随机梯度下降)。这个 SGDR 最好的部分是一旦达到一个“像表面一样光滑的曲线”,它就不会再开始了。它实际上是在空间的这个好地方逗留,然后不断变得更善于找到合理的好位置。请检查下图。

使用 SGDR学*率查找器会给我们更好的结果。从学*率搜索器中,试着视觉上找到一个好的学*率,否则在 SGDR 它不会跳到一个平滑的表面上。借助**cycle_len** 参数重置学*率。这基本上意味着在每 1 个时期后重置学*率。下图显示了重置是如何发生的

注意:- 学*率的重置发生在每一个时期之后,因为cycle_len=1和学*率在每一个小批量之后保持变化。y 轴是学*率,其中 0.010 是我们从学*率查找器获得的学*率。所以 SGDR 会在 0 到 0.010 之间调整学*率。

建议在中间步骤继续保存模型。为此,请使用以下命令:-

learn.save('224_lastlayer')
learn.load('224_lastlayer')

该模型保存在 dogscats 文件夹下的 models 文件夹中,如下所示

所有预计算的激活都保存在tmp 文件夹中。因此,如果出现奇怪的错误,可能是由于半完成预计算激活或其他方式,继续删除tmp 文件夹,并检查错误是否已经消失。这是快速开关它的方法。

注意:- 预计算激活不需要任何培训。这些是预训练模型用我们下载的重量创建的。

我们还能做些什么来让模型变得更好?

到目前为止,预训练激活已经下载并直接使用。CNN 内核中预先训练的激活或预先计算的权重保持不变(即,尚未进行预先计算的权重的重新训练)。预先训练的模型已经知道如何在早期阶段找到边缘、曲线、梯度,然后找到重复的模式,最终找到主要特征。到目前为止,只有新的层被添加到顶部,模型学会了如何混合和匹配预先训练的功能。如果在 Imagenet 上训练的模型被扩展到诸如“卫星图像分类”的情况,其中特征完全不同,则需要重新训练大多数层,因为特征完全不同。因此,需要探索一个新概念,命名为:-

微调和差分学*率

要学*一套不同的功能或告诉学*者卷积滤波器需要改变,只需**unfreeze** 所有层。冻结的层是其权重没有被训练或更新的层。

!!!好吧好吧艾尔莎,我会让它去解冻层!!!😍 😍

解冻图层将使图层权重对训练或更新开放。但是与后面的层相比,最初的层需要很少或任何训练。这普遍适用,因为初始层的工作是学*边缘和曲线,而后面的层学*重要的特征。因此,对于不同的层集合,学*速率被设置为不同的。这个概念被称为差异学*率。****

learn.unfreeze()
lr=np.array([1e-4,1e-3,1e-2])

进行必要的更改后,按如下所示训练模型。

前面讨论了cycle_len=1number_of_cycles=3参数。再次提醒一下,cycle_len=1 是历元的数量,number_of_cycles=3 表示学*者将做 3 个周期,每个周期 1 个历元。现在一个新的参数被引入,命名为cycle_mult=2。此cycle_mult 参数在每次循环后乘以每次循环的长度。这里的倍增因子是 2。于是(1+2*1 +2*2 )epoch = 7 epoch。也就是说,如果周期长度太短,它开始下降,找到一个合理的好点,然后弹出,再次下降,弹出。它实际上从来没有找到一个好点,这既是一个很好的最小值,也是一个很好的概括。这是一个机会的问题。它没有探索表面。所以要探索地表更要设定cycle_mult=2。现在,图表看起来更具探索性

据观察,到目前为止,精度已经提高到99.0% ,损耗也大幅降低。还有最后一个方法可以让模型变得更好。它被称为

测试时间增加(TTA)

在验证/测试数据集上,所有输入都必须是正方形。这有助于 GPU 快速处理。如果验证数据集中的输入图像具有不同的维度,则处理速度不会很快。为了保持一致,在中间画出正方形。如下例所示:-

如果上面的图片在中间是方形的,模型将很难预测它是狗还是猫,因为它是唯一进入验证数据集的身体。为此(测试时间增加)使用了 TTA。它将随机进行四次数据增强,以及未经增强的原始中心裁剪图像。然后取所有这些图像上所有预测的平均值。这是我们最后的预测。

注:- 仅适用于测试和验证数据集。

如上所示,应用 TTA 后的精度为99.35%

为了得到我们的分类器的概要,画一个混淆矩阵。混淆矩阵用于分类,以了解有多少预测正确或不正确,如下图所示。

混淆矩阵的解释:-

混淆矩阵说明了我们的分类器有多好。如上所述,深蓝色区域已经被正确分类。996 张猫图片已被分类为猫,993 张狗图片已被正确分类为狗。7 张狗图片被归类为猫,4 张猫图片被归类为狗。因此,我们的分类器做得非常好。

希望这篇文章对你有所帮助。在我未来的博客文章中,我们将深入探讨。因为涵盖了很多重要的概念,你现在可能会有这种感觉。

!!坚持住,更多有趣的东西即将到来。直到那时再见😉!!

附注——如果你有兴趣,请在这里 查看代码

甲乙丙 - 一直在鼓掌。 👏 👏👏👏👏😃😃😃😃😃😃😃😃😃👏 👏👏👏👏 👏**

编辑 1:-TFW·杰瑞米·霍华德同意你的帖子。😃😃😃😃😃😃

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分

  1. 狗 Vs 猫图像分类
  2. 犬种图像分类
  3. 多标签图像分类
  4. 利用神经网络进行时间序列分析
  5. 对 IMDB 电影数据集的 NLP 情感分析
  6. 电影推荐系统的基础
  7. 从零开始协同过滤
  8. 使用神经网络的协同过滤
  9. 像尼采一样写哲学
  10. 不同神经网络在 Cifar-10 数据集上的性能
  11. 检测图像中最大物体的 ML 模型 Part-1
  12. ML 模型检测图像中最大的物体 Part-2

“犬种图像分类”

原文:https://towardsdatascience.com/fast-ai-season-1-episode-2-2-dog-breed-classification-5555c0337d60?source=collection_archive---------10-----------------------

建立一个最先进的图像分类器。

欢迎来到第二集的第二部分,我们将讨论狗的品种分类问题。我们有 120 种狗的图片需要分类。在我们开始之前,我想感谢雷切尔·托马斯 为民主化人工智能所做的努力。感谢牛逼的 fast.ai 社区和Sam Charringtonfor the onlineTWiML&AI x fast . AI 学*小组会议

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分:- 狗和猫的图像分类

  1. 犬种图像分类
  2. 多标签图像分类
  3. 利用神经网络进行时间序列分析
  4. IMDB 电影数据集上的 NLP 情感分析
  5. 电影推荐系统的基础
  6. 从零开始协同过滤
  7. 使用神经网络的协同过滤
  8. 像尼采一样写哲学
  9. 不同神经网络在 Cifar-10 数据集上的性能
  10. 检测图像中最大物体的 ML 模型 Part-1
  11. 检测图像中最大物体的 ML 模型 Part-2

没看过前一集的,请点击这里查看第 2.1 集。为了节省您的时间,我将在这里快速浏览最后一集。下面是我们构建一个最先进的分类器的步骤

  1. 启用数据扩充并设置 PRECOMPUTE = TRUE.
  2. 使用 lr_find() 找到损失仍在明显改善的最高学*率
  3. 从预先计算的几个时期的激活中训练最后一层。
  4. CYCLE_LEN=1训练数据增强的最后一层(即PRECOMPUTE=FALSE)2-3 个历元。
  5. 解冻所有层。
  6. 将前几层设置为比下几层更低的学*速率,并对其进行训练。
  7. 再次使用lr_find()
  8. cycle_mult=2训练全网,直到过拟合。

所以在这篇博文中,我们将讨论狗的品种识别。到这个 kaggle 数据集的链接出现在这里。主要目的是对 120 个品种的狗图像进行分类。

1。下载数据并导入包。

所以要开始,我们必须下载数据。为了轻松获得这些数据,我们将使用 kaggle api。要了解更多关于这个 API 的信息,请点击查看。但是底线是

  • 安装 kaggle api
  • 导入它
  • ****并用它将数据下载到你想要的路径。下面的快照中已经执行了提到的步骤。

Downloading data done right

接下来,让我们导入所有必需的包:-

[glob](https://www.npmjs.com/package/glob)包将使用 shell 使用的模式匹配文件。在下面的代码中,我们可以看到 glob 有助于获取上述路径中的所有文件。在下面的要点中从第 7 行开始提到了输出。

2。检查 GPU 可用性并解压缩下载的文件

要确保 GPU 对您可用,请运行以下命令。这些应该返回 true。

Cuda done right

下载完所有文件后,下面的代码有助于解压这些文件。

unzipppp

3。使用熊猫熟悉数据

import PANDAS as 🐼

现在让我们检查数据。拉开 train and test zip files的拉链后,我们会知道它有 120 种狗的图片。Sample_submission.csv files 告诉我们竞赛在提交过程中期望的文件内容。让我们看看labels.csv 文件的内容。

它包含狗的所有图像的image_id和狗所属的breed or labelslabels.csv为训练和测试数据集中的图像提供品种。这种变通方法使生活变得更加轻松。

让我们检查一下一个特定品种有多少只狗。

上面的输出显示了 120 种狗的品种,并以降序显示了对应于每种狗的图像数量。对不起,我不能在一张快照中容纳所有的品种。

通常,我们有一个训练、验证和测试数据集。我们在训练数据集上训练我们的模型,同时在验证数据集上预测它。这涉及到参数调整,以提高验证数据集的准确性。最后,当我们确信我们的模型是好的,我们用它来预测未知的数据集,即测试数据集。这个过程有助于防止过度拟合。

vaidation dataset done right

上面的第一行设置了 label.csv 文件的路径。第 2 行打开文件并计算数据集除标题之外的行数,因此减 1。这为我们提供了 csv 文件中的行数或图像数。第 3 行中的get_cv_idxs(n) 将随机返回 20%的数据,用作验证数据集。这将返回我们将用作验证数据集的文件的索引。让我们交叉核对这一个。

!!!似乎是合法的!!!验证数据集的大小实际上是总数据集大小的 20%。

现在,我们将使用预先训练好的resnext_101_64 架构来构建我们的模型。

当我写这篇博客的时候,fastai 库中没有预训练的resnext_101_64架构的权重,所以我们必须将其下载到这个位置'/usr/local/lib/python3.6/dist-packages/fastai/weights' ,然后运行我们的模型,否则它会抛出一个错误消息weights not found 。按照下面代码中解释的步骤进行操作。

获得预训练模型权重的步骤

  • 使用中提到的链接(第 3 行)将预训练模型下载到任何位置。
  • 将其移动到上述位置。(第 20 行)
  • 将上述位置作为您的当前目录。(第 23 行)
  • 并解压文件。(第 27 行)
  • 回到你存放数据的地方。(第 41 行)

resnext101 weights

注意:- 将来,如果发生新的 fastai 代码更新,可能会考虑上述步骤,因此该步骤可能是可选的。

在继续下一步之前,决定图像的大小、使用的架构以及要考虑的批量大小。

4。按照 FASTAI 格式设置数据

为了按照 fastai 格式设置数据,我们编写以下代码。请注意,之前我们曾经为狗与猫分类器做了ImageClassfierData.from_paths(),因为我们在单独的文件夹中指定了数据。在这种情况下,文件夹的名称就是标签的名称。

但是在这里,我们将数据(图像)呈现在 train 和 test 文件夹中,文件名汇总在labels.csv文件中。labels.csv 文件包含训练和测试数据集中每个图像的标签/品种,因此我们选择如下所示的ImageClassfierData.from_csv(...)

参数 **ImageClassfierData.from_csv(...)** 为:

  • PATH是数据的根路径(用于存储训练模型、预计算值等)。还包含所有的数据。
  • 'train' —包含训练数据的文件夹。
  • labels.csv文件中有不同狗狗图片的标签。
  • val_idxs 有验证数据。它指示已经放入验证数据集中的 labels.csv 中的索引号。
  • test_name='test'test 数据集。
  • 文件名实际上在末尾有一个.jpg,在labels.csv文件中没有提到,因此我们有suffix=’.jpg’。这将把.jpg添加到文件名的末尾。
  • tfms 是我们要申请的数据增强的转换。

上面已经创建了数据对象。使用data 对象,我们可以检查train_ds(训练数据集)。要知道使用数据对象还能访问什么,写data. 并按 tab 键。将出现一个下拉菜单,显示data 对象的属性。下面提到的fnames 告诉我们训练数据集中存在的文件名。

让我们检查图像是否位于正确的位置:-

图像的输出如下所示。正如我们所看到的,狗的图像占据了大部分的画面,因此不用担心变换(tfms)阶段的裁剪或缩放技术。

下面的第 6 行将文件名映射到文件的大小,并将其存储在size_d中。size_d 是一个字典,其中键是文件名,值是每个文件的维度。第 8 行有zip(*) 命令,帮助解压行和列,并保存在row_szcol_sz中。

图像的大小是:-

检查下面 1 号线train datasettest dataset 以及 5 号线number of data classes/dog breedswhat are the first five breed of dogs的尺寸。

在进一步讨论之前,让我们检查一下我们正在建模的数据的维度。这只是为了检查的目的。因此:-

在上面的直方图中,我们可以看到,我们有 5000 个尺寸约为 500 像素的图像,很少有图像大于 1000 像素。在下面的直方图中,我们只检查尺寸低于 1000 像素的图像。它还显示了有多少特定尺寸的图像。

5。建立一个最先进的分类器。

等待结束了。最终呈现在你面前的是最先进的分类器。

对于最先进的分类器,需要遵循几个步骤。它们如下:

5.1)启用数据扩充并设置 PRECOMPUTE =TRUE。

出于一致性目的,让我们调整数据的大小。get_data()有正常的几行代码。第一个是Setup data augmentation,另一个是Format your data ,我们把 image_size 和 batch_size 传递给这个函数。当我们开始处理新的数据集时,如果我们先处理小图像,那么一切都会变得非常快。因此我们从尺寸sz=224 and bs=64 开始。之后我们可以增加尺寸。如果在增加大小时我们看到Cuda Out of Memory error,重启内核,将批处理大小设置为较小的值,然后再次运行。

现在让我们用 precompute=True 设置神经网络:-

当使用ConvLearner.pretrained(…)声明架构时,预计算被设置为 True,这表示它实现了来自预训练网络的激活。预训练网络是已经学会识别某些事物的网络。对于我们的狗品种识别案例研究,使用的预训练网络(RESNEXT101_64)已经学会对 ImageNet 数据集中 120 万张图像的 1000 个类别进行分类。因此,采取倒数第二层(因为这是一层,有所有必要的信息来计算出图像是什么),并保存这些激活。卷积神经网络有称为“激活”的东西激活是丰富的功能。激活是一个数字,表示“这个特性在这个地方,具有这个置信度(概率)”。为每个图像保存这些激活,这些被称为预计算激活。现在,当创建新的分类器时,利用这些预先计算的激活,并基于这些激活快速训练模型。因此要实现这个设置precompute=True

预训练方法从arch 模型中创建我们的新神经网络。同时,它做如下两件事:-

  • 它所做的是,它保留除最后一层之外的所有层(最后一层是输出层,在 Imagenet 的情况下,它给出 1000 个类别内的概率)。
  • 最后一层被添加的几个层所取代,这些层以输出层结束,输出层给出了所有 120 种犬种的概率。

所以最初一切都是frozenprecompute=True,因此我们所学的都是我们添加的图层。与precompute=True 一样,
数据增强没有做任何事情,因为我们每次都显示完全相同的激活。precompute=True所做的是预先计算图像有多少看起来像激活的东西。Precomputed activations是我们不打算训练的每个冻结层中使用的激活函数的输出。这有助于我们在最后加速新添加的完全连接层的训练。我们只预计算网络倒数第二层的激活。在所有层上执行都是存储密集型的。

5.2)使用 **lr_find()** 找到损失仍在明显改善的最高学*率

以下命令有助于找到最佳学*率。

该命令产生如下图所示的图形,该图显示了学*率随着迭代次数的增加而增加的事实。

该命令绘制了损耗与学*率的关系,给出的结果表明,随着学*率的增加,损耗达到最小值,然后出现一个点,在该点之后,损耗超过最小值,因此损耗变得更大。因此,我们必须选择一个与最小损失相对应的学*率。但是此时的学*率已经太高了,所以我们从学*率表上的最小损失点后退一步,选择它作为最佳学*率。这里是0.01

5.3) 从几个时期的预计算激活中训练最后一层。

这里,我们选择最佳学*率(0.01)并训练 NN 的最后一层(因为预计算=真且第一层被冻结),即它们的权重将被更新,以最小化模型的损失。使用这种技术,我们达到了92%的精度。但是有一点点过度拟合,因为我们的验证损失大于训练损失。为了避免这种情况,我们引入了DropoutData Augmentationtraining on larger images

5.4) 在 CYCLE_LEN=1 的 2-3 个历元内,训练最后一层的数据扩充。

  • 辍学

ps 是漏失参数。它指的是随机丢弃 50%的神经元。这有助于神经网络防止过度学*,从而防止过度拟合。正如我们可以看到的,此时我们的精度已经下降到了91.6%,但好消息是我们的验证损失小于训练损失,这是一个明确的迹象,表明我们没有过度拟合。

  • 数据扩充

为了进一步改进模型,我们需要更多的数据,因此通过设置learn.precompute=False打开数据扩充。通过设置precompute=False,,我们仍然只训练我们在最后添加的层,因为它被冻结了,但是数据增加现在正在工作,因为它实际上从头开始经历和重新计算所有的激活。cycle_len 的概念在上一集已经详细讨论过了。

数据增加我们看到92.17%的精确度增加,没有任何过度拟合。

注意:- An epoch 是一次通过数据,a cycle 是一个周期中出现的时期数。所以这里 cycle 基本上和 epoch 是一样的。

  • 在较大的图像上训练是防止过度拟合的最好方法。

现在我们看到了拟合不足的情况,因为验证损失比训练损失低得多。我们的主要目标应该是使 val_loss 和 trn_loss 尽可能接*,同时注意精度。

Cycle_len=1可能太短了。让我们设置cycle_mult=2以找到更好的参数。这将有助于防止不合身。当我们拟合不足时,这意味着cycle_len=1太短(在它有机会放大并选择最佳参数之前,学*率被重置)。cycle_mult的概念已经在这里详细讨论过

让我们为更多的时代训练它。

!!!但是等等!!!

如果您仔细观察输出,我们的 val_loss 仍然略高于 trn_loss。这是否意味着它的过度拟合,对我们的神经网络有害。让我们来听听专家的意见,看看为什么一点点过度拟合是好的。查看下面的链接。

** [## 确定你什么时候过度适应,什么时候不适应,什么时候刚刚好?

过拟合 if:训练损失>验证损失恰到好处 if 训练损失~验证损失问题:我们应该如何…

forums.fast.ai](http://forums.fast.ai/t/determining-when-you-are-overfitting-underfitting-or-just-right/7732/5?u=ashis)

除此之外,这个数据集类似于 ImageNet 数据集。所以训练卷积层帮助不大。因此,我们不打算解冻所有的层。最后,我们正在做TTA ( 测试时间增加)并得到预测概率。

在最后一步,我们计算精度和损失。很高兴看到我们的模型在测试数据集上获得了93.3%的准确性,这简直是令人兴奋的

这就是我们如何得到最先进的结果,我的朋友。

附:随着我继续学*其他课程,这篇博文将会更新和改进。如果你对源代码感兴趣,请点击 查看

甲乙丙 - 一直在鼓掌。👏 👏👏👏👏😃😃😃😃😃😃😃😃😃👏 👏👏👏👏 👏

感谢大卫·罗宾逊的激励😃😃😃😃😃😃

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分

  1. 狗 Vs 猫图像分类
  2. 犬种图像分类
  3. 多标签图像分类
  4. 利用神经网络进行时间序列分析
  5. IMDB 电影数据集上的 NLP 情感分析
  6. 电影推荐系统的基础
  7. 从零开始协同过滤
  8. 使用神经网络的协同过滤
  9. 像尼采一样写哲学
  10. 不同神经网络在 Cifar-10 数据集上的性能
  11. 检测图像中最大物体的 ML 模型 Part-1
  12. 检测图像中最大物体的 ML 模型 Part-2

如果您有任何问题,请随时联系 fast.ai 论坛或 Twitter:@ ashiskumarpanda**

“多标签图像分类的一个例子”

原文:https://towardsdatascience.com/fast-ai-season-1-episode-3-a-case-of-multi-label-classification-a4a90672a889?source=collection_archive---------6-----------------------

建立一个最先进的多标签图像分类器。

欢迎来到第三集 Fastdotai ,在这里我们将接手多标签分类的案例。在我们开始之前,我想感谢 【杰瑞米·霍华德】雷切尔·托马斯 为民主化人工智能所做的努力。

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分

  1. 狗 Vs 猫图像分类
  2. 犬种图像分类
  3. 多标签图像分类
  4. 使用神经网络的时间序列分析
  5. IMDB 电影数据集上的自然语言处理情感分析
  6. 电影推荐系统的基础
  7. 从零开始协同过滤
  8. 使用神经网络的协同过滤
  9. 像尼采一样写哲学
  10. 不同神经网络在 Cifar-10 数据集上的性能
  11. 检测图像中最大物体的 ML 模型 Part-1
  12. ML 模型检测图像中最大的物体 Part-2

没看过前几集的,请点击这里查看 2.12.2

今天我们将处理多标签分类,这里我们有多个标签作为目标变量。在深入多标签分类之前,我们先了解:-

CNN(卷积神经网络)是如何工作的?

CNN 架构有不同的部分。让我们详细地讨论它们,之后,我们将把它们结合起来,详细地讨论 CNN 的架构。所以让我们从输入开始,也就是图像

  1. 图像:-

最初,我们有一个图像。图像实际上是一个数字网格。看起来像这张图片

This is how a gray-scale image representing # 7 looks like . The pixel values has been standardized between 0 and 1.

2。内核/过滤器:-

在图像的顶部,我们有一个内核。在这种情况下,核/过滤器是 3d 张量的 3×3 切片,有助于我们执行卷积。

这个 3 乘 3 切片内核在图像上滑动,并产生特征图。

3.激活:-

特征图由激活组成。激活是一个数字,计算方法如下

  • 取相同维度的输入切片。
  • 确保您的内核与输入片段的维度相同。
  • 将步骤 1 中得到的输入与步骤 2 中得到的内核进行逐元素相乘
  • 然后总结一下。
  • 它产生一个数字,比如“N”。
  • 在此基础上应用 ReLu(校正线性单位)激活功能。基本上 ReLu 就是max(0,N).的意思
  • 我们得到的数字被称为“激活”。

4.张量:-

假设我们的网络经过了训练,在训练结束时,它已经创建了一个卷积滤波器,其核值已经学会识别垂直和水平边缘。Pytorch 不会将这些过滤器值保存为两个不同的 9 位数组。它将值存储为张量。张量是一个高维数组。张量有一个额外的轴,可以帮助我们把这些过滤器堆叠在一起。

5。隐藏层:-

除了输入层和输出层之外的所有层都称为隐藏层。构成激活图的层就是这样一个隐藏层。它一般被命名为 Conv1Conv2 和是核卷积的结果。

然后我们得到了一个非重叠的 2 乘 2 最大池。它通过高度和宽度将分辨率减半。一般命名为 Maxpool

除此之外,我们还有密集层/全连接层。对于 max-pool 层中出现的每一个激活,我们创建一个权重,对应于被称为的全连接层。然后对每一个权重的每一次激活做一个和积。这将产生一个单一的数字。

使用额外全连接层的缺点 :-这会导致过度拟合,也会降低处理速度。

注意:-内核的尺寸和图像/激活图的切片的尺寸应该总是相同的。对于多通道输入,创建多通道内核。这有助于更高维的线性组合。

内核值是如何更新的?

基本上,我们从一些随机核值开始,然后在训练期间使用随机梯度下降来更新核值,以便使核中的值有意义。以这种方式,在几个时期之后,我们到达初始层内核正在检测边缘、角的位置,并且随后更高层内核正在学*识别更重要的特征。

我对使用 KERAS 对 MNIST 数据集进行分类的简单 CNN 的看法

代表代码的简图(概括地说是 CNN)

CNN in detail

所以我们从(28,28,1)输入图像开始。

  1. 我们使用过滤器/内核来减少或增加激活图的深度/宽度,并减少激活图的高度和宽度。当我们用 32 个维数为(5,5)的核卷积维数为(28,28,1)的输入图像时,我们得到(24,24,32)的输出。
  2. 使用{(n-f+1),(n-f+1),(#Kernels)}计算输出维度,其中
  • n=图像尺寸
  • f =内核维数
  • 内核数=内核数

  • 所以我们得到{(28–3+1),(28–3+1),(#Kernels)}=(24,24,32)

3。我们在深度学*中使用非线性函数/ReLU 激活函数。但是为什么呢?看看下面这个 Quora 帖子。

[## 为什么深度学*/架构只使用隐藏的非线性激活函数…

回答(第 1 题,共 9 题):“为什么使用非线性激活函数?”在没有非线性激活函数的情况下,神经网络…

www.quora.com](https://www.quora.com/Why-does-deep-learning-architectures-only-use-the-non-linear-activation-function-in-the-hidden-layers)

4。发帖称,我们使用最大池将内核的高度和宽度减少了 2 倍。

  • 因此,激活图(24,24,32)减少到(12,12,32)。

5。这个(12,12,32)激活图与 32 个维数为(3,3)的核以及现在的输出维数按照公式{(n-f+1),(n-f+1),(#核)} = {(12–3+1),(12–3+1),32}=(10,10,32)进行卷积。

6。这个(10,10,32)激活图与 10 个具有维度(10,10)的核进行卷积,现在输出维度按照公式

{(n-f+1),(n-f+1),(# Kernels)} = {(10–10+1),(10–10+1),10}=(1,1,10)。

7。最后,我们已经达到了激活的(1,1,10)维。这是倒数第二层。它吐出 10 个随机数。

8。然后我们在此基础上使用 softmax 激活将数字转换成概率。

9。soft max Activation返回范围从(0,1,2,3,…9)的 10 个数字的概率值,并且它还倾向于特别强烈地拾取一个事物。Softmax 只出现在最后一层。这些将是我们的预测值。因为这些是概率值,所以结果是 1。我们将把这些预测值与我们的目标值进行比较。请检查上述附加代码(keras.ipynb)的第 9 行,以了解目标值如何保存在一个热编码表单中。数字 5 表示如下。

10。之后,我们将使用损失函数尽量减少 10 个预测值和 10 个目标值之间的损失。为了计算损失函数,我们使用梯度下降的概念。使用梯度下降保持更新参数/内核值。

11。最后,考虑最小损耗点对应的参数。并且在对测试数据集进行预测期间使用这些参数/核值。这是单一标签分类的概念,如狗对猫或狗的品种分类。现在我们来看一个多标签分类的案例。

多标签分类的最好例子是 kaggle 竞赛星球:从太空了解亚马逊。所以让我们分两步来做。

1。 下载数据,导入所需的包。

使用以下命令下载数据

! pip install kaggle 
import kaggle
! kaggle competitions download -c planet-understanding-the-amazon-from-space
!pip install fastai==0.7.0
!pip install torchtext==0.2.3!pip3 install http://download.pytorch.org/whl/cu80/torch-0.3.0.post4-cp36-cp36m-linux_x86_64.whl 
!pip3 install torchvision

导入包并检查目录中是否存在这些文件

train_v2.csv file 具有训练数据集中存在的文件的名称以及对应于它们的labels

2。 用熊猫熟悉数据

单标签和多标签分类的区别

在单一标签分类中,图像是猫或狗,如下图所示

让我们检查多标签分类:-

正如我们可以看到的输出,在多标签分类的情况下,图像被分为两部分

  • 天气——资料中提到的天气有很多种。从中我们可以看到上面快照中的
  • 要素—上图中的要素列表为主要、农业、水。

原生代表原生雨林。

农业代表用于农业用地的空地。

代表河流或湖泊。

基本上,在多标签分类中,每个图像属于一个或多个类别。在上面的例子中,第一幅图像属于两类:原生雨林。第二幅图像属于 4 类:初级清晰、农业。Softmax 不是一个很好的分类这些图像的激活函数,因为它倾向于将一个图像分为一个类别,而不是多个类别。因此,Softmax 适用于单标签分类,不适用于多标签分类。

Fastai 在 **train_v2.csv** 文件中查找标签,如果发现任何样品有一个以上的标签,它会自动切换到多标签模式。

第 2.2 集所述,我们创建了一个占训练数据集 20%的验证数据集。下述命令用于创建验证数据集:-

3。 获取 FASTAI 格式的数据

这些步骤与我们在前两集所做的相同。get_data(sz)有两行代码:-

  • tfms_from_model 有助于数据扩充。aug_tfms=transforms_up_down表示垂直翻转图像。它实际上做的不止这些。正方形图像实际上有 8 种可能的对称性,这意味着它可以旋转 0、90、180、270 度,并且可以翻转其中的每一种。这是我们对正方形对称性所能做的一切的完整列举。它被称为dihedral 集团。这段代码将完成完整的 8 组翻转,即dihedral 组旋转和翻转加上小的 10 度旋转,一点缩放,一点对比度和亮度调整。要了解更多信息,请查看fastai 文件夹中的transforms.py文件。下面附上了transforms.py中执行二面角旋转的片段。请检查我们在transforms.py文件中应用的其他转换。

  • 参数 **ImageClassfierData.from_csv(...)** 为:

它有助于按照 fastai 格式读取文件。

  • PATH是数据的根路径(用于存储训练模型、预计算值等)。还包含所有的数据。
  • 'train' —包含训练数据的文件夹。
  • labels.csv文件有行星图像的标签。
  • val_idxs 有验证数据。它指示已经放入验证数据集中的 labels.csv 中的索引号。
  • test_name='test'test 数据集。
  • 文件名实际上在末尾有一个.jpg,在labels.csv文件中没有提到,因此我们有suffix=’.jpg’。这将把.jpg添加到文件名的末尾。
  • tfms 是我们要申请的数据增强的转换。
  • bs= 64 张图像的批量大小。

py torch 中数据加载器与数据集的概念:-

我们在之前的剧集中遇到的数据集将返回单个图像,而数据加载器将返回一小批图像。我们只能得到下一个小批量。为了将数据加载器转换成迭代器,我们使用了一个标准的 python 函数 iter。那是一个迭代器。要获取下一个迷你批次,请将 iter 传递给 next。它将返回下一批图像和标签。下文对此进行了描述

x,y = next(iter(data.val_dl))
y

上述命令是一个验证集数据加载器,将返回一个图像和标签的小批量y标签给出了下面的输出

正如我们所看到的,在这 64 个样品的小批量中有 17 个标签。在上面的get_data(bs)函数中已经明确提到了bs=64 。要理解这些热编码标签的含义,请查看下面的代码

list(zip(data.classes, y[0]))

data.classes 具有实际的标签名称,而y[0]给出了特定样本所属的所有标签的名称。如上所示,输出表示第一幅图像具有标签农业、清洁、初级。标签的一个热编码表示已经在下面的图像中被表示。标签的一次性编码由 Pytorch 框架在内部处理。

Data Representation

这个标签的热编码表示是实际值。神经网络提取 17 个这样的值(在这种情况下),这些值被称为预测值。我们使用损失函数和梯度下降的概念来最小化实际预测值之间的误差。

在某些情况下,图像不是那么清晰。在这种情况下,为了掌握图像的所有特征,可以使用 1.5/1.6/1.7 的倍增系数来增加图像的亮度,如下所示。

使用这些行星数据的最大好处是它与 ImageNet 不同。在现实世界中处理数据时,我们没有类似于 ImageNet 数据集的数据。

这里,我们首先将数据大小调整为(64,64)而不是原始大小(256,256)。我们不会在狗与猫分类的情况下开始这么小,因为预训练的 resnet 网络开始时几乎完美,所以如果我们将所有东西的大小调整为(64,64)并重新训练权重,它将破坏先前预训练为好的权重。大多数 ImageNet 模型是在(224,224)或(299,299)之上训练的。我们开始这么小的主要原因是 ImageNet 图像与这个星球竞赛数据集不相似。已经在 ImageNet 数据集上训练的 Resnet 网络的主要收获是可以检测边缘、拐角、纹理和重复图案的初始层。

它是这样工作的

获取所需大小的数据,即(64,64)。

sz=64
data = get_data(sz)
data = data.resize(int(sz*1.3), '/tmp')

4。 设置神经网络,寻找最佳学*率

from planet import f2metrics=[f2]
f_model = resnet34learn = ConvLearner.pretrained(f_model, data, metrics=metrics) 

f2 指标将在这篇博文的后面讨论。此外,在这个模型中,由于没有提到precompute=True,因此默认情况下它采用precompute=False。要了解这一点,点击shift+Tab,它将显示所有参数及其默认值。在这个时间点当precompute=False

  • 我们的数据扩充是在的
  • 倒数第二层之前的所有层都被冻结
  • 在倒数第二层之后,我们将额外完全连接的 附加到最后,然后我们就有了最终输出。

现在,让我们来看看最好的学*率发现者。

lrf=learn.lr_find()
learn.sched.plot()

正如我们在损失 对学*率的图表中看到的,最佳学*率可以接* 0.2。怎么会?

  • 如前所述,y 轴上的损失在 0.2 处最小,对应的学*率在 x 轴上是 10⁰ =1。
  • 正如前面讨论的,我们可以在损失最小的点之前获得最佳学*率,因此是 0.2。

现在使用最好的学*率0.2,让我们训练我们的模型,如下面的代码所示。

5。 从几个时期的预计算激活中训练最后一层。

lr = 0.2
learn.fit(lr, 3, cycle_len=1, cycle_mult=2)

Cycle_lenCycle_mult 的概念在第 2.1 集中已经详细讨论过了。到目前为止,我们只训练我们最后连接的额外的完整层。

训练所有的层直到最后,

  • 为层的子集设置不同的学*率。
  • 解冻冻结层。
  • 开始训练所有层。

要学*一组不同的特征或告诉学*者需要改变卷积滤波器,只需**unfreeze** 所有层。冻结的层是其权重没有被训练或更新的层。要了解解冻和冻结图层的工作原理,请查看第 2.1 集。由于行星竞赛中的图像不同于 ImageNet 数据集:-

  • 所以学*率高。
  • 而且前面几层比后面几层需要学的更多。

6。解冻层并训练所有层。

lrs = np.array([lr/9,lr/3,lr])
learn.unfreeze()
learn.fit(lrs, 3, cycle_len=1, cycle_mult=2)

下面我们可以看到,在每一个周期后,损失大幅下降。

learn.save(f’{sz}’)
learn.sched.plot_loss()

7。 改进我们的模型,防止过度拟合:-

从现在开始,我们将把图像尺寸增加到(128,128)并进一步增加到(256,256)以便

  • 减少过度拟合。
  • 减小 trn_lossval_loss 之间的间隙。
  • 训练神经网络的早期层(通过解冻它们),因为预训练的权重来自 ImageNet 模型,该模型与行星竞争数据集没有太多相似之处。
sz=128
learn.set_data(get_data(sz))
learn.freeze()
learn.fit(lr, 3, cycle_len=1, cycle_mult=2)

learn.unfreeze()
learn.fit(lrs, 3, cycle_len=1, cycle_mult=2)
learn.save(f'{sz}')

sz=256
learn.set_data(get_data(sz))
learn.freeze()
learn.fit(lr, 3, cycle_len=1, cycle_mult=2)

learn.unfreeze()
learn.fit(lrs, 3, cycle_len=1, cycle_mult=2)
learn.save(f'{sz}')

最后我们做一个 TTA( 测试时间扩增 )来得到。

multi_preds, y = learn.TTA()
preds = np.mean(multi_preds, 0)
f2(preds,y)

Accuracy

瞧,我们得到一个 ***93.6%*** 的准确度,这对于多标签分类来说太好了。

如果你陪我到这一步,给自己一个击掌。

??????????有问题的,请举手??????????

??? ???

Qs 1:-下面的命令中 **data.resize()** 是做什么的?

data = data.resize(int(sz*1.3), '/tmp')

如果初始输入是(1000,1000 ),那么读取该 jpeg 并将其大小调整为(64,64)比训练 convnet 每批所花费的时间要多。resize 的作用是,它表示不会使用任何大于 sz*1.3 的图像。所以仔细检查并创建新的size=sz*1.3的 jpegs。这一步不是必需的,但它加快了进程。

问题 2:-为什么行星卫星图像竞赛中这里使用的度量是 **f2** 而不是精度?

有很多方法可以将我们在狗和猫的分类中看到的混淆矩阵转化为准确度分数。那些是

  • 精确
  • 回忆
  • f-β

根据这个竞赛标准,准确性是根据 f-Beta 分数来判断的。在 f-Beta 评分中,Beta 表示你对假阴性和假阳性的权重是多少?在 f-β中,β值是 2。当我们建立神经网络时,我们将它作为一个metrics 来传递。查看下面的代码。

from planet import f2metrics=[f2]
f_model = resnet34learn = ConvLearner.pretrained(f_model, data, metrics=metrics)

Qs 3:-多标签和单标签分类的区别?

单标签分类问题的输出激活函数是 Softmax。但是如果我们必须预测特定图像中的多个标签,如下文最后一列所示

那么 Softmax 是一个可怕的选择,因为它有强烈选择特定标签的倾向。对于多标签分类问题,我们使用的激活函数是 Sigmoid。fastai 库如果观察到多标签分类问题,会自动切换到 Sigmoid。Sigmoid 公式是 ex/(1+ex)。Sigmoid 图看起来像:-

基本上,Sigmoid 图表示的是,如果激活小于 0.5,则 Sigmoid 将返回低概率值,如果激活大于 0.5,则 Sigmoid 将返回高概率值。多件事怎么可能有高概率。

问题 4:-蛋鸡训练如何进行?

这些层次非常重要,但其中预先训练的权重并不重要。所以最想训练的是后面几层。早期的层已经接*我们想要的,即检测边缘和角落。

因此,在狗与猫的情况下,当我们从预训练的模型创建模型时,它会返回一个模型,其中所有卷积层都被冻结,一些随机设置的完全连接层被添加到末端并被解冻。所以当我们说 fit 的时候,首先,它在最后训练随机初始化的全连接层。如果某样东西真的很接* Imagenet 数据集,那往往就是我们需要的。因为早期的层已经善于发现边缘、梯度、重复图案等。然后,当我们解冻时,我们将早期层的学*速率设置得非常低,因为我们不想对它们进行太多的更改。

而在卫星数据中,早期的层似乎比后期的层更好,但我们仍然需要对它们进行相当大的改变,这就是为什么我们的学*速率比最终的学*速率小 9 倍,而不是像前一种情况那样小 1000 倍。

问题 5:-为什么我们不能直接从解冻所有层开始?

我们可以做到,但是需要更多的时间。首先,通过解冻最终层并保持初始层冻结,我们正在训练最终层学*更重要的功能。卷积层包含预先训练的权重,因此它们不是随机的。对于那些接* ImageNet 的东西,它们真的很好,但是如果它们不接* ImageNet,它们总比没有好。我们所有的 FC 层都是完全随机的,因此你总是想通过先训练它们来使完全连接的层比随机层更好,因为否则如果你直接去解冻,那么我们将在早期层权重仍然随机时摆弄早期层权重。

需要记住的几点是

  • 训练就是更新核值的权重和 FC 层的权重。根据权重和先前层激活输出来计算激活。
  • **learn.summary()** 命令用来可视化模型。

如果你喜欢,那么ABC(永远被击节 )。 👏 👏👏👏👏😃😃😃😃😃😃😃😃😃👏 👏👏👏👏👏** )

如果您有任何问题,请随时在 fast.ai 论坛或 Twitter 上联系: @ashiskumarpanda

附:随着我继续学*其他课程,这篇博文将会更新和改进。如果你对源代码感兴趣,可以在这里查看

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分:- 狗和猫的图像分类

  1. 犬种图像分类
  2. 多标签图像分类
  3. 使用神经网络的时间序列分析
  4. 对 IMDB 电影数据集的 NLP 情感分析
  5. 电影推荐系统基础
  6. 从零开始协同过滤
  7. 使用神经网络的协同过滤
  8. 像尼采一样写哲学
  9. 不同神经网络在 Cifar-10 数据集上的性能
  10. 检测图像中最大物体的 ML 模型 Part-1
  11. 检测图像中最大物体的 ML 模型 Part-2

编辑 1:-TFW·杰瑞米·霍华德同意你的帖子。💖💖 🙌🙌🙌 💖💖。

“使用神经网络进行时间序列分析”

原文:https://towardsdatascience.com/fast-ai-season-1-episode-4-1-time-series-analysis-a23217418bf1?source=collection_archive---------6-----------------------

使用神经网络建立一个先进的时间序列预测模型。

欢迎来到第四集 Fastdotai ,在这里我们将处理结构化和时间序列数据。在我们开始之前,我想感谢 【杰瑞米·霍华德】雷切尔·托马斯 为民主化人工智能所做的努力。

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分:- 狗和猫的图像分类

  1. 狗 Vs 猫图像分类
  2. 犬种图像分类
  3. 多标签图像分类
  4. 利用神经网络进行时间序列分析
  5. 对 IMDB 电影数据集的 NLP 情感分析
  6. 电影推荐系统的基础
  7. 从无到有的协同过滤
  8. 使用神经网络的协同过滤
  9. 像尼采一样写哲学
  10. 不同神经网络在 Cifar-10 数据集上的性能
  11. ML 模型检测图像中最大的物体 Part-1
  12. 检测图像中最大物体的 ML 模型 Part-2

我们将讨论的笔记本是郭/伯克哈恩的[ 分类变量的实体嵌入 ]中详述的罗斯曼卡格尔竞赛第三名结果的实现。代码已经在 kaggle 内核的帮助下执行。所以会有一些额外的东西被写出来,这样代码就可以在 kaggle 上流畅地运行。如果您在任何其他云 GPU 平台上运行代码,这些额外的代码行可能是不必要的。我会在这篇博文的最后附上 kaggle 内核链接。

正如上面的代码片段所述,我们将拥有更多的数据集,这将有助于我们丰富特性,从而帮助我们获得更好的准确性。构成特征空间的这些数据集如下所述。

特征空间涉及:

  • train:包含每天的商店信息,跟踪销售、顾客、当天是否是假日等信息。
  • 商店:商店列表。商店的一般信息,包括竞争情况等。
  • store_states:商店到所在德国州的映射。
  • googletrend:某些 google 关键字随时间的变化趋势,用户发现这些关键字与给定的数据有很好的相关性。
  • 天气:每个州的天气情况。
  • 测试:与培训表相同,没有销售和客户。

让我们将这些数据文件名保存在如下所示的特定列表中:-

我们可以使用head()快速浏览每个表格的内容:

数据清理/特征工程:-

在下面的代码片段中,我们将进行数据清理:-

在继续之前,让我们看一下googletrends数据,因为接下来我们将对此进行特性工程。

让我们看一看特征工程后的googletrend 。检查新列Date ,State和对State列所做的更改。

以下步骤对特征工程非常重要:-

正如我们在下面的快照中所看到的,我们已经向googletrends 添加了更多的列,这些列是使用上面的命令从Date 列形成的。

在上面的代码片段中,joined 是我们的训练数据,joined_test 是我们的测试数据。众所周知,一幅画胜过 1000 句话。让我描述一下我们如何通过合并多个表得到训练数据— joined 和测试数据— joined_test的流程图。以下快照与joinedjoined_test相同。

删除额外变量前后的比较

正如我们在下面的代码中看到的,我们将填充训练数据— joined 和测试数据— joined_test中出现的缺失值。

输出如下所示:-

在下面的代码中,我们替换了离群值并做了更多的功能工程。

促销日期的相同功能工程。

让我们关注一下持续时间:-

这篇文章你已经看了一半了。干得好。继续走。从这里开始会很有趣。

现在,让我们关注分类变量和连续变量。

Categorical vs Continuous

决定哪个变量是分类变量还是连续变量?

在上面的代码中,我们已经分离了将被视为连续和分类的列。但是怎么做呢?这个需要详细解释。

因此,根据列/变量的基数可以说该列/变量是连续的或分类的。基数被定义为一个类别中级别的数量。例如,基数表示一周的天数=7

  • 无论哪个变量已经以分类形式出现在数据中,都将是模型中的分类变量。
  • 对于连续变量,我们必须检查它们的基数。如果它们的基数(不同级别的数量)太高,它将是连续的,否则它将被转换成分类变量。
  • 连续变量应该具有连续平滑的函数。例如,年份虽然是一个连续变量,但没有很多不同的级别,因此最好将其作为一个分类变量。在这种情况下,连续的是类型为floating point 或数据类型为int 的那些。
  • 我们可以绑定一个连续变量,然后将其转换为分类变量。有时候宁滨会很有帮助。

哪些变量是分类变量,哪些是连续变量,这是我们必须做出的建模决策之一。

在这个时间点上,我们的数据看起来像这样。它有一些连续的,一些布尔的,一些分类的等等。

在上面的代码中,Fastai 有一个名为 process _ data frame(proc _ df)的函数。

  • 它从数据帧‘joined _ samp’中取出因变量,即‘Sales’,并将其存储在单独的变量**y**中。
  • 除了因变量' Sales '之外的其余数据帧保存在**df** 中。
  • nas :返回它创建了哪个 nas 的字典,以及相关的中位数。
  • 映射器:一个数据帧映射器,存储相应连续变量的平均值和标准偏差,然后用于测试期间的缩放。
  • 它还处理缺失值,因此分类变量中的缺失值变为 0,其他类别变为 1,2,3,4,依此类推。
  • 对于连续变量,它用中值替换缺失值,并创建一个新的布尔列,表示是否缺失。

现在输出 df 的所有变量都是连续的。分类列由等价的连续值表示。查看“年份”和“产品组合”栏在此之前和之后的变化。

这样,所有的列都是连续的。

  • 连续的列保持不变。它们被改成了float32 ,因为这是 pytorch 接受的标准数字数据类型。
  • 分类列被转换成等效的连续类型。

验证数据集

根据 Kaggle,我们在 Rossman 数据中的问题陈述是预测接下来两周的销售。由于它是一个时间序列数据,我们的验证数据集不是随机的。相反,它是我们实际应用中的最新数据。

深度学*从这里开始。

  • 根据罗斯曼数据竞赛的 Kaggle 规则,我们将在 RMSPE(均方根百分比误差)的基础上进行评估。

  • RMSPE 将是度量而不是准确性,因此我们在下面的代码中对此进行了公式化:-

  • 让我们创建我们的模型数据对象:-

  • 早些时候是ImageClassifierData ,因为那时我们正在处理图像。现在在这种情况下,当我们处理纵列表格数据时,它是ColumnarModelData

  • 我们有了from_data_frame,而不是from_Paths

  • PATH —存储模型文件的位置。

  • val_idx —要放入验证数据集中的行的索引列表。

  • df —数据框。

  • y1 —由因变量组成。

  • cat_flds —将所有列视为分类变量,因为此时所有列都转换为数值。

  • bs —批量大小。

对分类变量应用嵌入:

上面的代码所做的是,它遍历每个分类变量(cat_vars)并打印出它所拥有的不同级别或类别的数量。上面代码中带有类别的+1 是为缺失值保留的。基本上,它打印每个变量的基数和变量名。

我们用每个变量的基数来决定它的嵌入矩阵应该有多大。

在上面的代码中,我们遵循一条经验法则,即嵌入大小是cardinality size//2 ,但不大于 50。

嵌入矩阵如何工作?

  • 当我们创建这些矩阵时,它有随机数。因此,我们将它们放入神经网络,并不断更新它们的值,以减少损失函数。这些嵌入矩阵可以与一组权重相比较,这些权重以减少损失的方式自我更新。这样,我们从这些权重的随机值到有意义的更新值。
  • 客观地说,嵌入矩阵的值可以在 0 和该类别的最大层数之间。然后我们可以索引那个矩阵,找到一个特定的行,我们把它附加到所有的连续变量上,之后的一切都和之前一样。

嵌入矩阵的图示:-

将神经网络应用于连续变量:-

上图显示了神经网络如何处理连续变量。查看矩阵乘法如何工作并产生相应的输出。这是一个 2 隐层神经网络。假设有 20 列作为输入,并且我们已经设计了神经网络,使得第一隐藏层具有 100 个隐藏单元,第二隐藏层具有 50 个隐藏单元。因此,我们的输入[1,20]乘以维度为[20,100]的权重矩阵将得到[1,100]。然后,我们将 ReLU 应用于这个[1,100]维度值,这导致[1,100]的激活。然后,这个[1,100]维激活乘以[100,50]维的权重,这导致具有[1,50]维的激活。这个[1,50]激活然后乘以维度[50,1]的权重,这导致 1 输出。我们在最后一层应用 Softmax 来得到最终的输出。

  • 注意:- 不要将 ReLU 放在最后一层,因为 Softmax 需要负值来创建更低的概率。ReLU 函数去掉了负值。在罗斯曼销售数据的情况下,我们试图预测销售,因此我们最终不需要 Softmax。

让我们创建我们的学*者。这就是我们如何建立我们的神经网络。

best lr = 1e-3

get_learner()中使用的参数。

  • emb_s —对每个分类变量使用此嵌入矩阵。
  • len(df.columns)-len(cat_vars) —表示连续变量的数量。
  • 0.04 —一开始就辍学。
  • 1 —最后一个线性层的输出。
  • [1000,500] —第一和第二线性层的激活次数。
  • [0.001,0.01] —用于第一和第二线性层的漏失。
  • y_range=y_range —前面已经介绍过了。
  • tmp_name=f”{PATH_WRITE}tmp” —(可选)仅在 kaggle 内核中使用。
  • models_name=f”{PATH_WRITE}models” —(可选)仅在 kaggle 内核中使用。

???有什么问题吗???

!!! Question Time !!!

Qs 1 :-星期嵌入中的四个值表示什么?

最初,我们从一些随机的四个值开始。它的功能与砝码相同。所以我们在最小化损失的同时更新这些值。当损失被最小化时,我们将以一些更新的四个值结束。此时,我们会发现这些特定的参数是人类可以解释的,而且非常有趣。

Qs 2 :-除了随机初始化,还有什么方法初始化嵌入矩阵?

如果罗斯曼有一个预先训练好的奶酪销售嵌入矩阵,我们可以用它来预测酒的销售。instacart 和 pinterest 正在使用这种技术。他们有产品和商店的嵌入矩阵,在组织内共享,这样人们就不必培训新的产品和商店。

Qs 3 :-使用嵌入矩阵比一键编码有什么优势?

以周日的一个热门编码向量为例:-

[1 0 0 0 0 0 0]

Sunday 的独热编码表示法的问题是它表示一个浮点数。它只代表一件事。更多的是线性行为。

有了嵌入,星期天就是一个四维空间的概念。更新这些值后我们得到的是丰富的语义概念。例如,如果结果是周末与工作日相比具有不同的行为,那么我们看到在这个嵌入矩阵中周六和周日的某个值会更高。通过拥有这些高维向量,我们给神经网络一个机会来学*这些潜在的丰富表示。正是这种丰富的表现让它能够学*如此有趣的关系。这种表示嵌入的思想被称为“分布式表示”。神经网络具有有时难以解释的高维表示。矩阵中的这些数字不一定只有一个意思。它可以随着上下文改变它的意思,因为它经历了丰富的非线性函数。

虽然一个热门的编码在一周的几天中有更多的维度,但它并不是有意义的高维。嵌入矩阵的使用有助于减小尺寸,并更恰当地表示变量。

问题 3:-嵌入适合某种类型的变量吗?

当我们遇到分类变量时,我们使用嵌入的概念。但是对于高基数的变量就不行了。

问题 4:add_datepart() 如何影响季节性?

fastai 库有一个add_datepart()函数,它接受一个数据帧及其表示日期的列。它可以选择删除日期列,而不是返回许多表示该日期有用信息的列。例如用dayOfWeekMonthOfYearYearMonthWeekDay等代替Date 等。所以daysOFWeek 现在可以用一个【8,4】嵌入矩阵来表示。从概念上讲,这允许模型挑选一些有趣的特征和模式。

  • 假设,有一个 7 天周期的东西,它在周一上涨,周四下跌,只有在柏林,它可以完全提取该模式,因为它有所有需要的信息。这是处理时间序列模型的好方法。我们只需要确保我们的时间序列模型中的周期指标或周期性应该以列的形式存在。

使用以下命令培养学*者并获得最佳的学*速度。

正如我们所看到的,最好的学*率在 10^-3.的某个地方所以我们将继续用 lr=10^-3.训练我们的神经网络

m.fit(lr, 3, metrics=[exp_rmspe])
[ 0\.       0.02479  0.02205  0.19309]                          
[ 1\.       0.02044  0.01751  0.18301]                          
[ 2\.       0.01598  0.01571  0.17248]m.fit(lr, 5, metrics=[exp_rmspe], cycle_len=1)
[ 0\.       0.01258  0.01278  0.16   ]                          
[ 1\.       0.01147  0.01214  0.15758]                          
[ 2\.       0.01157  0.01157  0.15585]                          
[ 3\.       0.00984  0.01124  0.15251]                           
[ 4\.       0.00946  0.01094  0.15197]m.fit(lr, 2, metrics=[exp_rmspe], cycle_len=4)
[ 0\.       0.01179  0.01242  0.15512]                           
[ 1\.       0.00921  0.01098  0.15003]                           
[ 2\.       0.00771  0.01031  0.14431]                           
[ 3\.       0.00632  0.01016  0.14358]                           
[ 4\.       0.01003  0.01305  0.16574]                           
[ 5\.       0.00827  0.01087  0.14937]                           
[ 6\.       0.00628  0.01025  0.14506]                           
[ 7\.       0.0053   0.01     0.14449] 

注意:- 从梯度推进切换到深度学*是好的,因为它需要更少的特征工程,并且它是需要更少维护的更简单的模型。这是使用深度学*方法的最大好处之一。使用这种方法,我们可以得到很好的结果,但工作量要少得多。

总结:-

第一步:- 列出分类变量名和连续变量名,放入数据框。

步骤 2:- 创建一个我们希望包含在验证集中的 row_indexes 列表。

步骤 3:- 创建柱状模型数据对象。

步骤 4:- 创建一个我们希望嵌入矩阵有多大的列表。

步骤 5:- 调用 get_learner 并使用确切的参数开始。

第六步:- 调用 m.fit()

我已经使用了威廉姆·霍顿的这篇博文中提到的内核。

!!!恭喜你在 fast.ai 上又学完了一课。干得好。!!!

如果你喜欢,那么ABC(永远被击节 👏 👏👏👏👏😃😃😃😃😃😃😃😃😃👏 👏👏👏👏👏** )

如果您有任何问题,请随时在 fast.ai 论坛或 Twitter 上联系: @ashiskumarpanda

注:随着我继续学*其他课程,这篇博文将会更新和改进。更多有趣的东西,可以随时查看我的Github账号。

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分

  1. 狗 Vs 猫图像分类
  2. 犬种图像分类
  3. 多标签图像分类
  4. 使用神经网络的时间序列分析
  5. IMDB 电影数据集上的 NLP-情感分析
  6. 电影推荐系统基础
  7. 从零开始协同过滤
  8. 使用神经网络的协同过滤
  9. 像尼采一样写哲学
  10. 不同神经网络在 Cifar-10 数据集上的性能
  11. 检测图像中最大物体的 ML 模型 Part-1
  12. 检测图像中最大物体的 ML 模型 Part-2

编辑 1:-TFW·杰瑞米·霍华德同意你的帖子。💖💖 🙌🙌🙌 💖💖。

“电影推荐系统”

原文:https://towardsdatascience.com/fast-ai-season-1-episode-5-1-movie-recommendation-using-fastai-a53ed8e41269?source=collection_archive---------7-----------------------

欢迎来到第五集 Fastdotai ,在这里我们将处理电影推荐系统。在我们开始之前,我想感谢 【杰瑞米·霍华德】雷切尔·托马斯 为民主化人工智能所做的努力。

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分

  1. 狗 Vs 猫图像分类
  2. 犬种图像分类
  3. 多标签图像分类
  4. 使用神经网络的时间序列分析
  5. IMDB 电影数据集上的自然语言处理情感分析
  6. 电影推荐系统的基础
  7. 从零开始协同过滤
  8. 使用神经网络的协同过滤
  9. 像尼采一样写哲学
  10. 不同神经网络在 Cifar-10 数据集上的性能
  11. 检测图像中最大物体的 ML 模型 Part-1
  12. ML 模型检测图像中最大的物体 Part-2

拿一份爆米花,我们开始吧。

首先,让我们导入所有需要的包。

%reload_ext autoreload
%autoreload 2
%matplotlib inlinefrom fastai.learner import *
from fastai.column_data import *

设置路径的位置

  • 输入数据被存储。
  • 将存储临时文件。(可选-在 kaggle 内核中使用)
  • 模型重量将被存储。(可选-在 kaggle 内核中使用)
path='../input/'
tmp_path='/kaggle/working/tmp/'
models_path='/kaggle/working/models/'
  • 数据的读取。
ratings = pd.read_csv(path+'ratings.csv')
ratings.head()
# This contains the userid , the movie that the userid watched , the time that movie has been watched , the ratings that has provided by the user .

movies = pd.read_csv(path+'movies.csv')
movies.head()
# This table is just for information purpose and not intended for         # modelling purpose

创建热门电影和用户 ID 的交叉表:-

g=ratings.groupby('userId')['rating'].count()
topUsers=g.sort_values(ascending=False)[:15]
# Users who have given most number of ratings to the movies are          # considered as top Users.g=ratings.groupby('movieId')['rating'].count()
topMovies=g.sort_values(ascending=False)[:15]
# Movies that have got most number of ratings are topMovies .top_r = ratings.join(topUsers, rsuffix='_r', how='inner', on='userId')
top_r = top_r.join(topMovies, rsuffix='_r', how='inner', on='movieId')
pd.crosstab(top_r.userId, top_r.movieId, top_r.rating, aggfunc=np.sum)

因此,我们将通过三种方式来处理电影推荐。

  1. 矩阵分解。
  2. 从无到有的协同过滤。
  3. 神经网络方法。

首先,我们将深入研究矩阵分解方法:-

  1. 矩阵分解:-

左侧方框中的表格显示了实际评级。这是我们的实际数据。

让我详细讨论一下右表是如何组成的,左表和右表是什么关系。

  • 制作预测收视率表(右表)

  • 右边的表以用户 id (users)为行,以电影 id (movies)为列。电影 id 和用户 id 用嵌入矩阵来描述。还记得我们在上一篇博文中讨论的嵌入矩阵吗?正如我们所知,嵌入矩阵是由嵌入向量组成的,在开始时,它们只是随机数。在上图中用紫色表示。
  • 例如,用户 Id 14 由四个随机数表示。类似地,电影 Id 27 由 4 个随机数表示。这些数字乘积的总和产生了预测的等级。每个嵌入向量在开始时被随机初始化。换句话说,每个预测的评级是两个嵌入向量的矩阵乘积。
  • 我们的目标函数是最小化预测评级和实际评级之间的 RMSE。如果我们看到下面的公式

  • SUMXMY2 函数计算数组中相应项之间的差的平方和,并返回结果的总和。为了分解公式,它取预测值和实际值之间的 MSE(均方误差),然后求和,得出一个数字。然后将该数字除以评级数量的计数。然后我们取这个数的平方根。在上图中,这个数字用蓝色表示。这就是我们要最小化的目标函数。

???有什么问题吗???

这些嵌入向量是什么意思?

  • 最初这些都是随机的,但是经过训练后,就开始有意义了。几个时期后,检查这些额定值。这些值会不断自我更新。因此,在几个时期之后,这些预测的额定值将接*实际额定值。据此,这些嵌入向量会自我调整。例如对于电影 Id 27(指环王):-由如下所示的 4 个数字组成的嵌入向量

  • 假设每个单元格表示(%科幻,%基于 CGI,%对话驱动,%现代,%喜剧)。它表示电影的类型。

  • 类似地,在用户 Id 嵌入向量的情况下,每个数字表示用户 Id 14 有多喜欢科幻电影、现代 CGI 电影、对话驱动电影等等。
  • 我们将在后面讨论偏见。

注意:-这里我们没有任何非线性激活函数或任何类型的隐藏层。因此,它会被认为是浅薄学*的一个例子。

Qs:-协同过滤与概率矩阵分解有何相同之处?

这里我们得到的预测结果是两个不同向量的叉积。问题是,我们没有关于每个用户或电影的适当信息,所以我们假设这是理解系统的合理方式,并使用 SGD 来找到将工作的优化数字。

Qs:-如何决定这些嵌入向量的长度?

我们应该选择一个嵌入维数,它足以代表手头问题的真正复杂性。同时,它不应该太大,否则会有太多的参数,运行时间太长,或者即使进行正则化也会产生过度拟合的结果。

Qs:-负数在嵌入向量中表示什么?

电影 id 为负数表示特定电影不属于该特定类型。在用户 ID 为负数的情况下,表示特定用户不喜欢该特定类型的电影。

问:-当我们有一部新电影或新用户时会发生什么?

如果我们使用网飞作为新用户,它总是问我们喜欢什么电影。并且它重新训练它的模型以便给出好的推荐。

  • 协同过滤的时间到了:-

协同过滤推荐系统方法是用户和项目的概念。假设有一个用户 Id -14 喜欢电影 Id- 24,那么协同过滤方法说,哪个其他用户喜欢那个电影- 24,那个用户 ID-14 也喜欢。然后,它浏览与用户 Id-14 有相同偏好的其他用户的电影列表,并将这些电影推荐给用户 Id-14。

所以它有两个部分:-

  1. 用户 Id 和电影 Id
  2. 评级值(因变量)
val_idxs = get_cv_idxs(len(ratings))
wd=2e-4  # L2 Regularization , helps in preventing overfitting
n_factors = 50 # Embedding dimensionalitiescf = CollabFilterDataset.from_csv(path, 'ratings.csv', 'userId', 'movieId', 'rating')
# 1\. path - where the file is stored.
# 2\. 'ratings.csv' - The excel file which contains the data to be read.
# 3\. 'userId' - What should be the rows .
# 4\. 'movieId' - What should be the columns .
# 5\. 'rating' - Values for predictions. learn = cf.get_learner(n_factors, val_idxs, 64, opt_fn=optim.Adam, tmp_name=tmp_path, models_name=models_path)# Finally, we train our model
learn.fit(1e-2, 2, wds=wd, cycle_len=1, cycle_mult=2)

math.sqrt(0.766)
# 0.8752142594816426
# Let's compare to some benchmarks. Here's [some benchmarks](https://www.librec.net/release/v1.3/example.html) on the same   # dataset for the popular Librec system for collaborative filtering. They # show best results based on [RMSE](http://www.statisticshowto.com/rmse/) of 0.91\. We'll need to take the square # root of our loss, since we use plain MSE.preds = learn.predict()

我们来分析一下结果:

movie_names = movies.set_index('movieId')['title'].to_dict()
# Contains movieid and their title in form of dictionaries

g=ratings.groupby('movieId')['rating'].count()
# Which  movie got how many ratings

topMovies=g.sort_values(ascending=False).index.values[:3000]
# Take the movieid of 3000 movies which has got most number of ratings.

topMovieIdx = np.array([cf.item2idx[o] for o in topMovies])
# Replace the movieid with contigious ids.
# Check out our model below. It has 50 embedding vectors for each of movies and users . And a bias for each movie and each user.

# First,  we'll look at the movie bias term. Here, our input is the movie # id (a  single id), and the output is the movie bias (a single float). movie_bias = to_np(m.ib(V(topMovieIdx)))

  • 代码to_np(m.ib(V(topMovieIdx)))将在遍历嵌入层中的每个 MovieIds 并返回其偏差后给出一个变量。
  • m.ib指项目/电影的嵌入层,即偏置层。我们知道有 9066 部电影和与之相关的偏见。m.ib将返回该图层的值。
  • 模型/层需要变量来跟踪梯度,因此有了V(…)
  • 使用to_np()将张量转换成数值。
  • 为了推理的目的,将模型从 GPU 移动到 CPU,使用m.cpu()。并使用m.cuda()将其移动到 GPU。
movie_ratings = [(b[0], movie_names[i]) for i,b in zip(topMovies,movie_bias)]
# A list comprehension where movie_bias is stored in b and topMovies in  # movie_names. Check out the below output which returns a list of tuples # having movies and its bias .

根据电影的倾向性对电影进行排序(即使用 lambda 函数对每个元组的第 0 个元素进行排序)。在检查中我们发现,偏见表明电影的质量。好电影有正面偏见,烂片有负面偏见。这就是如何解释偏见术语。

sorted(movie_ratings, key=lambda o: o[0], reverse=True)[:15]
# Sort the movies by its bias (i.e the 0th element of each tuple by using # lambda function). Reverse=True means in descending order of Bias       # values.

让我们来解释嵌入向量:-

movie_emb = to_np(m.i(V(topMovieIdx)))
# m.i(...) for item embeddings.movie_emb.shape

# Because it's hard to interpret 50 embeddings, we use [PCA](https://plot.ly/ipython-notebooks/principal-component-analysis/) to simplify    # them down to just 3 vectors.from sklearn.decomposition import PCA
pca = PCA(n_components=3)
movie_pca = pca.fit(movie_emb.T).components_
movie_pca.shape

fac0 = movie_pca[0]
movie_comp = [(f, movie_names[i]) for f,i in zip(fac0, topMovies)]
# Here's the 1st component. It seems to be 'easy watching' vs 'serious'.# Its upto us to decide what does these Embeddings mean . Check the output belowsorted(movie_comp, key=itemgetter(0), reverse=True)[:10]

# Lets interpret the 2nd component
fac1 = movie_pca[1]
movie_comp = [(f, movie_names[i]) for f,i in zip(fac1, topMovies)]
#  It seems to be 'CGI' vs 'dialog driven'.
sorted(movie_comp, key=itemgetter(0), reverse=True)[:10]

这就是我们如何分析一个电影推荐系统。评价标准是最小化 RMSE。早先的误差基准是 0.91 。使用 fastai,我们得到 0.87。

因此,这种模式表现良好。

在下一部分,我们将从头开始讨论协同过滤

如果你喜欢,那么ABC(永远被击节 👏 👏👏👏👏😃😃😃😃😃😃😃😃😃👏 👏👏👏👏👏** )

如果您有任何问题,请随时联系 fast.ai 论坛或 Twitter:@ ashiskumarpanda

注:随着我继续学*其他课程,这篇博文将会更新和改进。更多有趣的东西,可以随时查看我的Github账号。

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分

  1. 狗 Vs 猫图像分类
  2. 犬种图像分类
  3. 多标签图像分类
  4. 使用神经网络的时间序列分析
  5. 对 IMDB 电影数据集的 NLP 情感分析
  6. 电影推荐系统的基础
  7. 从无到有的协同过滤
  8. 使用神经网络的协同过滤
  9. 像尼采一样写哲学
  10. 不同神经网络在 Cifar-10 数据集上的性能
  11. 检测图像中最大物体的 ML 模型 Part-1
  12. 检测图像中最大物体的 ML 模型 Part-2

编辑 1:-TFW·杰瑞米·霍华德同意你的帖子。💖💖 🙌🙌🙌 💖💖。

“从零开始的协作过滤”

原文:https://towardsdatascience.com/fast-ai-season-1-episode-5-2-collaborative-filtering-from-scratch-1877640f514a?source=collection_archive---------14-----------------------

从头开始构建电影推荐的协同过滤

欢迎来到第五集 Fastdotai 的第二部分,我们将从零开始讲述协同过滤——一种广泛应用于推荐系统的技术。在我们开始之前,我想感谢 【杰瑞米·霍华德】雷切尔·托马斯 为民主化人工智能所做的努力。

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分

  1. 狗 Vs 猫图像分类
  2. 犬种图像分类
  3. 多标签图像分类
  4. 使用神经网络的时间序列分析
  5. IMDB 电影数据集上的自然语言处理情感分析
  6. 电影推荐系统的基础
  7. 从零开始协同过滤
  8. 使用神经网络的协同过滤
  9. 像尼采一样写哲学
  10. 不同神经网络在 Cifar-10 数据集上的性能
  11. 检测图像中最大物体的 ML 模型 Part-1
  12. 检测图像中最大物体的 ML 模型 Part-2

网飞背后的原因和寒意。

首先,让我们导入所有需要的包。

%reload_ext autoreload
%autoreload 2
%matplotlib inlinefrom fastai.learner import *
from fastai.column_data import *

设置路径的位置

  • 输入数据被存储。
  • 将存储临时文件。(可选-在 kaggle 内核中使用)
  • 模型重量将被存储。(可选-在 kaggle 内核中使用)
path='../input/'
tmp_path='/kaggle/working/tmp/'
models_path='/kaggle/working/models/'
  • 数据的读取。
ratings = pd.read_csv(path+'ratings.csv')
ratings.head()
# This contains the userid , the movie that the userid watched , the time that movie has been watched , the ratings that has provided by the user .

movies = pd.read_csv(path+'movies.csv')
movies.head()
# This table is just for information purpose and not intended for         # modelling purpose

u_uniq = ratings.userId.unique() 
user2idx = {o:i for i,o in enumerate(u_uniq)}
# Take every unique user id and map it to a contiguous user .
ratings.userId = ratings.userId.apply(lambda x: user2idx[x])
# Replace that userid with contiguous number.# Similarly, we do it for the movies. 
m_uniq = ratings.movieId.unique()
movie2idx = {o:i for i,o in enumerate(m_uniq)}
ratings.movieId = ratings.movieId.apply(lambda x: movie2idx[x]) 

将 movieId 和 userId 转换成连续的整数有助于我们决定嵌入矩阵。这些 userId 和 movieID 的值在开始时不连续。它可能从 100 万开始,并且不会是连续的。因此,如果我们使用这些值来决定我们的嵌入矩阵,那么嵌入矩阵的大小将会太大,这可能会导致缓慢的处理或过拟合。

class EmbeddingDot(nn.Module):
    def __init__(self, n_users, n_movies):
        super().__init__()
        self.u = nn.Embedding(n_users, n_factors)
        self.m = nn.Embedding(n_movies, n_factors)
        self.u.weight.data.uniform_(0,0.05)
        self.m.weight.data.uniform_(0,0.05)

    def forward(self, cats, conts):
        users,movies = cats[:,0],cats[:,1]
        u,m = self.u(users),self.m(movies)
        return (u*m).sum(1).view(-1, 1)model = EmbeddingDot(n_users, n_movies).cuda() # Class Instantiation

上述代码中涉及到 OOPs 的概念。所以我来详细解释一下。

  • self 是一个参考变量,当对象(即模型)被创建时,存储该对象。
  • def __init__(self, n_users, n_movies):是一个神奇的功能。每当为该类创建对象时,都会自动调用它。这种类型的函数被称为构造函数。
  • model = EmbeddingDot(n_users, n_movies).cuda()。这里创建了对象。随着它的创建,构造函数被自动调用。
  • 但是物体是什么?一个对象(即模型)是一个具有一些属性和行为的实体。
  • 这些行为是嵌入的形状和值,如下所示。
self.u = nn.Embedding(n_users, n_factors) # User Embeddings
self.m = nn.Embedding(n_movies, n_factors) # Movie Embeddings
self.u.weight.data.uniform_(0,0.05) # Values for User Embeddings
self.m.weight.data.uniform_(0,0.05) # Values for Movie Embeddings
  • 为了获得这些嵌入的值,我们使用了从nn.Module 继承而来的nn.Embedding ,使用了 OOP 的Inheritance 概念,使用了下面这行代码:- super().__init__()
  • self.u设置为嵌入类的实例。它有一个包含实际嵌入矩阵的 .weight属性。嵌入矩阵是一个变量。变量和张量一样,它会自动微分。
  • 要访问张量使用,self.u.weight.data属性。
  • self.u.weight.data.uniform_ :-末尾的下划线符号表示它是一个就地操作。self.u.weight.data.uniform_表示这个张量的适当大小的均匀随机数,不返回它,而是在适当的位置填充矩阵。
  • 当我们稍后进行拟合时,前进功能开始起作用。但是,让我们来详细了解一下当调用 forward 函数时会发生什么。
def forward(self, cats, conts):
        users,movies = cats[:,0],cats[:,1]
        u,m = self.u(users),self.m(movies)
        return (u*m).sum(1).view(-1, 1)
  • users,movies = cats[:,0],cats[:,1] :-抓取用户和电影的迷你批次。
  • u,m = self.u(users),self.m(movies) :-对于小批量的用户和电影,使用self.u(users),self.m(movies)查找用户和电影的嵌入矩阵。
  • 在得到用户和电影的嵌入后,我们将这两者进行叉积,得到一个数字,这就是预测的收视率。
x = ratings.drop(['rating', 'timestamp'],axis=1)
# The x contain movies and users from the dataframe. Independent     # variables.y = ratings['rating'].astype(np.float32)
# The y contains the dependent Variable i.e the ratings.data = ColumnarModelData.from_data_frame(path, val_idxs, x, y, ['userId', 'movieId'], 64)1# path :- path of the file.
2# val_idxs :- Validation data
3# x, y :- Described above as independent and dependent variable.
4# ['userId', 'movieId'] :- List of categorical variables.
5# 64 :- batch size.wd=1e-5 # Regularization parameter

opt = optim.SGD(model.parameters(), 1e-1, weight_decay=wd, momentum=0.9)
# Optimizer to be used to update the weights or model.parameters().
# model.parameters() is derived from nn.Module which gives list of all   # the weights that are needed to be updated and hence passed to optimizer # along with learning rate, weight decay and momentum.

为了拟合我们的数据,也就是为了训练,早先我们使用了learner,它是 fast.ai 的一部分,但是现在我们将使用 PyTorch 功能。当执行下面的fit 命令时,检查 fastai 文件夹中的model.py 文件,以了解 fit 命令的底层。基本上它做的是:-

  • 通过调用正向函数def forward(self, cats, conts):进行正向传递
  • 以及更新嵌入的反向传递,这是 PyTorch 的功能。

fit(model, data, 3, opt, F.mse_loss)

这里我们不会得到 SGDR 的功能,因此手动重置学*率,并检查损失。

set_lrs(opt, 0.01)

fit(model, data, 3, opt, F.mse_loss)

虽然我们的模型表现良好,但由于我们没有正确实施 SGDR,因此我们的损失比以前更高。

如何进一步完善模型??

现在我们将考虑偏见。会有一些用户非常热情,平均来说会给所有的电影更高的评价。因此,我们将为电影和用户添加一个常量。这个常数被称为偏差。

min_rating,max_rating = ratings.rating.min(),ratings.rating.max()
min_rating,max_ratingdef get_emb(ni,nf): 
# Input is #User,#Factors i.e Embedding Dimensionality
    e = nn.Embedding(ni, nf) # Creation of Embedding matrix
    e.weight.data.uniform_(-0.01,0.01)
 # Fill it with randomly initialized values between (-0.01,0.01)
    return eclass EmbeddingDotBias(nn.Module):
    def __init__(self, n_users, n_movies):
        super().__init__()
# Creating an embedding for User (self.u) , Movies (self.m), 
# User bias (self.ub), Movie bias (self.mb) by calling get_emb().(self.u, self.m, self.ub, self.mb) = [get_emb(*o) for o in [
            (n_users, n_factors), (n_movies, n_factors), (n_users,1), (n_movies,1)
        ]]

    def forward(self, cats, conts):
        users,movies = cats[:,0],cats[:,1]
        um = (self.u(users)* self.m(movies)).sum(1)
        res = um + self.ub(users).squeeze() + self.mb(movies).squeeze()
# Add in user bias and movie bias. Using .squeeze() does a broadcasting. res = F.sigmoid(res) * (max_rating-min_rating) + min_rating
# This is gonna squish the value between 1 and 5 . What it does is if its # a good movie then it will get a really high number else a low number.
#  F.sigmoid(res) is gonna squish it between 0 and 1. return res.view(-1, 1)wd=2e-4
model = EmbeddingDotBias(cf.n_users, cf.n_items).cuda()
opt = optim.SGD(model.parameters(), 1e-1, weight_decay=wd, momentum=0.9)
fit(model, data, 3, opt, F.mse_loss)

set_lrs(opt, 1e-2)
fit(model, data, 3, opt, F.mse_loss)

最后,我们达到了 0.8 的损失,这相当不错。

如果你喜欢,那么ABC(永远被击节 👏 👏👏👏👏😃😃😃😃😃😃😃😃😃👏 👏👏👏👏👏** )

如果您有任何问题,请随时联系 fast.ai 论坛或 Twitter:@ ashiskumarpanda

注:随着我继续学*其他课程,这篇博文将会更新和改进。更多有趣的东西,可以随时查看我的Github账号。

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分:- 狗与猫的图像分类

  1. 犬种图像分类
  2. 多标签图像分类
  3. 使用神经网络的时间序列分析
  4. 对 IMDB 电影数据集的 NLP 情感分析
  5. 电影推荐系统的基础
  6. 从零开始协同过滤
  7. 使用神经网络的协同过滤
  8. 像尼采一样写哲学
  9. 不同神经网络在 Cifar-10 数据集上的性能
  10. ML 模型检测图像中最大的物体 Part-1
  11. ML 模型检测图像中最大的物体 Part-2

编辑 1:-TFW·杰瑞米·霍华德同意你的帖子。💖💖 🙌🙌🙌 💖💖。

“使用神经网络的协同过滤”

原文:https://towardsdatascience.com/fast-ai-season-1-episode-5-3-collaborative-filtering-using-neural-network-48e49d7f9b36?source=collection_archive---------7-----------------------

利用神经网络构建电影推荐的协同过滤。

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分

  1. 狗 Vs 猫图像分类
  2. 犬种图像分类
  3. 多标签图像分类
  4. 使用神经网络的时间序列分析
  5. 对 IMDB 电影数据集的 NLP 情感分析
  6. 电影推荐系统的基础
  7. 从零开始协同过滤
  8. 使用神经网络的协同过滤
  9. 像尼采一样写哲学
  10. 不同神经网络在 Cifar-10 数据集上的性能
  11. ML 模型检测图像中最大的物体 Part-1
  12. ML 模型检测图像中最大的物体 Part-2

欢迎来到第五集 Fastdotai 的第三部分,在这里我们将讨论使用神经网络的协同过滤——一种在推荐系统中广泛使用的技术。在我们开始之前,我想感谢 【杰瑞米·霍华德】雷切尔·托马斯 为民主化人工智能所做的努力。

做好准备,因为表演时间到了。

首先,让我们导入所有需要的包。

%reload_ext autoreload
%autoreload 2
%matplotlib inlinefrom fastai.learner import *
from fastai.column_data import *

设置路径的位置

  • 输入数据被存储。
  • 将存储临时文件。(可选-在 kaggle 内核中使用)
  • 模型重量将被存储。(可选-在 kaggle 内核中使用)
path='../input/'
tmp_path='/kaggle/working/tmp/'
models_path='/kaggle/working/models/'
  • 数据的读取。
ratings = pd.read_csv(path+'ratings.csv')
ratings.head()
# This contains the userid , the movie that the userid watched , the time that movie has been watched , the ratings that has provided by the user .

movies = pd.read_csv(path+'movies.csv')
movies.head()
# This table is just for information purpose and not intended for         # modelling purpose

u_uniq = ratings.userId.unique() 
user2idx = {o:i for i,o in enumerate(u_uniq)}
# Take every unique user id and map it to a contiguous user .
ratings.userId = ratings.userId.apply(lambda x: user2idx[x])
# Replace that userid with contiguous number.# Similarly, we do it for the movies. 
m_uniq = ratings.movieId.unique()
movie2idx = {o:i for i,o in enumerate(m_uniq)}
ratings.movieId = ratings.movieId.apply(lambda x: movie2idx[x])

在我们之前的方法中,我们采用了一个电影嵌入和一个用户嵌入,并做了一个叉积来产生一个数字,这就是我们的预测评级。

同样的事情可以通过神经网络方法来完成。在神经网络方法中,我们将采用两种嵌入方式,将它们连接起来,并将其输入到神经网络中,以产生一个单一的数字,即评级。

流程图如下所示

步骤 1:- 从特定用户的用户嵌入矩阵中选取嵌入向量,并从特定电影的电影嵌入矩阵中选取嵌入向量。

第二步:- 连接两个向量。对所有的电影和用户做同样的事情,这是我们想要的。这将导致一个嵌入矩阵,其中每一行由电影和用户嵌入向量的连接组成。行数将与用户数和电影组合数相同。而列是由因子的个数决定的。与我们之前讨论的嵌入维度相同。所以我们现在拥有的维度是 (#(用户+电影)组合,#因素)

步骤 3 :- 把它喂给第一个线性层,线性层的维度是(#因子,10)。输出将是(#(用户+电影)组合,10)。

步骤 4:- 使其通过具有 ReLU 激活的第二线性层,其维度为(10,1)。输出将是(#(用户+电影)组合,1)。

第五步:- 这是我们想要的输出。之前我们为每个用户和电影做的是,我们做了他们嵌入的叉积,这给了我们一个单一的数字,即预测评级。在这里,我们使用神经网络来获得这个单一的数字,即预测评级。

步骤 6:- 然后,我们将尝试最小化预测评级和实际评级之间的损失,并进而更新模型参数(嵌入值)。这样我们可以使我们的预测更加准确。

让我们检查一下动手部分。

val_idxs = get_cv_idxs(len(ratings))
n_factors = 10min_rating,max_rating = ratings.rating.min(),ratings.rating.max()
min_rating,max_ratingclass EmbeddingNet(nn.Module):
    def __init__(self, n_users, n_movies, nh=10, p1=0.05, p2=0.5):
        super().__init__()
        (self.u, self.m) = [get_emb(*o) for o in [
            (n_users, n_factors), (n_movies, n_factors)]]
**# Getting the Embedding matrix for users and movies check out the output # below to know the Embedding dimensionality of User and Movies.** self.lin1 = nn.Linear(n_factors*2, nh)
**# The 1st Linear Layer dimensions is (100,10).** self.lin2 = nn.Linear(nh, 1)**# The 2nd Linear Layer dimensions is (10,1).**
        self.drop1 = nn.Dropout(p1)
        self.drop2 = nn.Dropout(p2)
**# Some drop-outs introduced in both the layer.** def forward(self, cats, conts):
        users,movies = cats[:,0],cats[:,1]
        x = self.drop1(torch.cat([self.u(users),self.m(movies)], dim=1))
        x = self.drop2(F.relu(self.lin1(x)))
        return F.sigmoid(self.lin2(x)) * (max_rating-min_rating+1) + min_rating-0.5wd=1e-5
model = EmbeddingNet(n_users, n_movies).cuda()
opt = optim.Adam(model.parameters(), 1e-3, weight_decay=wd)model

让我们训练我们的模型。

fit(model, data, 3, opt, F.mse_loss)

最后,我们优化了损失函数,得到了 0.78 的损失,这比我们之前在 5.15.2 中讨论的方法要好得多。

如果您对代码感兴趣,请查看我的 Github repositori es。

如果你喜欢,那么ABC(永远被击节 👏 👏👏👏👏😃😃😃😃😃😃😃😃😃👏 👏👏👏👏👏** )

如果您有任何问题,请随时联系 fast.ai 论坛或 Twitter:@ ashiskumarpanda

注:随着我继续学*其他课程,这篇博文将会更新和改进。更多有趣的东西,可以随时结账我的Github账号。

为了充分利用这个博客系列,请按照以下顺序随意探索这个系列的第一部分:- 狗和猫的图像分类

  1. 犬种图像分类
  2. 多标签图像分类
  3. 使用神经网络的时间序列分析
  4. 对 IMDB 电影数据集的 NLP 情感分析
  5. 电影推荐系统的基础
  6. 从无到有的协同过滤
  7. 使用神经网络的协同过滤
  8. 像尼采一样写哲学
  9. 不同神经网络在 Cifar-10 数据集上的性能
  10. 检测图像中最大物体的 ML 模型 Part-1
  11. 检测图像中最大物体的 ML 模型 Part-2

编辑 1:-TFW·杰瑞米·霍华德同意你的帖子。💖💖 🙌🙌🙌 💖💖。

fast.ai:生活中最好的东西总是免费的

原文:https://towardsdatascience.com/fast-ai-the-best-things-in-life-are-always-free-3b05c54913cd?source=collection_archive---------1-----------------------

[Image[1] (Image courtesy: https://pixabay.com)]

“与朋友促膝谈心,回忆往事;忙碌一天后,在舒适的床上美美地睡上一觉;与家人共度美好时光;为你真正相信并且一直想帮助的事业做志愿者;看着那个人的眼睛,让他/她感觉到他/她对你来说是多么的特别……”这些都是我们生活中最美好的事情。有很多这样的情况确实有助于让我们发挥出最好的一面。如果你仔细观察这些事情,你会非常惊讶地发现,我们生活中所有这些美好的时刻都有一个共同的特点。是啊!如题,“人生最美好的东西,永远是免费的”。

保持冷静!这篇文章不是关于我们生活的哲学方面:d .在这篇文章中,我将对一个 100%免费的学*平台发表我的意见(是的!这是一个金矿)在这里你可以"做和学*"深度学*。是啊!边做边学。请不要离开我,我会解释你需要知道的关于这个学*平台的每一分钟的信息。让我们开始行动吧,😄

我一直想学*数据科学和数据工程。我是计算机科学出身,接触过“模式识别”、“数据挖掘和数据仓库”、“分布式系统”、“高性能计算”,我意识到这是一个把所有的点连接起来的问题。所以我开始认真“开始做”数据科学和数据工程。最终我降落在“卡格尔”上。我开始向同龄人学*,这给了我很大的推动。每当我试图开始一个新的问题时,我都不得不在以前的项目上来来回回(这完全没问题,😄)。我从“探索性数据分析”[1][2]开始,逐步学*建立模型和做“严肃的事情”。此时,我正在做“Python”和“R”之间的成本效益分析,我想到了坚持使用“Python”。

Python 是众多入门方式之一。我最初想同时掌握 Python 和 R,然后在阅读了一些 Reddit 和 Quora 帖子后,我得出一个结论,目前,我打算坚持使用 Python。主要原因是,Python 更像是工程师的选择,而 R 是统计学家的选择。

Slow & Steady [Image[2] (Image courtesy:http://cathjayasuriya.blogspot.sg/2011/02/learning-from-ants.html)]

一开始,这是一个缓慢但稳定的旅程。要做“严肃的事情”,我知道我必须伸出手指“努力工作”。“努力工作”意味着拓宽我对“数据科学”主题的理解(我总是试图在“数据科学”和“数据工程”之间取得平衡,因为我个人更喜欢全方位的工作)。

正是在这一点上,我意识到加深对神经网络理解的重要性。探索又开始了。我遇到了几个主要的领先在线课程,杰弗里·辛顿教授的用于机器学*的神经网络、吴恩达教授的深度学*专业化以及 Udacity 的人工智能——深度学*纳米学位。这些无疑是在神经网络中掌握和超越的最佳资源。你可以免费学*所有这些材料(如果你想获得证书,那么只有你需要付费)。尽管这些资源是许多人追随的最好和最流行的方法,我仍然继续寻找我的问题的正确答案。然后就碰到了“ Udemy ”平台。在彻底复*了 Udemy 课程后,我选择了“深度学* A-Z:动手操作人工神经网络”,因为这门课程直接跳到了实现,而没有深入数学。这个课程是 10 美元,我不介意花这么多钱来学*一个能给我很大帮助的材料。如果你想探索神经网络背后的深层概念和数学,你需要阅读额外的材料(本课程的讲师提供了这些材料的链接)。我对正确答案、学*神经网络的正确平台的追求仍然存在。那些日子里,我花了大量时间在 Reddit 和 Quora 上衡量每个用户的观点。

它发生在:D

我记不清这个故事了。我坚信,经过一番努力,我找到的学*平台是满足我需求的正确答案。

fast.ai

我来自计算机科学背景,并在行业和计算机科学研究领域工作了 2 年多,我相信对我来说,学*“神经网络”必须是一种不同的方法,而不是先学*理论,然后实施,然后在 Kaggle 竞争,这是一种口语方法。“ fast.ai 提供了一种通过直接编码和实现真实的 Kaggle 比赛来掌握深度学*的实用方法。然后慢慢地,它对“神经网络”的基本概念,如何将这些概念应用到现实世界的场景中,以及它们(神经网络)的局限性建立了坚实的理解。这门课真正让我着迷的是,这门课的老师分享了他们自己的经历,这些经历帮助我把我前面提到的点联系起来。

让我简单介绍一下这门课的老师。

“fast.ai”的创始人是“杰瑞米·霍华德”——旧金山大学的研究科学家(贪婪的凯格勒(# 1));以及“瑞秋·托马斯”——她被福布斯选为“推进人工智能研究的 20 位杰出女性”之一。我鼓励你看看“fast.ai/about”来获得更多关于这两个不可思议的角色的信息。这两个美丽的灵魂使这门课程对所有人完全免费,❤

Jeremy Howard and Rachel Thomas [Image[3] (Image courtesy: http://www.fast.ai/)]

让我带你浏览一下 via " fast.ai 提供的课程

程序员实用深度学*,第 1 部分

对于任何具有计算机科学(或其他相关学科)背景的人来说,这是开始神经网络之旅的正确起点。在这个初级课程中,你将进行真正的 Kaggle 比赛。开发环境是 Amazon Web Services (AWS)或 Paperspace。在 7 个视频结束时,您将对“如何使用深度学*方法处理研究问题”有一个透彻的理解。每周投资 6-10 个小时来理解内容将是你作为深度学*实践者在未来职业生涯中所做的早期投资。每个视频最多 2 小时,看的时候最好反复看同样的内容,直到你掌握了基本原理。它的回报更高。我仍在学*这门课程,我将简要回顾一下到目前为止我所学的内容。

程序员的前沿深度学*,第二部分

这是第一部分“程序员实用深度学*,第一部分”的继续。我还没有开始这个课程,所以让我来分享一下第 2 部分的内容。

程序员的前沿深度学*,第 2 部分,在这里你将了解深度学*的最新发展,如何阅读和实现新的学术论文,以及如何解决具有挑战性的端到端问题,如自然语言翻译(摘自http://course.fast.ai/lessons/lessons.html)

相当令人兴奋,对吧,😄,我热切地期待着在我完成第一部分后,马上“开始做”这一部分。

也许你会认为这门课只是深度学*。保持冷静!!!。Jeremy 和 Rachel 都是带着让每个人都可以使用深度学*的愿景开始“fast.ai”的。当我参加“ fast.ai forums ”的时候,我注意到这两个美丽的灵魂发布了一个关于机器学*的课程。

又一次请客!提前获得机器学*介绍视频

这是“ fast.ai ”提供的第三个课程。我希望我在机器学*生涯的早期就发现了这一点。在本课程中,Jeremy 和 Rachel 讨论了如何通过 Kaggle 竞赛掌握将机器学*概念应用于现实世界问题的技能。我开始跟踪这些材料,以便进一步加深我对机器学*的理解,将机器学*应用于现实世界的问题。

好了,现在让我跟随“ fast.ai ”分享一些我的经验。我就不深入了。既然现在你知道了这个" fast.ai "平台的价值,我鼓励你去体验这个平台。一言以蔽之,我要通过这个平台来反映我到目前为止学到的东西(我从开始的地方走了多远:P)。

狗 vs 猫

Dogs vs Cats[Image[4] (Image courtesy: https://pixabay.com/)]

狗 vs 猫”是在 Kaggle 举办的一场比赛,这是“程序员实用深度学*,第 1 部分”试图通过最先进的方法找到解决方案的第一个任务。这个比赛是关于将图像分为两类,“猫”和“狗”。最初,我们得到了相应标记的训练数据集。我们的任务是使用这些训练数据集开发一个分类模型。最后,开发的模型需要正确分类未标记的测试数据集。好吧,这听起来很简单。但是当你“开始做”这项任务时,你会遇到大量以前从未遇到过的新事物。

以下是我在完成这个比赛后学到的东西:

  • 为深度学*设置 AWS 这可能一开始听起来很奇怪。但我认为,对于当时像我这样的初学者来说,这听起来可能并不奇怪。为了训练和开发深度学*模型,你需要有很高的计算能力。我之前确实尝试过几个小规模的深度学*任务。但是我没有迁移到云基础架构的要求。为深度学*设置 AWS 给了我关于 AWS 基础设施的大量实践经验。我了解了“ t2.xlarge ”实例和“ p2.xlarge ”实例。在 AWS IAM 中设置角色,创建 AWS 用户,将策略应用于用户, EC2 实例, S3 桶,一个认证者应用登录时的安全 root 帐户, VPCDynamo DB 以及更多++的应用(后四个是我通过简单地摆弄 AWS 管理控制台学会的)。
  • 在本地机器中配置 AWS,并使用别名通过命令行别名启动停止获取实例 id
  • 使用 tmux 进行多任务处理(以前没有使用过 tmux:(😛)
  • VGG16 模型和 ImageNet 竞赛——vgg 16 模型是使用各种标记图像的预训练模型。用于训练模型 VGG16 的这些图像的主要特征是,这些图像在图像本身上清晰可见。我的意思是,在训练图像中,除了一个可见的图像,没有其他对象可见。让我说得更清楚些。在图像的左侧,我们可以清楚地看到图像中的狗,而在右侧,我们可以看到两只狗,但这些狗不是景点的中心。VGG16 模型已经使用类似于左手侧的图像进行了训练。你可以参考伊曼吉内特【3】【4】了解更多细节。

Dogs vs Dog image with other objects[Image[5] (Image courtesy: Google Images)]

  • 将相同的技术应用于其他图像分类任务——您只需构建相同的文件夹结构。
  • 理解和应用 VGG16 模型

我认为这足以让你明白为什么这个课程是“最好的”。本课程和本课程的第二部分现在已经发展到一个更复杂的层次。在最新的系列中,杰瑞米·霍华德使用“fastai”库作为所有项目的基础库。这一次(截至 2018 年),云基础设施来自 Paperspace

现在,让我向您介绍一下我在完成“机器学*入门”视频系列的第一项任务后获得的一些关键学*成果。

推土机蓝皮书

Blue Book for Bulldozers [Image[6] (Image courtesy: https://pixabay.com/)]

这是杰里米在“机器学*导论”系列中讨论的第一个 Kaggle 项目。这个项目的目标是预测“销售价格”,这是一个连续的价值因变量。这个项目有多年来收集的数据。任务中使用的算法是“随机森林”。Jeremy 直截了当地指出“随机森林”如何用于开发一个成功的预测模型。在做模型的时候和模型建立之后,他会更深入,覆盖广度和深度。

我鼓励你遵循这些令人敬畏的免费材料。你会发现这些非常有用。成为高度参与的社区论坛的一部分。我保证你会从同龄人那里学到很多特别的内容。我通过这篇文章的最终目的是让你们了解这个令人敬畏的平台“ fast.ai ”。这就是为什么我在阐述这个平台的价值时只考虑了两个场景。我坚信我成功地以有效的方式向你们传达了这一信息。

接下第一项任务后,我想强调以下几点:

  • 首先,我学到了很多关于 Jupyter Notebook 的东西——主要是在笔记本上浏览功能实现和文档,快捷键,调试++
  • “日期”特征的值——“日期”可以由“年-月-日”格式或“年-月-日-时-分-秒”格式组成。在任何时间序列问题中,仔细检查“日期”参数是极其重要的。从“日期”我们可以派生出“一年中的星期”,“日期的星期”和许多其他功能。这些功能将有助于更广泛地了解我们的数据。我们都知道特征工程是机器学*中必不可少的一部分。如果你在“fast.ai”平台上看了这个视频,你会对特征工程感到惊讶和信服。
  • 将“字符串变量”转换为分类变量的过程和重要性,以及一旦完成分类,Python 库的内部工作如何将数值分配给变量。
  • 处理缺失值(数值和分类)
  • 以保存在 RAM 中的格式保存数据——这种方法有助于快速检索项目
  • 改进随机森林回归方程的方法

简而言之,这就是我完成第一个任务后学到的东西。

就此,我想以向你表示衷心的感谢来结束这篇文章。让我知道你对这篇文章的想法和评论。我很欣赏你的反馈。如果你觉得这篇文章很有收获,请在 Faceboook、Twitter、Google+和其他社交媒体平台上与你的朋友分享。请随意给我一拍、二拍、三拍或者热烈的掌声来激励我。这肯定会帮助我保持势头。

就像我在这篇文章的标题中提到的:

生活中最好的东西总是免费的!!!

【1】https://www . ka ggle . com/omarelgabry/a-journey-through-titanic
【2】https://www . ka ggle . com/MRIs dal/exploring-survival-on-the-titanic
【3】http://www.image-net.org/
【4】http://image-net.org/explore

Fast.ai:实用深度学*的 TOC 第 1 部分

原文:https://towardsdatascience.com/fast-ai-the-toc-of-practical-deep-learning-part-1-70c89187d654?source=collection_archive---------4-----------------------

如果 USF 数据学院的证书和来自 Fast.ai 的 MOOC 是一本书,这将是它的目录

Photo by: Shiro hatori

我目前正在将我对深度学*的兴趣和迷恋转化为职业的旅程中。作为一名软件工程出身的人,我比其他非博士/硕士稍微领先一点,但也不算多。

你可以在 Medium 上的 这里阅读我的辞职和职业转型帖子 ,以及在 LinkedIn 上的 更新评论版本

写博客是我旅程的一个重要部分,尤其是记录我实际学到了什么。不仅仅是为了此刻的自己,也是为了任何一个跟随类似脚步的人。所以这篇文章是写给那些对 Fast.ai 和 USF 数据学院深度学*项目感兴趣的人。

这篇帖子的部分灵感也来自一条推文,暗示出色的工作 雷切尔·托马斯 杰瑞米·霍华德 正在做的事情被简化了。

瑞秋回应的第 10 部分(11 部分全部看完,太棒了!):

第一部分

第 1 章:图像识别

  • 设置您自己的 AWS 实例
  • 深度学*简介以及它为什么有用
  • 深度学*的 7 行代码
  • 分解 VGG16
  • 进入一个 Kaggle 竞争:放置前 50%的狗对猫 redux

第二章:****CNN

  • 狗对猫 Redux:国家的最先进的模式解释
  • 预训练网络与随机权重
  • 微调的方式和原因
  • 稠密层、随机梯度下降和激活函数

第三章: 了解上下拟合

  • CNN 在工作:从点积到转换,再回到传播
  • 处理过度装配和装配不足
  • CNN 正则化技术
  • 半监督学*、伪标记和知识蒸馏
  • Excel 中的卷积和 SGD

第四章: 协同过滤、嵌入和更多

  • Excel 中的嵌入
  • 推荐系统和协同过滤
  • 潜在因素
  • 建立更多模型

第五章:****NLPs 和 RNNs 介绍

  • Keras 功能 API
  • 多尺寸 CNN
  • 情绪分析
  • NLP 迁移学*
  • 将神经网络可视化为计算图
  • RNNs 简介

第六章: 从零开始的 RNNs、嵌入和 Theano API

  • 在 Excel 中嵌入 rnn
  • 用 Keras 从头开始构建 RNN 模型
  • 用 ano API 构建 rnn

第 7 章: CNN 架构、包围盒和多输入

  • ResNet 和 Inception CNNs 概述
  • 数据泄露
  • CNN:如何处理多重输入、输出和包围盒
  • 全卷积网络

摘要

这个程序的第一部分已经涵盖了很多内容。对于每个“章节”,都有一个 2 小时的视频、附带的 Jupyter 笔记本、笔记/维基(主要由学生编写/更新)、Jeremy 建议的阅读材料(博客、论文等)、作业(没有标记,但建议练*)以及现场和在线学生令人惊叹的活跃论坛

教学风格是“自上而下”的方法,你可以在这里阅读更多关于的内容。个人觉得很棒!同样,我不需要知道汇编/机器码来编写 Python,我也不需要知道每个数学公式的复杂性来利用深度学*技术。

但是不要弄错了,如果你喜欢的话,有数学、公式、复杂的概念要理解,还有枯燥的学术论文要读。正是这种不同的/更好的方法吸引了许多人。就像任何在线或大学的课程或项目一样,你在事情上付出的努力。

对我来说,我已经成功地完成了第一部分,感觉比一个月前聪明多了。我不是深度学*方面的专家(目前还不是!)但因为 Fast.ai,我肯定比我的许多同事拥有更多的知识和实践经验。

现在,我正在努力完成第 2 部分,希望在 4 周内,你可以准备好我的后续文章。

思想?关于该计划的问题?欢迎在下面的评论区提出你的问题。

你将从 fast.ai (V2)第 1 课中学到什么

原文:https://towardsdatascience.com/fast-ai-v2-lesson1-synopsis-tl-dr-4985bba9eea2?source=collection_archive---------3-----------------------

fast.ai 是一个学*深度学*(DL)的在线平台。它有 14 节课,分为两部分,每部分 7 节课。第 1 部分主要涵盖与 DL(深度学*)在各个领域的应用相关的主题,以及如何为自己的项目构建这些模型。另一方面,第 2 部分让您深入了解数据科学的当前研究,这推动了前沿技术的发展。版本 2 (v2)是 fast.ai 的 2018 版本。

与其他大多数在线课程不同,fast.ai 采用自上而下的方式教授 DL。这意味着 fast.ai 不是专注于每个算法背后的理论,而是提供如何构建和使用 DL 模型的实践经验。在使用这些模型时,你将在需要时学*必要的主题。

这个博客为那些已经看过第一课视频的人做了一个总结,如果你还没有看过的话,它也是一个帮助你做好准备的来源。我试着把事情分解成小模块,这样每一段都谈论一个特定的主题。

如果你已经熟悉了 DL 和机器学*(ML)的基础,你可以直接跳到第一课总结。但是如果你是这个领域的新手,那么前几段是为你准备的。作为一名数据科学新手,有一些事情你必须知道。

最重要的是,的参数。参数是模型的全部。人们经常谈论参数或权重(两者都一样),下面是它们的意思。假设我们有已经分成两类的数据。模型的工作是将每个数据点分类到其各自的箱中。“参数”是那些决定哪个点将进入哪个类的值。

损失函数是你应该知道的下一件重要的事情。损失函数的作用类似于参数的质量检查。如果参数是对每个数据点进行分类的值,那么损失函数给我们关于参数对于给定数据有多好的信息。

所以训练一个模型无非是找到损失最小的正确参数。我们随机选取一组参数,并在每次迭代后更新这些参数,以获得最小损失。梯度下降用于决定哪个方向带我们到达最小值。

打个比方,如果你在山顶的车里,目的是往下开,梯度下降就是你的车行驶的方向。说到开车下坡,有一件事是我们在开车下坡时都会做的。或者说,我们必须这样做。那会是什么?大胆猜测一下。明白了吗?是啊!我们使用刹车。没有一个理智的人会在没有摩擦力的帮助下疯狂地开车。(除了刹车失灵)。当使用梯度下降更新参数时,我们应用一种特殊的刹车,通常称为学*率。

学*率提供了从随机参数到最新模型的平滑过渡。将学*率设置得太高就像加速汽车下坡。更别说到达山脚,加速度会让你偏离道路。学*率太高,不会收敛到最小损失。损失随着高学*率而增加,并且模型将停止学*。

如果学*率太小,就像过度使用刹车。模型肯定会达到最小值。但这需要很长时间。我们不能无限期地训练一个模型。所以设定正确的学*速度总是非常重要的。

最后,参数初始化。我们总是采用一组随机数作为参数,并使用梯度下降进行更新。初始化的经验法则:对称不起作用。我们的大脑都一样。我们对初始化的第一个想法非常简单。“为什么不能用全零?”没有。那不行。

最好的初始化方法是从高斯分布中抽取随机数。这仅仅意味着用随机数乘以 sqrt{2/n}。n 是所有层的参数总数。

话虽如此,让我们进入本博客的主题——fastai 第一课概要。

第 1 课总结:

第一课就像是每门课程教材的典型的第一章。
第一章:引言。

是啊!我说的是那一章,通常是你从那本书里读到的最后一章。(我也这么做。击掌!)嗯,fast.ai 的第一课就是那个入门章节。

第一课的要点可以大致分为四类。

  1. 通用深度学*简介
  2. 每个 fast.ai 视频的内容(前 7 个)
  3. 设置虚拟机
  4. 关于代码、构建代码的语言以及其他细节

1。深度学*概述:

深度学*相对于机器学*算法的优势在于,ML 需要大量的特征工程。ML 也有各种算法可供选择,对于每个数据集,我们应该检查哪一个效果最好。DL 通过使用深度神经网络(DNN) (因此得名深度学*)让生活变得更容易

神经网络(NN)看起来像这样。

©http://www.extremetech.com/wp-content/uploads/2015/07/NeuralNetwork.png

另一方面,DNN(深度神经网络)看起来像这样。

©https://qph.ec.quoracdn.net/main-qimg-7c35987ad55173b3b76214b9112830ff

不要担心它看起来有多复杂。只是欣赏美丽的图案。

深度学*有三重优势。无限灵活,通用参数拟合,快速&可扩展。

给定任何数据,神经网络理论上应该能够*似拟合它,只要我们给它 足够的参数。 这就是所谓的普适逼*定理。但是这在真实的数据集中是失败的,因为我们使用的数据有很多噪音。出于这个原因,我们通过层层叠加来使用深层网络。它非常有效。因此,灵活性—检查

DNN(深度神经网络)的目标是将参数尽可能完美地拟合到手头的数据。所以随机寻找最佳参数是行不通的。获得良好参数的更好方法是沿着损耗最小的方向。而梯度下降给出这个方向。给定任何问题,(负)梯度下降将指向最小损失。因此,所有目的参数拟合—检查

尽管深度神经网络需要相当长的时间来训练,但是预测时间是最小的。GPU 在过去十年中发挥了重要作用,减少了训练或预测所需的时间。

©https://www.karlrupp.net/2013/06/cpu-gpu-and-mic-hardware-characteristics-over-time/

几乎所有为深度学*研究而构建的语言,如 TensorFlow、Theano、PyTorch 等,都使用这些 GPU。快速&可扩展—检查

卷积神经网络(CNN)就是这样一类深度学*算法。在 fast.ai 的前几次讲座中,我们将在 CNN 工作。CNN 致力于一个叫做卷积的概念(很明显!!).卷积是一种数学方法,它整合两个函数,观察当一个函数发生变化时,另一个函数如何变化。

2.fast.ai '课程结构:

第一课——简介(无聊?我知道。但是继续读。有些事情你可能会感兴趣。)

第 2 课—不同数据集上的图像分类器。考虑各种数据集,学* DL 中不同的技术,对图像进行分类。

第 3 课——预测分析。从结构化数据中,我们将尝试预测销售或天气,或者检测帐户和其他酷应用程序中的欺诈行为。

第 4 课—自然语言处理。(NLP)理解给定文本数据中存在的内容。或者对文本属于哪个上下文进行分类。像这样的问题将在第四课中讨论。

第五课——协同过滤和推荐系统。这将是一堂非常有趣的课(也是我个人最喜欢的),我们将讨论如何根据之前的观看列表推荐一部电影或一本书。网飞、Prime Video 或其他类似网站使用推荐系统。

第 6 课——文本生成。想一个算法,它能为你的剧本提供莎士比亚风格的对话。在本课中,您将学*如何做到这一点

第 7 课—图像分割。在最后一课中,你将学*如何训练一个模型在给定的图片中找到一只猫或一只狗。fast.ai 的第一部分到此结束。

3.设置虚拟机:

我们已经讨论过深度学*如何使用 GPU 来处理复杂的任务。但并不是每个人都有一台笔记本电脑或一台配有良好 GPU 的台式机。而且买一个 GPU 好的系统是很大的投资。为了克服这一点,人们开始使用虚拟机。这些服务器向公众开放,每月收取象征性的费用。

已经设置了 fastai 的一些虚拟机包括:

  • Crestle :使用方便。可以在 CPU 和 GPU 之间切换,降低整体成本。
  • Paperspace :更便宜更快。

除了这两家之外,还有其他虚拟机提供商

  • 谷歌云平台:给你 300 美元积分,一年免费订阅。太好了。但是你需要在用完那 300 美元的积分后付款。
  • 亚马逊网络服务:有很多变体可供选择。其中一些非常便宜,而且几乎免费。AWS 还有一年免费层。
  • Google Colab:我的最爱。为什么这么问?完全免费。有什么条件?每次你向谷歌申请服务器时,它都会给你一个有限的时间来访问其中的一个。之后连接终止,刷新,访问权授予另一个用户。所以如果你超过了时间限制,那么你必须从头开始。

我可以详细说明如何设置这些虚拟机,但这将使我们偏离主题。在第 1 课中,Jeremy 在前 12 分钟介绍了这一点,您可以轻松设置 Crestle 或 Paperspace,没有任何问题。

如果您在设置任何其他虚拟机时遇到问题,请使用 Google Colab。所有你需要的 Colab 是一个工作的谷歌帐户。打开 Colab 笔记本后,在工具栏中进入运行时>改变运行时类型>硬件加速器> GPU。你可以走了。

关于代码的其他详细信息:

法斯泰图书馆。 fastai 是由杰瑞米·霍华德和瑞秋·托马斯创建的开源库。它基于 PyTorch 构建,使用 python 3.6。(当心!一些代码对你来说可能看起来很新,因为它没有运行在 python 3.5 上)要使用这个库,在你的终端中,
git 克隆https://github.com/fastai/fastai>CD fastai>conda env 更新。

lr _ find()函数。设置正确的学*速率对于学*正确的参数至关重要。在 fastai 库中,lr_find()函数以非常小的学*速率开始,并且在每次迭代后加倍。经过几千次迭代后,损失开始增加,此时 lr_find()停止,我们可以绘制损失与学*速率的关系。

损失急剧下降的区域是最佳学*率。在这种情况下,它在 1e-2 左右。

fast.ai V2 L1 的总结到此结束。正如我在开头所说的,fastai 的基本概念是在需要的时候学*必要的东西。我尊重他们的想法,所以我对每一个概念都做了大致的介绍,而没有深入到它们的细微差别。一旦你理解了神经网络是如何工作的,我可以用数学给你一个更好的描述。已经在路上了。

如果我错过了什么或者你想知道更多,请在评论中提出。我总是乐于接受积极的批评和讨论。

快乐学*。干杯!

是的。如果你喜欢这个博客,别忘了鼓掌..

使用位置敏感散列的快速*似重复图像搜索

原文:https://towardsdatascience.com/fast-near-duplicate-image-search-using-locality-sensitive-hashing-d4c16058efcb?source=collection_archive---------3-----------------------

一个快速的 5 部分教程,讲述深度学*如何与高效的*似最*邻查询相结合,用于在庞大的集合中执行快速语义相似性搜索。

第 1 部分:为什么最*邻查询如此重要

如果你在机器学*方面受过一些教育,最*邻居这个名字可能会让你想起 k-nearest neighbors 算法。这是一个非常简单的算法,看起来实际上没有“学*”:kNN 规则只是通过训练集中 k 个最*邻中的多数标签对每个未标记的例子进行分类。

k-NN algorithm: with k=3, the green example is labeled as red; with k=5, it is labeled as blue

这似乎是一个非常天真,甚至“愚蠢”的分类规则。是吗?这取决于你用什么作为你的距离度量,也就是:你如何选择来度量例子之间的相似性。是的,天真的选择——在“原始”特征中使用简单的欧几里德距离——通常在实际应用中导致非常差的结果。例如,这里有两个例子(图像),它们的像素值在欧几里德距离上很接*;但是有争议的是,仅仅因为左边的图像是右边图像的邻居,就把它归类为花是疯狂的。

Euclidean distance in pixel space = visual/syntactic/low-level similarity

但是,事实证明,将 kNN 规则与距离度量的适当选择结合起来实际上是非常强大的。“度量学*”领域表明,当在使用 kNN 规则之前应用机器学*来学*度量时,结果可以显著提高

我们当前的“深度学*时代”的伟大之处在于有大量可用的预训练网络。这些网络解决了某些分类任务(预测图像类别,或单词周围的文本),但有趣的是,它们在这些任务上的成功并不多,但实际上它们为我们提供了极其有用的副产品:密集向量表示,简单的欧几里德距离实际上对应于高级的“语义”相似度

Euclidean distance in deep embedding space = semantic similarity

关键是,对于许多任务(即通用图像和文本),我们已经有了一个很好的距离度量,所以现在我们实际上可以使用简单的 kNN 规则。我在过去已经谈过很多次这一点——例如,在以前的一篇文章中,我试图使用这样的搜索来验证这样的说法,即生成模型真的在学*底层分布,而不仅仅是记忆训练集中的例子。

这就给我们留下了实际寻找最*邻居的任务(我称之为 NN 查询)。这个问题——现在几乎是任何 ML 管道中的一个构建模块——已经得到了很多关注,无论是在 CS 理论文献中,还是从需要高度优化生产环境解决方案的公司那里。这里,社区再次受益,因为这个领域的几个大玩家实际上已经开源了他们的解决方案。这些工具使用精心制作的数据结构和优化的计算(例如在 GPU 上)来有效地实现 NN 查询。我最喜欢的两个是 Facbook 的 FAISS 和 Spotify 的asury。这篇文章希望能让你了解这些库“幕后”发生的事情。

当我们谈论最*邻查询时,第一个区别是在精确*似解之间。

精确算法需要返回数据集中给定查询点的 k 个最*邻。这里,简单的解决方案是简单地将查询元素与数据集中的每个元素进行比较,并选择具有最短距离的 k。该算法取 O(dN),其中 N 是数据集的大小,d 是实例的维度。乍一看,这似乎很令人满意,但是仔细想想:1)这只是针对一个查询!2)虽然 d 是固定的,但它通常可能非常大,最重要的是 3)在“大数据”范式中,当数据集可能非常大时,数据集大小的线性不再令人满意(即使你是谷歌或脸书!).其他精确查询的方法使用树结构,可以获得更好的平均复杂度,但是它们最坏的情况复杂度仍然接* n 中的线性复杂度。

*似算法留有一定余地。有几个不同的公式,但主要思想是它们只需要返回实例,这些实例到查询点的距离是真正最*邻居的距离的几乎(其中‘几乎’是算法的*似因子)。允许*似解打开了随机化算法的大门,它可以在次线性时间内执行 ANN(*似 NN)查询。

第 3 部分:位置敏感哈希

一般来说,实现次线性时间算法的一个常见的基本构件是散列函数。散列函数是将输入映射到固定大小(通常是较低维度)的数据的任何函数。最著名的例子是校验和散列,你可能只是从网上下载文件时遇到过。他们背后的想法是生成一个“指纹”——也就是说,一个特定的数据块有希望是唯一的一些数字——可以用来验证数据在从一个地方转移到另一个地方时没有被破坏或篡改。

checksum hash: good for exact duplicate detetction

这些散列函数的设计只有一个目的。这意味着它们实际上对输入数据的微小变化非常敏感;即使一个比特发生了变化,也会完全改变哈希值。虽然这确实是我们对精确重复检测所需要的(例如,当两个文件确实相同时进行标记),但它实际上与我们对*似重复检测所需要的正好相反。

这正是位置敏感哈希(LSH)试图解决的问题。顾名思义,LSH 依赖于数据的空间性;特别是在高维度上相似的数据 项,会有更大的几率收到相同的 hash 值。这是目标;有许多算法可以构造具有这种特性的散列函数。我将描述一种方法,这种方法非常简单,并展示了随机投影令人难以置信的惊人力量(另一个例子,参见美丽的约翰逊-林登斯特劳斯引理)。

基本思想是我们使用以下过程生成大小为 k 的散列(或签名):我们生成 k 个随机超平面;项目 x 的哈希值的第 I 个坐标是二进制的:当且仅当 x 在第 I 个超平面之上时,它等于 1。

the hash value of the orange dot is 101, because it: 1) above the purple hyperplane; 2) below the blue hyperplane; 3) above the yellow hyperplane

整个算法只是重复这个过程 L 次:

an LSH algorithm using random projections with parameters k and L

让我们了解一下如何使用 LSH 来执行人工神经网络查询。直觉如下:如果相似的项目具有(很有可能)相似的散列,那么给定一个查询项目,我们可以用只与具有相似散列的项目进行比较来替换对数据集中所有项目的“原始”比较(在普通的行话中,我们称之为“落在相同桶中”的项目)。这里我们看到,我们愿意满足于精度的事实正是允许次线性时间的原因。

因为在桶内我们计算精确的比较,所以 FP 概率(即,说一个项目是 NN,而它实际上不是)是零,所以算法总是具有完美的精度;然而,我们将只返回那个桶中的项目,所以如果真正的 NN 最初没有被散列到桶中,我们就没有办法返回它。这意味着在 LSH 的背景下,当我们谈论准确性时,我们实际上是指回忆。

形式上,使用 LSH 的 ANN 查询按如下方式执行:1)找到查询项的“桶”(哈希值)2)与桶中的每个其他项进行比较。

我们来分析一下这个算法的计算复杂度。会很快很容易的,我保证!

阶段 1)费用丹麦;阶段 2)成本 N/2^k 预期 ( 因为在数据集中有 n 个点,在我们的分区空间中有 2^k 区域)。由于整个过程重复 l 次,总成本平均为 LDK+LDN/2^k.。当 k 和 l 约为 logN 时,我们得到所需的 O(logN)。

第 4 部分:LSH 超参数,或精度-时间权衡

我们已经看到了 LSH 的基本算法。它有两个参数,k(每个哈希的大小)和 L(哈希表的数量)—k,L 值的不同设置对应于不同的 LSH 配置,每个配置都有自己的时间复杂性和准确性。

正式分析这些有点棘手,需要更多的数学知识,但一般来说是这样的:

通过仔细设置这些参数,你可以得到一个任意精确的系统(不管你对“*似重复”的定义是什么),但是其中的一些会以很大的 L 为代价,即很大的计算成本。

一般来说,根据经验解决这种权衡的一个好方法是在一个明确定义的任务上量化它们,你可以用最少的手工劳动来设计。在这种情况下,我使用的是 Caltech101 数据集(没错,是旧的;是的,在 ImageNet 之前就有图像数据集了!),带有 101 个简单物体的图像。作为我的 LSH 方案的输入,我使用了 4096 维的特征向量,这些特征向量是通过将每个图像经过预先训练的 VGG 网络而获得的。为了简单起见,我假设来自同一类别的其他图像是特征空间中的真实 NN。

Caltech101

有了“基本事实”,我们可以尝试不同的超参数组合,并测量它们的准确性(召回)和运行时间。绘制结果可以很好地权衡精度和时间:

我们清楚地看到更好的召回是以更长的运行时间为代价的。请注意,实际结果取决于任务:一般来说,您认为“接*”的项目越相似(在高维度中),任务就越容易。高效地找到远处的邻居是一项艰巨的任务,当心!

第 5 部分:为一个示例应用程序将所有这些放在一起

我想把这个管道拼凑成一个个人项目,更有效地浏览我的个人照片集。旅行归来,我经常会从几个设备上拍下照片,其中许多照片非常相似——我对风景的欣赏通常会给我留下几十张几乎相同的照片。语义相似到救援!以下是一些结果。

每行代表一个查询;左边是查询图像,右边是散列到同一个桶的图像,它们的实际距离用绿色表示。很酷的东西!

总结(TL;博士)。

我们回顾了两个非常有用的想法:

  1. 位置敏感哈希(LSH)是一个有用的工具,用于执行*似最*邻查询,即使对于非常大的数据集也能很好地扩展。
  2. 深度学*的时代为我们提供了免费的图像、文本和音频的“现成”表示,其中相似向量(在简单、欧几里德、距离上)是语义相似(图像的 VGG 特征向量,文本的 Word2Vec)。

最后,我们看到了这两种想法的结合——即,不在原始数据(图像、文本)上而是在深层表示上应用 LSH——如何用于在庞大的集合中执行快速相似性搜索

噪声文本的快速分词

原文:https://towardsdatascience.com/fast-word-segmentation-for-noisy-text-2c2c41f9e8da?source=collection_archive---------3-----------------------

Vergilius Vaticanus

TL;速度三角形定位法(dead reckoning)

更快用三角矩阵代替动态规划分词。集成的拼写纠正允许嘈杂的输入文本。GitHub 上的 C#源代码

对于西方人来说,单词之间用空格分隔似乎是显而易见的,而在汉语、日语、朝鲜语(CJK 语言)、泰语和爪哇语中,单词之间是没有空格的。

甚至古典希腊语和晚期古典拉丁语都没有这些空格。这被称为continua脚本。

似乎我们还没有失去我们的能力:我们可以很容易地破译

quickbrownfoxjumpsoverthelazydog

如同

敏捷的棕色狐狸跳过懒惰的狗

我们的大脑以某种方式直觉地和无意识地做到这一点。我们的阅读速度稍微慢了一点,这是因为我们的大脑需要处理所有的背景信息。如果我们尝试以编程的方式来做,我们将会看到它到底有多少。

为什么?

但是,如果人们无论如何都能阅读未分段的文本,我们为什么要以编程方式实现分词呢?

对于单词间没有空格的 CJK 语言来说 就更明显了。

像谷歌或百度这样的网络搜索引擎必须以一种允许高效快速检索的方式对文本进行索引。那些网络搜索引擎是基于倒排索引的。在抓取每个单词的过程中,会创建一个单独的链接列表。每个列表都包含指向出现该特定单词的所有网页的链接。

如果我们搜索一个单词,那么列表中包含的所有链接都是有效的搜索结果。如果我们对两个单词进行布尔搜索(AND ),那么这两个列表相交,并且只有包含在两个列表中的链接作为结果返回。

拼写纠正允许纠正拼错的单词。这是通过在字典中查找可能拼错的单词来完成的。如果找到该单词,则该单词被认为是正确的。如果没有找到该单词,那么字典中最接*候选的那些单词(根据编辑距离度量,如 Damerau-Levenshtein )被呈现为拼写纠正建议。当然,计算每个字典条目的编辑距离的简单方法是非常低效的。符号拼写是一个快得多的算法。但无论如何,前提条件是首先识别单词边界,以便首先为拼写校正算法提供输入。

机器翻译,语言理解,S 感知分析等很多信息处理任务也是基于单词的。

但是对于单词之间已经有空格的语言,我们为什么还需要分词呢?嗯,即使在那些通常有空格的语言中,有时也会缺少空格!应用领域多得惊人:

  • 规范化书写可变的英语复合名词:例如,ice box = ice-box = icebox 猪圈=猪圈=猪圈)进行搜索&索引。
  • 复合词分词:原词和拆分词部分都应编入索引。
  • 打字错误可能导致空格丢失。
  • 转换错误:在转换过程中,word 之间的一些空格可能会丢失,例如,通过删除换行符而不是用空格替换它们。
  • OCR 错误:原始文档或手写文本的质量较差,可能会导致无法正确识别单词之间的所有空格。
  • 传输错误:在噪声信道上传输期间,可能会丢失空格或引入拼写错误。
  • 关键字提取从 URL 地址、域名、表格列描述或无空格书写的编程变量。
  • 对于密码分析,可能需要从密码中提取术语。
  • 语音识别,如果在口语中不能正确识别单词之间的空格。
  • 自动编程变量

但是,除了自然语言之外,单词分割也可能是令人感兴趣的,例如,将 DNA 序列分割成单词 (PDF)。

分段变体生成

一个字符串可以用几种方式来划分。每个不同的分割变体被称为一个组合。存在多少种不同的成分?

  • 在长度为 n 的字符串中,潜在字边界的数量n’= n-1(在字符串的每个字符之间)。
  • 这些位置中的每一个实际上都可以用作字边界,也可以不用作字边界。我们可以认为这是一个二进制形式的数字,其中每一位都可以设置或不设置。
  • 在二进制数字系统中,一个 n 位数可以代表 x=2^n 数。因此,分割变体的数量也是x=2^n'(n’潜在单词边界的数量)
  • 每个长度为 n 的字符串可以被分割成个 2^n−1** 个可能的个组合。**

必须根据两个标准评估钻柱的成分:

  1. 作文是否是有效的分词,即由真实的单词组成(我们将学*如何处理未知单词)。
  2. 对于特定的输入字符串,哪个有效的单词分段(可能存在几个)具有最高的概率,并且将被选为最终结果。

递归方法

最简单的方法是生成所有可能的变体,将字符串分割成子字符串(候选单词),并在字典中查找这些候选单词。所有子字符串都是有效单词的那些分段变量将作为结果返回。

以下递归算法枚举所有合成:

对于“ isit ”作为输入,它将生成所有 8 个可能的组合:

i s i t
i s it
i si t
**i sit**
is i t
**is it**
isi t
isit

两个作文由真正的英语单词组成,并且将是有效的分段建议。在分段变量选择部分,我们将学*如何确定两个变量中哪一个更有可能。

但是有一个问题。长度为 n 的每一串可以被分割成 2^n−1 可能的成分。这是巨大的!

朴素的算法是指数不会缩放更长的字符串!

例如,我们的字符串quickbrownfoxjumpsoverthelazydog的长度为 35。这导致产生超过170 亿个切分变体,它们的所有单词都要在字典中进行验证,最后,这些变体按概率进行排序。

我们通常没有那么多时间和计算能力。我们需要想出更聪明、更有效的方法。

局部最优的增量计算

我们不需要为了找到最好的而生成所有的作文!

在朴素算法中,生成分割变量的整个树。对于重复子串,也重复生成分段。并且仅在最后,所有生成的完整分割被比较以找到最佳分割。

但是每个特定的子串我们只需要分割一次。我们只为每个子串计算一次最佳部分分割,并在整个输入串的增量分割期间重用它。

局部最优的选择基于假设连续的部分分割是独立的。****

只计算一次每个子串的最佳分段并重用它节省了生成和存储重复模式所需的大量时间和内存

下一节将介绍两种不同的方法来实现这一点。

动态规划方法

改进算法的一种方法是使用动态编程:

这是一种解决复杂问题的方法,将复杂问题分解成一系列更简单的子问题,每个子问题只解决一次,然后存储它们的解。下一次出现相同的子问题时,不用重新计算它的解,只需查找先前计算的解,从而节省计算时间。每个子问题解都以某种方式被索引,通常基于其输入参数的值,以便于查找。将子问题的解存储起来而不是重新计算的技术叫做“ 记忆化 ”。【来源:维基百科】

每次在我们的程序进行递归调用来分割剩余的字符串之前,我们都要检查这个精确的子串以前是否被分割过。如果是这样,我们只需消除递归调用,并从缓存中检索该子串的最佳分割结果(在特定子串第一次被分割时存储在缓存中)。

这种技术已经被多次用于分词:

由于我在网上找不到 C#端口,下面是我对动态编程方法的实现:

WordSegmentationDP source code

三角矩阵方法

****动态规划方法使用递归字典来记忆剩余子串的最佳分段。

****三角矩阵方法使用嵌套循环循环数组来存储前缀子串的最佳分段。

生成长度递增的部件的三角形矩阵,组织成圆形阵列。此允许恒定的 O(1)内存消耗(与动态编程的线性 O(n)相比),因为一旦不再需要中间分段变量,它们就会被覆盖。不是存储完整的分段串,而是仅使用潜在空间位置的位向量。这减少了存储分段变量的内存消耗(1 位而不是 1 字符)并且垃圾收集友好。****

Triangular Matrix algorithm

以及三角矩阵方法的 C#实现:

WordSegmentationTM source code

动态规划与三角矩阵

那么,这两种方法的相同点和不同点是什么呢?

  • 两种算法提供相同的结果
  • 两者具有相同的线性计算复杂度 O(n)。
  • 两者都存储特定子串的最佳分段变量,因此只需计算一次。
  • DP 连续计算特定剩余子串的所有分段变量。最好的变体是存储在缓存字典(哈希表)中的。为了访问特定余数的分割结果,子串被用作关键字
  • TM 在内部循环的特定位置计算特定前缀子串** 非连续的分段变量。最好的变体是存储在数组中的。为了访问特定前缀子串的分割结果,循环位置被用作索引。**
  • TM 有一个常量内存消耗** (数组大小= O(1)= maxSegmentationWordLength),而 DP 有一个线性内存消耗 (缓存字典条目数= O(n) =输入文本长度)。**
  • 此外,即使对于相同数量的条目,数组(MT)的内存消耗也低于字典(DP)的内存消耗。
  • 此外,TM 仅存储潜在空间位置的位向量,而 DP 存储完整的分段串。这进一步减少了存储分段变量的内存消耗(1 位而不是 1 字符)并且垃圾收集友好。****
  • 通过索引(MT)访问数组的比通过键(DP)访问缓存字典的更快。
  • 两者的词频词典的查找号码类似于
  • 迭代通常比递归快,并防止可能的递归限制(超过最大递归深度/堆栈溢出)。

在我的基准测试中,三角矩阵方法比动态编程方法快 2 倍。它有更低的内存消耗更好的可伸缩性,并且是 GC 友好的。****

最初我认为这两种方法完全不同。 但在比较了它们的特点后,我认为三角矩阵方法是 只是一种特殊形式的动态编程 ,它使用一个 数组代替字典 进行记忆,使用 循环代替递归 并增量优化 前缀字符串而不是

最大字长

候选单词是从最大长度的字符串中生成的。Norvig 将最大单词长度任意选择为 20。由于最长的单词是语言相关的(中文最多 6 个字符),最好从字典中存在的最长单词中导出。虽然这是试探性的,但是不太可能存在大于字典中包含的最长单词的有效真实单词。它还可以防止查找我们已经知道不在字典中的单词,并创建包含这些不存在的单词的组合。这将确保最大的分割速度。

计算的复杂性

动态规划和三角矩阵方法都有一个线性运行时间 O(n)** 来寻找最佳组合。**

文本长度 n 和运行时间的确切关系是 O(n*Min(n,最大字典字长)/ 2)

分段变量选择

不过,将字符串拆分成单词可能有几种有效的方法:

isit 可能是 i sit 或者是**it**

词频(或单词出现概率)用于确定最可能的分段变量。

单词 出现概率 P =字数 C /语料库规模 N

语料库大小 N 是用于生成频率词典的文本语料库中的总字数。只有当字典是完整的,n 才等于频率字典中所有计数 c 的和,但如果字典被截断或过滤,n 就不等于。

朴素贝叶斯规则

我们假设两个单词的单词概率是独立的。因此,单词组合的朴素贝叶斯概率是两个单词概率的乘积:

P(AB)=P(A)P(B)*

使用双词概率代替单字概率可以进一步提高切分质量。

对数标度

我们不是计算概率的乘积,而是计算概率对数的和。因为单词的概率是关于 10^-10 的,所以许多这样的小数字的乘积可能超过(下溢)浮点数的范围并变成零。****

log(P(AB))= log(P(A))+log(P(B))

已知单词

为了计算单词出现的概率,我们可以使用不同的方法:

  1. 通过统计大型文本语料库中的单词来创建我们自己的词频词典。如果字典来源于与你要处理的文档相似的语料库,那么相似词出现概率分布将确保最优结果
  2. 使用包含字数的现有频率词典,例如 Google Books Ngram 数据。缺点是 Google Books Ngram 数据不仅包含有效单词,还包含拼写错误和其他片段。虽然许多拼写错误由于概率低,无论如何都不会有影响,但这并不总是有保证的。例如,常用词的频繁拼写错误可以战胜真正的稀有词。
  3. 词典质量对于分段质量至关重要。为了实现这一点,两个数据源可以通过交集来组合:巨大的 Google Books Ngram 数据提供了有代表性的词频(但是包含许多有拼写错误的条目),甚至对于罕见的单词SCOWL——面向拼写检查器的单词列表,其确保了真实的英语词汇(但是不包含在相同编辑距离内对建议进行排序所需的词频)。

我已经决定使用变体 3,即真正的英语单词词典与来自 Google Books Ngram 语料库的词频的交集,因为即使对于罕见的单词也有相关的词频。但是与变体 1 相比的缺点是谷歌语料库来源于不同世纪的书籍。随着时间的推移,语言的使用已经发生了变化,语言的使用在不同的领域也有所不同(如医学、法律、散文、新闻、科学)。

未知单词

我们不能完全依赖字典。没有一本字典是完整的。有生僻词、新词、外来词、人名、品牌名、产品名、缩略语、非正式用词、俚语、拼写错误。即使对于字典中不包含的单词,我们也希望分词算法选择最可能的分词变体。

因此,我们必须估计一个词出现的概率,以未知的词。我们拥有的甚至是未知单词的信息就是它们的长度。

乔治·金斯利·齐夫观察到单词的长度和它们的频率成反比。经常使用的词,如“the”,往往很短(Zipf g . The psycho biology of Language)。Zipf 用“最小努力原则”(Zipf g . Human Behavior and the Principle of less Effort)对此进行了解释。

Peter Norvig 在《自然语言语料库数据》第 224 页中提出了以下计算未知单词概率的公式:

*似词出现概率 P=10 / (N * 10^word 长度 l)

我们必须意识到,这是一个包含启发式参数原始估计值,可能需要针对除英语之外的语言进行调整。关于单词长度和词频关系的更多信息可以在 Miller,Newmann,Friedmann 的书面英语的长度-频率统计和 Strauss,Grzybek,Altmann【单词长度和词频】中的不同语言方面找到。****

当然,我们可以想到更复杂的概率计算,例如,通过使用马尔可夫链已知前缀和后缀来估计特定子串成为真正单词的概率。这将使正确分割连续的未知单词成为可能。

语言

分词算法本身是语言独立的。但是词频词典是特定于语言的。为了对以某种语言编写的文本进行分词,需要该语言的频率词典。 Google Books n-gram 数据包括许多语言的词频。

此外,如上所述,根据未知单词的长度来估计未知单词的概率的公式包含启发式参数,必须针对每种语言单独调整这些参数,以获得最佳分割结果。

分词和拼写纠正

如上所述,存在几种分词解决方案。

符号拼写。分词结合了分词和拼写纠正

在切分过程中,会生成许多潜在的候选单词,所有候选单词都需要进行拼写检查,并对候选建议进行排序。

这只有通过利用 SymSpell 的极限查找速度才是可行的:

通过最大编辑距离的一个参数,我们可以控制允许多少拼写纠正。在 maxEditDistance=0 的情况下,我们有没有拼写校正的纯单词分割。在 maxEditDistance=2 的情况下,如果字典中的所有单词都在一个 Damerau-Levenshtein 编辑距离≤2 的范围内,我们就认为它们是子字符串的有效候选词。

更高的最大编辑距离允许校正更多的错误,但是以假阳性校正和更低的分割性能为代价。实际的权衡取决于投入材料的质量。它可以使有错误的输入变得可读,但也可能给原本完美的输入带来错误。

例 1

input:                 isit
Norvig segment:        is it             -> no spelling correction
WordSegmentation ed=0: is it             -> no spelling correction
**WordSegmentation ed=1: visit             -> spelling correction** LookupCompound ed=0:   i sit             -> no spelling correction
**LookupCompound ed=1:   visit** -**> spelling correction**

例 2

input:                 independend
Norvig segment:        in depend end      -> no spelling correction
WordSegmentation ed=0: in depend end      -> no spelling correction
**WordSegmentation ed=1: independent        -> spelling correction** LookupCompound ed=0:   independend        -> no spelling correction
**LookupCompound ed=1:   independent        -> spelling correction**

例 3

input:                 whocouqdn’tread
Norvig segment:        who couqdn’t read  -> no spelling correction
WordSegmentation ed=0: who co uqdn’t read -> no spelling correction
**WordSegmentation ed=1: who couldn’t read  -> segmentation+correction** LookupCompound ed=0:   whocouqdn’tread    -> more than 1 space/token
LookupCompound ed=1:   whocouqdn’tread    -> more than 1 space/token

*为了使 SymSpell 的算法具有可比性。分词和 Norvig 的分词相同 频词典 一直在使用。

单词分段与查找复合

SymSpell 拼写纠正和模糊搜索库附带一个方法lookup compound。它支持多单词输入字符串的复合感知自动拼写纠正,有三种情况:

  1. 在正确的单词中错误地插入空格导致了两个不正确的术语
  2. 错误地省略了两个正确单词之间的空格,导致了一个不正确的组合术语
  3. 有/无拼写错误的多个输入术语

拆分错误、连接错误、替换错误、换位错误、删除错误和插入错误可以混合在同一个单词中。

那么,符号之间有什么区别呢。单词切分符号拼写。LookupCompound** ,和什么相似?**

  • ****两个都可以在多词输入字符串中插入和删除空格,以及纠正拼写错误。
  • LookupCompound 可以只在令牌中插入一个空格(由现有空格分隔的字符串片段)。它用于单词分段文本的拼写纠正,但可以修复偶尔丢失的空格。因为每个标记只有一个空格,所以要生成和评估的变量较少。因此,它更快,并且校正的质量通常更好。
  • ****分词可以在一个令牌中插入任意多的空格。因此,它也适用于没有任何空间的长字符串。缺点是速度和校正质量较慢,因为存在更多的潜在变量,需要生成、评估和从中选择。

应用

CJK 语言文本或嘈杂文本的分词是搜索引擎和搜索即服务搜索 API 的文本处理管道的一部分,在这里你必须每秒索引数千个文档。在分词甚至不是主要处理任务,而只是文本预处理中许多组件之一的情况下,您需要最快的分词算法。

源代码

分词 拼写纠正 :

worsegmentationtmworsegmentationdp并在 GitHub 上发布为开源MIT 许可下。****

分词 拼写更正:

WordSegmentationlookup compoundSymSpell 库的一部分,在 GitHub 上发布为开源MIT 许可下。****

Keras 为来自 Google 开放图像数据集 V4 的自定义数据实现了更快的 R-CNN(对象检测)

原文:https://towardsdatascience.com/faster-r-cnn-object-detection-implemented-by-keras-for-custom-data-from-googles-open-images-125f62b9141a?source=collection_archive---------0-----------------------

介绍

在探索了一段时间 CNN 之后,我决定尝试计算机视觉的另一个重要领域,物体检测。这方面有几种流行的方法,包括更快的 R-CNN、RetinaNet、YOLOv3、SSD 等。我在这篇文章中尝试了更快的 R-CNN。在这里,我想总结一下我所学到的东西,如果你对这个话题感兴趣,也许会给你一点启发。

我用的较快 R-CNN 的 Keras 版本的原代码是由 yhenon (资源链接: GitHub 编写的。)他使用了 PASCAL VOC 2007、2012 和 MS COCO 数据集。对我来说,我只是从谷歌的开放图像数据集 V4 中提取了三个类,“人”、“车”和“手机”。我应用了与他不同的配置来适应我的数据集,并删除了无用的代码。顺便说一句,为了在 Google Colab (免费 GPU 计算长达 12 小时)上运行这个,我将所有代码压缩为三段。ipynb 笔记本。抱歉结构混乱。

首先,我假设你知道 CNN 的基本知识和什么是物体检测。这是原文的链接,名为“更快的 R-CNN:用区域提议网络实现实时目标检测”。对于想在更快的 R-CNN 上实现来自 Google 的开放图像数据集 V4 的自定义数据的人,你应该继续阅读下面的内容。

我阅读了许多解释与更快的 R-CNN 相关的主题的文章。他们对此有很好的理解和更好的解释。Btw,如果你已经了解了关于更快 R-CNN 的细节,并且对代码比较好奇,可以跳过下面的部分,直接跳转到代码解释部分。这是我这个项目的 GitHub 链接。

推荐阅读:

更快的 R-CNN:现代物体探测的兔子洞

用于物体检测的深度学*:综述

物体检测深度学*算法综述

更快的 R-CNN(简要说明)

R-CNN (R. Girshick 等人,2014) 是更快的 R-CNN 的第一步。它使用搜索选择性 ( J.R.R. Uijlings 和 al。(2012) )找出感兴趣的区域并将其传递给 ConvNet。它试图通过将相似的像素和纹理组合到几个矩形框中来找出可能是对象的区域。R-CNN 的论文使用了来自搜索选择的 2000 个建议区域(矩形框)。然后,这 2000 个区域被传递给一个预先训练好的 CNN 模型。最后,输出(特征图)被传递到 SVM 进行分类。计算预测边界框(bbox)和地面真实 bbox 之间的回归。

Example of search selective. Source: J.R.R. Uijlings and al. (2012)

快速 R-CNN(R . Girshick(2015))向前移动一步。它不是将 2000 倍的 CNN 应用于提议的区域,而是只将原始图像传递给预先训练的 CNN 模型一次。基于前一步骤的输出特征图计算搜索选择算法。然后,ROI 池层用于确保标准和预定义的输出大小。这些有效输出作为输入被传递给完全连接的层。最后,使用两个输出向量,通过 softmax 分类器预测观察到的对象,并通过线性回归器调整边界框定位。

更快的 R-CNN (简称 frcnn)比快速 R-CNN 更进一步。搜索选择过程被替换为区域建议网络 (RPN)。顾名思义,RPN 是一个提出区域的网络。例如,在从预先训练的模型(VGG-16)获得输出特征图之后,如果输入图像具有 600x800x3 尺寸,则输出特征图将是 37×50×256 尺寸。

First step of frcnn

37x50 中的每个点都被视为一个锚点。我们需要为每个锚点定义特定的比例和大小(在原始图像中,三个比例为 1:1、1:2、2:1,三个大小为 128、256、512)。

One anchor projected to the original image.

Anchor centers throught the original image. Source: https://tryolabs.com/blog/2018/01/18/faster-r-cnn-down-the-rabbit-hole-of-modern-object-detection/

接下来,RPN 连接到具有 3×3 滤波器、1 个填充、512 个输出通道的 Conv 层。输出连接到两个 1x1 卷积层进行分类和盒子回归(注意这里的分类是确定盒子是不是物体)。

Convolutional implementation of an RPN architecture, where k is the number of anchors. (k=9 in here) Source: https://tryolabs.com/blog/2018/01/18/faster-r-cnn-down-the-rabbit-hole-of-modern-object-detection/

Javier:为了训练,我们把所有的主播,分成两个不同的类别。那些与具有大于 0.5 的并集 (IoU)上的 交集的地面实况对象重叠的被认为是“前景”,而那些不与任何地面实况对象重叠或与地面实况对象的 IoU 小于 0.1 的被认为是“背景”。

在这种情况下,每个锚点在原图中都有 3×3 = 9 个对应的盒子,也就是说原图中有 37×50×9 = 16650 个盒子。我们只是从这 16650 个盒子中选择 256 个作为小批量,包含 128 个前景(pos)和 128 个背景(neg)。同时,应用[non-maximum suppression](https://www.youtube.com/watch?v=A46HZGR5fMw)来确保所提议的区域没有重叠。

经过以上步骤,RPN 就完成了。然后我们到 frcnn 的第二阶段。与快速 R-CNN 类似,ROI 池用于这些建议区域(ROI)。输出为 7x7x512。然后,我们用一些完全连接的层来展平这一层。最后一步是使用 softmax 函数进行分类和线性回归,以确定盒子的位置。

R-CNN architecture. Source: https://tryolabs.com/blog/2018/01/18/faster-r-cnn-down-the-rabbit-hole-of-modern-object-detection/

代码解释

第 1 部分:从 Google 的开放图像数据集 v4(边界框)中提取定制类的注释

下载并加载三个。csv 文件

在官方网站中,点击下图底部的红色方框Class Names即可下载class-descriptions-boxable.csv。然后去Download from Figure Eight下载另外两个文件。

Screen shot of Open Images website

在八字网站,我下载了如下图的train-annotaion-bbox.csvtrain-images-boxable.csv

Screen shot of Figure Eight

下载完之后,我们现在来看看这些文件里面都有什么。train-images-boxable.csv包含可装箱的图像名称和它们的 URL 链接。class-descriptions-boxable.csv包含与它们的 class LabelName 对应的类名。train-annotations-bbox.csv有更多信息。train-annotations-bbox.csv中的每一行包含一幅图像的一个边界框(简称 bbox)坐标,并且还包含该 bbox 的 LabelName 和当前图像的 ID (ImageID+)。jpg'=Image_name)。XMin, YMin是这个 bbox 的左上角,XMax, YMax是这个 bbox 的右下角。请注意,这些坐标值是标准化的,如果需要,应该计算实际坐标。

First 5 rows of three .csv file

获取整个数据集的子集

包含 600 个类的开放图像数据集 V4 的整个数据集对我来说太大了。所以我提取了 1000 张图片,分别用于“人”、“手机”和“汽车”三个类别。

下载完这 3000 张图片后,我将有用的注释信息保存在一个. txt 文件中。每行的格式如下:file_path,x1,y1,x2,y2,class_name(两个值之间没有空格,只有逗号)其中 file_path 是该图像的绝对文件路径,(x1,y1)和(x2,y2)表示原始图像的左上和右下真实坐标,class_name 是当前边界框的类名。我用 80%的图片进行训练,20%的图片进行测试。训练图像和测试图像的预期数量应该是 3x800 -> 2400 和 3x200 -> 600。但是,可能会有一些重叠的图像同时出现在两个或三个类别中。例如,一幅图像可能是一个人走在街上,街上有几辆车。所以训练图像的 bbox 数是 7236,测试图像的 bbox 数是 1931。

One sample from my extracting data. The left is original image downloaded from given url and the right is drawn by adding bounding boxes parsered from train-annotations-bbox.csv.

第 2 部分:更快的 R-CNN 代码

我将解释代码中的一些主要功能。每个函数的完整注释都写在。jpynb 笔记本。请注意,为了更快地训练,我将调整后的图像保持为 300,而不是我在第 1 部分中解释的 600。

重建 VGG-16 的结构并加载预训练模型(nn_base)

VGG-16 structure. Source: https://www.quora.com/What-is-the-VGG-neural-network

准备培训数据和培训标签(get_anchor_gt)

输入数据来自 annotation.txt 文件,该文件包含一组图像及其边界框信息。我们需要使用 RPN 方法来创建建议的 bboxes。

  • 此函数中的参数
    all _ img _ data:list(file path,width,height,list(bboxes))
    C:config
    img _ length _ calc _ function:根据输入图像大小
    计算最终图层的特征图(基本模型)大小的函数:“训练”或“测试”;“培训”模式需要加强
  • 返回此函数中的值
    x_img :调整大小和缩放后的图像数据(最小尺寸= 300 px)
    Y:【Y _ rpn _ cls,Y _ rpn _ regr】
    img _ data _ aug:增强后的图像数据(增强后的原始图像)
    debug_img :显示调试图像
    num_pos

计算每个图像的 rpn(calc _ rpn)

如果特征图的形状为 18×25 = 450,锚尺寸为 9,则有 450×9 = 4050 个潜在锚。每个锚的初始状态是“否定的”。然后,如果 IOU > 0.7,我们将锚设为正。如果 IOU > 0.3 且<0.7, it is ambiguous and not included in the objective. One issue is that the RPN has many more negative than positive regions, so we turn off some of the negative regions. We also limit the total number of positive regions and negative regions to 256. 【 represents if this anchor has an object. 【 represents if this anchor overlaps with the ground-truth bounding box.

For ‘positive’ anchor, 【 =1, 【 =1.
为‘中性’锚,y_is_box_valid =0,y_rpn_overlap =0。
对于‘负’锚,y_is_box_valid =1,y_rpn_overlap =0。

  • 此函数中的参数
    C:config
    img _ data:增强图像数据
    width :原始图像宽度(如 600)
    height :原始图像高度(如 800)
    resized _ width:根据 C.im_size(如 300)

  • 返回此函数中的值
    y _ rpn _ cls:list(num _ bbox es,y _ is _ box _ valid+y _ rpn _ overlap)
    y _ is _ box _ valid:0 或 1 (0 表示盒子无效,1 表示盒子有效)
    y_rpn_overlap : 0 或 1 (0 表示盒子不是对象,1 表示盒子是对象)【T20

y_rpn_cls的形状是(1,18,25,18)。18x25 是特征图大小。特征图中每个点有 9 个锚点,每个锚点分别有 2 个值y_is_box_validy_rpn_overlap。所以第四个图形 18 来自 9x2。

y_rpn_regr的形状是(1,18,25,72)。18x25 是特征图大小。特征图中每个点有 9 个锚点,每个锚点有 4 个值,分别为txtytwth。注意,这 4 个值有自己的y_is_box_validy_rpn_overlap。所以第四个形状 72 来自 9x4x2。

从 RPN (rpn_to_roi)计算感兴趣区域

  • 此函数中的参数(num _ anchors = 9)
    rpn _ layer:rpn 分类的输出层
    shape (1,feature_map.height,feature_map.width,num_anchors)
    如果调整后的图像宽度为 400,regr _ layer
    :rpn 回归的输出层
    shape (1,feature_map.height,feature_map . 36)如果调整大小后的图像宽度为 400,C 为 300
    :config
    use _ regr:是否在 rpn
    max_boxes :非最大抑制的最大 bboxes 数量(NMS)
    overlap _ thresh:如果 NMS 的 iou 大于此阈值,则丢弃此框****
  • 返回此函数中的值
    结果:来自非最大抑制的框(shape=(300,4))
    :框的坐标(在特征图上)

对于上一步中的 4050 个锚点,我们需要提取max_boxes(代码中的 300)个盒子作为感兴趣的区域,并将它们传递给分类器层(frcnn 的第二阶段)。在函数中,我们首先删除超出原始图像的方框。然后,我们使用阈值为 0.7 的非最大抑制。

The green box is ground-truth bounding box. The purple box is the anchor (label) calculated by RPN layer.

RoIPooling 层和分类器层(RoiPoolingConv,classifier_layer)

RoIPooling 层的功能是将 roi 处理为 max pooling 输出的特定大小。每个输入 roi 被分成一些子单元,我们对每个子单元应用最大池。子单元的数量应该是输出形状的尺寸。

********

If the large red rectangle in the left image is RoI and it’s supposed to perform a RoI Pooling layer with 2x2 output, it would be divided to 4 sub-cells and be applied a max pooling process. The right image is the 2x2 output result. Source: http://wavelab.uwaterloo.ca/wp-content/uploads/2017/04/Lecture_6.pdf

分类器层是整个模型的最后一层,位于 RoIPooling 层之后。它用于预测每个输入锚点的类名及其边界框的回归。

  • 此函数中的参数
    base_layers : vgg
    input_rois : (1,num_rois,4) ROI 列表,带排序(x,y,w,h)
    num_rois:一次要处理的 ROI 数量(此处为 4)
  • 返回此函数中的值
    list(out_class,out_regr)
    out_class:分类器层输出
    out_regr:回归层输出

****首先,将池层扁平化。
然后,接着是两个全连接层和 0.5 的压差。
最后,有两个输出层。

out_class: softmax 激活函数,用于对对象的类名进行分类

out _ regr:bboxes 坐标回归的线性激活函数****

资料组

同样,我的数据集是从谷歌的开放图像数据集 V4 中提取的。选择了“汽车”、“人”和“移动电话”三个类别。每个类包含大约 1000 张图片。“汽车”、“手机”和“人”的边界框数量分别为 2383、1108 和 3745。

因素

  • 调整后的(im_size)值为 300。
  • 主播人数为 9 人。
  • 非最大抑制的最大数量是 300。
  • 模型中要处理的 RoI 数量是 4(我没有尝试更大的尺寸,这可能会加快计算速度,但需要更多内存)
  • Adam 用于优化,学*率为 1e-5。如果我们应用原始论文的解决方案,可能会有所不同。他们在 PASCAL VOC 数据集上对 60k 小批量使用了 0.001 的学*率,对接下来的 20k 小批量使用了 0.0001 的学*率。
  • 对于图像放大,我打开了水平翻转、垂直翻转和 90 度旋转。

环境

谷歌的 Colab 用特斯拉 K80 GPU 加速进行训练。

培训时间

我选择的每个纪元的长度是 1000。注意,这里每个批处理只处理一个图像。我训练的纪元总数是 114。每个纪元在这种环境下花费大约 700 秒,这意味着训练的总时间大约为 22 小时。如果你像我一样使用 Colab 的 GPU,你需要重新连接服务器,并在它自动断开连接时加载权重,以便继续训练,因为它对每次会话都有时间限制。

结果

我们对 RPN 模型和分类器模型都应用了两个损失函数。正如我们之前提到的,RPN 模型有两个输出。一个是用于分类它是否是一个物体,另一个是用于包围盒的坐标回归。从下图中,我们可以看到它在前 20 个纪元学*得非常快。然后,分类器层变得更慢,而回归层仍然继续下降。其原因可能是,在我们训练的早期阶段,对象的精确度已经很高了,但同时,边界框坐标的精确度仍然很低,需要更多的时间来学*。

Epochs vs. Loss value for RPN model’s classifying output and bboxes regression output

相似的学*过程显示在分类器模型中。比较这两个曲线,它们显示出相似的趋势,甚至相似的损失值。我认为这是因为他们预测的值非常相似,只是他们的层结构略有不同。比较两个用于分类的图,我们可以看到预测对象比预测 bbox 的类名更容易。

Epochs vs. Loss value for Classifier model’s classifying output and bboxes regression output

Epochs vs. Total loss for two models

这个总损失是上述四项损失的总和。它有减少的趋势。然而,mAP(平均精度)并不随着损失的减少而增加。当历元数为 60 时,该图为 0.15。当历元数为 87 时,该图为 0.19。当历元数为 114 时,该图为 0.13。我认为这是因为少量的训练图像导致了模型的过度拟合。

我们可以调整的其他事情

  1. 对于较短的训练过程。我选择 300 作为图片尺寸调整的im_size,而不是原码(和原纸)中的 600。所以我选择更小的anchor_size【64,128,256】而不是【128,256,512】。
  2. 我选择 VGG-16 作为我的基本型号,因为它的结构更简单。然而,像 ResNet-50 这样的模型可能具有更好的结果,因为它在图像分类上具有更好的性能。
  3. 模型中有很多阈值。我像原始代码一样使用它们中的大部分。rpn_max_overlap=0.7rpn_min_overla=0.3是区分每个锚点的“正面”、“中性”和“负面”的范围。overlap_thresh=0.7是非最大抑制的阈值。

图像测试

在笔记本中,我将培训过程和测试过程分成两部分。运行测试前,请按如下方式重置所有运行时间。ipynb 笔记本。运行测试笔记本时,您可能需要关闭培训笔记本,因为内存使用几乎超出限制。

Screen shot for ‘Reset all runtimes’

********

Some result for the test data

终于

为了获得乐趣,你可以创建自己的数据集,它不包括在谷歌的开放图像数据集 V4 中,并训练它们。对于我在本文中使用的封面图片,他们是中国制造的三个瓷器僧侣。我只是根据他们的面部表情给他们取了名字(不确定是不是困的那个)。它们不包括在开放图像数据集 V4 中。所以我自己用 RectLabel 来标注。我花了 3 个小时左右的时间,拖了 6 节课 465 张图片(包括'苹果笔'、唇膏'、剪刀'、瞌睡和尚'、不安和尚快乐和尚)。对于anchor_scaling_size,我选择【32,64,128,256】,因为唇膏在图像中通常很小。找到这些方形的小唇膏。我为更强的模型添加了更小的锚尺寸。考虑到 Apple Pen 又长又细,anchor_ratio 可以使用 1:3 和 3:1,甚至 1:4 和 4:1,但我没有尝试过。训练时间不长,表现还不错。我猜是因为背景相对简单,场景平淡。事实上,我发现更难的部分不是注释这个数据集,而是思考如何拍摄它们以使数据集更健壮。****

好了,这篇文章就到这里。感谢您的观看。这是我这个项目的 GitHub 链接。继续训练你自己的物体探测器。如果您有任何问题,请留下您的评论。很高兴收到你的来信:)

********

Some result for my custom dataset

(几乎)实时检测物体:FasterRCNN 用代码解释

原文:https://towardsdatascience.com/fasterrcnn-explained-part-1-with-code-599c16568cff?source=collection_archive---------1-----------------------

FasterRCNN 是一个做物体检测的网络。正如它的名字所解释的,它比它的后代 RCNN 和 FastRCNN 更快。有多快?几乎实时快速。这个网络在自动驾驶汽车、制造业、安全领域都有用例,甚至在 Pinterest 上也有使用。

这篇论文于 2015 年发表,有许多精彩的帖子解释了它是如何工作的(例如: #1#2#3 )。所以我想探究它是如何处理这个回购协议提供的公共实现的:https://github.com/jwyang/faster-rcnn.pytorch

我们通过一个例子来了解一下 FastRCNN。让我们看一个给定的图像 x。

使用 FastRCNN 的较慢过程将如下进行: 1)在图像上使用类似选择性搜索的算法来生成感兴趣的框/区域
2)通过 CNN 运行图像来获得特征图 3)对于步骤 1 中生成的每个框,使用特征图和几个完全连接的层来输出类+边界框坐标(稍后将详细介绍)

faster CNN 如何工作: 1)通过 CNN 运行图像以获得特征图 2)通过称为区域提议网络(RPN)的独立网络运行激活图,该网络输出感兴趣的框/区域
3)对于来自 RPN 的感兴趣的框/区域,使用几个完全连接的层来输出类+边界框坐标

这里的不同之处在于,FasterRCNN 解决了第一步必须对每个图像进行选择性搜索的瓶颈。选择性搜索的大多数实现都是在 CPU 上进行的(很慢),它本质上是一个独立的算法,所以让我们去掉它吧!

直觉是:使用 FastRCNN,我们已经在 CNN 中计算了一个激活图,为什么不通过几个层来运行激活图以找到感兴趣的区域,然后通过预测类+ bbox 坐标来完成向前传递呢?

好了,现在让我们来看一些代码。

代码库用 Resnet101 和 VGG16 实现了 FasterRCNN。由于架构简单,我将使用 VGG16 进行解释。第一步,将网络定义为 RCNN_base,RCNN_top。RCNN_base 就是做第一步,从图像中提取特征。RCNN_top 是网络的其余部分,它通常使用提取的特征来分类/预测东西。

Get all the layers except the layers

RCNN Base is the first part of the VGG

现在我们有了基本的特征地图,我们把它传递给区域提议网络,它应该找到感兴趣的区域。它返回感兴趣区域、关于是否找到对象的损失以及关于对象位置的损失。

好吧,那 RPN 是怎么回事?

在我们谈论这个之前,我们必须定义锚,锚是不同大小的盒子,用于帮助检测各种大小的物体(例如,人、车辆等)。在默认配置中,有 3 个比例和 3 个比率,总共有 9 个锚。在我们的特征图中的每个点,我们将运行这 9 个锚点(稍后会详细介绍)。

Picture Source: Vahid Mirjalili https://www.quora.com/How-does-the-region-proposal-network-RPN-in-Faster-R-CNN-work

好了,让我们回到弄清楚 RPN 是干什么的。

rpn.py 中的第一行获取基本的特征地图,无论它是什么维度,都使用 3x3 内核将其缩放到 512 的固定维度。

结果然后被发送到两个不同的卷积层:让我们称它们为类层和 BBox 坐标层
1)类为每个锚点
预测 2 个类概率(对象存在/无对象)2) BBox 坐标预测一个边界框相对于每个锚点的 4 个坐标

Code for above Layer 1,

Code for above Layer 2

假设一个给定的图像是 600 x 891。到 RCNN_base 完成时,它将被整形为批量大小 x 1024 x 38 x 56。然后,它将被第一个 rpn conv 标准化为批量 x 512 x 38 x 56。

如上所示,对于 38 x 56 特征地图中的每个点:
1)conv 类图层的结果为每个点输出 18 个值。这是有意义的,因为 18 个值对应于(存在/缺失)* 9 个锚的 2 类概率。结果是批量 x 18 x 38 x 56

BBOX 层的结果为每个点输出 36 个值。这是有意义的,因为 36 个值对应于 4 个边界框坐标* 9 个锚点。

类别概率的注释:
类别概率为 0 - > 1,因为应用了软最大值函数

BBox 系数注意:
边界框坐标是相对于特定锚点的值[0,1]。x、y、w 和 h 表示盒子的中心坐标及其宽度和高度。*值=地面真相。例如,t_x 表示 x 的系数(方框中心)。你可以把 t_x 乘以 w_a,然后加上 x_a,得到预测的 x,反之亦然。

所以 RPN 计算类概率和 bbox 系数,我认为它应该找到感兴趣的区域?

好的,所以如果你有一个 38 x 56 x 9 个锚点的特征图,以 16 的步幅采样,那就有很多建议了!(38 x 56 x 9) / 16 =单个图像的 1192 个建议。显然,我们不能把它们都保存下来,一张图片上可能只有一些有趣的东西。

因此,RPN 对提议进行排序,以找到具有相应最高概率的提议。因为我们有如此多的提议,所以肯定会有认同相同对象的提议。我们应用非最大抑制,只保留最有把握的建议,并删除 IOU > 0.7 的所有其他建议。

https://www.pyimagesearch.com/wp-content/uploads/2014/10/hog_object_detection_nms.jpg

太好了。所以 RPN 提出建议,如何评价网络的其余部分?

因此,一旦 RPN 产生了感兴趣的区域,这些 ROI 的大小可能会不同。我们正计划将这些 ROI 输入另一个 CNN,该 CNN 预计有一个固定的大小,所以我们必须做兴趣池区域。

在汇集结束时,我们希望将大小为 38 x 56 x 512 的特征地图转换为大小为 7 x 7 x 512 的特征地图。有三种方法可以做到这一点: ROI 裁剪ROI 对齐ROI 池。在最初的论文中,他们使用了 ROI Pooling ,它将特征图分成 7×7 个部分,并获得每个部分的最大值。

然而,正如在这个视频中所解释的那样,由于不均衡的划分,投资回报池似乎丢失了一些信息。实际的默认实现是 ROI 对齐。要阅读更多关于 ROI Align 的内容,请查看使用它的 Mask-RCNN 论文,它通过标记其像素来完成更困难的检测对象的工作。

好了,现在我们有了名为 pooled_feat 的 7x7 要素地图,我们将它传递给我们之前定义的 RCNN_top!如下所示,_head_to_tail 函数首先将 7x7 展平为 1x49,然后将其传递给 RCNN_top。

作为参考,这是 RCNN_top 的样子。是两个 fc 层。第一个图层包含 25088 个要素,因为我们的要素地图的形状是 7x7x512 = 25088。

RCNN top

最后一步!

我们采用 4096 特征,并通过两个独立的完全连接的层来运行它,以获得类分数和边界框预测。

训练网络

更快的 RCNN 由两个不同的网络组成:提出建议的区域建议网络,以及接受建议并评估类/bbox 的评估网络。这两个网络有两个不同的目标,所以你必须对它们进行稍微不同的训练。

对于地区提案网络,您希望教会它更好地提出这些提案。在代码中有一个锚目标类,它接受地面真相盒并获得相应的类分数/bbox 系数。如果锚和地面真实的 IOU 重叠超过 0.7,则锚目标得到“1”类,并且其 bbox 系数是 gt 的系数。如果小于 0.3,就是反面例子。

对于分类,我们使用交叉熵损失,它衡量输出为 0 到 1 的分类模型的性能。

对于 Bbox 回归,我们使用平滑的 L1 损失,它是预测值和实际值之间的绝对值。他们的理由是,与 L2 等损失相比,L1 损失对异常值不太敏感,这使误差平方。

一旦 RPN 网络损失函数被定义,我们为评估层定义另外两个损失函数。逻辑完全相同,除了交叉熵损失是在多个类之间:“猫、狗、火鸡”而不是“在场/不在场”。bbox 回归是一样的。

在 Pytorch 中,您可以将一个损耗定义为多个损耗的组合,因此这是 RPN 的两个损耗和评估层的两个损耗的组合。然后你可以同时优化这两层。

然而,在论文中,他们使用了一种在训练 RPN 和评估层之间交替的训练方案,但这是一个可选的细节。

【FasterRCNN 到此为止。感谢您花时间阅读我的文章!

使用移动 web 应用和 REST APIs 服务、演示和测试深度学*模型的最快方式

原文:https://towardsdatascience.com/fastest-way-to-serve-demo-and-test-your-deep-learning-model-with-a-mobile-web-app-and-rest-apis-38cfbbf90a52?source=collection_archive---------8-----------------------

一旦我们设计、训练并完善了我们的深度学*模型,快速简单地部署该模型以用真实生活输入来评估它并向他人演示它的方法总是受欢迎的。虽然有许多全面的 DL 模型服务框架,如 Tensorflow 服务、MXNet 模型服务(MMS ),但其中大多数都是为可扩展的生产部署而设计的,编写脚本和设置都是资源密集型和耗时的。

寻找廉价和轻量级解决方案的 ML 开发人员通常最终使用 Flask 编写轻量级 RESTful 端点,并公开托管它,使用 curl 或一些定制客户端来消费这些 REST apis。

我们的团队从最*几个月开始一直致力于提出一个解决方案,它可以

  1. 允许我们创建公共 RESTful 端点来服务我们的模型,而不需要或只需要很少的编码和设置。
  2. 主机 a,即用型,web app,使用上述 REST api,快速评估模型。这个 web 应用程序应该能够接受各种类型的输入——图像、视频、音频、文本和其他文件,并直观地显示输出。
  3. 上述 web 应用程序应响应迅速,移动友好,以便许多基于机器视觉的模型可以很容易地在现场评估,使用手机摄像头。

在我们继续致力于一个通用、灵活和无缝的解决方案的同时,我们很高兴地宣布服务于的 Clouderizer 的首次发布。

每个 Clouderizer 项目现在都有一个选项,在 SETUP 选项卡下启用 Clouderizer 服务。

Image 1 : Clouderizer Serving option in project settings

一旦打开这个选项,Clouderizer 将自动在运行项目的机器上设置一个 Flask 服务应用程序。服务应用程序将可以从 Clouderizer 控制台访问,就像 Jupyter 笔记本和终端一样。

Image 2 : Clouderizer project running with Serving

Clouderizer 社区已经预配置了几个项目来演示 Clouderizer 服务。

  1. 使用张量流的目标检测
  2. 基于 PyTorch 的快速神经风格转换

在本文中,我们将使用对象检测模板进行演示。下面是让 Clouderizer 投入使用的步骤

  • 如果你还没有一个帐户,请在这里注册一个免费的 Clouderizer 帐户。
  • 登录 Clouderizer 控制台并转到社区项目。
  • 搜索 Obj 检测 TF 模板。本项目从这里开始设立官方 Tensorflow 物体检测项目。按克隆。

Image 3 : Tensorflow Object Detection community template

Image 4 : Machine setup for Object Detection project

  • 在所有其他选项卡上单击“下一步”,完成向导。
  • 现在从主控制台,按下这个项目的开始。Clouderizer 完全自动化基于 EC2 的项目,旋转一个新的 spot 实例并启动项目。对于基于本地机器的项目,您需要复制启动命令并将其粘贴到目标机器的终端上(或 Google Colab 代码块)。
  • 一旦启动,您可以在控制台上看到自动安装进度。应该需要 5-6 分钟来设置一切和项目状态,以转向运行。

Image 5 : Object Detection project Running with Clouderizer Serving

  • 我们在这里可以看到,这个项目现在有了一个新的按钮,发球
  • 按下此按钮将启动 Clouderizer 服务 web 应用程序。您也可以在移动网络浏览器上打开此 URL

Image 6 : Clouderizer Serving web app for Object Detection project

  • 按网络摄像头选项卡。这需要设备摄像头的许可。一旦允许,它应该允许您使用设备摄像头捕捉输入图像。将相机对准感兴趣的对象,然后按下 capture。这将设置输入图像。

Image 7 : Captured input image from Clouderizer Serving web app

  • 现在按评估键。这将调用 Flask app REST api 进行评估。瞧啊。!检测到物体的输出图像如下所示。

Image 8 : Output image from Clouderizer Serving REST endpoint

既然我们已经看到了魔术,让我们列出一些关于 Clouderizer 服务的细节

  • 这个服务应用程序与您开发模型的 Clouderizer 项目运行在同一台机器上。
  • 提供应用程序 web URL 不需要会话身份验证。这意味着您可以与他人共享该 URL,而无需共享您的 Clouderizer 控制台凭据。当您想要演示或与其他人共享您的模型结果时,这非常有用。
  • 此外,上述网络应用程序完全响应,这意味着它真的很好地与手机网络浏览器和手机摄像头。这有助于使用您周围的真实生活图像和数据来评估您的模型。

Image 9 : Clouderizer Serving web app in action on phone browser

  • 输入图像也可以来自本地文件。只需选择本地文件标签和浏览文件从您的机器。

Image 10 : Local file as input

  • 用于模型评估的直接 REST api 模式可以在页面顶部的黑色丝带中找到。我们可以从 CURL 调用它,或者用它来与其他客户端集成。

Image 11 : Flask REST endpoint curl command

  • 可以通过顶部导航栏上的“配置”按钮访问此 web 应用程序的配置。此分区受用户名和密码保护。默认凭据是管理员/管理员。
    你可以从配置部分更新这些凭证(如果你打算与他人分享你的服务 URL,强烈推荐)。
  • Clouderizer 服务提供了两种评估模型的方法。
  1. Shell 命令:这是快速启动和运行服务的最简单方法。如果您的项目能够使用 bash shell 命令进行评估,那么您可以在这里指定它。以下特殊占位符可用于输入和输出图像
    \(IMG1\) - >输入图像路径。这在执行
    \(OIMG1\) - >输出图像路径之前被输入图像替换。这被服务输出文件夹所取代。当您的 bash 命令将输出文件放在这里时,Clouderizer Serving 返回这个文件作为对 REST 调用的响应。
  2. Python 代码:这允许您修改项目中 serve 子文件夹下的文件 script.py。该文件使用两个重要的函数
    init - >实现了一个 python 类 ClouderizerEval,该构造函数是应用程序启动时任何一次初始化的理想位置。现在是在这里加载模型的好时机。
    eval - >该函数接收 REST HTTP 请求表单参数。这个函数的输出可以是一个 json 对象或一个图像路径。

本文中的对象检测项目使用 Python 代码进行评估。这是它的要点。实现就是从这个谷歌云项目衍生出来的。

神经风格转移是另一个预煮的模板,你可以很容易地克隆和尝试。这里是它看起来的一瞥

Image 12 : Clouderizer Serving for Neural Style Transfer

虽然 Clouderizer 服务的第一个版本更侧重于支持机器视觉项目,但我们的团队正在努力使它更加通用,以处理各种输入输出格式——文本、音频、视频、json。

fastText++包括电池

原文:https://towardsdatascience.com/fasttext-batteries-included-fa23f46d52e4?source=collection_archive---------11-----------------------

在我的上一篇文章中,我概述了 fastText 是如何实现的,并阐明了一些设计决策。fastText 的主要创新是用子词信息丰富了 word2vec 模型。然而,我们不需要局限于仅仅学*单词。fastText 可以对任何符号序列进行建模,只要序列的顺序对它有一定的意义。例如用户穿越一个站点的旅程。我将更详细地讨论这一点,并指出为此使用 fastText word2vec 的一些限制。最后,我将通过利用 word2vec 模型从语料库中提取语义结构以及在 fastText 中提供这些的实现,介绍一些有助于解决这些问题的巧妙研究。这目前在我的 fastText 分支中,但是如果我得到足够多的请求,我可能会合并到上游。我也很感激你对它的任何反馈。

fastText 主要是通过添加一包字符 n-grams 来扩展经典的 word2vec 模型。虽然这对于文本来说很好,其中单词的 n 元语法仍然有一些意义,但对于主要由 id 组成的语料库来说没有意义,因为这些单词的 n 元语法没有内在意义。

Word2vec 通过理解单词出现的上下文来捕捉单词的意思。类似地,如果我们在一系列事件上训练 word2vec,比如用户在网站上的旅程,我们可以学*这些事件的潜在质量以及它们彼此之间的关系。通过对一系列事件(用户执行的搜索、他们点击的项目等)训练 word2vec 模型,我们有效地学*了如何使用户在一个会话中选择的项目彼此相似。这是雅虎可扩展语义匹配论文的总体思路。用 word2vec 的话说,这些跨站点的用户交互(搜索查询、点击等..)可以解释为一句话。所以每次互动都变成了一个词。

这个序列的 word2vec 公式允许我们在给定用户参与上下文(CBOW)或基于用户交互的上下文(Skip-gram)的情况下,对用户交互的概率进行建模。该模型可用于各种推荐、候选人选择以及搜索、广告和推荐问题的特征化。

以这种方式公式化序列有一些很好的特性:

  1. 它也允许我们在我们的词汇表中考虑单词时有很大的灵活性。它可以是搜索会话查询、商品 id、市场、位置。
  2. 我们可以为多种类型的对象创建一个共享的嵌入空间,给我们一个可能难以定义的跨多种事物的关系(例如,一个查询与一个地理区域的相似性)。
  3. 我们可以利用当前问题空间之外的上下文(例如,利用搜索结果生成广告,或生成推荐)。

然而,传统的 word2vec 模型不允许我们表达这些丰富的语义关系。我们来看 word2vec 模型公式。跳格目标是最大化平均对数概率:

where w^I and w^O are the input and output vector representations of w.

使用负采样损失(NEG) (2.2),概率可以被分解为上下文和目标词的正和负对的和,其中负采样被应用以获得负词。

Where S is the set of negative samples drawn from the entire vocabulary

这个公式来自噪声对比估计(NCE) ,它假定一个好的模型应该能够通过逻辑回归来区分数据和噪声。进一步简化,学*任务变成从噪声分布图w_s中区分目标单词w_o

让我们看一个例子。考虑以下用户旅程:

user u -> search query 'watch' -> saw items a, b, c -> clicked c -> purchased c

将用户的旅程建模为一系列动作,包括搜索查询和参与动作的 fastText 的输入将是:

query_watch item_c item_c

接下来,让我们看看使用 word2vec 来模拟用户旅程的一些限制。我们将继续讨论这个例子。

1.模拟隐含否定

word2vec 模型不允许我们捕捉的一个重要关系是隐含的负面信号。这些对于模拟用户的旅程尤其重要。例如,我们知道,如果搜索结果中的一个项目被点击,它左边的项目最有可能被用户看到,因此不相关。正如我们在上面的 NEG 公式中看到的,word2vec 不允许我们显式地对负数建模,所有的负数都是从整个分布中随机抽取的。

在这种形式中,改变损失函数的信号是简单的。对于引入的跳格损失,我们可以使用自定义负数扩展预测概率,如下所示:

Where C is the set of custom negatives for a particular positive token

这只是 NEG 公式的扩展,其中学*任务是将目标单词w_o与噪声分布的绘制w_s 以及所有隐含的否定w_c区分开来。

为了能够指定这一点,我们需要扩展 fastText 的词汇表,即它能够理解输入数据中的标记。fastText 的输入格式是一个文本文件,每个单词由一个空格字符分隔,每个句子由一个换行符分隔。对于监督学*,fastText 使用前缀__label__作为标签来标记单词。前缀可以通过-label标志定制。

v0.2.0 中,我扩展了这个词汇表以支持前缀__neg__。所有带有前缀__neg__的标记都是上下文特定的否定,可以添加到训练文件中。任何带有__neg__前缀的单词都作为否定词添加到它前面的最后一个肯定性单词,并且是损失函数中集合C的一部分。前缀可以通过-negPrefix标志定制。标志-ignoreCNegs可用于禁用自定义底片。如果禁用,这些令牌仍将被解析,但将在训练期间被丢弃。

上述示例输入将是,带有隐含否定的:

query_watch item_c __neg__item_a __neg__item_b item_c

2.应用全球背景

在为用户的旅程建模时,很难找到正确的归属。可能有多种因素导致最终结果,例如,对于一个电子商务网站,可能有多个用户查看的项目(多个推荐、内容页面等),以及他们采取的行动(点击多个项目、发出不同的搜索、浏览多个类别等)最终导致他们做出最终决定。对于多点触摸属性模型,我们希望与整个用户动作序列共享最终动作的意图。这可以被建模为在该特定会话中应用所有动作的全局上下文。将全球背景加入到我们迄今为止累积的损失中:

where G is the set of global contexts for that particular sequence

v0.2.0 词汇表也支持前缀__global__。前缀为__global__的所有标记都是全局上下文标记,并且是损失函数中集合G的一部分。在模型训练期间,具有该前缀的单词被附加到该特定行的每个目标单词。前缀可以通过-globalPrefix标志定制。标志-ignoreGContext可用于禁用全局上下文令牌。如果禁用,这些令牌仍将被解析,但将在训练过程中被丢弃。

使用用户和购买的项目作为全局上下文,上面的示例变成:

__global__user_u __global__item_c query_watch item_c __neg__item_a __neg__item_b item_c

3.编码重要性

基于模型被训练用于的特定任务,不同的动作可以具有不同的相对重要性。在电子商务中,添加到购物车是比点击更清楚的用户购买意图的例子。因此,为了模拟购买意图,能够赋予购物车添加比点击更重要的意义是很有用的。

v0.2.0 中,您可以为每个带有后缀:WEIGHT的目标单词指定权重。权重的取值范围可以从1255。如果指定权重,请确保您的学*率仍然合理,否则您可能会在训练过程中遇到爆炸梯度。通过平均权重缩小学*权重是一个很好的启发。

在每个特定项目上的停留时间也可以表示为指定给给定标记的权重。加权模式ηt = log(1 + t)在可扩展语义论文中指定。我发现停留时间通常与购买率线性相关,直到某一点,所以设定最大值是一个好方法。这是使用-parseWeights参数指定的。这样,如果我们给点击一个权重1,购买一个权重25,训练示例看起来像这样:

__global__user_u __global__item_c query_watch item_c:1 __neg__item_a __neg__item_b item_c:25

4.控制词汇量

在同一个向量空间中嵌入多个对象真的很有用;它允许我们捕获不同实体之间的关系,比如特定查询与某个区域的关系。然而,这带来了一个困难。通常,语料库中的项目总数因实体而异,因此对不同的语料库使用相同的阈值策略(读取数据)可能不会给我们带来理想的结果。例如,如果我们将区域的嵌入和查询一起编码,区域的数量与用户发出的搜索查询数量级不同。 v0.2.0 提供了一些不同的选项来帮助解决这个问题。

使用-maxVocabSize参数可以指定控制词汇表大小的。这使得训练可以扩展到训练模型的机器的极限。

符合与-minCountGlobal分开的全局上下文令牌的令牌的最小计数。

通过使用__cc__前缀识别特定令牌并通过-minCountCustom标志控制计数,为任意令牌定制最小计数。

如果我们遇到具有多个前缀的同一个令牌,那么这个特定令牌的类型由下面的优先顺序决定:customCountWord > globalContext > word,也就是说,如果存在由-minCountCustom指定的计数,那么它就是优先的,以此类推。

除了这些之外,fastText v0.2.0 还有很多新增功能。下面是 v0.2.0 中跳过 gram 模型训练的选项列表,新标志以粗体显示。

$ fasttext skipgramEmpty input or output path.The following arguments are mandatory:-input              training file path
-output             output file pathThe following arguments are optional:-verbose            verbosity level [2]The following arguments for the dictionary are optional:**-minCount           minimal number of word occurences [5]****-minCountLabel      minimal number of label occurences [0]****-minCountGlobal     minimal number of global context occurences [1]****-minCountCustom     minimal number of custom token [5]**-wordNgrams         max length of word ngram [1]
-bucket             number of buckets [2000000]
-minn               min length of char ngram [3]
-maxn               max length of char ngram [6]**-maxVocabSize       max tokens in vocabulary. Pruning happens at 0.75 of this: [30000000]**-t                  sampling threshold [0.0001]
-label              labels prefix [__label__]**-negPrefix          negative token prefix [__neg__] negative tokens are associated with preceeding positive token****-globalPrefix       global context token prefix [__global__] global context is associated with all tokens in the line****-ccPrefix           token prefix for custom counts [__cc__]****-splitPrefix        prefix for tokens to split [__split__]  prefix stripped off when creating token****-splitChar          char to split text on [_] these tokens are considered words and not ngrams. Using splits and ngrams together is not supported****-ignoreCNegs        ignore negative tokens. Negatives tokens have [__neg__] preceding them [false]****-ignoreGContext     ignore global context tokens. Global cotext tokens have [__global__] preceding them [false]****-ignoreSplits       ignore split prefix. Only the original token is used, with prefix [__split__] stripped off [false]****-parseWeights       parse weights from word tokens, does not apply to neg, global or split. Weight is unsigned int in range [1-255], eg. word:3 [false]**The following arguments for training are optional:-lr                 learning rate [0.05]
-lrUpdateRate       change the rate of updates for the learning rate [100]
-dim                size of word vectors [100]
-ws                 size of the context window [5]
-epoch              number of epochs [5]
-neg                number of negatives sampled [5]
-loss               loss function {ns, hs, softmax} [ns]
-thread             number of threads [12]
-pretrainedVectors  pretrained word vectors for supervised learning []
-noSubsampling      disable subsampling [false]
-saveOutput         whether output params and vector should be saved [false]The following arguments for quantization are optional:-cutoff             number of words and ngrams to retain [0]
-retrain            whether embeddings are finetuned if a cutoff is applied [false]
-qnorm              whether the norm is quantized separately [false]
-qout               whether the classifier is quantized [false]
-dsub               size of each sub-vector [2]

承认

非常感谢赵晓婷的合作,以及对 v0.2.0 的帮助, Mihajlo Grbovic 对语义嵌入的澄清,Giovanni Fernandez-kin cade对本文的反馈。

学*快速文本

原文:https://towardsdatascience.com/fasttext-ea9009dba0e8?source=collection_archive---------5-----------------------

一点个人背景

这是我在学*机器学*上重新开始的自我折磨的尝试。几个月前,我从在线纳米学位工厂 udacity 获得了一名机器学*工程师Nanodegree。纳米可能意味着它是无限小和微不足道的。

不确定。

金钱方面,大约是 1000 美元;就努力而言,我在 6 个月内投入了大量的工作。我有时让我的 CPU 超时工作,满负荷运行;看到我自己的学*项目结出了果实,我感到非常满意:识别狗的品种,对肺炎进行分类,让一架虚拟四轴飞行器悬停在起飞点上方约 10 个像素处(这都是荣耀)。我现在认为自己是机器学*领域的“文盲”。像CNN这样的术语将不再仅仅代表“假”新闻作品;我可以让一个非 ML 的人听起来很聪明,比如说RNNsLSTMGANsreinforcement learning等等。但除此之外,我的纳米学位对我没有任何影响。

尽管如此,在人工智能时代,不学*不是一个选项。所以我决定振作起来,继续前进,在机器学*理论、技术、突破和新前沿的洪流中跌跌撞撞。

为学*而学*。

我通过谷歌搜索“有趣的机器学*项目”来“发现”fas text。找到文章过去一年 30 个惊人的机器学*项目(v.2018) 。fastText 是数字 1。它拥有 16,185 颗 Github 星(这是数以万计的开发者的信任票),并且仍在上升。眼花缭乱。

所以我必须学*。

fast text是一个高效学*单词表示和句子分类的库。

词向量

单词表示和句子分类是自然语言处理领域的基础。NLP 之于人工智能,就是语言之于人类文明。这是一个允许你的 Siri、Alexa、谷歌助手(Google assistant)和一群语音助手对你拼写错误、用词不当、不完整、可能令人尴尬的问题做出回应的领域,并给出聪明和信息丰富的答案(希望如此)。这就是为什么当你阅读一些关于烹饪、健身和其他一切的文章时,谷歌或脸书会用“智能”广告跟随你。

简单的单词表示将文本集视为一个不加选择的单词包,也称为BoWBoW只关心 2 件事:a)已知单词列表;b)词频统计。它不关心句子中的单词、文本中的句子之间的句法(结构)和语义(意义)关系。对于某些目的,这种处理已经足够好了,例如,垃圾邮件检测。对其他人来说,BoW功亏一篑。相反,单词向量成为单词表示的最新形式。

单词向量将单词表示为多维连续浮点数,其中语义相似的单词被映射到几何空间中的邻*点。更简单地说, 一个单词向量是一行实数值 (与虚数值相反),其中 每个点捕获单词含义的一个维度其中语义相似的单词具有相似的向量

这是一大堆数学术语,代表了无限维度的数学宇宙。

当单词被矢量化时,它们可以被增加或减少。

妻子+丈夫+孩子=家庭(希望如此)

不确定以下数学公式是否正确:

妈妈*妈妈=奶奶?

反正在一个词向量里,smartintelligent是相邻而坐的两个词,catsdogs占据同一个动物球,gowentgone平行于eatateeaten

Word vector (From Introduction to Word Vectors)

有两种主要的架构/模型用于将大量文献训练成单词向量:一种连续单词袋模型(cbow)和连续跳格模型。有许多文章和博客文章提供了关于技术实现和解释的细节,例如单词向量的惊人力量Word2Vec 教程—Skip-GramWord2Vec 教程第二部分:连续单词袋模型

在一个过于简化和幼稚的版本中,给出一些例句:the farmer takes the wife, the wife takes the kids, the kids take the cats(摘自一首小孩儿的歌)。skip-gram使用一个随机单词作为输入,并输出单词列表中每隔一个单词成为所选单词的“邻*单词”的概率;相比之下,cbow模型使用一系列单词(上下文)作为输入,并输出每隔一个单词作为目标单词的概率。

所以把take这个词放进skip-gram机,它会粗制滥造出farmerwifekidscatsthe的概率;对于cbow,你需要喂它thefarmerwife,它会尝试猜单词take

FastText 支持连续CBOWskip-gram两种模式。

文本分类

文本分类是基本的,因为它是不言自明的。文本分类的应用范围从垃圾邮件过滤、情感分析、内容标记/分类。它也是搜索和排名等复杂系统的核心。分类和归类是人类和机器处理数量和复杂性不断增加的文本的第一步。在数字信息的浩瀚宇宙中,这让你能够找到你感兴趣的主题,跟随你想要占据的回音室,等等。

传统上,文本分类使用纯数学/统计方法。开发了各种特征提取技术,例如Principal Component Analysis (PDA).

那么统计方法就会变得不充分、太慢、太少。因此出现了机器学*,它可以更好地理解互联网上数百万兆字节的信息。机器学*中的文本分类,根据数据模型遵循的学*原理,可以分为三类:监督文本分类、非监督文本分类、半监督文本分类(Korde & Mahender,2012)。

FastText 使用简单有效的基线进行句子分类(将句子表示为单词包(BoW)并训练线性分类器)。它使用negative samplinghierarchical softmaxN-gram特征来降低计算成本和提高效率。

不得不说,所有的术语都让我晕头转向。

实施

以下是我跟随各地给出的例子学*和试用 fastText(例如这里)。

训练文集是加西亚·马尔克斯的《T4》一书

训练单词向量

使用skipgram

**.**/fasttext skipgram -input file.txt -output model

使用cbow

./fasttext cbow -input file.txt -output model

使用skipgramcbow,将生成一个.vec.bin文件。.vec文件包含了向量这个词,每行一个词,那是给我们人类的检查,.bin是给机器消耗的。

我们可以提前查看向量输出的内容:

head -n 4 model.vec

Sample output of fastText vector

有许多参数可以调整以微调字向量,最重要的是维度(dim)和子字的大小范围(minnmaxn)。

./fasttext skipgram -input file.txt -output model -minn 3 -maxn 5 -dim 100

阅读一个单词向量就像阅读二进制 0 和 1 一样有趣和有启发性。所以我可以直接输出我关心的花言巧语,这是一种解脱。

echo “imagination miracles magic desperation” | ./fasttext print-word-vectors model.bin

Word vector of a few choice words

还是不太好玩。所有这些数字只会让我头晕。

FastText 允许您查询最*的邻居,这允许我们查看单词向量是否正确地捕捉了单词之间的语义关系。

为此,我们运行nn命令。

./fasttext nn model.bin

Nearest Neighbors for the word “imagination”

我的训练词汇库可能太小,我不确定为什么extermination排在imagination的最*邻。无论如何也想象不到。那么我不经常理解机器的内部工作。

文本分类

对于文本分类,我使用了公开可用的Yahoo Answers数据(nider hoff/NLP-datasets有一个完整的公共领域数据集列表,其中包含用于自然语言处理的文本数据)。

在将我的数据插入 fastText 的训练机器之前,我做了一些轻微的处理,所以格式符合要求(文本文件的每一行都包含一个标签列表,后面跟着相应的文档。所有标签都以__label__前缀开头)。

现在是训练时间。

./fasttext supervised -input data/yahoo_answers_csv/train_modified.csv -output model_yahoo_answers

预测时间:

./fasttext predict model_yahoo_answers.bin -

fastText Predictions After Training

所以 fastText 将第一个问题归类为1\. Society & Culture,第二个问题归类为Education & Reference,第三个问题归类为7\. Business and Finance

在我看来没错。

使用测试数据集,我们可以通过检查精度和召回值来衡量训练模型的质量。

./fasttext test model_yahoo_answers.bin data/yahoo_answers_csv/test_modified.csv

因此,在只有 60,000 个问题的测试数据集下,只需几秒钟的训练,fastText 的精度和召回率为 0.652。

终于……

fastText 确实又快又棒,但是,学*和写它几乎花了我一辈子的时间(不得不吃饭、睡觉、网飞等等)。又多了一个不要让我迟钝的生物大脑手动做任何事情的理由。

快速文本:引擎盖下

原文:https://towardsdatascience.com/fasttext-under-the-hood-11efc57b2b3?source=collection_archive---------2-----------------------

fastText 作为一个高效学*单词表示和句子分类的库。它是用 C++编写的,在训练时支持多重处理。FastText 允许您训练单词和句子的监督和非监督表示。这些表示(嵌入)可以用于数据压缩的许多应用,作为附加模型的特征,用于候选选择,或作为迁移学*的初始化器。

FastText 支持使用负采样、softmax 或分层 softmax 损失函数来训练连续单词包(CBOW)或跳格模型。我主要使用 fastText 来训练语义嵌入,用于几千万大小的语料库,我对它在这项任务中的表现和规模感到满意。除了入门的文档之外,我很难找到其他文档,所以在这篇文章中,我将带你了解 fastText 的内部结构及其工作原理。期望对 word2vec 模型如何工作有所了解。克里斯·麦考密克的这篇文章很好地解释了这个问题。

运行快速文本

我们可以使用以下命令通过 fastText 训练一个跳格模型:

$ fast text skip program-输入数据. txt-输出模型

其中data.txt是输入数据,可以是一个文本序列,输出模型保存在 model.bin 下,输入项的矢量表示保存在model.vec下。

表现

FastText 能够实现非常好的单词表示和句子分类性能,特别是在使用字符级信息的罕见单词的情况下。

除了单词本身之外,每个单词都被表示为一包字符 n 元语法,因此,例如,对于单词matter,n = 3,字符 n 元语法的快速文本表示为<mamatatttteterer>。<和>是作为边界符号加入的,用来区分单词的 ngram 和单词本身,所以比如 mat 这个词是词汇表的一部分,就用<mat>来表示。这有助于保留较短单词的含义,这些单词可能会显示为其他单词的组合。本质上,这也允许你捕捉后缀/前缀的含义。

您使用的 n-grams 的长度可以由分别用于最小和最大字符数的-minn-maxn标志来控制。这些控制要获取 n 元语法的值的范围。该模型被认为是单词袋模型,因为除了 n 元语法选择的滑动窗口之外,不存在考虑用于特征化的单词的内部结构,即,只要字符落在窗口之下,字符 n 元语法的顺序就无关紧要。您也可以通过将 n-gram 嵌入都设置为 0 来完全关闭它们。当您的模型中的“单词”不是特定语言的单词,并且字符级 n 元语法没有意义时,这可能是有用的。最常见的用例是当你输入 id 作为你的单词时。在模型更新期间,fastText 学*每个 n 元语法以及整个单词标记的权重。

读取数据

虽然 fastText 的训练是多线程的,但是读入数据是通过单线程完成的。解析和标记化是在读取输入数据时完成的。让我们详细看看这是如何做到的:

FastText 通过输入数据的-input参数获取一个文件句柄。不支持从 stdin 读入数据。FastText 初始化两个向量来跟踪输入信息,内部称为word2int_words_word2int_在单词串的散列上被索引,并存储一个到words_数组(std::vector)的顺序 int 索引作为它的值。在读取输入时,words_数组按照唯一单词出现的顺序递增,并将封装了单词标记所有信息的 struct entry存储为其值。entry包含以下信息:

struct entry {
  std::string word;
  int64_t count;
  entry_type type;
  std::vector<int32_t> subwords;
};

这里需要注意一些事情,word是单词的字符串表示,count是输入行中相应单词的总计数,entry_type{word, label}中的一个,标签仅用于被监督的情况。不管entry_type如何,所有的输入令牌都存储在同一个字典中,这使得扩展 fastText 以包含其他类型的实体变得容易得多(我将在后面的文章中详细讨论如何做到这一点)。最后,subwords是一个特定单词的所有单词 n-grams 的向量。这些也是在读取输入数据时创建的,并传递给训练步骤。

word2int_向量的大小为MAX_VOCAB_SIZE= 30000000;这个号码是硬编码的。在大型语料库上进行训练时,这个大小可能会受到限制,并且可以在保持性能的同时有效地增加。word2int_数组的索引是一个字符串到 int hash 的值,并且是 0 和MAX_VOCAB_SIZE之间的唯一数字。如果存在哈希冲突,并且已经向哈希中添加了一个条目,则该值会递增,直到我们找到一个唯一的 id 来分配给一个单词。

因此,一旦词汇表的大小达到MAX_VOCAB_SIZE,性能就会大大下降。为了防止这种情况,每当散列的大小超过MAX_VOCAB_SIZE的 75%时,fastText 就会修剪词汇表。这是通过首先增加一个单词的最小计数阈值以使其有资格成为词汇表的一部分,然后删除字典中计数小于该阈值的所有单词来实现的。当添加每个新单词时,会检查 75%阈值,因此这种自动修剪可以在文件读取过程的任何阶段进行。

除了自动修剪之外,作为词汇表一部分的单词的最小计数通过分别使用单词和标签的-minCount-minCountLabel 标志(用于监督训练)来控制。基于这些标志的修剪发生在整个训练文件被处理之后。如果中的唯一单词总数触发了前面指定的自动修剪,则词典的阈值可能会高于手动指定的最小计数。然而,指定 minCount 的阈值将始终出现,有效地确保具有较低计数的单词不会成为您输入的一部分。

对于负采样损失,然后构建大小为NEGATIVE_TABLE_SIZE = 10000000 的负单词表。注意,这是⅓MAX_VOCAB_SIZE的大小。该表是通过绘制每个单词频率的平方根的一元分布来构建的,即。

where U(w) is the count of a particular word, W is the set of counts of all words

这确保了每个单词在否定表中出现的次数与其频率的平方根成正比。然后这张表被打乱以确保随机化。

接下来,如原始 word2vec 扩展论文的第 2.3 节中所概述的,构建一个用于丢弃频繁单词的采样表。这背后的想法是,经常重复的单词比不常用的单词提供的信息少,并且在看到同一个单词的许多实例后,它们的表示不会有太大变化。

该论文概述了以下丢弃方法:以概率丢弃训练字

where t is the chosen threshold and f(w) is the frequency of occurrence of word w.

作者认为t = 10e-5是一个合理的默认值。该公式丢弃频率大于阈值的单词,并且有效地采样不太频繁的单词,同时仍然保持它们的相对频率,并且因此仅仅起到抑制频率的夸大效果的作用。

另一方面,FastText 将这种分布定义为

where t = 10e-4 is the chosen threshold, f(w) is the frequency of occurrence for word w

默认阈值可以通过-t参数手动编辑。阈值t 在 fastText 中的含义与在原始 word2vec 文件中的含义不同,应该根据您的应用进行调整。

仅当在训练阶段,从 0 和 1 之间的均匀分布中随机抽取的值大于丢弃的概率时,单词才被丢弃。下面是默认阈值范围从 0 到 1 的分布图。如图所示,听牌大于 P 的概率随着频率的增加而增加,因此,听牌被弃牌的概率也随着频率的增加而增加。这只适用于无监督的模型。对于监督模型,单词是而不是丢弃的。

Probability of discard in fastText with default threshold for frequency f(w)

如果我们用-pretrainedVectors标志初始化训练,来自输入文件的值被用来初始化输入层向量。如果未指定,则创建一个维度为 MxN 的矩阵,其中M = MAX_VOCAB_SIZE + bucket_sizeN = dimbucket_size对应于分配给所有 ngram 令牌的数组总大小。通过-bucket标志设置,默认设置为 2000000。

通过 ngram 文本的数字散列(相同的散列函数)初始化 ngram,并在对应于MAX_VOCAB_SIZE + hash的位置将该散列数的模拟合到初始化的矩阵上。注意,在 ngrams 空间中可能会有冲突,而对于原始单词来说冲突是不可能的。这也会影响模型性能。

Dim 代表训练中隐藏层的尺寸,因此也代表嵌入的尺寸,通过-dim标志设置。默认情况下,该值设置为 100。矩阵初始化为 0 和1/dim之间的均匀实数分布,在单位立方体中是均匀的。

培养

一旦输入和隐藏向量被初始化,多个训练线程被启动。线程数量由-thread arg 指定。所有的训练线程都有一个指向输入和隐藏向量矩阵的共享指针。所有线程都从输入文件中读取,用读取的每个输入行更新模型,即批处理大小为 1 的随机梯度下降。如果遇到换行符,或者如果我们读到的字数达到了最大允许的行数,输入行将被截断。这是通过MAX_LINE_SIZE设置的,默认为 1024。

连续单词包和 Skip-gram 模型都更新大小在 1 和由-ws确定的值之间的随机均匀分布的上下文的权重,即窗口大小是随机的。

损失函数的目标向量通过所有输入向量的归一化和来计算。输入向量是原始单词以及该单词的所有 n 元语法的向量表示。计算损失,设置前向传递的权重,前向传递一路传播回反向传播传递中输入层的向量。在反向传播过程中发生的输入向量权重的这种调整允许我们学*最大化同现相似性的表示。学*率-lr影响每个特定实例对权重的影响程度。

Topography of unsupervised Skip-gram fastText model

模型输入权重、隐藏层权重以及传入的参数保存在。bin 格式和-saveOutput标志控制是否也输出一个. vec 文件,该文件包含 word2vec 文件格式中隐藏层的矢量。

我希望这个演练有助于阐明 fastText 的内部工作原理。我个人在使用这个库方面取得了很多成功,并强烈推荐它来满足您的嵌入需求。在我的下一篇文章中,我将讨论我添加到 fastText 中的一些附加功能,以概括它的功能。敬请期待..

承认

非常感谢Giovanni Fernandez-kin cade对这篇文章的反馈。

数据科学家最喜欢的 MOOCs

原文:https://towardsdatascience.com/favorite-moocs-for-data-scientists-10b16a950e36?source=collection_archive---------9-----------------------

我最*在 LinkedIn 上询问了每个人最喜欢的数据科学 MOOCs。这个帖子引发了很多关于人们有经验的课程(和课程平台)的讨论。某些课程被多次提及,显然是由机构群体推荐的。

帖子是这样的:

最大的收获:

基里尔·叶列缅科或安德鲁·吴的作品受到高度评价并被频繁提及。

所以我决定重温这篇文章,并汇总分享的信息,以便那些正在寻找优秀课程来构建数据科学工具包的人可以使用这篇文章作为起点。

你会注意到在 Coursera 下面有最多的提及,这主要是由吴恩达的机器学*课程(仅该课程就有 11 次提及)和 Python For Everybody (6 次提及,也在 Coursera 上)推动的。同样,Kirill 在 Udemy 上有很多课程都被多次提及,这也让 Udemy 在评论中被多次提及。(课程链接在本文靠下)。

两个空白是由于一个特定的课程。这是斯坦福大学的一门课程。不幸的是,我无法在网上找到它。也许有人可以在评论中发布在哪里可以找到该课程?

更新! Tridib Dutta 和 Sviatoslav Zimine 在这篇文章发布后几分钟内联系了我们,分享了斯坦福课程的链接。

还有一个推荐的 Edx 课程,目前没有,“从数据中学*(机器学*入门)”,所以我不会链接到那个课程。

如果你熟悉 MOOCs,许多平台都允许你旁听课程(例如免费观看视频和阅读材料),所以如果你不担心测验分数,一定要去看看这个选项。

要想上榜,一门课程必须得到至少两个人的推荐(涵盖 SQL 和机器学*基础数学的课程除外,因为这些课程没有被提及很多,但主题非常重要:)。

我整理了按主题提到的课程的链接。当课程的描述被方便地放在网站上时,它们被包括在内。

免责声明:这些链接中的一些是附属链接,这意味着如果你购买课程,我会收到佣金,而不需要你支付任何费用。

结构化查询语言

  1. “saber metrics 101:棒球分析入门—Edx”“saber metrics、棒球分析、数据科学、R 语言和 SQL 入门。”
  2. “数据基础”——uda city“通过学*使用 Excel、SQL 和 Tableau 操作、分析和可视化数据,从今天开始培养您的数据技能。”

数学

《面向机器学*专业化的数学》——Coursera《面向机器学*的数学》。了解数据科学和机器学*应用的必备数学知识。”

(舞台上由人扮的)静态画面

“Tableau 10 A-Z:数据科学实践 Tableau 培训!”— Udemy (这是一门基里尔·叶列缅科的课程)

稀有

  1. “R 编程”——Coursera“本课程涵盖了统计计算中的实际问题,包括 R 编程、将数据读入 R、访问 R 包、编写 R 函数、调试、分析 R 代码以及组织和注释 R 代码。”
  2. “R Programming A-Z:R For Data Science With Real practices!”— Udemy (这是一门基里尔·叶列缅科的课程)在 R 和 R 工作室学*编程。数据分析、数据科学、统计分析、软件包、函数、gg plot 2”

计算机编程语言

  1. “Python for Everybody Specialization”——Coursera“将使用 Python 编程语言介绍基本的编程概念,包括数据结构、网络应用程序接口和数据库。”
  2. “学* Python”——code academy

用于数据科学的 Python

  1. “Python 专业化的应用数据科学”——Coursera
  2. “用于数据科学的 Python”——Edx“学*使用强大的开源 Python 工具,包括 Pandas、Git 和 Matplotlib,来操作、分析和可视化复杂的数据集。”

机器学*

  1. “机器学*”——Coursera(这是吴恩达的课程)
  2. “机器学* A-Z:数据科学中的实践 Python&R”——Udemy(这是一门基里尔·叶列缅科的课程)
  3. “Python for Data Science and Machine Learning boot camp”——Udemy“了解如何使用 NumPy、Pandas、Seaborn、Matplotlib、Plotly、Scikit-Learn、Machine Learning、Tensorflow 等等!”

深度学*

“深度学*专业化”——Coursera(这是一门吴恩达课程)在五门课程中,你将学*深度学*的基础,了解如何构建神经网络,学*如何领导成功的机器学*项目。您将了解卷积网络、RNNs、LSTM、Adam、Dropout、BatchNorm、Xavier/He 初始化等等。”

没有人对任何特定的课程有什么不好的看法,但是,有些人确实对平台有偏好。你可以自己在这里阅读原帖。

我希望这些课程能帮助你理清过多的选择(太多了!)我希望你能学到一些可以在职业生涯中应用的新知识。快乐学*!

如果你在寻找数据科学领域工作的帮助,或者需要简历方面的帮助,我想推荐你去找凯尔。我很了解凯尔,这是他的人生目标!。他帮助数据科学家获得数据科学职位。你可以在这里观看他谈论这个话题的视频。

原载于 2018 年 8 月 1 日【datamovesme.com】

恐惧因素:枪支与恐怖主义

原文:https://towardsdatascience.com/fear-factor-guns-vs-terrorism-e6b92ebb576d?source=collection_archive---------5-----------------------

几周前,我和一位在美国的家人(我是美国公民,目前居住在德国)聊天,我们讨论了最*袭击美国的一连串天气和其他自然灾害。当我们快完成的时候,他评论道,“虽然这里很疯狂,但我会把它放在任何一天,而不是你正在处理的事情。”

我对上下文有点困惑,问他指的是什么灾难。他澄清道,“不,我指的是所有开着卡车冲进人群,在火车上引爆炸弹的恐怖分子。”

啊,对了。自从我搬到欧洲后,这个故事我听了很多次,但一直不太明白。尽管恐怖袭击发生时毫无意义且令人毛骨悚然,但现实是,与其他死亡原因相比,欧洲和美国并没有太多与恐怖袭击相关的死亡。我确信美国的暴力犯罪率远远高于恐怖主义造成的伤亡率,于是回答说:“你知道,美国每天死于枪击的人数比欧洲每年死于恐怖主义的人数还要多。你应该害怕的是走出你的前门。”

我们同意保留不同意见,谈话友好地结束了。然而,这让我思考:我是对的吗?一个欧洲人受到恐怖分子威胁的风险是否比一个美国人受到另一个持枪美国人威胁的风险小?如果不是,为什么来自恐怖主义的恐惧因素比枪支暴力大得多?

第一个问题听起来像是一个非常直接的数据分析练*,所以我拿出一个 Jupyter 笔记本来探索,抓取了一些数据并挑战了这个假设。

为了分析恐怖主义,我选择了全球恐怖主义数据集(GTD) ,这是过去半个世纪以来全球恐怖主义的一个非常全面的集合。枪支暴力数据集更难获得,部分原因是美国步枪协会(NRA)成功的游说努力阻止了政府对枪支暴力的研究,所以我选择与疾病控制中心 多种死亡原因数据集合作,该数据集对美国所有死亡进行分类,包括枪支死亡。GTD 和疾病预防控制中心设定的完全重叠的最*一年是 2015 年,所以我选择这一年作为重点。

恐怖主义

让我们先来看看恐怖主义。在世界范围内,*十年来恐怖主义活动激增,其中绝大多数来自中东、非洲和南亚。

如果我们放大到这十年,只看美国和西欧,这就是我们看到的情况:

当你看上面两张图中 Y 轴的刻度时——世界其他地方是几万,西方是几十——很明显,在欧洲或美国比世界其他地方安全得多(安全两个数量级)。如果你生活在西方,这是个好消息,但对其他人来说就不是了。

尽管自 2015 年底以来,欧洲与恐怖主义相关的死亡人数相对激增,但欧洲的人口也是美国的两倍左右。为了更好地了解这与美国的死亡人数相比如何,我们需要看看每百万人的死亡人数。以下是我们得到的结果:

2015 terror deaths EU: 171.0 total, or 0.23 per million residents

因此,在 2015 年,一个欧洲人死于恐怖袭击的概率大约是 400 万分之一。听起来很小。出于好奇,我研究了这与美国本土的恐怖袭击有何不同:

2015 terror deaths US: 44.0 total, or 0.14 per million residents

我讨厌写这个,因为一些傻瓜会断章取义地引用它,但在 2015 年,欧洲人成为恐怖主义受害者的概率大约是美国人的两倍。但这就像说一个人被熊杀死的可能性是被鲨鱼杀死的两倍——两个数字都很低,差异在很大程度上是无关紧要的,因为两者都属于同一个“极不可能”的桶。(事实上,死于鲨鱼或熊袭击的几率与死于恐怖分子袭击的几率相差不远,但那是另一篇文章了。)

让我们看看问题的另一面。

美国的枪支死亡(第一轮)

好吧,这和在美国死于枪下的风险相比如何?以下是 2015 年美国枪支死亡人数的详细分析:

suicide     22060
homicide    13018
accident      489
other         284

这与*年来被引用的数字和比率相一致——每年大约有 3.5 万人死于枪支,其中约 1/3 是杀人,约 2/3 是自杀——所以没什么好惊讶的。

因为恐怖袭击本质上是谋杀,所以让我们排除自杀,只看每百万人中的枪支谋杀,并将其与恐怖威胁进行比较:

2015 gun homicides US: 13018 total, or 40.29 per million residents

因此,以每百万居民约 40 起持枪杀人案计算,美国人死于持枪杀人案的可能性是欧洲人死于欧洲恐怖分子的约 175 倍。嗯。

但是……可以说这不是一个公平的比较。我听到过一些类似这样的观点:“恐怖分子倾向于随机袭击,杀害无辜的、毫无防备的受害者。美国的枪支暴力大多发生在贫困的市中心,涉及帮派和罪犯。换句话说,美国的枪支暴力是关于‘他们’,我们不是‘他们’,所以这种比较并不适用。”(注:我不赞同这种想法,我完全了解种族和社会经济的污名化;这是我的观察。)

那么,我们如何使分析适应“不是他们”的模糊概念呢?

美国的枪支死亡(第二轮)

让我们看看在深入研究疾控中心的数据时能发现什么…

从绝对数字来看,美国男性成为枪支暴力受害者的可能性要高出 6 倍,而从百分比来看,男性和女性的根本原因相似,自杀是主要原因。

种族怎么样?

这里的差异是惊人的——白人数量最多,其次是黑人和西班牙裔,但自杀占白人枪支死亡的绝大多数(尽管这不是按总人口的百分比标准化的)。让我们以百分比为基础查看这些相同的数字,以获得不同的视角:

不同种族群体在意图上的显著差异在这里显而易见:黑人面临着被杀的巨大风险,而白人则面临着自杀的风险。

好吧,也许教育在其中扮演了一个角色,或者是直接的,或者是社会经济地位的代表:

同样,这也是一个很强的相关性。

现在让我们看看年龄。这里有两种观点,一种根据意图,另一种根据种族:

(注意:50 岁左右的增长是由于白人男性自杀率的上升…记住,记住 11 月…)

虽然悲剧,“自杀”、“事故”和“原因不明”事件与此分析无关,因此我们将排除那些专门关注杀人的事件,并从这个角度重新审视年龄与种族的关系图:

显而易见,美国的枪支死亡严重倾向于年轻的黑人和没有大学学位的西班牙裔男性。显然,这是一件非常糟糕的事情,也是美国需要解决的一个大问题。也就是说,我听到的大多数“欧洲如此危险”的担忧都来自年龄较大、受过大学教育的白人,因此在这次分析中,我将筛选 30 岁以上、拥有大学学位的白人:

2015 gun homicides US (white, over 30, college degree): 392 total, or 1.21 per million residents

所以,即使这个有限的人口统计数据仍然是~ 5X 在美国死于枪击的可能性比欧洲人死于恐怖袭击的可能性更大。

结论

好了,我们来回顾一下:

  • 2015 年,欧洲一个人被恐怖分子杀害的几率远低于百万分之一。
  • 同年,一个美国人被另一个美国人用枪杀死的几率在百万分之一到百万分之四十之间(取决于你把谁包括在分析中)。

在这一点上,我想我可以非常自信地说我最初的假设是正确的:一个美国人被另一个美国人用枪杀死的风险比一个欧洲人被恐怖分子杀死的风险更高。

在探索这些数据的过程中,我不得不承认我对我发现的一些事情感到惊讶,并希望进一步探索它们,例如:

  • 世界其他地方的恐怖主义是怎么回事?我承认我不知道每年有成千上万的人被恐怖分子杀害。
  • 枪支和恐怖主义的伤亡率与其他可预防的死亡相比如何?
  • 为什么恐惧因素与实际风险的现实正交?

敬请关注。

(注 1:有兴趣可以看看 上分析的代码这个 Kaggle 内核 。)

(注 2:这是博客【http://www.dancripe.com对原文章的更新转载。)

机器学*时代的恐惧

原文:https://towardsdatascience.com/fear-in-the-age-of-machine-learning-87ee33b5b264?source=collection_archive---------7-----------------------

这是我关于人工智能和大数据系列的第三篇文章。最*完成了这个主题的博士学位,我计划涵盖几个与人工智能相关的有争议的话题,以及我为公司实施这项技术所做的工作。不用担心,没有违反保密协议,也没有公司机密通过这些帖子泄露出去。

这篇特别的文章是关于不确定性的。这是关于在面对机器学*对科技公司的统治时承认并拥抱恐惧。

我们所知道的< What we don’t

The 悲观主义者说“一切都很糟糕,不可能变得更糟了”,而乐观主义者说“哦,是的,会的。”(白宫风云第五季第 21 集)

我对悲观主义持乐观态度。我必须这样。大多数创业公司都会失败。在加拿大,我们有一个“普通”规模公司的口头禅:中小型企业(SMEs)。这些中小企业通常不到 100 名员工。精益阶段门和其他快速失效方法已经对这些试图生存的中小企业构成了挑战。在冒险创办或发展一家小型科技企业时,已经有足够多的恐惧了。例如,获得种子资金并不容易。将机器学*(ML)添加到组合中确实打乱了许多早期公司的计划,这些公司现在需要了解人工智能以及成功的标准蛋糕烘焙配方(云、SaaS、REST 等)。等等。)

不要说理解它是如何工作的,许多中小企业根本不明白机器学*有什么好处,而他们的利益相关者要求知道他们将如何抵御即将到来的人工智能机器大军。

假装我们有权力帮助我们感到安全。这是泻药。但由于人工智能的冲击,中小企业的处境将变得艰难。让我们来谈谈这些公司在 2 年内面临的情况。

海啸到达海岸

对 ML 服务的需求远远超过了供给,并且大多数 ML 服务的购买者对于在组织内哪里最适合应用 ML 缺乏了解。未来几年将会看到大量的创造性破坏,以及科技巨头为保护其寡头垄断而进行的收购。我喜欢市场分析师用方这个词来谈论这些巨头(脸书、亚马逊、网飞、谷歌)。如果你是一个典型的 100 人公司,动态对你不利。高素质的数据科学家很难找到,因为他们正在大量穿梭于承诺大笔股权的初创公司或提供大笔现金的大巨头之间。你坐在这里,夹在中间,对你的中小企业没有什么好的选择。当然,两年后情况会稳定下来。更多的数据科学家和工程师正在努力填补这个空白,并将在某个时候上线…但现在呢?

有一种有害的贪婪对恐惧的计算,甚至对于像我这样的顾问,他们进入公司来填补这个资源缺口。供求定律意味着低供给和高需求的交叉会推高价格,因此顾问也更喜欢与成熟的公司或有资金支持的初创公司合作。学术界没有给中小企业多少喘息的机会。公司直接进入大学招聘人才,与大学合作进行非研究核心开发对一个项目来说不是好兆头。大学项目的运行时间可能比预期的要长,并且不能保证成功。如果项目失败,你拿不回你的钱。学生来来去去。事情发生了。

从公司和工人的角度来看,让我们来看看技术方面的事情。不确定性也困扰着数学机器学*世界。你可能没有注意到机器学*如何编码不确定性的一些奇怪之处。看看下面这张来自 Adrian Rosebrock 优秀的 pyimagesearch 博客的图片。

What’s wrong with this picture?

这里有点不对劲。有些不太对劲。你看到了吗?如果你是科学家,或者经常处理不确定性,你会注意到预测是标量的。没有误差线。因此,像“我看到一个足球,有 93%的把握”这样的预测应用到现实生活中就变得荒谬了。比如“99%的降雨概率”的预测,当你发现真正的降雨概率是“99 25%的降雨概率”或者可能是“99 1%的降雨概率”时,可信度会降低吗?不过,这也不全是坏消息。Yarin Gal 和其他人最*在解决机器学*中的这个问题方面做了一些令人兴奋的工作。更多见此处

结论

不确定性是当今的主流。它不会消失。它会一直留在这里。随着我们都*惯于广泛采用 ML,公司、人甚至机器学*模型都需要更好地量化、容忍和规划不确定性。

祝我们所有人好运!

-丹尼尔
丹尼尔@lemay.ai ←打个招呼。
LEMAY . AI
1(855)LEMAY-AI

您可能喜欢的其他文章:

Spark 2.3.0 简化了特征编码—第 2 部分

原文:https://towardsdatascience.com/feature-encoding-made-simple-with-spark-2-3-0-part-2-5bfc869a809a?source=collection_archive---------8-----------------------

"人工智能的关键一直是表现."~杰夫·霍金斯

这是最新的 Spark 2.3.0 特性编码技巧系列的第 2 部分。请参考之前的第一部分,因为那里的很多概念在这里都会用到。如前所述,我假设您对 spark 及其数据类型有基本的了解。如果没有,spark 有一个惊人的文档,如果能通过就太好了。关于 spark 本身的背景,请点击这里查看摘要

我们在之前的文章中讨论过分类编码。在本帖中,我们将主要关注数字特征的各种转换。对于这个例子,我将使用葡萄酒数据集。(我这里有一个小帖子,看看如何在 databricks 上做到这一点。)

假设数据现在已经上传到 databricks 上(或者您喜欢的任何地方),让我们来看看数据。

**val** wineData = spark.read.table("winequalityreds_csv")
.**withColumnRenamed**("_c0", "ID")
.**withColumnRenamed**("fixed.acidity", "fixed_acidity")
.**withColumnRenamed**("volatile.acidity", "volatile_acidity")
.**withColumnRenamed**("citric.acid", "citric_acid")
.**withColumnRenamed**("residual.sugar", "residual_sugar")
.**withColumnRenamed**("free.sulfur.dioxide", "free_sulfur_dioxide")
.**withColumnRenamed**("total.sulfur.dioxide", "total_sulfur_dioxide")**display**(wineData)//note: had to change the names here because spark had a problem with recognising "." as a column name.

Wine Dataset Preview

Spark 为我们提供了许多转换选项来标准化/规范化数据。我将在这里讨论标准缩放器、规格化器和最小最大缩放器。为了实现上述任何一种变换,我们需要将这些特征组合成一个特征向量。猜猜我们能在这里用什么?正确,矢量装配工!

让我们在应用变换之前将特征变换为特征向量。

**val** wineFeatures = wineData.columns.filterNot(_.contains("ID"))
                                   .filterNot(_.contains("quality"))**val** wineVectorAssembler = **new** VectorAssembler()
                      .setInputCols(wineFeatures)
                      .setOutputCol("features")**val** pipelineVectorAssembler = **new** Pipeline().setStages(Array(wineVectorAssembler))**val** result_df = pipelineVectorAssembler.fit(wineData).transform(wineData)result_df.show()

Note: the features vector generated here is a dense vector but if there are too many zeros then spark can change that to a sparse vector

标准缩放器:

应用这种转换的格式与我们在编码分类特征时看到的非常相似。它转换矢量行的数据集,将每个要素归一化为单位标准差和零均值。

然而,spark 中的标准化有一个警告。不幸的是,标准定标器不会在内部将稀疏向量转换为密集向量。因此,在运行此步骤之前,将稀疏向量转换为密集向量非常重要。虽然我们的数据帧没有真正的稀疏向量,但 spark 有时会将向量汇编器的输出更改为稀疏向量,这可能会给出一些不正确的结果,因为这不会真正引发错误。

它可以应用于我们的葡萄酒数据集,如下所示:

**import** org.apache.spark.ml.feature.StandardScaler//convert the sparse vector to a dense vector as a fail safe
**val** sparseToDense = **udf**((v : Vector) => v.toDense)
**val** result_df_dense = result_df.withColumn("features", sparseToDense($"features"))**val** scaler = new StandardScaler()
  .setInputCol("features")
  .setOutputCol("scaledFeatures")
  .setWithStd(true)
  .setWithMean(true)// Compute summary statistics by fitting the StandardScaler.
**val** scalerModel = scaler.fit(result_df_dense)// Normalize each feature to have unit standard deviation.
**val** scaledData = scalerModel.transform(result_df_dense)**display**(scaledData.select("features", "scaledFeatures"))

规格化器:

规格化器将每个向量规格化为单位范数。它接受参数 p(默认值=2 ),该参数指定用于归一化的 p 范数。当您的稀疏数据集包含不同比例的要素时,这通常很有用。不要忘记使用密集向量作为输入!

**import** org.apache.spark.ml.feature.Normalizer
**import** org.apache.spark.ml.linalg.Vectors// Normalize each Vector using $L^1$ norm.
**val** normalizer = new Normalizer()
  .setInputCol("features")
  .setOutputCol("normFeatures")
  .setP(1.0)**val** l1NormData = normalizer.transform(result_df_dense)**display**(l1NormData.select($"features", $"normFeatures"))

L1-Norm features

MinMaxScaler:

通过将每个要素缩放到给定范围来变换要素。这通常在数据遵循的分布不是高斯分布时使用,如标准定标器所假设的那样。

**import** org.apache.spark.ml.feature.MinMaxScaler
**import** org.apache.spark.ml.linalg.Vectors**val** scaler = new MinMaxScaler()
  .setInputCol("features")
  .setOutputCol("minMaxScaledFeatures")// Compute summary statistics and generate MinMaxScalerModel
**val** minMaxScalerModel = scaler.fit(result_df_dense)// rescale each feature to range [min, max].
**val** minMaxScaledData = minMaxScalerModel.transform(result_df_dense)

**display**(minMaxScaledData.select("features", "minMaxScaledFeatures"))

以上三种一般是最常用的特征缩放方法。我想通过一些其他的火花转换,当我们必须处理连续的特征时,我们可以这样做。

:

bucketizer 将一列连续特征转换为一列特征桶。存储桶由参数“splits”决定。由分割 x,y 定义的存储桶保存范围[x,y]内的值,除了最后一个存储桶也包含 y。此处的分割应该严格递增。如果上限/下限未知,则应提供无穷大作为最小值和最大值,以避免任何超出存储桶界限的异常。这并不处理 NAN 值,所以最好在此之前去掉这些值。

让我们将它应用于葡萄酒数据集中的一列。

**import** org.apache.spark.ml.feature.Bucketizer//define the splits that I want **val** splits = Array(0.0, 0.1, 0.2, 0.3, 0.5, 1.0) **val** bucketizer = new Bucketizer()
  .setInputCol("citric_acid") //example column from wineData
  .setOutputCol("bucketedFeatures")
  .setSplits(splits)// Transform original data into its bucket index.
**val** bucketedData = bucketizer.transform(wineData)**display**(bucketedData.select($"citric_acid", $"bucketedFeatures"))

n buckets defined for n+1 splits

分位数离散化:

这非常类似于 bucketizer,在您没有真正定义拆分时非常有用。它也可以处理 NANs。当遇到时,有一个“handleInvalid”设置器来选择移除 NAN 或引发异常。如果设置了 nan,那么将创建一个特殊的桶来处理它们。

将此应用于 wineData 中的相同柠檬酸列

**import** org.apache.spark.ml.feature.QuantileDiscretizer**val** discretizer = new QuantileDiscretizer()
  .setInputCol("citric_acid")
  .setOutputCol("quantileBins")
  .setNumBuckets(10)
  .setHandleInvalid("skip")**val** result = discretizer.fit(wineData).transform(wineData)
**display**(result.select($"citric_acid", $"quantileBins"))

其他有趣的变形金刚,我不打算做太多的细节(因为它们非常简单,在文档中有很好的解释),是二进制化器估算器、、多项式展开PCA 。请随意建议在评论区添加一些例子,我很乐意添加一些。我会谨慎对待估算者,因为估算缺失值是一个需要彻底调查的过程。缺少数据并不意味着丢失数据,我们应该始终小心不小心在数据中添加了某种偏差。

另一个我没怎么合作过的变形金刚,但在互动中似乎很有趣。除了输出更多的是输入向量的叉积之外,它的功能类似于向量汇编器。这可能会在我们的数据中产生不同的特征交互。我将在实际管道中对此进行更多的评估,以了解使用它的好处,并更新本文。如果我们将它应用到我们的数据集,我们将会看到:

**import** org.apache.spark.ml.feature.Interaction
**import** org.apache.spark.ml.feature.VectorAssembler**val** assembler1 = new VectorAssembler()
  .setInputCols(Array("fixed_acidity", "volatile_acidity", "citric_acid")) //taking features indicating acidity
  .setOutputCol("vec1")**val** assembled1 = assembler1.transform(wineData)**val** assembler2 = new VectorAssembler()
  .setInputCols(Array("free_sulfur_dioxide", "total_sulfur_dioxide")) //taking features indicating sulfur content
  .setOutputCol("vec2")**val** assembled2 = assembler2.transform(assembled1).select("ID", "vec1", "vec2")**val** interaction = new Interaction()
  .setInputCols(Array("ID", "vec1", "vec2"))
  .setOutputCol("interactedCol")**val** interacted = interaction.transform(assembled2)**display**(interacted)

我希望这篇文章对开始使用 spark 进行特性转换有所帮助。您可以为您的管道构建的定制转换的类型是无限的,spark 提供了一个可伸缩的、快速的和几乎可靠的( 😃 )基础设施来做到这一点。请提出你认为有助于这篇文章更好的改进意见。我将很高兴相应地更新。

我将在下一篇文章中用 kaggle 数据集处理特征提取器和端到端管道。快乐阅读!!

ps:如果你喜欢,请鼓掌!帮助我知道它帮助了你,提升了文章!

Spark 2.3.0 简化了特征编码—第 1 部分

原文:https://towardsdatascience.com/feature-encoding-with-spark-2-3-0-part-1-9ede45562740?source=collection_archive---------4-----------------------

“每一次解码都是另一次编码”~戴维·洛奇

正如在之前的博客中提到的,接下来的几篇博客将关注特性工程。机器学*项目中的许多工作都归结于此。不管我们喜不喜欢,我们都要花 95%的时间来生成特征向量,这将使我们的数据发挥最大作用。

Spark 为我们如何优化这一流程提供了很多余地。我将简要介绍一下我发现有用的编码类型,然后更详细地讨论使用大数据时可能会遇到的问题。出于这篇博文的目的,我假设您对 spark 函数及其数据类型有基本的了解。如果不是,为了合理的背景理解,请参考此文档

管道:

我将从管道开始,因为它使您的特性转换更加容易。管道背后的主要概念是结合复杂的算法和转换来创建工作流。假设您必须对一些分类特征进行热编码,并运行 xgboost 模型。您应该采取以下步骤。

  • 索引类别特征
  • 编码成一个热点向量
  • 集合成一个特征向量
  • 火车模型

这四个步骤可以作为一系列管道阶段运行,以形成工作流。数据预处理部分将是一组适合输入数据帧的转换器(如 one hot 编码器)和估算器。可以按如下方式创建管道对象:

Note: the uid here “myPipeline” is optional

让我们看看如何包含阶段并使管道模型适合输入数据帧。我们可以使用 spark 中称为字符串索引器的一种特性索引方法来理解字符串索引器和管道。

字符串索引器:

字符串索引器将一列字符串标签/类别编码为一列索引。索引的排序是基于流行度完成的,范围是[0,numOfLabels。让我们举一个简单数据帧的玩具例子。

Toy Data Frame

要使用字符串索引器索引类别,您需要执行以下操作:

Transformed Dataframe

请注意如何指定希望列输出被调用的名称。当您拥有包含大量需要编码的分类特征的大数据时,这非常有用。使用一点 scala 和 spark magic,这可以在几行代码中完成。让我们将另一列追加到我们的玩具数据帧中。

Toy Dataframe with a extra column

现在,一点火花管道和 scala 魔术…

并且如下所示的结果数据帧具有颜色和类别索引。整洁!这里的编码特征可以被设置为流水线阶段。然后,可以将其与输入数据进行拟合,以创建管道模型。我们使用这个模型将数据帧转换成如下所示的结果数据帧。

Note: You can retrieve the labels that were transformed by the string indexer by using the inverse called IndexToString.

让我们在 spark 中探索更多的编码方法,并在我们的管道中添加更多的阶段!

一个热编码器:

一个 hot 编码器将标签索引映射到至多具有单个 1 值的二进制向量表示。当我们需要使用分类特征但算法期望连续特征时,通常使用这些方法。spark one hot 编码器从字符串索引器获取索引标签/类别,然后将其编码为稀疏向量。这与通常的虚拟列创建风格略有不同。让我们在上面的例子中添加一个热编码器,看看它是如何工作的。

并且产生的数据帧…

在这一点上,对于那些不熟悉 spark 中矢量类型的人,我想指出上面数据帧中看到的稀疏矢量有 4 个不同的组成部分。第一个为 0 的分量表示它是一个稀疏向量。第二部分是关于向量的大小。第三个组件讨论填充向量的索引,而第四个组件讨论这些索引是什么值。这将截断向量,当您有非常大的向量表示时非常有效。如果你想看到它的密集向量表示,很容易使用 udf 来转换它。类似这样的操作示例如下:

Note: Spark has two vector types, org.apache.spark.mllib.linalg.Vector is also valid.

Both sparse and dense representations for category_vec

到目前为止,我们已经讨论了管道、分类特性的一些索引和编码。我们现在有两个索引和编码的特征。spark 中的大多数机器学*算法都期望一个编码的数字向量作为输入。为了做到这一点,我们使用了一种叫做矢量汇编器的东西。

向量汇编程序:

矢量组装器的工作是将原始特征和各种变换生成的特征组合成一个单一的特征矢量。它接受布尔型、数字型和矢量型输入。让我们修改前面的代码,将类别和颜色向量合并成一个特征向量。

Adding vector assembler to get the final feature vector

Resulting data frame

通常,当您希望在训练模型或对模型评分之前组合所有功能时,Vector assembler 将始终出现在您的工作流中。spark 中也存在的一种转换是矢量索引器。

向量索引器:

在我们的例子中,向量索引器将让我们跳过对分类特征进行编码的一个热编码阶段。该算法基于特征值自动进行推断,并进行变换以获得最终的特征向量。我们可以改变上面的例子,添加向量索引器如下:

Applying vector indexer to the string indexer’s output

Feature is the output of the assembler but the categorical features are not encoded yet. The vector indexer will do this and produces indexed_features as the final feature vector

以上几点评论。在不明显的情况下,直接使用字符串索引器的输出作为一个特征是没有意义的,因为如果苹果被索引为 1,而桔子被索引为 2,这可能被推断为苹果比桔子等级高,或者桔子比苹果大。这些都没有意义,因此我们不对它们进行编码。向量索引器做同样的事情,但是在后端。我通常更喜欢在自己的工作流程中直接使用 one hot 编码器。

到目前为止,我们只涉及了分类特性和一些关于管道和向量组装器的概念。在第二部分中,我将介绍一些数字特征编码的概念。我们还将涉及如何处理高基数分类特征。请随时提问或指出任何可能没有意义的事情。_

ps:如果你喜欢,请鼓掌!让我知道它帮助了你!

特征工程:宁滨的贝叶斯方法

原文:https://towardsdatascience.com/feature-engineering-bayesian-methods-for-binning-38d29a29bb88?source=collection_archive---------0-----------------------

任何数据科学难题中最关键的一块,或许也是最不迷人的一块:特征工程。这可能是漫长而令人沮丧的,但如果做得不好,它可能会给随后的任何建模或分析带来灾难。在这篇文章中,我希望揭示一种令人愉快的推理技术。

“应用机器学*”基本上是特征工程——吴恩达

将数据点“组合”在一个特征中是一种常见的策略。根据您对某个特性的期望,它可以从简单到复杂。考虑这样一种情况,您想要对具有大量不同值的要素进行热编码。基于每个不同值的分桶可能会给你留下很大的特征空间,并且将来的模型容易过度拟合。

那么怎么斗呢?已经提出了几种经验法则,包括斯科特法则克努特法则弗里德曼-迪康尼斯法则。这些方法的问题是它们都假设相同大小的箱,这是有问题的,并且不一定是最佳的。

是时候打破一些神话了。首先,数据点必须被分类以使它们有意义。第二,容器必须大小相等。第三,箱必须足够大,以便每个箱都有“统计上显著的”样本量。

许多人陷入了一种思维定势,认为减少噪音的最佳方式是平滑他们的数据,处理数据点的最佳方式是将数据存储起来。这种宁滨方法是有问题的,因为它们丢弃了信息并引入了对以下参数的依赖:(1)平滑度和(2)面元大小——并且指定参数是不好的。理想情况下,面元宽度应该仅取决于数据本身的属性,并且所得到的直方图不应该是先验固定的。

"一定有我们能做的事情!"我听见你哭泣,睁大眼睛,长着爱因斯坦般的头发。有。

贝叶斯块

贝叶斯块框架是一种自适应的方法,用于自动识别容器大小和划分数据。像其他非参数方法一样,贝叶斯块寻求一种通用的表示,避免提供先验限制的关于平滑度和形状的假设。

最佳分割是一个简单而有效的优化问题,其目标是最大化标准的定量表达,或者最小化误差测量。更重要的是,它能够计算全局最优值,而不仅仅是局部最优值。

在高层次上:给定一个任意但固定的大小的直方图,如左图所示,我们可以使用贝叶斯似然框架,该框架使用一个适应度函数,该函数仅取决于(1)每个块的宽度和(2)每个块内数据点的数量。最佳宁滨模式将是块配置,基于块之间的边缘(称为改变点,其将变化),具有最大的适应性。

注意:任何尝试扩大这种方法的暴力版本都是徒劳的。可能的配置数量按 2^N.的顺序呈指数级增长,如果不是因为动态编程技术的美丽,这是不可能的。

为了澄清,变化点是序列中经历突然转变的点,其一个或多个参数瞬间跳到新值。这里,我们将块适应度作为相对于块高度的最大相关可能性

适应度函数是对恒定水平表示块内数据有多好的方便测量,它也仅取决于该块内的数据,而不取决于除了指定块边缘位置的模型参数之外的模型参数。有不同的方法来定义适应度函数,其价值将根据最适合手头数据的方式而有所不同。

接下来本质上是数学归纳法。首先,我们对数据进行排序。接下来,我们从第一个数据单元格开始,并进行迭代。在每一步,增加一个单元,直到所有数据点都被分析完(为了优化,在下面链接的论文中描述了一个触发器,当检测到第一个变化点时停止)。在步骤 R,对于前 R 个单元,我们识别出最佳单元划分,在每个步骤存储最佳适应度(在称为最佳的数组中表示为 F(r ))和最佳划分的最后变化点的位置(在称为最后的数组中)。

Bayesian Blocks fitted to two concatenated, randomly sampled beta distributions

对于给定的单元位置 R,可以通过首先考虑前 R+1 个单元的所有分区的集合,并使用该集合中唯一可能是最佳的成员是第一个 R 的最佳分区,然后是 R+1 处的最后一个块的知识,来计算单元位置 R+1 处的最佳分区。这个划分的适合度是 F(r)的和。

现在存储了在范围 r 上可能是最优的所有分区的适合度。产生最优解的 r 值可以通过找到最大值 A(r)简单地计算出来。

迭代完所有点后,我们现在需要获取最佳分区的变点位置。为此,我们使用 last 数组中的最后一个值来确定最佳分区的最后一个变化点。我们“剥离”对应于最后一个块的部分并重复。

差不多就是这样。

谢谢你过来。要了解更多关于贝叶斯块的信息,一定要看看 Jeffrey D. Scargle 的原始论文和 Jake Vanderplas 的酷帖。

天文时间序列分析研究。不及物动词贝叶斯块表示法 —杰弗里·d·斯卡格尔

Python 中的动态编程:贝叶斯块

股票市场预测中的特征工程:量化市场与基本面

原文:https://towardsdatascience.com/feature-engineering-in-stock-market-prediction-quantifying-market-vs-fundamentals-3895ab9f311f?source=collection_archive---------5-----------------------

开发旨在预测股票是否会产生收益的算法的一个重要部分是确定股票的技术分析和市场分析的价值。即使是经营最好的公司也可能因为熊市而遭受损失,这就是为什么能够量化股票运动对其所属公司相对于整个市场的依赖性是有用的。

简而言之:股票是在自行波动还是在跟随市场波动?

这样做可以告诉我们,不要太看重特定于个股的基本面和技术面分析,而要更看重市场指标,如市场波动性和预期市场表现。那么,我们如何量化市场和基本面之间的紧张关系呢?

“从根本上说”,我们知道,当股市因牛市或熊市而波动时,它们往往会朝着同一个方向波动。这意味着,如果一篮子股票正朝着同一个方向移动,这种移动似乎更有可能与市场有关,而不是个股的投资潜力。因此,我们寻找一种方法来量化这个篮子中股票运动的异同。看起来计算方差是确定这些股票价格运动有多相似的直观方法。

第一步是决定我们的一篮子股票。我们将从标准普尔 500 中挑选 50 只股票。我们收集每日百分比变化数据,以相对于价格对变动进行标准化(即,我们获取价格变动并将其换算为股票价值)。下面是我们对 Quandl 的方法调用的屏幕截图,收集了这个历史百分比变化数据:

我们将做 50 个(每种股票一个)。每次调用都会给我们一个数据框架,显示被引用股票的调整后收盘价的每日百分比变化,我们会将所有这些合并到一个大的数据框架中。然后,我们将找到每一行的方差(每一行代表一天),这将告诉我们每天股票运动的方差。

鉴于我们正试图预测这些股票在未来 30 天内是否会上涨,我们有必要从更长远的角度来看股票相对于自身还是相对于整个市场的走势。因此,对这些差异值使用 30 天平均值似乎是谨慎的。这意味着分配给每一天的将是 50 只所选股票在过去 30 天内的移动的平均方差。这应该让我们对市场与基本面的紧张关系有一个更长远的看法。下面是我们数据的一个例子:

这表明这两周股票走势的方差低于总体方差,表明股票比总体更趋向于同一个方向。这种分析有助于我们权衡特定股票数据和特定市场数据的效用。

鉴于这种数据可以告诉我们如何查看其他数据,将它作为任何预测股票表现的算法的输入数据可能是有用的。它表征了市场中看涨/看跌条件的强度,可用于告诉投资者(或算法)是优先考虑市场数据还是股票数据。因此,数据科学家应该利用这种或类似的方法来量化这些条件。

在大型金融数据集上使用机器学*的特征工程

原文:https://towardsdatascience.com/feature-engineering-using-machine-learning-on-large-financial-datasets-8584dacd3a4d?source=collection_archive---------3-----------------------

对于在银行处理大型金融数据集的数据科学家和分析师来说,计算出信用违约或坏账的概率是他们所做的最重要的活动之一。这一行动的重要任务是确定银行的信贷政策、风险管理和信贷操作,这是银行向潜在客户销售信贷产品的真正竞争优势。

然而,对于大型数据集,对于分析师来说,这变成了一个非常基于判断的判断(并且通常是不准确的),会对下游财务产生影响。此外,如果不消除决策的非关键特征,最先进的机器学*算法也会变得无能为力,因为它们被提供了“无意义”的数据。

最*的机器学*范例提供了使用内置算法的解决方案,这些算法可以帮助数据分析师为销售和运营团队提供业务见解,以便在客户获取和活动管理方面采取主动行动。

以下流程是使用来自 Lending Club 的真实客户数据(公开信息)开发的。当然,这不包括客户的机密信息,如姓名、地址、联系方式和社会保障信息。但是,出于此活动的目的,我们不需要任何机密的客户信息。公共数据集中提供的特征应该足够好,足以让我们提出我们想要的见解。

我们将使用 Jupyter Notebook 编写一个简短的 python 程序,涵盖以下活动——

  • 数据采购
  • 数据探索和清理
  • 特征重要性
  • 绘图和可视化

让我们开始吧。

第一步——获取数据

我们可以使用公共领域中的 Lending club 数据,这些数据包含真实世界的贷款和信用违约数据点。数据(csv 文件)下载完成后,可以上传到 Jupyter notebook 的相应文件夹中。

注:如果没有 Jupyter 笔记本,强烈推荐下载/安装和 anaconda(https://www.anaconda.com/download/)

步骤 2 —数据探测&清理

导入必要的包并读取数据集

删除不相关的字段

做一些基础的探索

作为这一领域的人,雇佣期是信用管理的关键因素之一,雇佣期的数据是完全混乱的,这是很直观的。我们需要清理一下。

类似地,清理条款和利率的可用信息。

使用 dummy 将关键分类值转换为相关数字

现在开始处理目标特性,即“贷款状态”。除了“全额付款”和“当前”客户,我们可以让其余所有客户处于拖欠状态,因此具有更高的违约倾向。

利率领域似乎完全混乱了,我们需要清理一下。

现在看起来我们有了一个相当干净的数据,我们可以在这个数据的基础上用算法得到一些下降的结果。但在此之前,最好以 csv 格式备份干净的文件,以供将来参考和离线报告。

让我们做一些基本的探索,使用一些绘图技术来研究数据属性。

plt.hist(df['loan_amnt'],histtype='bar', align='mid', color='red', label=None, stacked=False, normed=None,data=df)

plt.figure(figsize=(10,6))
df[df['loan_status']==0]['int_rate'].hist(alpha=0.5,color='blue',bins=30,label='loan_status=0')
df[df['loan_status']==1]['int_rate'].hist(alpha=0.5,color='orange',bins=30,label='loan_status=1')
plt.legend()
plt.xlabel('int_rate')

步骤 3 —使用随机森林的重要特性

这是本文中最重要的一步,它强调了使用随机森林找出最重要的分析特性的技术。这对于评估机器学*任务中特征的重要性非常有用,尤其是当我们处理大量特征时。换句话说,我们可以说这是数据清理的一个高级阶段,删除那些对我们的目标特性没有任何意义的非必要数据。

#### Use Random Forests for Plot the Importance of Featuresprint(__doc__)from sklearn.datasets import make_classification
from sklearn.ensemble import ExtraTreesClassifierX=np.array(df.drop('loan_status',axis=1))
y=np.array(df['loan_status'])# Build a forest and compute the feature importances
forest = ExtraTreesClassifier(n_estimators=250,
                              random_state=0)forest.fit(X, y)
importances = forest.feature_importances_
std = np.std([tree.feature_importances_ for tree in forest.estimators_],
             axis=0)
indices = np.argsort(importances)[::-1]# Print the feature ranking
print("Feature ranking:")for f in range(X.shape[1]):
    print("%d. feature %d (%f)" % (f + 1, indices[f], importances[indices[f]]))Feature ranking:
1\. feature 20 (0.124970)
2\. feature 24 (0.074578)
3\. feature 23 (0.070656)
4\. feature 19 (0.067598)
5\. feature 18 (0.066329)
6\. feature 16 (0.055700)
7\. feature 17 (0.054894)
8\. feature 25 (0.053542)
9\. feature 0 (0.044944)
10\. feature 1 (0.044642)
11\. feature 2 (0.044474)
12\. feature 4 (0.043504)
13\. feature 105 (0.027864)
14\. feature 3 (0.019966)
15\. feature 106 (0.015091)
16\. feature 21 (0.015081)
17\. feature 104 (0.012508)
18\. feature 121 (0.012266)
19\. feature 107 (0.008324)
20\. feature 111 (0.006282)
21\. feature 22 (0.006171)
22\. feature 108 (0.005095)
23\. feature 110 (0.003950)
24\. feature 112 (0.003154)
25\. feature 49 (0.002939)
26\. feature 118 (0.002719)
27\. feature 109 (0.002582)
28\. feature 7 (0.002469)
29\. feature 77 (0.002402)
30\. feature 56 (0.002310)
31\. feature 72 (0.002296)
32\. feature 79 (0.002294)
33\. feature 55 (0.002291)
34\. feature 52 (0.002280)
35\. feature 66 (0.002280)
36\. feature 70 (0.002266)
37\. feature 6 (0.002249)
38\. feature 84 (0.002242)
39\. feature 65 (0.002238)
40\. feature 68 (0.002235)
41\. feature 9 (0.002233)
42\. feature 67 (0.002215)
43\. feature 58 (0.002212)
44\. feature 51 (0.002210)
45\. feature 71 (0.002208)
46\. feature 14 (0.002203)
47\. feature 15 (0.002199)
48\. feature 62 (0.002198)
49\. feature 69 (0.002175)
50\. feature 57 (0.002153)
51\. feature 60 (0.002148)
52\. feature 45 (0.002145)
53\. feature 5 (0.002130)
54\. feature 83 (0.002115)
55\. feature 12 (0.002114)
56\. feature 73 (0.002112)
57\. feature 82 (0.002102)
58\. feature 85 (0.002088)
59\. feature 50 (0.002071)
60\. feature 33 (0.002038)
61\. feature 10 (0.001880)
62\. feature 78 (0.001859)
63\. feature 59 (0.001828)
64\. feature 120 (0.001733)
65\. feature 63 (0.001660)
66\. feature 27 (0.001549)
67\. feature 32 (0.001509)
68\. feature 61 (0.001481)
69\. feature 117 (0.001448)
70\. feature 64 (0.001417)
71\. feature 11 (0.001401)
72\. feature 115 (0.001389)
73\. feature 8 (0.001366)
74\. feature 119 (0.001329)
75\. feature 13 (0.001158)
76\. feature 80 (0.001037)
77\. feature 100 (0.000837)
78\. feature 76 (0.000823)
79\. feature 97 (0.000781)
80\. feature 116 (0.000766)
81\. feature 113 (0.000741)
82\. feature 99 (0.000681)
83\. feature 81 (0.000679)
84\. feature 44 (0.000572)
85\. feature 26 (0.000486)
86\. feature 40 (0.000466)
87\. feature 102 (0.000458)
88\. feature 43 (0.000440)
89\. feature 42 (0.000400)
90\. feature 98 (0.000398)
91\. feature 38 (0.000395)
92\. feature 101 (0.000348)
93\. feature 41 (0.000345)
94\. feature 48 (0.000344)
95\. feature 35 (0.000343)
96\. feature 103 (0.000343)
97\. feature 39 (0.000342)
98\. feature 37 (0.000333)
99\. feature 34 (0.000305)
100\. feature 47 (0.000272)
101\. feature 53 (0.000272)
102\. feature 46 (0.000271)
103\. feature 36 (0.000264)
104\. feature 31 (0.000135)
105\. feature 54 (0.000131)
106\. feature 75 (0.000103)
107\. feature 30 (0.000052)
108\. feature 29 (0.000045)
109\. feature 74 (0.000034)
110\. feature 28 (0.000004)
111\. feature 114 (0.000000)
112\. feature 93 (0.000000)
113\. feature 91 (0.000000)
114\. feature 90 (0.000000)
115\. feature 89 (0.000000)
116\. feature 96 (0.000000)
117\. feature 88 (0.000000)
118\. feature 87 (0.000000)
119\. feature 95 (0.000000)
120\. feature 86 (0.000000)
121\. feature 94 (0.000000)
122\. feature 92 (0.000000)

根据大小,运行此步骤可能需要相当长的时间。所以有点耐心:-)

现在,所有 122 个特性都按照重要性降序排列&作为一名在这个领域工作的数据分析师/科学家,删除非关键特性应该不是一件难事。

步骤 4——绘图&可视化

尽管我们有一个重要功能的列表,但出于各种操作或管理目的,提供该列表的视觉确认总是可取的。

# Plot the feature importances of the forest
plt.figure()
plt.title("Feature importances")
plt.bar(range(X.shape[1]), importances[indices],
       color="r", yerr=std[indices], align="center")
plt.xticks(range(X.shape[1]), indices)
plt.xlim([-1, X.shape[1]])
plt.show()

因为我们有 122 个特征,所以上面的情节看起来又脏又丑。让我们试着探索 10 个最重要的特性,看看它是如何出现的

# Plot to show the most important 10 Featuresp = importances[indices][:10]
q=indices[:10]
plt.figure()
plt.title("Feature importances")
plt.bar(range(10), p,
    color="r", yerr=std[q], align="center")
plt.xticks(range(10), q)
plt.xlim([-1,10])
plt.show()

现在有了这个,我们或多或少可以假设特征 20 是决定贷款违约的最关键的特征。您可以根据您的组织的要求来处理该图。你也可以通过这种机制将功能的数量从“几千”减少到不到一百。这确实为银行提供了一个强大的选择,在数据被送入复杂的机器/深度学*算法之前,对数据进行优化。

感谢阅读——如果你觉得这篇文章有趣并想保持联系,你可以在 Twitter 上找到我 这里 LinkedIn

特征工程:机器学*的动力是什么

原文:https://towardsdatascience.com/feature-engineering-what-powers-machine-learning-93ab191bcc2d?source=collection_archive---------2-----------------------

如何从原始数据中提取特征用于机器学*

这是我们如何在功能实验室进行机器学*的四部分系列中的第三部分。整套文章是:

  1. 概述:机器学*的通用框架
  2. 预测工程:如何设置你的机器学*问题
  3. 特征工程(本文)
  4. 建模:教授一种算法进行预测

这些文章涵盖了应用于预测客户流失的概念和完整实现。project Jupyter 笔记本在 GitHub 上都有。(完全披露:我在 Feature Labs 工作,这是一家初创公司开发工具,包括 Featuretools ,用于解决机器学*的问题。这里记录的所有工作都是用开源工具和数据完成的。)

特征工程

常说“数据是机器学*的燃料”这并不完全正确:数据就像机器学*的原油,这意味着它必须被提炼为特征——预测变量——才能对训练模型有用。没有相关特征,就无法训练出准确的模型,无论机器学*算法有多复杂。从原始数据集中提取特征的过程称为 特征工程

特征工程过程

特征工程是机器学*管道中的第二步,它从第一步——预测工程——中获取标签次数,以及需要提炼的原始数据集。特征工程意味着为每个标签构建特征,同时根据标签的截止时间过滤用于特征的数据,以生成有效的特征。这些特征和标签然后被传递到建模,在那里它们将被用于训练机器学*算法。

The process of feature engineering.

虽然特征工程需要标签时间,但是在我们的通用框架中,对于仅对应于一个预测问题的特定标签,它不是硬编码的。如果我们为单个问题编写特征工程代码——就像传统的特征工程方法一样——那么每次参数改变时,我们都必须重复这个费力的步骤。

相反,我们使用像 Featuretools 这样的 API,可以为任何标签集构建特性,而不需要修改代码。这意味着对于客户流失数据集,我们可以使用完全相同的功能工程代码解决多个预测问题——预测每月、每隔一周或提前两个月而不是一个月的流失。

这符合我们机器学*方法的原则:我们 分段 流水线的每一步,同时标准化输入和输出。这种独立性意味着我们可以改变预测工程中的问题,而不需要改变下游的特征工程和机器学*代码。

使机器学*过程的这一步在预测问题上可重复的关键是自动化特征工程

自动化特征工程:更快地构建更好的预测模型

传统上,特性工程是手工完成的,利用领域知识一次构建一个特性。然而,这种手动过程容易出错,繁琐,必须对每个数据集从头开始,最终受到人类创造力时间的限制。此外,在依赖于时间的问题中,我们必须根据截止时间过滤每个特征,这很难避免会使整个机器学*解决方案无效的错误。

自动化特征工程通过一种可重用的方法从关系数据集中自动构建数百个相关特征,从而克服了这些问题。此外,该方法基于截止时间过滤每个标签的特征,创建丰富的有效特征集。简而言之,自动化特征工程使数据科学家能够在很短的时间内建立更好的预测模型。

Manual vs Automated Feature Engineering Pipelines.

自动化特征工程的动机

在解决了一些机器学*的问题后,很明显许多用于构建特征的操作在数据集上重复。例如,我们通常会找到某个事件的工作日—无论是交易还是航班—然后找到每个客户或航空公司一周中某天的平均交易金额或航班延误。一旦我们意识到这些操作不依赖于底层数据,为什么不将这个过程抽象成一个框架,可以为任何关系数据集构建特性?

这是自动化特征工程背后的思想。我们可以将相同的基本构建模块(称为特征原语)应用于不同的关系数据集,以构建预测变量。作为一个具体的例子,应用于客户交易的“max”特征原语也可以应用于航班延误。在前一种情况下,这将为每个客户找到最大的交易,在后一种情况下,将为给定航班号找到最长的航班延误。

Source: How Deep Feature Synthesis Works

这是抽象的思想的一个体现:通过构建利用许多问题共有操作的更高级工具,消除处理细节的需要——为每个数据集编写特定代码。

最终,自动化特征工程让我们作为数据科学家更加高效,因为我们不再需要重复繁琐的问题操作。

特征工程的实施

目前,唯一使用多表进行自动化特征工程的开源 Python 库是由特征实验室开发和维护的特征工具。对于客户流失问题,我们可以使用 Featuretools 为我们在预测工程中创建的标签时间快速构建功能。(完整代码可在本 Jupyter 笔记本中获得)。

我们有三个数据表数据:客户背景信息、交易和用户收听日志。如果我们使用手工特征工程,我们会头脑风暴,手工构建特征,例如客户交易的平均值,或者她去年周末的总支出。对于每个特征,我们首先必须在标签的截止时间之前将数据过滤到。相比之下,在我们的框架中,我们利用 Featuretools 在几行代码中自动构建数百个相关特性。**

我们不会讨论 Featuretools 的细节,但该库的核心是一种称为深度特征合成的算法,该算法堆叠了称为原语的特征工程构建块(像“max”或找到事务的“weekday”这样的简单操作),以构建“深度特征”。该库还会根据截止时间自动过滤要素数据。

有关 Featuretools 中自动化特征工程的更多信息,请参见:

Featuretools 需要一些后台代码来通过关系将表链接在一起,但是我们可以使用以下代码自动为客户流失创建特性(参见笔记本以了解完整的详细信息):

这一行代码为cutoff_times中的每个标签提供了 200 多个特性。每个特征是特征基元的组合,仅使用相关截止时间之前的数据构建。

Sample of features from Featuretools automated feature engineering.

Featuretools 构建的特性可以用自然语言来解释,因为它们是从基本操作中构建的。例如,我们看到特征AVG_TIME_BETWEEN(transactions.transaction_date)。这表示每个客户的平均交易间隔时间。当我们用标签的颜色来绘制这个图时,我们看到,频繁交易的客户的平均交易间隔时间似乎稍长。

Distribution of time between transactions colored by the label.

除了获得数百个有效的相关特征之外,在 Featuretools 中开发自动化的特征工程管道意味着我们可以对数据集的不同预测问题使用相同的代码。我们只需要将正确的标签时间传递给cutoff_times参数,就能够为不同的预测问题构建特征。

自动化特征工程意味着我们可以在通常完成一个问题所需的时间内解决多个问题。参数的改变意味着调整几行代码,而不是实现一个全新的解决方案。

为了解决不同的问题,而不是重写整个管道,我们:

  1. 调整预测工程代码以创建新的标签时间
  2. 输入要素工程和输出要素的标注时间
  3. 使用特征来训练和监督机器学*模型

(简单说明:特性工程代码可以使用 Dask 或 Spark 和 PySpark 并行运行。对于后一种方法,请参见功能实验室工程博客上的这本笔记本这篇文章。)

后续步骤

正如来自预测工程的标注时间流入特征工程一样,特征用作下一阶段的输入,即建模:训练算法根据特征预测标注。在本系列的最后一篇文章中,我们将看看如何使用机器学*模型来训练、调整、验证和预测,以解决客户流失问题。

作为预览,图中是机器学*调整后的精确召回曲线。(GitHub 上有完整的笔记本)

Precision Recall Curve for Machine Learning

结论

特征工程往往是用机器学*解决问题的一个单调乏味的方面,也是妨碍解决方案成功实施的错误来源。通过在通用机器学*框架中使用自动化特征工程,我们可以:

  • 为任何关系数据集自动构建数百个特征
  • 通过过滤截止时间的数据仅创建有效特征

此外,特征工程代码不是针对来自预测工程的输入而硬编码的,这意味着我们可以使用相同的精确代码为多个预测问题制作特征。在结构化框架中应用自动化特征工程,我们能够将特征工程从一个痛苦的过程转变为一个快速、可重用的过程,使我们能够解决许多有价值的机器学*问题。

如果构建有意义的高性能预测模型是您关心的事情,那么请联系我们的功能实验室。虽然这个项目是用开源的 Featuretools 完成的,但是商业产品为创建机器学*解决方案提供了额外的工具和支持。

特征重要性和前向特征选择

原文:https://towardsdatascience.com/feature-importance-and-forward-feature-selection-752638849962?source=collection_archive---------7-----------------------

一种模型不可知的特征选择技术

高维数据的处理非常具有挑战性。“高”意味着数千个维度,试着想象(即使你不能)一个 70k 维的空间。依赖欧几里德距离作为两点之间距离的度量的算法开始失效。这被称为维度的诅咒。K *邻和线性回归等模型很容易过度拟合高维数据,因此需要仔细调整超参数。因此,降维对于任何预测模型都是非常有利的。然而,人们不能随意丢弃特性,毕竟,数据是新的石油。已经开发了降维技术,其不仅有助于提取用于数据建模的区别特征,而且通过将高维数据转换成低维嵌入,同时保留原始可用信息的一部分,有助于在 2D、3D 或 nD(如果可以可视化的话)空间中可视化高维数据。在 PCA 的情况下,该信息包含在所提取特征的方差中,而 TSNE(T 分布式随机邻域嵌入)基于模型的复杂性,试图保存尽可能多的点的邻域信息。TSNE 是目前可用的最先进的技术。

这篇文章的重点是根据 KPI 选择分类问题中最有鉴别能力的特征子集。出于解释目的,选择分类准确性作为 KPI。我将使用机器学*的“hello world”数据集,你猜对了,非常著名的虹膜数据集

数据集由 150 行和 4 列组成。这是一个平衡的数据集,每个数据集都有 50 个实例。如果我们观察这三个类的花瓣长度和花瓣宽度的分布,我们会发现一些非常有趣的事情。

很明显,这两个是很好的鉴别器,可以将刚毛藻与杂色菊和海滨菊区分开来。我们希望找到准确预测输入花的类别的最重要的特征。

为了解决这个问题,我们将采用一种叫做正向特征选择的技术。这种功能上的减少提供了以下好处

  • 减少培训时间
  • 简化和可解释的模型
  • 减少过度拟合的机会,即较小的方差
  • 减少维数灾难的影响

向前特性选择的代码看起来有点像这样

代码非常简单。首先,我们创建了一个空列表,我们将向其中追加相关的特性。我们首先选择一个特性,并计算交叉验证数据集上每个特性的度量值。提供最佳度量值的特征被选择并附加到特征列表中。重复该过程,这一次使用两个特征,一个从先前的迭代中选择,另一个从已经选择的特征集合中不存在的所有特征集合中选择。为每组 2 个特征计算度量值,并且将提供最佳度量值的特征附加到相关特征的列表中。重复这个过程,直到我们得到所需数量的特征(本例中为 n )。因此,我们可以把特征集看作一个超参数。前向功能选择允许我们调整这个超参数以获得最佳性能。

理论讲够了,让我们看看这个算法是否与我们对 iris 数据集的观察一致。回想一下,花瓣的大小是区分海滨锦鸡儿和杂色花的很好的鉴别器。我们按照重要性降序排列这四个特征,下面是选择 f1_score 作为 KPI 时的结果

瞧啊。结果与我们的观察完全一致。正如代码中提到的,这种技术是模型不可知的,可以用于评估任何分类/回归模型的特征重要性。

时间复杂度呢?很明显,这取决于所使用的模型。线性模型比非线性模型花费更少的训练时间。为了简单起见,假设训练一个模型需要线性时间(在行数上是线性的)。这个假设在小 m 的情况下是正确的。如果数据集中有 r 行,那么运行上述算法所需的时间将是

这简化为

我们可以观察到,尽管这种方法是可靠的,但是运行起来需要相当长的时间。

正向特征选择到此为止。如果你知道更好的技术来提取有价值的特征,请在下面的评论区告诉我。

下次见,再见…

要素选择-相关性和 P 值

原文:https://towardsdatascience.com/feature-selection-correlation-and-p-value-da8921bfb3cf?source=collection_archive---------1-----------------------

本文正被移至我的 子栈发布 。这里 可以免费阅读文章 。这篇文章将于 2022 年 6 月 18 日被删除。

通常,当我们获得一个数据集时,我们可能会在数据集中发现过多的要素。我们在数据集中找到的所有特征可能都无法用于建立机器学*模型来进行必要的预测。使用某些特征甚至可能使预测变得更糟。因此,特征选择在建立机器学*模型中起着巨大的作用。

在本文中,我们将探讨两种方法,我们可以使用这些数据来选择正确的功能。

什么是相关性?

相关性是一个统计学术语,通常指的是两个变量之间有多接*线性关系。

例如,两个线性相关的变量(比如,x = 2y 时相互依赖的 xy )将比两个非线性相关的变量(比如,u = v2 时相互依赖的 u 和 v)具有更高的相关性

相关性对特征选择有什么帮助?

相关性高的特征更具线性相关性,因此对因变量的影响几乎相同。所以,当两个特征高度相关时,我们可以去掉其中一个特征。

p 值

在我们试图了解 p 值之前,我们需要了解零假设。

零假设是两个被测现象之间没有关系的一般说法。

测试(接受、批准、拒绝或否定)零假设——并由此得出结论,有或没有理由相信两种现象之间存在联系(例如,潜在的治疗具有可测量的效果)——是现代科学实践的中心任务;统计学领域给出了拒绝无效假设的精确标准。

来源: 维基百科

关于零假设的更多信息,请查看上面的维基百科文章

什么是 p 值?

本文其余部分已移至出版物 机器学*——科学、工程和 Ops 。这里 可以免费阅读整篇文章

文本分类中的特征选择

原文:https://towardsdatascience.com/feature-selection-on-text-classification-1b86879f548e?source=collection_archive---------7-----------------------

W 当建立机器学*模型进行文本分类时,有很多特征。因为特征是由词构成的,所以语料库的上下文更宽,特征的维度更高。当我为新闻分类、情感分析、网页分类等构建机器学*时,就会发生这种情况。

这些特征消耗大量的时间和计算能力来得到结果。例如,我需要半个小时的时间来获得情绪分析的结果,用 3 种算法进行基准测试,然后我想到了一些事情,是否可以只选择一些对某些类别重要的单词?

几十年来,特征选择一直是一个研究课题,它被应用于生物信息学、图像识别、图像检索、文本挖掘等许多领域。理论上,特征选择方法可以基于统计学、信息论、流形和粗糙集。

特征选择方法可以分为 4 类。过滤器、包装器、嵌入式和混合方法。过滤器对特征空间进行统计分析,以选择有区别的特征子集。另一方面,包装器方法选择各种特征子集,首先使用分类器识别然后评估。当嵌入方法时,特征选择过程被嵌入分类的训练阶段。混合方法利用了过滤器和包装器方法的优点。

实际上,Scikit-learn 上有一些可用的特性选择,如卡方检验、方差阈值和互信息。Sklearn 还提供了 SelectKBest,用于选择您想要进行的功能。但是我最*看了很多关于这个的论文。我发现了许多特征选择技术,尤其是过滤方法,我在研究中发现了 30 多种过滤方法,并且还在继续。

一些包装器方法的算法也发展起来解决这个问题。使用生物启发算法也称为元启发式算法被应用于该方法,例如遗传算法、粒子群优化、萤火虫算法、蚁群优化、人工蜂群等等。如果要应用包装器方法,可以使用inspired或者meta heuristic _ algorithms _ python

最*有很多论文改进了以前的特征选择,其中一些解决了冗余特征,一些解决了最大化相关性。这里是我想让你知道的最*的特征选择算法。

多元相对判别准则 [1]

而特征选择的目的是选择具有最大鉴别能力的紧凑特征子集,这要求在所选特征子集内具有与类别标签的高相关性和低冗余度。建议 MRDC 在评估过程中考虑相关性和冗余概念。关于 MRDC 是如何工作的,首先使用相对区分标准度量来计算每个特征的相关性,然后使用皮尔逊相关来计算特征之间的相关值。

最小冗余-最大新分类信息 [2]

有两组用于特征选择,一组集中于最小化冗余,另一组最大化新的分类信息。专注于最小化特征冗余的方法不考虑新的分类信息,反之亦然,从而导致选择具有大量新分类信息但高冗余的特征,或者具有低冗余但几乎没有新分类信息的特征。

Gao 等人提出了一种混合特征选择方法,该方法通过考虑两种类型的特征冗余来集成两组特征选择方法,并且克服了上面提到的局限性。

MNCI 先生考虑了新的分类信息和特征冗余。特征冗余可以分为两类:类相关特征冗余和类无关特征冗余。这两种类型的特征冗余对于特征选择都很重要。

特色选择器【3】

云萨尔等人提出了一种新的基于过滤器的概率特征选择方法。考虑到对术语特征的某些要求,DFS 选择有区别的特征,而排除无信息的特征。该方法试图回答这样一个共同的问题,即用户正在寻找新的技术来选择有区别的特征,从而可以提高分类精度并减少处理时间

在他们的论文中,他们将 DFS 与一些流行的过滤方法进行了比较,如卡方检验、信息增益、基尼指数和偏离泊松分布进行时间分析。结果给出 DFS (0.0343s),GI (0.0371s),CHI2 (0.0632s),IG (0.0693s),DP (0.0797s)越小越好。

有一些流行的数据集用于文本分类任务。比如亚马逊评论电影评论20 个新闻组路透社-21578 。都是很好的开始。

此外,流行的算法用于基准特征选择,如朴素贝叶斯,KNN,决策树,SVM,K-Means,层次聚类。朴素贝叶斯是文本分类中最流行的方法。

[1]拉巴尼,m .,莫拉迪,p .,艾哈迈德扎尔,f .,贾利利,m .,2018。文本分类问题中一种新的多元滤波特征选择方法。人工智能的工程应用。

[2]高,魏,胡,李,张,张,王,等,2018 .综合两组特征评价标准的特征选择。专家系统及其应用。

[3]阿·云萨尔,南·古纳尔,2012 年。一种新的文本分类概率特征选择方法。基于知识的系统。

如果你喜欢这篇文章,请随意点击鼓掌按钮👏🏽如果你对接下来的帖子感兴趣,一定要在 medium 上关注我

Python 机器学*中的特征选择技术

原文:https://towardsdatascience.com/feature-selection-techniques-in-machine-learning-with-python-f24e7da3f36e?source=collection_archive---------0-----------------------

新的一天带来了新的力量和新的思想——埃莉诺·罗斯福

我们都可能面临这样的问题:从一组数据中识别相关特征,并删除不相关或不太重要的特征,而这些特征对我们的目标变量没有太大贡献,以便实现我们模型的更高精度。

特征选择是机器学*的核心概念之一,它会极大地影响模型的性能。您用来训练机器学*模型的数据特征对您可以实现的性能有着巨大的影响。

不相关或部分相关的特征会对模型性能产生负面影响。

特征选择和数据清理应该是模型设计的第一步,也是最重要的一步。

在这篇文章中,你会发现可以在机器学*中使用的特征选择技术。

特征选择是自动或手动选择对您感兴趣的预测变量或输出贡献最大的那些特征的过程。

数据中包含不相关的要素会降低模型的准确性,并使模型基于不相关的要素进行学*。

如何选择特征,在对数据建模之前执行特征选择有什么好处?

减少过度拟合:冗余数据越少,基于噪声做出决策的机会就越少。

提高精度:误导性数据少意味着建模精度提高。

减少训练时间:数据点越少,算法复杂度越低,算法训练越快。

我想借此分享一下我的亲身经历。

我通过选择所有功能准备了一个模型,我得到了大约 65%的准确性,这对于预测模型来说不是很好,在做了一些功能选择和功能工程后,没有对我的模型代码做任何逻辑更改,我的准确性跃升至 81%,这非常令人印象深刻

现在你知道为什么我说特征选择应该是你的模型设计的第一步,也是最重要的一步。

特征选择方法:

我将分享 3 个易于使用且效果良好的特征选择技巧。

1.单变量选择

2.特征重要性

3.热图相关矩阵

让我们用一个例子来逐一看看这些技术

您可以从这里下载数据集https://www . ka ggle . com/iabhishekofficial/mobile-price-class ification # train . CSV

上述文件中变量的描述

battery_power:电池一次可以储存的总能量,单位为毫安

蓝色:有无蓝牙

clock_speed:微处理器执行指令的速度

dual_sim:是否支持双 sim 卡

fc:前置摄像头百万像素

四 _g:有没有 4G

int_memory:以千兆字节为单位的内部内存

m_dep:移动深度,单位为厘米

mobile_wt:手机重量

n_cores:处理器的内核数量

电脑:主摄像头百万像素

px _ 高度

像素分辨率高度

像素分辨率宽度

ram:以兆字节为单位的随机存取存储器

sc_h:手机屏幕高度,单位为厘米

sc_w:手机屏幕宽度,单位为厘米

talk_time:单次电池充电持续的最长时间

三 _g:有没有 3G

触摸屏:有无触摸屏

wifi:有没有 wifi

price_range:这是目标变量,值为 0(低成本),1(中等成本),2(高成本),3(非常高成本)。

1。单变量选择

统计测试可用于选择那些与输出变量关系最密切的特征。

scikit-learn 库提供了 SelectKBest 类,该类可用于一套不同的统计测试,以选择特定数量的特性。

以下示例使用非负特征的卡方(chi)统计测试从移动价格范围预测数据集中选择 10 个最佳特征。

import pandas as pd
import numpy as np
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2data = pd.read_csv("D://Blogs//train.csv")
X = data.iloc[:,0:20]  #independent columns
y = data.iloc[:,-1]    #target column i.e price range#apply SelectKBest class to extract top 10 best features
bestfeatures = SelectKBest(score_func=chi2, k=10)
fit = bestfeatures.fit(X,y)
dfscores = pd.DataFrame(fit.scores_)
dfcolumns = pd.DataFrame(X.columns)
#concat two dataframes for better visualization 
featureScores = pd.concat([dfcolumns,dfscores],axis=1)
featureScores.columns = ['Specs','Score']  #naming the dataframe columns
print(featureScores.nlargest(10,'Score'))  #print 10 best features

Top 10 Best Features using SelectKBest class

2.特征重要性

通过使用模型的要素重要性属性,可以获得数据集每个要素的要素重要性。

要素重要性为数据的每个要素提供一个分数,分数越高,要素对输出变量越重要或越相关。

特征重要性是一个内置的类,带有基于树的分类器,我们将使用额外的树分类器来提取数据集的前 10 个特征。

import pandas as pd
import numpy as np data = pd.read_csv("D://Blogs//train.csv")
X = data.iloc[:,0:20]  #independent columns
y = data.iloc[:,-1]    #target column i.e price range
from sklearn.ensemble import ExtraTreesClassifier
import matplotlib.pyplot as plt
model = ExtraTreesClassifier()
model.fit(X,y)
print(model.feature_importances_) #use inbuilt class feature_importances of tree based classifiers
#plot graph of feature importances for better visualization
feat_importances = pd.Series(model.feature_importances_, index=X.columns)
feat_importances.nlargest(10).plot(kind='barh')
plt.show()

top 10 most important features in data

3。与热图相关的矩阵

相关性说明了特征之间或与目标变量之间的关系。

相关性可以是正的(增加一个特征值会增加目标变量的值),也可以是负的(增加一个特征值会减少目标变量的值)

热图便于识别哪些要素与目标变量最相关,我们将使用 seaborn 库绘制相关要素的热图。

import pandas as pd
import numpy as np
import seaborn as snsdata = pd.read_csv("D://Blogs//train.csv")
X = data.iloc[:,0:20]  #independent columns
y = data.iloc[:,-1]    #target column i.e price range
#get correlations of each features in dataset
corrmat = data.corr()
top_corr_features = corrmat.index
plt.figure(figsize=(20,20))
#plot heat map
g=sns.heatmap(data[top_corr_features].corr(),annot=True,cmap="RdYlGn")

看一下最后一行,即价格范围,看看价格范围与其他特性的关系,ram 与价格范围的关系最密切,其次是电池功率、像素高度和宽度,而 m_dep、clock_speed 和 n_cores 似乎与价格范围的关系最不密切。

在本文中,我们发现了如何使用单变量选择技术、特征重要性和相关矩阵从数据中选择相关特征。

如果你觉得这篇文章很有用,请给它鼓掌并与他人分享。

谢谢你

使用随机森林的特征选择

原文:https://towardsdatascience.com/feature-selection-using-random-forest-26d7b747597f?source=collection_archive---------1-----------------------

群体的智慧

Photo by Noah Silliman on Unsplash

随机森林是最流行的机器学*算法之一。它们之所以如此成功,是因为它们总体上提供了良好的预测性能、较低的过拟合和易于解释的能力。这种可解释性是由这样一个事实给出的,即很容易推导出每个变量在决策树中的重要性。换句话说,很容易计算出每个变量对决策的影响程度。

使用随机森林的特征选择属于嵌入式方法的范畴。嵌入式方法结合了过滤器和包装器方法的优点。它们是由算法实现的,这些算法有自己内置的特征选择方法。嵌入式方法的一些好处是:

  • 它们非常精确。
  • 他们概括得更好。
  • 它们是可以解释的

随机森林如何选择特征?

随机森林由 4 到 1200 个决策树组成,每个决策树都是基于从数据集中随机提取的观察值和随机提取的特征构建的。不是每棵树都能看到所有的特征或所有的观察结果,这保证了树是不相关的,因此不容易过度拟合。每个树也是一系列基于单一或组合特征的是非问题。在每个节点处(这是在每个问题处),这三个节点将数据集分成两个桶,每个桶存放的观察值彼此更相似,但与另一个桶中的观察值不同。因此,每个特征的重要性来源于每个桶的“纯净”程度。

分类和回归的工作方式不同吗?

对于分类,杂质的度量或者是基尼杂质或者是信息增益/熵。

对于回归,杂质的度量是方差。

因此,在训练树时,可以计算每个特征减少杂质的程度。一个特征减少杂质越多,该特征就越重要。在随机森林中,每个特征的杂质减少可以跨树进行平均,以确定变量的最终重要性。

为了给出更好的直觉,在树的顶部选择的特征通常比在树的末端节点选择的特征更重要,因为通常顶部分裂导致更大的信息增益。

让我们来看一些关于如何使用随机森林选择要素的 Python 代码。

在这里,我不会将随机森林应用于实际的数据集,但它可以很容易地应用于任何实际的数据集。

  1. 导入库
import pandas as pd
from sklearn.ensemble import RandomForestClassfier
from sklearn.feature_selection import SelectFromModel

2.在所有特征选择过程中,通过仅检查训练集来选择特征是一个好的实践。这是为了避免过度拟合。

考虑到我们有一个训练和一个测试数据集。我们从训练集中选择特征,然后将变化转移到测试集中。

X_train,y_train,X_test,y_test = train_test_split(data,test_size=0.3)

3.在这里,我将在一行代码中完成模型拟合和特征选择。

  • 首先,我指定了随机森林实例,指出了树的数量。
  • 然后我用 sklearn 的selectFromModel对象自动选择特征。
sel = SelectFromModel(RandomForestClassifier(n_estimators = 100))
sel.fit(X_train, y_train)

默认情况下,SelectFromModel将选择重要性大于所有特征的平均重要性的那些特征,但我们可以根据需要改变该阈值。

4.为了查看哪些特征是重要的,我们可以在拟合的模型上使用 get_support 方法。

sel.get_support()

它将返回一个由布尔值组成的数组。重要性大于平均重要性的特征为真,其余为假

5.我们现在可以列出并统计所选的特性。

selected_feat= X_train.columns[(sel.get_support())]
len(selected_feat)

它将返回一个整数,表示随机森林选择的要素数量。

6.获取所选特征的名称

print(selected_feat)

它将返回所选特征的名称。

7.我们还可以检查并绘制重要性的分布。

pd.series(sel.estimator_,feature_importances_,.ravel()).hist()

它将返回一个直方图,显示使用该特征选择技术选择的特征的分布。

我们当然可以调整决策树的参数。我们选择特性的截止点有点武断。一种方法是选择前 10、20 个特征。或者,前 10%的人。为此,我们可以将 mutual info 与 sklearn 的 SelectKBest 或 SelectPercentile 结合使用。

随机森林的局限性有:

  • 相关特征将被赋予相同或相似的重要性,但是与没有相关对应物而构建的相同树相比,整体重要性降低。
  • 一般来说,随机森林和决策树优先选择基数高的特征(树偏向于这些类型的变量)。

通过使用树导出的特征重要性来选择特征是为机器学*选择良好特征的一种非常直接、快速且通常准确的方式。特别是,如果我们要构建树方法。

然而,正如我所说的,如果树是在没有相关对应物的情况下构建的,那么与它们的重要性相比,相关的特征将在树中显示出相似和较低的重要性。

在这种情况下,最好递归地选择特性,而不是像我们在这里所做的那样一起选择。

变形金刚:隐藏的宝石

原文:https://towardsdatascience.com/feature-transformers-hidden-gems-917bc1237f90?source=collection_archive---------9-----------------------

可以说,进入监督学*模型的特征比模型本身更重要。也就是说,总是很难找到如何设计和预处理特征以使分类器/回归器最大化其性能。

有多种特征转换技术构成了每个数据科学家工具箱的标准部分。编码、输入和缩放是必不可少的。在某些情况下,很明显,某种转换会提高性能。一个很好的例子是在使用任何梯度下降算法之前缩放数字特征。然而,一般来说,为了最大化预测潜力,不存在如何预处理和转换特征的单一最佳方法。那么什么是正确的方法呢?嗯,一个人只需要尝试不同的技术,看看哪种表现最好。

最*,我一直在使用自动化超参数搜索包,即 auto-sklearntpot 。他们都试图找到最大化样本外性能的管道。他们不仅能够以一种聪明的方式做到这一点(使用贝叶斯优化或遗传算法的元学*),而且还使用法简单得令人尴尬。令人惊讶的是,性能最好的管道通常包括一组类似的变压器,这正是这篇文章的动机。系好安全带,享受旅程。

变压器到底是什么?

遵循 scikit-learn API,我们可以将转换器定义为实现了fittransform方法的base.BaseEstimator的任何子类。自然,在官方文档中有几十个已经实现的转换器被很好地记录。然而,当使用管道时,它们的真正力量就变得明显了。等等,什么?管道(pipeline.Pipeline)是一系列转换器,通常以分类器/回归器结束。它使用户能够在逻辑上连接预处理和任务的机器学*部分,避免从训练到测试集泄露信息,并且(最重要的是)在所有步骤中找到最佳超参数。

老朋友

在变得过于花哨之前,让我们先列出最常用的变压器:

  • 定标器(StandardScalerMinMaxScalerRobustScaler、…)
  • 单变量选择器(SelectKBestSelectPercentile、…)
  • 带核主成分分析
  • 多项式特征

他们够好吗?当然,它们被一次又一次地证明对各种数据集是有用的,永远不应该被丢弃。然而,没有理由不进一步探索。

好了,现在我们终于准备好看看 3 种不同的技术,它们不像基本技术那样常见。然而,它们有巨大的潜力为最终的评估者产生伟大的特性。

随机树嵌入

决策树/随机森林因能够捕捉复杂的非线性依赖关系而臭名昭著。人们可以利用这一特性来生成被称为随机树嵌入(RTE)的高维特征变换。具体怎么做呢?当用作估计器时,决策树将每个样本分配给唯一的叶节点,并在相同的节点内进行相同的预测。我们可以将注意力转向叶节点本身,并将其作为一种将每个样本编码为一个热点向量的方式,而不是专注于预测。零表示我们的样本没有结束的所有叶节点,而唯一的 1 对应于我们的样本到达的节点。人们可以用同样的方式处理任意数量的树,并堆叠所有隐含的一个热向量。这自然会产生一个稀疏的高维向量。下面是这种想法在 3 棵决策树中的示意图——绿色特征对应于 1,红色特征对应于 0。

RTE 是一种无监督的算法,通过生成完全随机的树来实现上述功能!在ensemble.RandomTreesEmbedding下的 scikit-learn 中可以很容易地获得实现。一些更相关的参数是:

  • n_estimators —树木数量
  • max_leaf_nodes —每棵树的最大叶节点数(实际数量可以更低)

这两个参数允许我们控制变换特征的维度。尺寸最多为n_estimators * max_leaf_nodes

堆积估计量

集成学*是一组广泛使用的技术,能够将不同的模型组合成一个模型。最常见的技术是装袋和增压。然而,让我们把注意力集中在他们邪恶的孪生兄弟身上。堆叠估计器(SE)的目标是从原始特征创建元特征。首先,选择一个估计器,该估计器使用原始特征作为输入,并输出分类概率(对于分类器)或预测(对于回归器)。将估计器应用于每个样本,我们可以将输出视为附加特征,并通过水平堆叠将它们与原始特征向量相结合。这个过程可以重复,并添加不同的估计器(输入总是原始特征)。自然地,人们甚至可以嵌套这个过程(输入是原始特征以及所有先前估计器的输出)。

下面是一个你可以在头脑中分配的可能的心理图片(或者只是在参考资料中看到一些 www 上提供的更详细的图表)。

由于 Stacking Estimator 不是 scikit-learn 的一部分,所以需要在其他地方寻找( mlxtend )或者自己创建这个转换器。下面显示了一个最小版本。

递归特征消除

在我们有太多特征的情况下,希望有一个纯粹用于特征选择的转换器。这意味着实际的转换包括删除一定数量的要素,而保持其余要素不变。递归特征消除(RFE)正是通过迭代过程做到这一点的。像许多其他变形金刚一样,scikit-learn 在feature_selection.RFE下有一个很好的算法实现。

让我们简单描述一下事情是如何进行的。首先,需要指定变换特征的期望维度,然后指定每次迭代期间要丢弃的特征的数量。在一次迭代中,特性选择的逻辑非常简单——拟合一个包含coef_feature_importances_的模型,并丢弃最不相关的(最接*零或最低feature_importances_coef_)。

实际上,任何线性模型都可以用来获得coef_,但最好使用正则化/稀疏模型,如脊形、套索和弹性网。对于feature_importances_,基于树的算法是自然的候选。

RFE 有三个重要的超参数:

  • estimator:包含coef_feature_importances_的估计器
  • n_features_to_select:我们想要达到的特征的最终数量/百分比
  • step:每次迭代中要删除的特性的数量/百分比

见下面的例子,其中n_features = 16,step = 1,n_features_to_select = 11。

请注意,如果您事先不知道n_features_to_select应该是什么,请考虑在feature_selection.RFECV下使用该算法的交叉验证版本。

结论

这篇文章描述了 3 个现成的变压器背后的基本逻辑。其中两个转换器增加了特征向量的维数——随机树嵌入和堆叠估计器。第三种,递归特征消除,降低了维数。虽然 SE 和 RFE 非常通用,并且可以成功地应用于手头的任何问题,但是 RTE 更具有领域特异性。

自然,还有几十个其他令人惊叹的变形金刚没有被讨论。让我们至少给它们中的一些一个荣誉奖——fa stica、随机厨房水槽、自动编码器、特征聚集和流形学*。

参考

随机树嵌入

堆积估计量

递归特征消除

原载于 2018 年 6 月 17 日jank repl . github . io

二月版:数据可视化

原文:https://towardsdatascience.com/february-edition-data-visualization-ee524ca64416?source=collection_archive---------9-----------------------

10 篇必读文章

拿破仑是有史以来最好的将军,数学证明了这一点。

伊森·阿尔什特——10 分钟阅读

当非洲人问汉尼拔认为谁是最伟大的将军时,汉尼拔选择了 亚历山大……至于谁会排第二,汉尼拔选择了 皮拉斯……问谁 汉尼拔 认为第三,他接着,西庇阿大笑起来,说道:“如果你打败了我,你会说什么?”—李维

15 种令人惊叹的数据可视化(以及你能从中学到什么)

Payman Taei — 7 分钟阅读

我们淹没在数据中。每天都有 2.5 万亿字节的数据产生。这相当于全球 90%的信息——仅在过去两年中就产生了这些信息。这就是我们所说的“大数据”

如果出租车旅行是萤火虫:13 亿次纽约出租车旅行被绘制

通过 Ravi Shekhar — 9 分钟读取。

纽约市出租车和豪华轿车委员会(TLC)公开发布了一个从 2009 年 1 月到 2016 年 6 月的出租车出行数据集,其中包含起点和终点的 GPS 坐标。

如何可视化分布

Marc Laforet — 5 分钟阅读。

您已经将所有必要的数据整理成一种清晰的格式,您已经恰当地执行了一个时髦的统计分析,现在是分析结果的时候了。

陌生事物:分析和交流数据的五堂课

乔丹·德沃金 — 8 分钟阅读。

作为一名统计领域的研究生,我很快意识到,不与数据打交道的人对统计这个词通常会有两种反应:“哦,我讨厌那门课!”和“你一定很喜欢数学!”

漂亮的数据科学演示文稿

詹姆斯陈 — 5 分钟阅读

这篇简短博客文章的目标读者是对 3 种不同用途的演示感兴趣的人:销售工具包、流程和分析报告。

公司级仪表盘的三个常见错误

Chris Dowsett — 4 分钟阅读。

公司级仪表板很特殊。他们掌握着所有部门和业务领域最重要的关键绩效指标(KPI)。

描绘神经科学的图景

法赫德阿尔哈兹米 — 5 分钟读取。

关于现代神经科学研究,对 1M+文章的分析能告诉我们什么?

用 d3 构建共现矩阵分析学位论文中的重叠主题

由德博拉·梅斯基塔——7 分钟阅读。

我硕士学位研究的目标是在不同领域的研究人员之间激发新的合作机会。但在此之前,我需要后退一步,看看是否有任何合作已经发生。酷,但是如何开始做这件事呢?

TED 中反复出现的话题是什么

汉娜·韩嫣读了 3 分钟。

为了可视化各个主题及其各种组合的频率,我使用了 R/python/D3 中的一个工具,名为 UpSet ,它是由一组哈佛研究人员开发的,使用矩阵、条形图和附加属性图来描述部分到整体的关系以及不同集合的交集。

We also thank all the great new writers who joined us recently, Sara Robinson, Charlie Bonfield, Chalita Lertlumprasert, 黃功詳 Steeve Huang, Martina Pugliese, Oren Dar, Ruben Van Paemel, Radek, Vincent Chen, Luke James, Vadim Smolyakov, Sarah Schoengold, Robert de Graaf, Jithu R Jacob, Thushan Ganegedara, Ivan Zhou, Carolina Ödman-Govender, Nikolay Ryabykh, Artem Duplinskiy, Jesse Moore, Ambarish Ganguly, Cass Petrus, and many others. We invite you to take a look at their profiles and check out their work.

联邦拜占庭协议

原文:https://towardsdatascience.com/federated-byzantine-agreement-24ec57bf36e0?source=collection_archive---------3-----------------------

随着区块链技术获得牵引力,开发人员越来越多地调整和试验共识机制

达成共识的最传统方式是通过拜占庭协议(区块链技术中的一个基本概念)。区块链上的节点通过对给定问题的解决方案达成共识来验证数据块。当某个最小数量的节点(称为法定人数)同意所给出的解决方案是正确的时,就达成了拜占庭协议,从而验证了一个块并允许其包含在区块链上。

联邦拜占庭协议

涟漪区块链首创了联邦拜占庭协议(FBA)共识机制。恒星区块链进一步完善了这种方法,采用了第一个可证明安全的 FBA 协议。在 FBA 系统中,每个节点不必提前知道和验证,成员是开放的,控制是分散的。节点可以选择信任谁。系统范围的法定人数是由单个节点做出的决定形成的。

法定切片

法定人数是系统内达成一致所需的节点数量。FBA 改用“仲裁片”。仲裁片是仲裁的子集,它可以说服另一个特定节点同意。

一个节点可以依赖于许多切片,并且节点的选择可以依赖于外部标准。例如,“节点 X”可以说,“为了达成共识,我们必须让我们选择的五家银行中的三家的节点参与进来”。五个存储体中的三个现在可以确定节点 X 是否同意。增加另一层复杂性节点 X 可能是另一个节点的仲裁片的一部分。

如果将一个节点编程为依赖于一个法定切片,用户必须相信该法定切片是足够可信的,如果它同意某件事,该节点肯定会同意。

A Quorum slice.

法定交集

信任是在节点的配置文件中建立的。由于节点可能具有不同的配置文件,因此网络中的片和定额可以动态形成。好的法定人数共享节点,导致法定人数重叠。这种重叠被称为“法定交集”。当法定人数不相交时,系统以‘不相交的法定人数’结束。不相交的法定人数是不可取的,因为他们中的每一个都可以独立地同时就矛盾的事务达成一致,从而破坏了整体共识。

Quorum Intersections.

阻塞与发散状态

区块链应该又快又安全。如果节点在达成协议的过程中被“阻塞”,区块链就会变慢。当区块链上的节点呈现不同于其他节点的值时,系统是“发散的”。发散的系统比阻塞的系统更危险:阻塞的系统只是速度慢,但是发散的系统开始显示矛盾的数据。

3 Disjoint Quorums.

FBA 的优势

开放成员和分散控制

没有看门人或中央机构—单个节点可以决定信任谁来获取信息

选择每个节点信任谁的能力分散了网络

节点可以有多个切片

进入门槛低(任何人都可以加入)

面对故障时保持稳健(一个节点可以关闭,而系统的其余部分将保持完整)

可以对节点进行编程,使其信任仲裁片或外部源,具体取决于其随时间推移的性能

单个节点的选择可以基于外部标准(例如,属于汽车金融公司的节点可能需要来自可信的银行节点、可信的信贷机构以及与机动车辆部门相关联的节点的确认,以接受有效的交易)

结论

FBA 分类帐可以是最新的和准确的,而不要求其所有节点一致。相反,每个节点的选择会产生一个法定人数。

法定切片可以说服单个节点达成一致,而法定切片可以说服整个系统达成一致。如果某个节点发现某个特定的仲裁片完全可信,它可以同意接受该仲裁片同意的任何内容。

传统拜占庭协议系统和 FBA 系统的区别在于,在后者中,每个节点选择自己的法定切片。

沙安雷

关注媒体上的 Lansaar Research ,了解最新的新兴技术和新的商业模式。

对手中稀疏的数据感到气馁?给因式分解机一个机会(1)

原文:https://towardsdatascience.com/feel-discouraged-by-sparse-data-in-your-hand-give-factorization-machine-a-shot-1-7094628aa4ff?source=collection_archive---------11-----------------------

如果你是一名工业界的数据科学家,你是否有过这样的经历:面对你的客户,告诉他们由于数据稀疏,项目可能无法实现他们的期望?

的确,没有人能无草制砖。准确地说, 中的 大量 名副其实的 数据是数据科学家期待的‘稻草’。然而,事实并不总是如此。我们应该让数据的弱点阻止我们进行我们的项目吗?不要!

今天,我将介绍一个高性能模型,即使没有理想的数据,它也能产生出色的结果。就是 因式分解机 (FM)。

因式分解机 是 2012 年 Steffen Rendle 在日本大阪大学工作期间想出的。它已经成为推荐系统和文本分析的主流模型。

作者强调了 FM 的三大优势:

1。 对稀疏数据友好。

2。 线性计算复杂度。

3。 一个通用的预测器。

在阐明因式分解机之前,让我们用一个应用场景来描述这个模型。

“电子商务网站要求你根据每个顾客的历史评分数据,预测他们对每件商品的评分。”

该比率从 1 到 5 递增,适用于来自 非常差差、一般到好以及优秀 的印象。

现在,让我们来看一下历史数据。

historical rated data by users to merchandises

表示商品名称,包括“靴子”、“咖啡豆”、“杯子”、“耳机”、“花”、“足球”、“帽子”、“笔记本电脑”、“连指手套”和“毛衣”。 指的是用户名包括 April、Brian、Daniel、Eric 和 Frank。

矩阵中的每个值都是用户对该行中该列商品的评分。

然而,在实际场景中,网站通常需要支持数百万用户和商品的高吞吐量。只有用户购买的商品才能从顾客那里得到分数。很有可能我们会得到一个非常 大的稀疏矩阵 ,其中的大部分值都是零。

在继续之前,让我们将问题简化为"基于用户如何与他/她购买的商品(X) 进行交互来对分数(Y)建模。"

这里来 2 度因式分解机的模型方程。

The model equation of factorization machine of 2 degrees

看着眼熟? 是的,它是在线性回归的基础上增加了自变量之间的相互作用这一项而发展起来的。该等式中的 Wij 是在我们的示例中量化用户和机构之间的交互的系数。

如何估计相互作用系数 Wij 也是本文讨论的重点,也是因式分解机的显著特点。

回到我们讨论的大型稀疏数据,如果我们直接进行系数估计会发生什么?不难知道,由于历史数据中没有交互(用户和机构之间),大量系数将被估计为零。

如果我们还陷入直接从已知去研究未知的思维*惯,怎么给一个用户从来不评分的项目打分呢?这就是 因式分解机 的用武之地。

“因式分解在机器中通过因式分解对交互进行建模,这允许在稀疏性下对高阶交互进行高质量的参数估计。”

听起来很抽象?

现在就让 用更多的角色来丰富用户 的描述吧。April 是一名 26 岁的亚洲女性,是一名科学家,住在洛杉矶。四月的形象通过她的 性别、年龄、职业、种族和居住地 变得具体。

同样, 她评价的杯子是为圣诞节设计的绿色陶瓷杯,70 美元,星巴克的。杯子的更多细节被考虑进去,如 颜色、质地、类型、季节、价格和公司

在系数估计中描述两个具有多重特征的自变量的过程就是因式分解的过程。

因此,在数学中,独立变量表示如下。

The feature vector representing independent variables

k 是描述自变量的数量特征。 i 是自变量的个数。在圣诞杯四月得分的例子中,用户和商品分别有 6 个特征。

The feature vector of user

The feature vector of merchandise

因此,用户和商品之间的交互可以用下面的格式表示。

The interactions between i-th and j-th variable

The calculation process of the interaction coefficient

模型方程可以重写如下。

The model equation of factorization machine of 2 degrees

到目前为止,你可能想知道为什么要费心通过特征向量将变量扩展到多堆维度?痛点和策略有什么关系?

因为它们通过分解相互作用参数打破了它们的独立性。一般来说,这意味着一个相互作用的数据也有助于估计相关相互作用的参数。”

让我用我们掌握的数据来说明这一点。

historical rated data by users to merchandises

从上面的观察来看,由埃里克咖啡豆 的费率差不多,分别是 5(【W(埃里克,咖啡豆) )和 4(【W(埃里克,杯) )。于是特征向量 V(咖啡豆)V(杯子) 可以视为大致相同, V(咖啡豆) = V(杯子)

因此 W(四月,咖啡豆) ,四月率到咖啡豆,可以推断为与W(四月,杯) 相同,即 1

完美解决痛点。哈?

让我们把独立变量的所有特征向量放入矩阵。

The matrix containing all feature vectors

The feature vectors in matrix

左边两个矩阵 是自变量特征向量的展开。

右矩阵 包含两个特征向量相乘的交互系数。

The interaction matrix of 2-degree Factorization Machine

标有蓝色的那一半矩阵正是要估计的相互作用项。

那么如何估计模型的系数呢?为什么说计算复杂度是线性的?让我们把它们放在下一篇文章中。

简报:

本文通过推荐系统中的一个应用场景来介绍因式分解机,通过矩阵分解来解决稀疏数据下的系数估计问题。

paper . DVIhttps://www.csie.ntu.edu.tw/~b97053/paper/Rendle2010FM.pdf

如果您有任何问题,请随时留下您的评论。

对手中稀疏的数据感到气馁?给因式分解机一个机会(2)

原文:https://towardsdatascience.com/feel-discouraged-on-the-sparse-data-in-your-hand-give-factorization-machine-a-shot-2-b2e54d670cf8?source=collection_archive---------11-----------------------

打好矩阵分解的基础,你对矩阵分解概念衍生出的一系列高级模型 的探索就会顺利很多,比如 LDA、LSI、PLSA、张量分解等等

The models derived from the concept of Matrix Factorization

上一节中,我们讲过 因式分解机 背后的基础理论。今天让我们揭示模型背后的技术细节和数学。

本文将讨论两个问题:

  1. 如何估算 因式分解机 的系数?随机梯度下降(SGD)?交替最小二乘法(ALS)?
  2. 为什么计算复杂度是线性的?

在陷入系数估计的深渊之前,让我们先回顾一下 因式分解机 的模型方程。

The model equation of Factorization Machine

我们的目标 是找到最优化的系数,使得变量和真实反应之间的关系可以用最准确的方式描述。

机器 通过最小化 损失函数 来学*模型的系数,该损失函数描述真实响应(地面真实值)与设计模型的估计值之间的距离。为了使概念形象化,系数更新的数学表达式如下。

The goal of machine learning / model training

ѳ*是一组系数。标为蓝色的项目是L2-诺姆 ,惩罚模型的复杂性,避免 过拟合 为了简化数学推导,下图中省略了 L2 范数。

第一个需要回答的问题就这样呈现在我们面前。 模型的损失函数是什么?

  1. 回归: 我们通常用最小二乘误差来处理回归问题。

The equation of least square error

2。二进制分类 : y = [-1,+1]

铰链损失或对数损失作为损失函数应用于二元分类。

铰链损耗:

The equation of hinge loss

(y = 1)和(y = -1)下的铰链损耗如下图所示。

The hinge loss plot for y = 1 and y = -1

日志丢失:

The equation of log loss

σ(x)是 sigmoid 函数。

下面是铰链损耗和对数损耗的对比图。随着估计值逐渐接*真实值,损耗变得越来越小。

the plot of hinge loss and log loss (y = 1)

在阐明损失函数之后,如何最小化它成为我们研究的第二个关注点。

how to reach the bottom of valley within the shortest time?

随机梯度下降因其在系数优化方面的出色表现而被引入。 关于方法的一个很棒的比喻 到达谷底的最快方法(损失函数的最小值)就是沿着最陡的方向迈步(迭代梯度下降法)(梯度的负值)。

The equation of gradient descent

这个想法是以数学的方式实现的。 损失函数的导数 用红色标记圈起来代表步长方向。 η 是要走的步幅。 w 是要更新的权重集。

同时,因式分解机中系数的导数/梯度成为第三个焦点

  1. 对原木损耗进行分类的导数:

The derivative of log loss for classification

你可能想知道如何得到它。下面用 4 个步骤来说明演绎过程。

step 1

顺着逻辑, sigmoid 函数σ(x) 的导数是什么?

step 2

step 3

step 4

2。回归损失函数的导数:

The derivative of loss function for regression

因此,到目前为止,在上方用红色标记圈起来的估计响应的导数被置于聚光灯下。

FM 模型的一个重要性质,多重线性,可以对回答这个问题做出很大的贡献。让我们重新表述方程来形象化这个概念。

  1. 关于 FM 对 W0 的偏导数:把 W0 放到一边,重新组织公式。

The model equation of Factorization Machine

W0 的 FM 的梯度/偏导数为 1。

  1. 至于 FM 对 W l:W l 放在一边重新组织公式。

The model equation of Factorization Machine

FM 对Wl 的梯度/偏导数为Xl .

3.至于 FM 对lm*的偏导数:把lm*放到一边,重新组织公式。**

The model equation of Factorization Machine

FM 对V**lm的梯度/偏导数就是上式中标记为红色的项目。**

综上所述,FM 的导数为:

估计响应的导数集在随机梯度下降系数学*过程中起着重要作用。

随机梯度下降训练因式分解机怎么样?

通过回顾算法中待估计的所有参数,收集了其中的 3 组参数。

a. W 0:全局偏差

b. W i:第 I 个变量的强度

c. < V i, V j >:第 I 个和第 j 个变量之间的相互作用

Iterate until stopping criterion is met

迭代直到满足停止标准。

到目前为止,接下来是关于计算次数的讨论。特征向量带来了参数数量的增加,从而增加了计算量。 线性时间复杂度 大大缓解了这个问题。

让我们快速反思一下模型方程(度= 2)。

The model equation of Factorization Machine

复杂度的直接计算在 O (k n ) 中,因为必须计算所有成对的相互作用。

Time complexity of machine factorization

让我把时间复杂度的方程拿到显微镜下,进行详细的推导。将复杂性公式分为三部分:

a. n + (n-1):

在上述模型方程中,自变量权重的计算时间用黄色标出。

b . {[k+(k-1)+2][(n-1) n/2]+[(n-1) n/2-1]}:***

模型方程中用红色表示的交互项的计算时间。

c. 2:

3 个项目的 2 次添加

模型方程中交互项的复杂性可能最吸引你的眼球。下面的推论会清楚地梳理你的想法。

The deduction of complexity for interaction items in model equation

把其他项目的复杂程度加起来,我们就得到了整个计算结果。

The deduction of complexity for the FM model

但是正如我们之前提到的,通过重构交互项,复杂度下降到 线性 运行时间。

The reformulation of interaction items

方程现在在 k 和 n 中只有线性复杂度 O(kn) 。我会留给读者一个问题。遵循上面类似的逻辑,如何得到基于方程重构后的线性复杂度?稍后我会在评论区附上答案。欢迎你在这里给我留下你的评论或想法。

女性 CEO 的薪酬中位数较高,但这与她们的性别有关吗?

原文:https://towardsdatascience.com/female-ceos-have-a-higher-median-pay-but-is-it-related-to-their-gender-40d0662b7d4f?source=collection_archive---------1-----------------------

T 何《华尔街日报》2017 年 5 月 31 日发表文章,标题为 虽然寡不敌众,但女性首席执行官的收入却超过了男性首席执行官 。《华尔街日报》的分析显示,女性首席执行官的收入一再超过男性。去年,21 位女性首席执行官的薪酬中值为 1,380 万美元,而 382 位男性首席执行官的薪酬中值为 1,160 万美元。

我很好奇,也有点怀疑。当我仔细观察时,我注意到他们报告了收入的中位数。中位数比平均数更稳健,但我很好奇女性首席执行官的薪酬分布情况,并想知道这是否有所不同。由于今年标准普尔 500 公司中只有 23 名女性首席执行官,很可能这些女性只是在正确的公司,所以这一统计数据是真实的。

例如,我从数据中随机抽取了 10 个样本(占总人口的 4.6%,相当于 500 名首席执行官中的 23 名女性),最终得出的平均值为 1397 万美元,标准差为 71 万美元,平均值为 1800 万美元,标准差为 148 万美元。从这个例子中,我们可以看到中值更加稳健,但是,仍然存在足够大的误差,足以导致 WSJ 结果中值的差异。

如果我可以建立一个 CEO 薪酬模型,这个模型是否能够使用公司排名作为输入,准确预测首席执行官的薪酬?

为了检验我的假设,我需要一些数据。我从美国劳工联合会-产业工会联合会关于首席执行官薪酬的页面上找到了一些数据,为了节省时间,我使用 ImportIO 来搜集这些数据。AFL-CIO 的数据有点大杂烩,包含 2015 年、2016 年和 2017 年的薪酬数据,所以我无法直接复制《华尔街日报》的分析,但我认为这将是一个不错的*似值。使用的所有代码(和数据!)可从我的 GitHub repo 获得。

快速浏览数据

A representation of the compensations of our top 500 CEOs. We can see there’s a rapid drop off after Sundar Pichai leading to a much lower compensation package for Thomas L Carter. This representation is every 16th CEO in the data, which gives us 32 CEOs. (Interesting side note: Rex Tillerson happened to make it into this figure.)

乍一看,我很惊讶地发现数据集包含 3031 个条目,尽管我正在查看标准普尔 500 的数据。将数据限制在 500 强公司之后,是时候看一眼数据了。看左边的补偿分布,首先想到的是来自化学或者物理的阿伦尼乌斯方程(可能是因为我的生物物理化学背景)。

T 阿伦尼乌斯方程是一个指数函数,可以让你预测给定温度下的反应平衡常数(上图方程)。这个方程可以线性化,使它成为一些 OLS 回归(底部方程)的一个很好的候选。

准备数据

在进一步考虑这个模型之前,我需要做一些数据清理。为了将数据分段,按性别区分首席执行官,我需要找出哪些是女性首席执行官。我使用维基百科Catalyst 获得了女性 CEO 的名单。使用这两个名单的理由是名字的变化,即玛丽·巴拉对玛丽·t·巴拉或帕蒂·波佩对帕特里夏·k·波佩。使用这组组合名称的目的是为了在屏蔽熊猫数据帧以找到女性首席执行官的特定数据时,最大限度地提高匹配的机会。这种方法只给了我 23 个 CEO 中的 16 个。为了找出我遗漏的数据,我用《财富》( Fortune)杂志(T10)找到了哪些公司有女性首席执行官,这最终让我找到了另外 4 家公司的数据。最终,卫报人寿保险公司的数据似乎丢失了。美国公司、格雷巴电气公司和 CH2M 希尔公司。

我们的数据中包括的女性首席执行官有:马克·v·赫德、V.M 罗梅蒂、卢英德、玛丽·t·巴拉、菲比·n·诺瓦科维奇、玛丽琳·a·休森、艾琳·罗森菲尔德、乌苏拉·m·伯恩斯、林恩·j·古德、苏珊·m·卡梅隆、维基·霍卢伯、丹尼斯·m·莫里森、芭芭拉·伦特勒、a·格雷格·伍德林、黛布拉·l·里德、伊琳·s·戈登、玛丽·a·拉辛格、谢里·麦考伊、金伯利·s·卢贝尔和约翰·p·塔格。值得注意的是,这些首席执行官中有一些是男性。我假设男性首席执行官的薪酬足够接*,我们可以直接进行替换。

描述数据集

H 薪酬方案的价值如何比较?使用 Pandas describe()函数,我们看到男性 CEO 数据包含 480 名成员,平均薪酬为 1646 万美元,中值薪酬为 1347 万美元,最小值和最大值分别为 975 万美元和 1.0063 亿美元。女性首席执行官数据包含 20 名成员,平均薪酬为 1605 万美元,中值薪酬为 1322 万美元,最小值和最大值分别为 946 万美元和 4112 万美元。

绘制样本分布和数据直方图为我们提供了这个漂亮的图形:

男性和女性首席执行官直方图的差异是最令人震惊的特征之一。当以同样的比例看这两张图表时,女性首席执行官的条形图几乎看不到,这戏剧性地显示了顶级公司中女性首席执行官的数量是多么少。

描述模型

正如我上面提到的,我怀疑阿伦尼乌斯方程是描述数据的良好基础。然而,等式本身的符号对我们的情况毫无意义。我改写了这个等式,使其采用以下形式之一:

在该模型中, c 是高管的薪酬, b 是基本薪酬(最低薪酬的下限,在一些图中有时表示为 c_0 ),α、β、γ和δ是模型中的调整参数。当我们线性化方程时,形式(A)和(B)之间的主要区别将是显而易见的。这些模型的图表看起来与数据相似。

Model (A) was plotted with two different values for alpha and beta and Model (B) was only plotted for a single gamma and delta value. The values for the parameters were set by using the maximum compensation and the minimum compensation along with their respective ranks.

当我们将数据线性化时,我们得到以下方程和相应的曲线图:

在查看线性化方程和图表后,很明显我们可以从线性回归分析中排除模型(B ),因为它与1/等级成比例,而不是与等级成比例。

建立回归模型

I 通过从补偿中减去基数,将补偿数据转换为线性形式,并取对数。由于基数是最低补偿的下限,我们避免了 log(0)未定义的问题。log( c-b )对排名的曲线大部分是线性的,但对于前 50 名左右的公司来说,有一些非常非线性的点。

Plots of the 2015 and 2016 CEO data after being linearized.

转换完数据后,我把数据集分成两部分。我做了一份只有女性 CEO 数据的副本,另一份有男性 CEO 数据的副本。女性首席执行官的数据将被用作抵制测试集。我还使用了样本量为 33%的 sci-kit 的train_test_split函数来创建使用男性 CEO 数据的训练和测试集。

通过使用训练数据和 sci-kit learn LinearRegression(normalize=True)模型拟合归一化的 OLS 模型。模型的最佳拟合线是 log (c-b) = -0.00636 秩+ 3.108 。使用测试数据,模型的均方误差为 0.0487,r 平方值为 0.957。使用女性首席执行官抵制测试数据,模型表现稍好,均方误差为 0.0198,r 平方值为 0.9581。

看一看残差显示,在排名分布的末端,即前 10%和后 10%的公司,肯定存在一些非线性行为。

为了改进模型,我决定尝试一个更稳健的回归变量,Huber 回归变量。我交叉验证了ε和α参数并选定了

HuberRegressor(alpha=71.428600000000003, epsilon=9.2000000000000064, fit_intercept=True, max_iter=100, tol=1e-05, warm_start=False)。(alpha 和 epsilon 值的长尾是浮点伪像。)

以与之前相同的方式拟合HuberRegressor,我们得到 log(c-b)=-0.00636 rank+3.108!这和我们在 OLS 得到的模型一样。我计划尝试 RANSAC 和 Theil-Sen 回归,但考虑到 Huber 模型与 OLS 模型相同,我觉得没有必要。创建 OLS 模型的下一步可能是利用一些高阶项或使用[sklearn.preprocessing](http://scikit-learn.org/stable/modules/classes.html#module-sklearn.preprocessing).[PolynomialFeatures](http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html#sklearn.preprocessing.PolynomialFeatures)对数据进行预处理。

The 2015 and 2016 CEO data plotted with the Huber/OLS model as a solid line.

更进一步:树模型

我想看看我是否能使用不同类别的模型做出更好的估计。我选择决策树有两个原因:数据的非线性无关紧要,决策树可以产生容易理解的输出。

开始时,我使用了 sci-kit 的tree.DecisionTreeRegressor,其max_depth为 4。完整的回归变量看起来是
DecisionTreeRegressor(criterion='mse', max_depth=4, max_features=None, max_leaf_nodes=None, min_impurity_split=1e-07, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, presort=False, random_state=None, splitter='best')

当模型符合数据时,树看起来像这样:

它给出的预测也不是那么糟糕:

模型的 MSE 对于测试数据是 8.29 x 10⁴,对于维持数据是 0.0164。

在使用交叉验证优化树模型的max_depth之后,我发现最佳数量在 10 到 11 个决策层之间变化。该模型的图形是

A screenshot of the model. The actual image was way too big to put on Medium. You can view the rotated version on the GitHub page.

这个模型的预测要好得多。测试数据的模型 MSE 为 0.000994,维持数据的模型 MSE 为 0.00213。数据用下面的预测绘制:

Predicted values (mustard yellow) overlaid on the training data (hunter green) for the tree model with a max_depth of 11.

结论

基于线性和 Huber 回归模型以及树形模型的预测质量,我认为数据表明公司的排名是 CEO 薪酬的良好预测指标。这并不能证明 CEO 的性别没有影响,但这确实降低了这一论点的分量。

为了进一步分析,我将使用 sci-kit 的PolynomialFeatures进行实验,看看这是否会提高线性模型的拟合度。我还会添加一个虚拟变量来表示 CEO 的性别,并探究该术语的权重大小。看看回归模型是否可以通过使用树模型作为管道的一部分来改进也是很有趣的。

有什么建议吗?我很想听听你的想法,无论如何,我可以改进我的分析。请留言评论!还记得吗,我在项目的 GitHub Repo 中包含了我使用的数据和全部代码。

发酵数据可视化:自学 Python 的一个夏天

原文:https://towardsdatascience.com/fermenting-data-visualization-a-summer-of-self-directed-python-learning-7d78dfd10462?source=collection_archive---------14-----------------------

我已经烤面包八年了。在那段时间里,我在食谱上画了一个非常宽泛的路线。但在我的创作中,无论是奶油蛋卷、芋头面包还是 focaccia,有一个重要的不变因素是我使用了活性干酵母。而且理由很充分!商业脱水酵母不油腻,反应灵敏,使烘焙成为一天的活动。

脱水酵母的主要替代品是培养活酵母培养物,也称为发酵剂。对我来说,这是一个令人生畏的复杂性飞跃。与耐储存的干酵母不同,发酵剂是一种活的、动态的微生物群落,需要定期喂食以保持活力。用活菌烘焙可以将你的烘焙周期从三个小时增加到三十个小时——整整一个数量级!

My winsome loaf

但是一片新鲜的酸面团是有嚼劲的,扑鼻的,美味的。今年夏天,当我发现自己有多余的空闲时间时,我决定尝试一下酸奶。抓了野生曲,自学面团水合,买了醒发筐。这是一个耗费时间的过程,但我在这个过程中学到了很多,最终的产品也不算太差。

然而,ourdough 并不是我唯一的暑期项目!在同一时期,我也为自己设定了一个目标,用Python 编程语言来发展自己的技能。Python 是数据科学事实上的脚本语言,这也是我目前的工作领域。就像我对脱水酵母的依赖一样,我过去一直避免使用 Python,而是倾向于使用简单的业务 智能 工具(与结构化查询语言协同使用)来展现、可视化和发布见解。必要性和好奇心偶尔会促使我偶尔涉足 Python,通常是为了执行传统 BI 工具根本不可行的任务,例如访问 API 和管理不同的数据源。但是,总的来说,我很难证明花时间在 Python 中进行分析项目是合理的,否则利用现有的技术资源可以更有效地完成这些项目。

但就像烘焙酸面团一样,对我的领域有更基本了解的前景一直吸引着我。最大的障碍是找时间去追求它。同样,一个自由的夏天给了我这个机会。

构建方法

项目需要时间。更大的项目需要大量的时间。但是时间本身并不足以成功。对于自我指导的项目来说尤其如此,在那里陷阱可能很多。不切实际的目标会让你无法到达终点。定义不当的过程会让你原地打转。非目标导向的任务会只见树木不见森林。为了避免这些陷阱,我需要扩展我的关注点,而不仅仅是提高我的编程技能:我还需要兼职项目管理、冲刺规划、产品策略等等。

That’s a lot of hats!

为了驾驭这些职责,我选择借鉴一下科技行业围绕目标设定的最佳实践。具体来说,我挑战自己说出我对这个项目的最高目标。以下是我想要完成的目标:

  • 学*:特别是我想学* Python 编程语言的基础分析
  • 学*之后,我想将这些知识应用到一个完全原创的项目制作中,让更多的观众感兴趣
  • 最后,我希望自己能够成功地申请到一份需要这些技能的工作,并在这份工作中表现出色

除了帮助我让自己保持在正确的轨道上,这些目标有望为在此过程中做出的任何低级决策提供一些清晰度。从理论上讲,任何一项任务都应该服务于这三个目标中的至少一个;如果不是,我很可能偏离了轨道!

既然我已经陈述了我的目标,我需要想出如何实现它们。这需要一点耐心、研究和计划,但最终将有助于保持我的诚实和正确。概括地说,我开发了以下路线图。:

  1. 一个准备阶段,在这个阶段我将遵循一个有指导的学*课程。这样做有助于我的学*目标。
  2. 一个项目阶段,在这个阶段,我将把我的知识应用到一个自我构思的、原创的任务中。除了巩固我的知识,这个阶段也将满足我的建设目标。
  3. 一个出版阶段,在这个阶段,我会考虑将我的作品分发给观众的最佳方式。这有望推进我的职业目标。

1。准备阶段

为了构建我的项目,我首先需要学*如何构建它。在实践中,这意味着进行线性的、基于课程计划的学*,这在学术界很常见。谢天谢地,这种资源在互联网上随处可见。我的主要工具是以锻炼为重点的在线课程技术手册,以及我发现自己正在努力解决的特定主题的博客/视频博客。

My other study desk

我不会把我的清单作为一个说明性的清单——每个人都有自己喜欢的学*方式。事实上,我优先考虑的甚至不是找到最好的资源。相反,我想找到最能让我顺利完成项目阶段的资源,而不会筋疲力尽。就这一点而言,如果你是那种长时间坐在电脑显示器前会感到疲惫的人,我强烈建议你买一本实体书。确实有一些时候,我认为我学*累坏了,但事实上我只是需要走出家门,在公园的长椅上继续我的学*。呼吸新鲜空气可以创造奇迹!

在许多方面,这一阶段是三个阶段中最直接的。这种方法的结构化和规定的本质意味着我的日常目标通常很简单,比如“花四个小时做 Python 练*”我所有的决定都是战术性的(“我如何应用这个 lambda 函数”),而不是战略性的(“我下一步做什么?”),这是我经常欣赏的。

也就是说,一种预定的、僵化的学*方法也有其缺点。在最糟糕的日子里,我感觉自己就像跑步机上的老鼠。从严格的功利主义角度来看,我发现这些练*的价值随着远离学科的基础而减少。像定制函数和 IO 管理这样的基本概念可能与我最终从事的项目密切相关。相比之下,花一个下午的时间对 Matplolib 图表应用自定义样式就更不合理了。

在这一点上,我将提供一个重要的建议:b 你一定要监控自己的疲劳程度!实现一个特定的目标可能有很多方法,尝试不同的方法可能是突破和崩溃的区别。

2.项目阶段

与其他学科相比,从物质的角度来看,编程是非常容易理解的。理论和应用之间几乎没有逻辑障碍。出于这个原因,人们可以相当快地进入基于项目的学*。我决定,当我超越 Python 的中级功能和它的核心分析库时,我将停止系统化的学*,并将我的重点放在特定项目的开发上。以下是我这样做的主要原因:

  • 动机:我认为一个目标导向的、专注的项目是完美的动机助推器。我已经陷入了“被动学*疲劳”的单调沉闷状态,足以知道什么时候改变是合适的。
  • 重复:我不擅长媒体的重复消费。我很少重新看电影,我不重新阅读书籍,我可能不会喜欢重温相同的编码练*。但我也知道重复是巩固知识的重要工具。鉴于我对死记硬背的厌恶,我将一个项目视为一种不错的方式,来欺骗自己在不同媒介的伪装下重温以前的概念。
  • 陈述:我希望我的过程能够以总结和体现我所有的学*成果而告终。虽然理论上一个课程证书可以满足这个目的,但是我相信一些更独特的东西将会提供一个生动的,容易理解的表现。

One of the earliest known Python applications

当然,这种方法说起来容易做起来难。为一个项目想出一个好主意可能很难,尤其是如果你希望它与一套特定的应用知识重叠的话。也不能保证每个项目都会成功。此外,项目的真实范围可能很难衡量,因此很难预算必要的时间和精力(可能比你想象的要多)。但是,正是这些挑战的存在,使得一个令人印象深刻的项目在投资组合中更加有价值:它的存在本身就可以证明你的奉献精神、创造力和毅力。

对于有抱负的数据鼓吹者来说,有大量的在线资源可以从中找到灵感和材料资源。 Kaggle 是一个特别丰富的公共数据集库,包含了人们如何使用它们的例子。

就我个人而言,我有机会利用来自 Rarebits 的好人的数据集,它包含 Etherium 平台上加密收藏品拍卖数据的标准化表示。虽然我通过交易进行数据分析,但我很快意识到我个人对加密拍卖分类账的兴趣有限,相反,我更感兴趣的是如何在这个数据集上促进分析。有了这些知识,我决定使用 Potly 的 Dash 库来创建一个在线数据可视化仪表板。Dash 库为 web 浏览器中的交互式数据可视化提供了一种高度可定制、易于发布且以 Python 为中心的方法。

你可以在这里看到输出

Interactive scatter visualization of crypto asset auction details

3.出版阶段

随着我的项目本身的完成,我的重点从编码转向了通信。具体来说,我需要思考谁是我的受众,以及我如何才能最有效地与他们沟通。我大致看到了四个可能对我的仪表板感兴趣的主要群体:Python 数据可视化社区、潜在雇主、密码收集爱好者和对自我导向学*感兴趣的人(尤其是围绕编码和数据分析主题)。这些观众中的每一个都有不同的兴趣。

Python 数据爱好者:这些观众最感兴趣的是我的作品的可访问性和可复制性。我想给他们提供干净的、公开的、文档完整的代码。

潜在雇主:除了技术能力的展示,潜在雇主可能会对诸如沟通、项目管理和战略思维等软技能感兴趣。

自我导向的学*者:这些观众主要对我对过程本身的观点和方法感兴趣。对他们来说,项目本身对于产生它的组织上层建筑来说可能是次要的。

加密爱好者:我与这些观众的主要目标是开发一个有趣的工具——也许是实用的。出于时间考虑,我不得不放弃对区块链本身的研究,因此我降低了对专业知识的标准,即“不要听起来像个白痴”

考虑到这些因素,我采取了以下步骤来从我的项目中获得最大的潜在效用:

  • 我使用谷歌应用引擎在网上发布了我的最终产品。这确保了不需要安装 Python 库和下载我的代码,人们可以简单地导航到网站来看我的最终产品。
  • 我把我的代码上传到 Github 。这使得其他程序员(和有抱负的程序员)可以看到我是如何创建我的项目的。我广泛使用了代码注释来帮助提供我的编码选择的上下文。
  • 我写了一个“自述”描述我的项目。这份文档,你可以在 Github 页面上看到,为任何可能好奇的人提供了该项目的简要概述。除了技术上的考虑,我还提出了一点来提供数据集本身的背景。
  • 我接触了我的观众。我在 Plotly 的 Dash 库Reddit 的 Etherium 开发社区的论坛上分享了我的项目。通过这样做,我精心制作了一份针对特定受众的简短的定制信息。

下一步是什么?

现在这个项目已经成为过去,我可以很舒服地说,我对这个过程的进展很满意。在我分配给自己的时间范围内,我设法学*了相当多的 Python,制作了一个项目,我为自己的投资组合中有这个项目而自豪,甚至发现了一两件关于自我导向学*的事情。至于我的找工作……嗯,我刚刚开始着手这个过程。如果事情不顺利,我可以把我的职业生涯转向烘焙。

人工智能和大数据可以改变交通违法区域的几种未来方式开始遵守交通规则

原文:https://towardsdatascience.com/few-futuristic-ways-ai-and-big-data-can-convert-law-breaking-regions-of-traffic-start-following-ba11574681ed?source=collection_archive---------15-----------------------

赛卡特 苏坎特库拉纳

Photo by mauro mora on Unsplash

自 1912 年莱斯特·威尔发明了第一个交通灯以来,情况已经发生了变化,当时他希望它能够向行人和车辆发出信号,要求他们遵循和遵守新制定的道路运输规则和条例。虽然信号传递被证明是成功的,但另一半却没有。

在当今时代,交通已经成为一个经常发展的问题,更是一个所有人口高度密集的主流城市都面临的危险问题。每天,人口呈指数级增长,而道路的大小和管理它们的人员却没有增加,将像班加罗尔这样有湖泊、花园和宁静气氛的城市变成了一个负担过重的城市,无法应对沸腾的权力。

那么,是交通专家睡着了,导致了这场混乱吗?不,这不是所有地方的问题。例如,正如文章“米佐拉姆的驾车者如何遵循一个简单的规则来避免交通堵塞&确保道路无拥堵”[1]中所述,我们可以从视频中推断出那里的交通管理比混乱的印度其他地方更好,其中包括四轮车和两轮车在他们应该驶入的地方有自己的一侧。不用着急,因为所有的车辆都保持稳定的速度,不会互相超车,这足以让任何一辆来自另一条车道的摩托车小心翼翼地开到属于摩托车手的右车道。这种理解的表现是我们解决这一全球性问题的一种方式。

但是,这真的能在各地推行吗?让我们以印度为例,它是人口密度最高的国家之一,却缺乏交通纪律。在德里、班加罗尔、加尔各答、孟买等许多城市,来自不同文化背景的人们在沟通和合作方面仍然存在差距,每个人都有不同的思维方式和需要解决的不同问题。要开发一个中央集权的系统并解决这个问题,我们需要比简单的人类警察管理或人民教育更多的力量。

让我们思考一下这个问题,因为它不仅仅是“交通管理”。我们谈论的是当今城市中非常缺乏的刑事执法。就在最*,我们读到了一篇新闻报道——“一辆汽车在 Wawa 外被盗,车内有两个孩子”[2]。一名妇女将车停在停车场,带着两个孩子快速跑进一家商店,当她五分钟后到达时,车和孩子都不见了。

在最*的交通规则执行调查[3]中,古吉拉特邦 83%的人懒得遵守交通规则,比如戴头盔,这最终会导致他们“把脑袋埋在沙子里”。2016 年,古吉拉特邦有 8136 人在街头事故中丧生,大量死亡是由于伤亡人员没有戴帽子或安全带。

虽然在某些领域人口过多是不利的,但在交通管理领域可能并非如此。直到最*,我们一直试图用人力来解决交通管理问题,虽然我们在一些地方取得了成功,但我们大多都失败了。然而,在这个领域采取大数据和人工智能的方法可以为我们提供不同的结果。

Photo by Richard Lee on Unsplash

我们人类相信我们个人是理性的,然而在集体的场景中,非理性似乎扮演了主要角色,交通管理问题就是证明。为了个人利益的一次自私的超车,或者甚至是一次刹车合并,它会发出一连串的刹车,形成一个链条,吞没所有的交通。然而,人工智能(AI)可以提供帮助。

在迈克尔·伯恩的一篇题为“新的人工智能算法击败了世界上最糟糕的交通”[4]的文章中。他写道,只有 10%的汽车必须连接到网络才能工作。但是这到底是怎么回事呢?

判断力对驾驶有很大影响。人们是贪婪的,他们倾向于主要为自己而不是全人类做好事。这是交通堵塞首先发生的原因之一。但是,如果有一天我们完全从这个系统中移除人类思维,并引入另一个复杂的网络,该网络将连接到运行在其上的每一辆汽车,做出对所有汽车都最优的决策,每一秒钟提供最佳解决方案,会怎么样?那不是很神奇吗?

大多数情况下,事故的发生是因为一些人在开车时睡着了,在酒精或睡意的影响下。然而,假设我们将整个系统自动化,使其根据特定的环境做出正确的决定,并根据以前的经验进行学*,这些问题就永远不会出现。

人工智能需要大数据来做出判断。假设,有一辆自动驾驶汽车在人工智能上运行,它可以规划路线,并相应地在街道上安全移动。这种自动驾驶汽车将如何做出判断,例如从哪里左转,如何避免碰撞,交通信号的状态如何,是否应该根据道路上的交通密度停止或继续移动或加速?对于这些场景和许多其他场景,人工智能需要大量数据的输入——主要来自传感器,来自它所属的网络,反馈机制,等等。所有这些数据都不是相同的格式,因为我们从不同的来源获取数据,因此不能以相同的方式处理。要分析如此大量的非结构化数据,会成为一个大数据问题。

随着世界的增长,数据也在增长,人工智能是一种让连接的机器能够学*、进化和增长的技术,而这只能通过“通过递归实验和人类干预重复和持续更新数据库”来实现[5]。

让我们看看迄今为止一些成功的尝试。Drive.ai 是一家使用深度学*的自主自动驾驶车辆软件创业公司。它专注于“汽车理解周围环境并做出决策所必需的软件”[6]。通过深度学*,人类大脑的工作可以被复制,以便产生可以解决复杂问题的程序。

但是这一切和犯罪有什么关系呢?让我们看看 AI 与大数据结合时的潜力。我们处理的是不遵守规则的流量,这是因为我们给了他们遵守或不遵守规则的选择。如果我们取消这个选项,让一切都自主化,那么人们将不得不接受正在发生的事情,系统非常详细,交通问题的几率将趋于零。现在,这种情况可能只是一个梦想,但不会太久。有些人甚至会认为这是一场噩梦。

你可能会问,我们如何强迫人们只使用自动驾驶汽车,如果他们中的一些人不同意,他们想自己驾驶汽车怎么办?是的,可能是这样。人们大多不会很快接受变化。必须向他们证明,如果建立新系统,它将比现有系统更好,这样它将防止各种不可预见的事件,并降低整体犯罪率。这可能不仅仅是为了驾驶,有了人工智能和大数据,我们可以让车辆的所有部分都变得智能。接下来会发生什么,假设有人试图闯入你的车,他们打破了窗户,你的车会自动向你发出警告信号或某种信息,或者会启动某种紧急协议,阻止罪犯实现他/她想要的。

通过适当的强化学*,这些汽车将被训练在所有类型的地形上行驶,从而消除了我们驾驶它的麻烦。

现在想象一下这样一个系统可以实现什么。如果我们能制造自动警车或机器人,我们就能阻止整个城市的几乎所有犯罪。这是一个遥远的乌托邦或反乌托邦的未来,但却是一个有趣的想法。通过适当的数据挖掘,我们可以实时分析过去几年发生的和现在正在发生的犯罪,可以构建一个系统来分析和发现什么类型的犯罪发生在城市的什么区域。将警力分配到适当的位置并不像我们上面想的那样超前,而是可以很容易实现的事情。这是初创企业应该抓住的一个想法,否则我们可能会自己动手。

这个系统不仅仅可以用于犯罪,我们可以将这个人工智能集成到救护车上。在过去几年中,由于救护车延误,数千人已经死亡。这个人工智能可以做的是,当救护车在街上时,增加救护车的优先级,因此周围的所有其他车辆都将减速并有效地定位自己,以构建一条无障碍的路径,使救护车比平时更快地到达医院。这将在拥挤的城市如加尔各答、孟买、班加罗尔等每年拯救数百人的生命。

不管我们愿不愿意,下一代即将到来。人口每月呈指数增长,只有一种方法可以优化我们的生存——通过智能,即使是人工的。我们很多人不会马上接受这些变化,因为我们已经*惯了。但我们都不得不同意——人类是不可靠的。现在我不是说机器不是,而是改变所有人类的行为和改变少数机器的行为——我们都知道哪一个是可行的。

参考资料:

[1]

https://www . thebetterindia . com/98500/mizo ram-traffic-management/

米佐拉姆的司机如何遵循一个简单的规则来避免交通堵塞&确保道路畅通

经过

Lekshmi Priya S

[2]

https://www . Delaware online . com/story/news/crime/2018/01/05/car-stopped-two-kids-inside/1006445001/

车在瓦瓦外面被偷,里面有两个孩子

经过

约瑟芬·彼得森,新闻杂志

[3]

https://timesofindia . India times . com/city/vado Dara/83-gujaratis-don ' t-give-two-hoots-to-traffic-rules/articleshow/62360310 . CMS

83%的古吉拉特人根本不在乎交通规则

经过

图沙尔泰雷| TNN

[4]

https://motherboard . vice . com/en _ us/article/jp3d n7/new-ai-algorithm-beats-even-the-world-worst-traffic

新的人工智能算法甚至打败了世界上最糟糕的交通

经过

迈克尔·伯恩

[5]

https://hacker noon . com/how-big-data-is-empowering-ai-and-machine-learning-4e 93 a 1004 c8 f

大数据是如何赋能 AI 和机器学*的?

经过

史蒂文·汉森

[6]

https://Mashable . com/2017/09/28/drive ai-lyft-deal/# k 0 ugocxpmmqr

Drive.ai 是自动驾驶汽车领域炙手可热的新公司

经过

贾森

关于:

Saikat Bhattacharyya 先生是一名研究人员,与 Sukant Khurana 博士一起研究人工智能和大数据在打击犯罪中的应用。

Sukant Khurana 博士经营着一个学术研究实验室和几家科技公司。他也是著名的艺术家、作家和演说家。你可以在 www.brainnart.com或 www.dataisnotjustdata.com了解更多关于苏坎特的信息,如果你希望从事生物医学研究、神经科学、可持续发展、人工智能或数据科学项目,为公众谋福利,你可以在 skgroup.iiserk@gmail.com 联系他,或者通过 LinkedInhttps://www.linkedin.com/in/sukant-khurana-755a2343/联系他。

这里有两个关于 Sukant 的小纪录片和一个关于他的公民科学努力的 TEDx 视频。

[## Sukant khu Rana(@ Sukant _ khu Rana)|推特

Sukant Khurana 的最新推文(@Sukant_Khurana)。创始人:https://t.co/WINhSDEuW0 和 3 家生物技术创业公司…

twitter.com](https://twitter.com/Sukant_Khurana)

更少的航班,更大的延误和 JetBlue 糟糕的一年:2017 年美国航空业的 17 张图表

原文:https://towardsdatascience.com/fewer-flights-bigger-delays-and-a-bad-year-for-jetblue-17-charts-on-the-u-s-d718f867b351?source=collection_archive---------11-----------------------

美国航空公司这几年过得多姿多彩。随便看看头条:拖客、爆发动机、大合并

但是标题只是故事的一部分。为了更全面地了解美国航空旅行的现状,我们查阅了数据,并检查了超过 500 万次航班的记录。

这是我们的发现。

1.按城市划分的飞行痛苦

就晚点出发和到达时间而言,往返旅行最糟糕的城市是新泽西州的纽瓦克,其次是纽约和旧金山。同时,准时出发和到达的最佳城市是阿拉斯加的安克雷奇。

虽然有人会认为航班量与晚点的出发和到达密切相关,但实际上仍有一些航班量低的城市表现不佳。例如,印第安纳州韦恩堡的航班量不到纽约的 3%,但准点到达率却比纽约更低。路易斯安那州的巴吞鲁日和纽约州的怀特普莱恩斯也是如此;这两个城市的航班量都很低,但准点率却是所有城市中最低的。

2.航班减少

如果 2018 年旅行感觉比以前更糟糕,那不仅仅是你的怀旧之言。自 2010 年以来,航空旅客可乘坐的航班数量每年减少 100 多万次,而乘客数量却在增加

这些数字是怎么加起来的?从好的方面来看,航空公司在填满所有座位方面做得更好了。2008 年,美国航空公司在国内航班上的座位里程达到了 79.74%。到 2017 年底,这个数字已经上升到 84.57% 。这意味着你不像 10 年前那样喜欢空着的中间座位。

但是还有另一个潜在的因素在起作用;航空公司缩小座位以增加载客量。当你把更多的乘客和托运行李费结合在一起,鼓励顾客把他们所有的东西都装进他们的随身行李时,难怪头顶行李箱空间的耗尽已经成为一个常见的旅行头痛

3.和更多的延迟

快速浏览一下航班准点性能统计,总体延误(蓝条)似乎自 2010 年以来一直保持相对稳定,2013 年和 2014 年有所上升。但是这种乐观的景象得益于时间表填充——航空公司有意计划航班晚点以提高准点率的做法。据《华尔街日报》报道,达美航空自 2009 年以来每年都在增加其日程安排。因此,许多航班提前到达。

当你把所有的早班航班都视为准点到达时,一个不好的模式出现了:实际延误(绿色条)在过去八年中呈上升趋势。

4.价格减免?

乍一看,整合时代似乎压低了美国主要航空公司旅客的平均票价。但是读一下小字。运输统计局的这一数据“只包括购票时支付的价格,不包括行李费等可选服务的费用。”

这是一个很大的警告,特别是在主要航空公司 2017 年* 30%的利润来自行李费的情况下。2016 年的行李费为 42 亿美元,2015 年的行李费为 38 亿美元,相比之下,这一数字达到了 46 亿美元。航空公司也找到了其他新颖的收费方式向消费者收费。在 2015 年第四季度,达美航空销售“舒适+”座位赚了 1.25 亿美元,西南航空一年内在提前检票费用上赚了大约 2.6 亿美元

因此,虽然节俭的旅行者可以找到比以前更好的交易,但普通旅行者会支付更多。

5.捷蓝航空经历了糟糕的 2017 年

唯一一家航班延误和取消统计数据比捷蓝航空更糟糕的航空公司是维珍美国航空公司和已经不存在的维珍美国航空公司。即便如此,它至少在让飞机准时起飞方面做得更好。

另一方面,看看联合航空和达美航空的准点飞行数据。他们的起飞延误与大多数其他航空公司相似,但他们学会了如何在混乱中留下足够的缓冲。虽然批评调度填充是对系统的游戏是公平的,但达美航班在 2017 年有 85%的时间按时或提前到达,胜过除夏威夷航空公司以外的所有其他主要航空公司,夏威夷航空公司的网络更容易管理。

6.不,事实上捷蓝航空的 2017 年非常糟糕

根据 JetBlue 航班的规模和整个行业的平均取消率,JetBlue 应该有大约 950 次因运营商方面的问题而取消的航班。相反,该航空公司的人数几乎是这个数字的两倍(1805 人)。

情况变得更糟。航空公司还对天气和国家航空系统的延误进行过采样,这些延误有时是伪装的承运人延误。

雪上加霜的是,在所有仍在运营的美国主要航空公司中,捷蓝航空的准点率最低,在一个受欢迎的年度航空公司排名系统中,其排名下降了四位。

7.星期二=无机场忧郁日

如果你能灵活安排旅行时间,就准时到达和离开而言,周二和周六是一周中最可靠的日子。周五的延误最严重,其次是周一。

8.早走=少头疼

平均来说,航班起飞的时间越晚,延误越严重。这里的机械问题和那里的天气延迟一整天都在发生。但是,早点飞,一切运行良好。平均而言,午夜至早上 8 点之间起飞的航班往往会提前到达。

9.红眼航班准时到达

爱他们也好,恨他们也罢,凌晨降落的深夜航班一般都是准点的。平均而言,早上 6 点到 10 点之间的航班实际上会提前到达。

10.不要怪航班量

看一下按小时划分的延误图表,很容易将当天晚些时候延误增加归咎于航班量,但数据并没有证实这一点。虽然下午 5 点是最繁忙的时段,但机场交通在早上 8 点至晚上 7 点之间相对稳定,晚上 9 点时段的累积痛苦排名第四,到达或离开的航班数量排名第五。

11.航空公司非常重视感恩节

看看航班准点性能统计,你会发现航班延误在暑假期间最严重,在 11 月最好,这个月包括一年中最繁忙的旅行日之一。

11 月是 2017 年航班晚点率最低的月份。这可能是日程安排的产物,但是 11 月份的航班实际上提前到达了

12.你从未听说过美国第四大航空公司。

就航班数量而言,美国第四大航空公司是 SkyWest。没听说过他们?那是因为他们是一家白标航空公司,经营阿拉斯加、美国、达美和联合航空的业务。

13.洛杉矶和旧金山的空中交通在美国名列前茅

2017 年,旧金山和洛杉矶之间的空中高速公路的原始交通量超过了美国其他地区——而且差距很大。洛杉矶和旧金山以 47%的得票率超过排名第十的洛杉矶和芝加哥。

14.繁忙的天空=更大的延误

在前 200 条最繁忙的航线中,洛杉矶和旧金山也有一些最严重的到达延误。

总的来说,随着航线容量的增加,航班延误越来越严重,但也有一些值得注意的异常值。从纽约到芝加哥的航班平均来说非常准时。相比之下,从佛罗里达到纽瓦克的航班比预计时间晚了很多。

15.为什么不能直飞,第一部分

如果你要去美国最大的城市之一,或者它的主要枢纽之一,你可以很容易地搭乘直达航班。但是如果你想从迈阿密到得梅因,你可能需要在芝加哥停留。

2017 年出行量排名前 200 的航班只连接了 43 个城市,不到美国有机场城市的 14%。

16.为什么你不能乘坐直达航班,第二部分

当你包括所有的航线时,这幅图看起来很不一样。洛杉矶从第 3 位跌至第 13 位。波士顿、华盛顿和奥兰多等主要目的地完全跌出了榜单。与此同时,达拉斯/沃斯堡——在主要路线的连接上甚至没有进入前 15 名——跃升至第 4 名。

17.你不能从这里到达那里

交通统计局在 2017 年的航班和航班延误统计数据中列出了 312 个有机场的城市,但你只能在一家主要航空公司找到其中的 205 个。要到达 107 中的任何一个,你都需要一架私人飞机或一家小型地区性航空公司。

18.垃圾进,垃圾出

总的来说,机场是他们网络的受害者。如果你检查航班准点性能数据,你会发现在机场的平均到达延误和平均离开延误之间有接* 1:1 的关系。但是有些特别糟糕。从好的方面来说,任何从玛莎葡萄园岛或楠塔基特岛旅行的人可能都处于一种放松的心态。

在过去的一年里,飞行给你带来了怎样的变化?你有什么不好的经历想分享吗?欢迎在下面的评论区给我留言。

本帖 原版 最早出现在 Visme 的 视觉学*中心

光纤神经网络

原文:https://towardsdatascience.com/fibre-optic-ai-for-my-apartment-wall-99f2efd4c507?source=collection_archive---------4-----------------------

好莱坞在过去对人工智能(AI)做出了许多重大承诺:它将如何摧毁我们,它将如何拯救我们,以及它将如何给我们带来好处。承诺的一件不太令人难忘的事情是它看起来有多酷。

Jarvis AI interacting with Ultron AI ©Marvel

令人惊叹的人工智能可视化的一个伟大例子是在《复仇者联盟》中,当托尼·斯塔克的人工智能巴特勒·贾维斯与奥创互动时,我们看到了这个光变形和脉动的有机浮动网络。

我想做一些类似的东西来填补我公寓墙上的一些空白(应该比通常的宜家艺术要好)。很明显,我不可能再创造出像漂浮的光球贾维斯那样神奇的东西。然而,有一种机器学*算法,通过一些古怪的数据可视化看起来很有趣:神经网络!它采用了生物灵感元素,旨在复制人类大脑的工作方式(我们认为)。

如果你还不熟悉机器学*中的神经网络:它们受到大脑中生物神经元的启发。网络中的每个节点与网络中的其他节点相连。当信号流经网络时,节点之间的连接会改变信号,直到信号到达网络的末端。在算法训练阶段学*连接调整信号的具体方式。

neural network algorithm structure (https://en.wikipedia.org/wiki/Artificial_neural_network)

我着手用光重建一个神经网络。对于我在半透明塑料中 3D 打印出定制形状的节点,以及节点之间的连接,我使用了所谓的侧发光光纤,这是普通的光纤管道,沿着管道的长度发光(看起来非常科幻)。

The fruits of painstaking soldering and gluing. (more images of its making here)

实际的光源是一个 RGB LED 条,它被费力地切割、焊接和粘合到每个节点上(每个节点需要大约 30 分钟来安装电子设备)。

告诉 LED 做什么的组件是一个 Arduino 板,它由一个小 Raspberry Pi Zero 告诉它做什么,这使整个事情与 WiFi 连接!

现在它是如何工作的!?光网络本身就是一个美化了的 WiFi 灯。真正的人工智能运行在我连接到同一个 WiFi 的笔记本电脑上。我写了一段方便的代码,插入到我的标准神经网络编程环境中,当我训练我的算法时,它将连接值(绿色=高值,红色=低值,蓝色=接*零)实时发送到光网络。然后我就可以亲眼看到我的神经网络学*了!!!

Voilà! A physical light visualisation of AI learning!

它现在将快乐地生活在我的墙上,作为人工智能的光辉象征!

(graph 1) Data that the neural network is learning from

那么它在学*什么呢?G raph 1 是神经网络试图复制的数据模式。仅基于 x 和 y 值(图中的特征 1 和特征 2),神经网络将尝试输出正确的分类(图中的颜色)。下面是另一个动画,展示了光线网络沿着它的预测数据倾斜。正如你所看到的,数据点的颜色不断变化,直到它们与原始数据非常接*,这就是学*!

The light network learning along side its live predictions for the data

关于该项目的所有细节技术信息以及所有代码,你可以在我的 Github->【https://github.com/ZackAkil/rgb-neural-net上找到。

2018 年世界杯:数据驱动的理想球队阵容方法

原文:https://towardsdatascience.com/fifa-world-cup-2018-a-data-driven-approach-to-ideal-team-line-ups-93505cfe36f8?source=collection_archive---------6-----------------------

随着 2018 年俄罗斯世界杯的到来,世界各地的每个足球迷都渴望预测今年哪个队会赢。对于球迷来说,另一个迫在眉睫的问题是他们最喜欢的国家队应该如何排队:应该使用什么阵型?应该选哪些球员?哪些人应该留在替补席上或从锦标赛中淘汰?

作为一个狂热的足球迷,我开始思考:为什么我不能在世界杯上为我最喜欢的球队建立自己的梦之队?作为一个热爱数据科学并在玩 FIFA 长大的人,我意识到我可以使用 EA Sport 去年发布的非常受欢迎的视频游戏 FIFA18 中的数据来做我的分析。

在这篇博文中,我将一步一步地向你介绍我在本届世界杯上为 8 支公认的最佳球队打造最强大阵容的方法:法国、德国、西班牙、英格兰、巴西、阿根廷、比利时和葡萄牙。

FIFA 18 数据集

我在 Kaggle 上找到了 FIFA18 数据集。该数据集包含 17,000 多名 FIFA18 中的球员,每名球员都有 70 多种属性。它是从网站 SoFiFa 通过提取玩家的个人数据、ID、玩法&风格统计数据刮来的。有各种有趣的特点,如球员价值,工资,年龄,和性能评级,我真的很想挖掘。

加载数据后,我只选择了我想分析的最感兴趣的列:

interesting_columns = [
    'Name', 
    'Age',  
    'Nationality', 
    'Overall', 
    'Potential', 
    'Club', 
    'Value', 
    'Wage', 
    'Preferred Positions'
]
FIFA18 = pd.DataFrame(FIFA18, columns=interesting_columns)

以下是根据数据集中的总体评分快速查看的前 5 名玩家:

数据可视化

为了让你更好地理解这个数据集,我对球员的年龄、总体情况、首选位置、国籍、价值和工资做了一些可视化处理。让我们逐一查看:

正如你所看到的,大多数玩家年龄在 20 到 26 岁之间,巅峰时期在 25 岁。

该图呈正态分布,平均综合评分为 66 分。

这里,球员最喜欢的 4 个位置依次是中后卫、前锋、守门员和中场。

我使用包 plot.ly 来绘制玩家国籍的地理可视化。如你所见,玩家在欧洲非常集中。准确地说,是英国、德国、西班牙和法国。

在价值方面,我做了一个散点图,展示了球员的年龄和总体评价。峰值似乎相应地落在 28-33 岁的年龄范围和 90+的总评分上。

在工资方面,我还做了一个散点图,显示了球员的年龄和总体评分。随着年龄范围从 30 岁到 33 岁以及总体评分为 90 分以上,最高工资似乎会相应下降。

最佳阵容分析

好吧,让我们为国家队建立一些最佳阵型。为了简化分析,我只引入我感兴趣的数据:

FIFA18 = FIFA18[['Name', 'Age', 'Nationality', 'Overall', 'Potential', 'Club', 'Position', 'Value', 'Wage']]
FIFA18.head(10)

我写了两个非常重要的函数, get_best_squad_n (给定一个球队阵型和球员的国籍,完全根据总体评分返回在各自位置上拥有最佳球员的球队)和 get_summary_n (给定一个球队阵型选择和国家队的列表,根据各个阵型中球员的平均总体评分比较这些不同的阵型)。

我也使阵容选择更加严格:

squad_343_strict = ['GK', 'CB', 'CB', 'CB', 'RB|RWB', 'CM|CDM', 'CM|CDM', 'LB|LWB', 'RM|RW', 'ST|CF', 'LM|LW']squad_442_strict = ['GK', 'RB|RWB', 'CB', 'CB', 'LB|LWB', 'RM', 'CM|CDM', 'CM|CAM', 'LM', 'ST|CF', 'ST|CF']squad_4312_strict = ['GK', 'RB|RWB', 'CB', 'CB', 'LB|LWB', 'CM|CDM', 'CM|CAM|CDM', 'CM|CAM|CDM', 'CAM|CF', 'ST|CF', 'ST|CF']squad_433_strict = ['GK', 'RB|RWB', 'CB', 'CB', 'LB|LWB', 'CM|CDM', 'CM|CAM|CDM', 'CM|CAM|CDM', 'RM|RW', 'ST|CF', 'LM|LW']squad_4231_strict = ['GK', 'RB|RWB', 'CB', 'CB', 'LB|LWB', 'CM|CDM', 'CM|CDM', 'RM|RW', 'CAM', 'LM|LW', 'ST|CF']squad_list = [squad_343_strict, squad_442_strict, squad_4312_strict, squad_433_strict, squad_4231_strict]squad_name = ['3-4-3', '4-4-2', '4-3-1-2', '4-3-3', '4-2-3-1']

1 —法国

让我们探索法国不同阵容的可能性,以及它如何影响收视率。

France = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['France'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall']) France.set_index('Nationality', inplace = **True**) France['Overall'] = France['Overall'].astype(float) print (France)

让我们来看看 4-3-3 阵容中最好的 11 名法国球员。

rating_433_FR_Overall, best_list_433_FR_Overall = get_best_squad_n(squad_433_strict, 'France', 'Overall')print('-Overall-')
print('Average rating: **{:.1f}**'.format(rating_433_FR_Overall))
print(best_list_433_FR_Overall)

Antoine Griezmann

2 —德国

卫冕冠军肯定是今年第一名的有力竞争者。

Germany = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['Germany'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall'])Germany.set_index('Nationality', inplace = **True**)Germany['Overall'] = Germany['Overall'].astype(float)print (Germany)

正如你所看到的,德国目前的收视率在 3-4-3 或 4-3-3 阵型中达到顶峰。我将采用 4–3–3 选项。

rating_433_GER_Overall, best_list_433_GER_Overall = get_best_squad_n(squad_433_strict, 'Germany', 'Overall')print('-Overall-')
print('Average rating: **{:.1f}**'.format(rating_433_GER_Overall))
print(best_list_433_GER_Overall)

Toni Kroos

3 —西班牙

2010 年的冠军怎么样?

Spain = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['Spain'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall'])Spain.set_index('Nationality', inplace = **True**)Spain['Overall'] = Spain['Overall'].astype(float)print (Spain)

好吧,西班牙在 4-3-3 或者 4-2-3-1 上表现最好。出于多样性考虑,我会选择 4–2–3–1 阵型。

rating_4231_ESP_Overall, best_list_4231_ESP_Overall = get_best_squad_n(squad_4231_strict, 'Spain', 'Overall')print('-Overall-')
print('Average rating: **{:.1f}**'.format(rating_4231_ESP_Overall))
print(best_list_4231_ESP_Overall)

Sergio Ramos

4 —英格兰

尽管拥有欧洲最好的足球联赛,英格兰似乎在国家层面做得并不好。让我们来看看他们对即将到来的世界杯有什么选择:

England = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['England'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall'])England.set_index('Nationality', inplace = **True**)England['Overall'] = England['Overall'].astype(float)print (England)

那么英格兰应该坚持 4-3-3。

rating_433_ENG_Overall, best_list_433_ENG_Overall = get_best_squad_n(squad_433_strict, 'England', 'Overall') print('-Overall-') 
print('Average rating: **{:.1f}**'.format(rating_433_ENG_Overall)) print(best_list_433_ENG_Overall)

Harry Kane

5 —巴西

桑巴队赢得了历史上最多的世界杯冠军,毫无疑问,它将是今年夏天俄罗斯世界杯的最大热门之一。

Brazil = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['Brazil'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall'])Brazil.set_index('Nationality', inplace = **True**)Brazil['Overall'] = Brazil['Overall'].astype(float)print (Brazil)

如你所见,巴西和英格兰有相似的选择。全程 4-3-3。

rating_433_BRA_Overall, best_list_433_BRA_Overall = get_best_squad_n(squad_433_strict, 'Brazil', 'Overall')print('-Overall-')
print('Average rating: **{:.1f}**'.format(rating_433_BRA_Overall))
print(best_list_433_BRA_Overall)

Neymar

6 —阿根廷

莱昂内尔·梅西还在等待他职业生涯中唯一一个还没有拿到的奖杯。在 4 年前决赛失利后,他能带领阿根廷登顶吗?

Argentina = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['Argentina'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall'])Argentina.set_index('Nationality', inplace = **True**)Argentina['Overall'] = Argentina['Overall'].astype(float)print (Argentina)

3-4-3 和 4-3-3 对阿根廷球员来说都很好。我会选择 3–4–3。

rating_343_ARG_Overall, best_list_343_ARG_Overall = get_best_squad_n(squad_343_strict, 'Argentina', 'Overall')print('-Overall-')
print('Average rating: **{:.1f}**'.format(rating_343_ARG_Overall))
print(best_list_343_ARG_Overall)

Lionel Messi

7 —比利时

红魔拥有一些英超联赛中最好的球员,但似乎永远无法在国家队中取得成功。哈扎德和德·布鲁因这次能把他们逼远吗?

Belgium = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['Belgium'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall'])Belgium.set_index('Nationality', inplace = **True**)Belgium['Overall'] = Belgium['Overall'].astype(float)print (Belgium)

同样,4-3-3 是比利时的最佳阵型。

rating_433_BEL_Overall, best_list_433_BEL_Overall = get_best_squad_n(squad_433_strict, 'Belgium', 'Overall')print('-Overall-')
print('Average rating: **{:.1f}**'.format(rating_433_BEL_Overall))
print(best_list_433_BEL_Overall)

Kevin De Bruyne

8 —葡萄牙

2016 年欧洲杯的冠军和连续三次获得世界最佳球员的克里斯蒂亚诺·罗纳尔多也有机会参加这次比赛。

Portugal = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['Portugal'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall'])Portugal.set_index('Nationality', inplace = **True**)Portugal['Overall'] = Portugal['Overall'].astype(float)print (Portugal)

好吧,我选葡萄牙 4-2-3-1。

rating_4231_POR_Overall, best_list_4231_POR_Overall = get_best_squad_n(squad_4231_strict, 'Portugal', 'Overall')print('-Overall-')
print('Average rating: **{:.1f}**'.format(rating_4231_POR_Overall))
print(best_list_4231_POR_Overall)

Cristiano Ronaldo

9 —乌拉圭

乌拉圭拥有欧洲最好的两名前锋:苏亚雷斯和卡瓦尼。他们这次能表演吗?

Uruguay = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['Uruguay'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall', 'Potential'])Uruguay.set_index('Nationality', inplace = **True**)Uruguay[['Overall', 'Potential']] = Uruguay[['Overall', 'Potential']].astype(float)

print (Uruguay)

太棒了,乌拉圭以 4-3-1-2 的比分表现最好。

Edison Cavani

10 —克罗地亚

嗯,我是莫德里奇和拉基蒂奇的超级粉丝。他们的中奖*惯就不用说了吧?

Croatia = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['Croatia'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall', 'Potential'])Croatia.set_index('Nationality', inplace = **True**)Croatia[['Overall', 'Potential']] = Croatia[['Overall', 'Potential']].astype(float)

print (Croatia)

毒品,克罗地亚以 4-2-3-1 领先。

Luka Modric

最终比较

好的,让我们将这 10 个阵容与这些 2018 年世界杯最强竞争者的球员的当前评级进行一些比较。

所以纯粹基于 FIFA 18 的数据:

  • 西班牙的平均综合评分最高,其次是德国和巴西。
  • 德国总值最高,其次是西班牙和法国。
  • 西班牙的平均工资最高,其次是德国和巴西。

我的赌注是 T2 对法国,第三名是 T4 对巴西。而 Les Bleus 将会赢得一切!你有什么想法?

你可以通过这个链接查看我的 GitHub repo 中的所有源代码(https://github.com/khanhnamle1994/fifa18)。如果您有任何问题或改进建议,请告诉我!

— —

如果你喜欢这首曲子,我希望你能按下拍手按钮👏因此其他人可能会偶然发现它。你可以在GitHub上找到我自己的代码,更多我的写作和项目在【https://jameskle.com/】上。也可以在 上关注我推特 直接发邮件给我 或者 在 LinkedIn 上找我 注册我的简讯 就在你的收件箱里接收我关于数据科学、机器学*和人工智能的最新想法吧!

利用最大似然技术预测 2018 年世界杯

原文:https://towardsdatascience.com/fifa-world-cup-2018-predictions-using-ml-techniques-48354e22cd8?source=collection_archive---------4-----------------------

嘿机器学*,谁会是下一届世界杯冠军?

我的预测?比利时将成为冠军。

但似乎我的很多朋友,包括我的线性回归模型和神经网络模型,都偏爱巴西。

暑假我正在自学机器学*模型,FIFA 世界杯现在就在我们脚下!所以我在想:为什么不做一个用 ML 模型预测世界杯结果的实践项目呢?

我为期三天的预测之旅开始了!

第一天:玩数据集

真正引发我开始这个项目的兴趣的数据集实际上是这个 Kaggle 的数据集(嗯,如果你订阅了 Kaggle,它刚刚出现在我的电子邮件中)。该数据集包含自 1930 年以来 FIFA 世界杯的所有比赛、球员和冠军。我甚至受到启发,建立了一个模型,其中包含玩家在比赛中的属性,因为玩家对游戏的胜利做出了重大贡献,我们可以访问数据集中的这条信息。

但是最后,我个人觉得这个数据集太乱了,里面塞满了太多不必要的数据。然后我偶然发现了这个数据集,里面有所有国际足球比赛的信息。在这篇中型文章中提到了 ML 结果预测,尽管文章中的模型使用了逻辑回归。我个人更喜欢这个数据集,因为:

  • 它只有 1 张 csv 表(哈哈!)
  • 当我们做预测时,我们不仅应该关注世界杯比赛,还应该关注其他国际比赛
  • 通过使用所有国际比赛的数据,我们应该有一个更大的训练数据量,这应该可以提高我们的预测性能

基本上,数据集包含一场比赛的年份日期、两队的名称两队的得分比赛类型城市国家中立(无论比赛是否在任何一队自己的地点举行)。所以我会说这个数据集相对来说更干净,简洁,而且直截了当。

设置属性和数据预处理

我从这一部分学到的一个重要教训是数据总是又脏又乱。我打了一个比方,将数据科学比作烹饪——首先,数据就像你的肉和蔬菜。挑选那些新鲜、干净、最适合你的。

就像一个厨师并不真的需要使用很酷的技术来烟熏或液氮来烧烤他的食物,因为他的主要目标是用简单的方法为他的食客提供美味的食物。对于一个数据科学家来说,这是类似的——我们并不真的需要建立一个非常花哨、复杂的 ML 模型(除非复杂的任务需要),但主要目的是能够从你挑选的数据中辨别事物。

关键是 你如何分辨事物 —在这种情况下,你选择的是哪个 属性

这些是我总结出来的属性,非常简单易懂:

在预测的时候,我们应该考虑球队在比赛举办年份的排名。如果没有数据,我的处理方式是放一个大数(我用的是 200,因为球队不到 200)作为排名。

  • 中奖数和抽奖数

在她所有的国际比赛中,意味着一个队的胜利和平局。不需要丢失计数,因为它只是两者的补充。

  • 一队净胜球

在她所有的国际比赛中,净胜球意味着一个团队的。如果 A 队和 B 队打了一场 5 比 0 的比赛,那么 A 队的净胜球是 5,B 队是-5。这不仅仅是衡量输赢,而是衡量团队能在多大程度上赢得比赛。

  • 对对手的赢数和平局数

基本上是比赛中两队的比赛历史。注意,我们应该注意比赛的日期,只考虑过去的比赛历史数据

看一支球队是否在自己的国家比赛。

这也是我在 pandas 上练*的机会,这是一个非常方便的数据操作库。所以我写的第一个脚本是FIFA-results-preprocess . py,主要是从 results.csv 中的原始数据生成我想要的属性。

有一点要分享的是——这个脚本运行了大约 18 分钟!原因是对于每一行比赛数据,我们必须计算两个队的比赛历史。对于该计算,我们需要遍历特定行之前的所有行,因为我们的数据是按时间顺序排列的。这显然需要 O(n)。

预处理生成了 results_processed.csv ,我手动删除了一些列以得到results _ processed _ dev . CSV

第二天:机器学*日

将大蒜和洋葱切碎,牛肉切片,你就可以开始做菜了。

所以基本上这个预测任务可以被框定为一个分类任务。给定这些属性,我们将对主队是输(0 类)、赢(1 类)还是平(2 类)进行分类。

我首先尝试使用我的脚本 fifa-ml.py 将我的数据输入几种类型的分类器。令人震惊的是,所有分类器返回的训练和测试准确率都在大约 55% 左右,并且没有一个分类器优于另一个。

所以,我宁愿在最后使用线性回归,因为它没有太大的区别。线性回归器可以被认为是一个一层神经网络,接受 n 个特征并最终返回每个逻辑的概率。在这种情况下,它返回比赛中主队的赢、输和平局概率。你也可以使用逻辑回归,只是在我看来,在这个特定的任务中,两者做同样的事情。

请注意,对于线性回归,所有 Y 示例都需要进行一次热编码。在 sklearn 中,我是通过使用一个 LabelBinarizer 来完成的;在 Keras 中,我通过to _ categorial()来实现。

我做到了!我在这里附上了对淘汰赛的预测:

所以前 4 名球队是:巴西,西班牙,阿根廷,德国。

完整结果(包括小组赛结果和概率),查看这里:results _ predict _ output _ final . CSV

第三天:神经网络日

然后我就在想:既然经典的分类器都做不好,那么神经网络的表现会更好吗?于是我用 Keras 想出了一个神经网络脚本: fifa-ml-nn.py

答案是否定的。

即使对于具有许多隐藏单元的大型网络,其准确度似乎也只是缓慢地收敛到 55%左右(有时略高,NN 是我唯一达到 59%测试准确度的模型,这是目前最高的)。但我有 300、500 甚至 1024 个单元的密集层,但性能仅提升了不到 5%。不值得。

尽管如此,NN 的预测和 LR 的预测之间还是有细微的差别。让我在这里附上 NN 对淘汰赛阶段的预测:

所以这次的前 4 名球队是:巴西、西班牙、德国、葡萄牙。

完整结果(包括小组赛结果和概率),查看这里:results _ predict _ output _ nn _ final . CSV

结论和调查结果

我想说,这是一个非常好的数据科学入门迷你项目,它经历了数据争论、提出分类属性和实现分类模型的整个过程。

我的结论是 足球比赛保持不可预测 ,当我读到这篇 LinkedIn 帖子时,我完全同意的观点。帖子甚至附上了这篇论文使用随机森林并融入大量属性进行预测,但仍然无法做出准确的预测。

使用 ML 并不能预测所有的事情。它有其局限性。

对于我的模型,我只能说,像巴西、西班牙和德国这样的球队更倾向于我设置的属性,这主要是考虑到一支球队的获胜统计数据。但我们都知道,赢得历史并不能说明什么——毕竟,当我写这篇博客的时候,德国已经被强大的韩国以 2 比 0 淘汰了。

总而言之,预测在这里并不是最重要的。最重要的是学*处理数据的技巧,从中讲述故事,最后但同样重要的是… 全力支持比利时!

原载于gud gud 96 . github . io

用人工智能对抗癌症:第 0 部分——深度学*

原文:https://towardsdatascience.com/fighting-cancer-with-artificial-intelligencepart-0-deep-learning-a6f0b375c8c?source=collection_archive---------3-----------------------

Cutaneous anaplastic large cell lymphoma (ALCL) By L. Wozniak & K. W. Zielinski — Own work, CC BY-SA 3.0

今年 8 月,我听到了没有人想从他们的医生那里听到的话:“你得了癌症。”我被诊断患有一种罕见的非霍奇金淋巴瘤。经过几周混乱的测试和第二意见后,很明显我的预测是好的。几个月的治疗让我开始思考我的运气;尽管我不得不忍受癌症,但我很幸运有一个良好的预后。我发现自己在思考一个古老的问题,“这有什么原因吗?”

在这段时间里,我真正开始钻研数据科学。我开始思考机器学*(ML)和人工智能(AI)对癌症治疗的影响及其对预后的影响。鉴于我的情况,我想知道我是否应该开始专注于研究数据科学的这个领域。这篇文章是这样做的第一步。

2018 年 1 月 12 日星期五,我的医生很高兴地告诉我,我的 PET 扫描结果很清楚。这一系列文章对我来说是一种庆祝和宣泄。在第一篇文章中,我将介绍深度学*。

深度学*正在开发,以帮助阅读放射学扫描 (PET/CT,MRI,X 射线等)。)以提高癌症的早期检测,帮助减少乳腺癌筛查中的假阳性和不必要的手术,以实现结肠直肠癌筛查期间息肉的*实时分析,以及其他提高检测的方法。我将在随后的文章中看到这些。

什么是深度学*?

由于我将探索的大多数与癌症诊断相关的工作都严重依赖于深度学*,所以我决定该系列应该从深度学*的一些基础知识的简短介绍开始。
免责声明:我不是深度学*方面的专家,但我已经对这篇文章的准确性进行了审查。

深度学*是机器学*领域中人工智能的子集。它使用大型神经网络来学*数据中哪些特征是重要的,以及如何利用这些特征来预测新数据集[ 123 ]。

我们所说的(有监督的)学*是什么意思?嗯,机器学*算法需要三样东西才能发挥作用:输入数据,预期输出的例子(训练数据,以及一个反馈信号来表明算法执行得有多好。本质上,机器学*算法以一种有用的方式转换数据,从而产生有意义的输出。例如,我将查阅的一篇论文拍摄了一张皮肤病变的手机照片,并输出了该病变是否为恶性的预测。因此,在这种情况下,学*就是自动寻找更好的表达方式。

FIG 1: Diagram of a multi-layer feedforward artificial neural network. By Chrislb (derivative work: — HELLKNOWZ, TALK, enWP TALK ), CC BY-SA 3.0 via Wikimedia Commons

我说深度学*用的是大型神经网络,但是是什么是神经网络?神经网络是基于人类对大脑的理解。与大脑不同,在大脑中,神经元可以与任何其他神经元建立连接,神经网络被离散成具有信息流方向性的层[ 45 ]。这在图 1 的中进行了说明。数据被传递到第一层神经元并被处理。处理后的输出被向前传递到另一层,依此类推,直到它返回一个结果。

神经网络的基础——神经元

神经网络由称为神经元的类似物组成。我们将看看神经元的两种常见实现:感知器和 sigmoid 神经元[ 1 ]。历史上,神经网络起源于感知器。感知器最初是在 20 世纪 50 年代和 60 年代由弗兰克·罗森布拉特(Frank Rosenblatt)提出的。

一个感知机本质上表现得像一个逻辑门 [ 3456 。如果你对逻辑门不熟悉,它们是实现布尔逻辑[ 346 ]的模拟电路。它们将获取输入值并对其进行处理,以确定是否满足特定条件[ 图 2 ]。

FIG 2: A schematic representation of a neuron. The inputs, X, are weighted (indicated by the varying width of the arrows) and processed by the neuron’s activation function producing the output, y.

一个特别重要的门是与非门(一个负与门)。与非门在计算中是通用的,这意味着任何其他布尔函数都可以表示为与非门[ 178 ]的组合。这种想法的含义是,由于感知器可以实现与非门,感知器在计算中也是通用的[ 1 ]。

FIG 3: Illustration of the threshold function. This variation has a third component: if the product of the inputs is equal to the bias, that is they sum to zero, the output is 0.5. By PAR~commonswiki, CC-BY-SA-3.0 via Wikimedia Commons

神经元的两种实现在它们的激活/传递函数(决定神经元是开还是关的方程)[ 15 ]上有所不同。罗森布拉特感知机的美妙之处在于它的简单性。感知器将接受输入,并根据它们的权重组合它们,如果输入表明被分析的对象是该类的成员,则输出值 1,如果不是成员,则输出值 0[图 2 ]。感知器使用阈值函数,该函数将输出值 0,除非加权输入的和大于感知器的偏差阈值,在这种情况下,它将输出 1 [ 图 3图 4

阈值函数的问题是,感知器的权重或偏差的微小变化会在输出[ 1 ]的行为中产生难以控制的结果。这是因为激活函数的全有或全无性质。当试图优化神经元网络时,这就成了一个问题。

FIG 4: Vector representations of the activation functions of the two main types of neurons.

我们可以通过使用一个 sigmoid 函数 [ 图 5 ]而不是阈值函数来避免这个问题。

FIG 5: Illustration the the sigmoid function. Public Domain via Wikimedia Commons

sigmoid 函数(也称为逻辑函数,因为它是所用 sigmoid 函数的特殊形式)具有扁平 S 形的特性[ 图 5 ]。这与阈值函数曲线的“开/关”形状相比较[ 图 3 ]。

sigmoid 函数为神经元的输出产生更平滑的过渡。当我们接*图形的边缘时,神经元的行为就像感知器输出大约 0 或 1。神经元将随着 wx + b 的值变大而开启,随着其变小而关闭。零附*的区域是我们行为变化最大的地方。这个平滑和连续的区域允许我们对感知器的权重和偏差进行小的改变,而不会产生阈值函数可能产生的输出的大的改变。事实上,乙状结肠神经元是这些权重和偏差变化的线性函数[ 1 ]。这两个函数之间的另一个区别是,sigmoid 函数的允许输出是 0 和 1 之间的任何值,而 threshold 函数将输出 0 或 1 [ 1 ]。这对于确定某些特征是有用的,但是当应用于分类时就不那么清楚了[ 1 ]。解释这个单个神经元输出的一种方法是作为属于正在讨论的类别的概率。

将神经元结合成网络

单个神经元对于做出单个决定是有用的,但是我们如何扩展它们的有用性呢?在图 1 中,网络显示多个神经元可以组合起来组成一层神经元。只看图中的输入层,我们可以看到它由三个神经元组成,因此它能够做出三个非常简单的决策(尽管由于有两个输出神经元,网络本身只会进行两种分类)。我们可以通过增加层中神经元的数量来扩展简单决策的数量。该层的输出是数据[ 12 ]的表示。理想情况下,该表示提供了对正在解决的问题的一些洞察[ 图 6 ]。

FIG 6: Example mean activation shapes in a learned hierarchy. These are the representations of the data that are learned by the network. ViCoS Lab

神经元层可以堆叠起来进一步处理数据。我们可以把每一个后续层看作是获取前一层的输出,并进一步提取数据中包含的信息。多层网络能够提取足够的数据来做出复杂的决策。

FIG 7: A schematic representation of a multi-layer neural network. The input layer takes data from X and processes it and passes it to the first hidden layer. Each hidden layer processes and passes the data to the next. The output layer makes a prediction that is an array of probabilities of the input belonging to each of the possible classes. The result is checked by the loss function to determine the networks accuracy and this is passed to the optimizer which adjusts the weights of the information passing to each layer.

图 7 中显示了一个多层网络的例子。一些输入数据由神经网络的第一层转换(输入层)。转换后的数据由第二层处理(称为隐藏层,因为它既不是输入也不是输出)[ 1 。这个输出将或者到下一个隐藏层或者到输出层。输出层将返回一个概率分数数组(其总和为 1) [ 2 ]。

网络的输出通过损失函数(或反馈信号)进行分析,该函数测量预测的准确性 2 。网络的权重由一个优化器** [ 2 ]改变。**

****FIG 8: A schematic of the information flow during optimization. The data loss shows the difference between the scores and the labels. The regularization loss is only dependent on the weights. Gradient descent allows us to find the slope of the weights and update them. Optimization: Stochastic Gradient Descent.

优化器使用梯度下降来确定如何更新权重。本质上,该算法遵循损失函数表面的斜率,直到找到一个谷[ 34图 8 ]。该信息通过反向传播的过程得到增强:“反向传播可以[……]被认为是门相互通信(通过梯度信号)它们是否希望它们的输出增加或减少(以及多强烈),以便使最终输出值更高” 5 。反向传播提供了关于改变权重和偏差将如何影响整个网络的详细信息。[ 6

****FIG 9: Detailed activation of neurons in five layers. The activations show the representations that are deemed important by the network. Zeiler and Fergus, 2013.

包裹

总而言之:

  • 深度学*在癌症检测、活检分析中发挥着重要作用,并为在难以找到医生的地区增加筛查提供了可能性
  • 神经网络的基本构件是神经元
  • 神经元可以用不同的激活函数起作用,每个激活函数都有其优点和缺点
  • 神经元可以堆叠成层,并且这些层可以堆叠在一起,这增加了网络可以做出的决策的复杂性
  • 这些决策提供了数据的新表示[ 图 6图 9 ],这些数据有望提供洞察力
  • 可以使用损失函数和反向传播来优化神经元的输出,以提高网络的复杂度

感谢伊尔胡姆·沙夫卡特约翰·比约恩·尼尔森阅读我的草稿,提出很好的建议并确保准确性。我还要感谢我的妻子校对并提出建议,以提高本文的流畅度和清晰度。我要特别感谢我的朋友们,他们对技术的不同熟悉程度让我确信这能被广大的观众所接受。

我希望您喜欢这篇关于深度学*的介绍,并会回来阅读本系列的下一篇文章。关注我获取新帖子通知;留下评论让我知道你的想法;发送带有反馈的推文或开始对话;或者看看我的项目组合

参考

标题将链接到适当的资源,而[^将带你回到你正在阅读的部分。

什么是深度学*?

****【1】机器学*精通。什么是深度学*?^
【2】英伟达博客。AI 和 ML 有什么区别?【^】
【3】技术评审。深度学*:凭借海量的计算能力,机器现在可以实时识别物体和翻译语音。人工智能终于变聪明了。^
【4】弗朗索瓦·乔莱。用 Python 进行深度学*。第一章。[【^】
迈克尔尼尔森神经网络和深度学*。第一章。^

神经网络的基础——神经元

迈克尔·尼尔森神经网络和深度学*。第一章。【
【2】维基百科。弗兰克·罗森布拉特——感知器。【^
【3】维基百科。逻辑门。^
【4】数据怀疑论者。前馈神经网络。[^]
凯文·斯温勒。第二讲:单层感知器。^,弗朗西斯克·卡米洛。逻辑门的神经表示。【^】
【7】百科。与非门。【^
维基百科。与非门逻辑——利用与非门制作其他门。^

将神经元结合成网络

迈克尔·尼尔森神经网络和深度学*。第一章。[^
【2】弗朗索瓦·乔莱。用 Python 进行深度学*。第二章。[^]
【3】塞巴斯蒂安·鲁德。梯度下降优化算法概述。【^
【4】安德烈·卡帕西CS231n:视觉识别的卷积神经网络优化:随机梯度下降。【^
安德烈·卡帕西CS231n:视觉识别的卷积神经网络反向传播,直觉。【^
迈克尔尼尔森神经网络和深度学*。第二章。^

Pandas、Tidyverse、Pyspark 和 SQL 中的过滤、聚合和连接

原文:https://towardsdatascience.com/filter-aggregate-and-join-in-pandas-tidyverse-pyspark-and-sql-71d60cbd5330?source=collection_archive---------17-----------------------

Alike but different (Source)

祝福与诅咒

鼓舞人心的数据科学家最常问的一个问题是,他们应该为数据科学学*哪种语言。最初的选择通常是在 Python 和 r 之间。已经有很多对话可以帮助做出语言选择(这里的和这里的)。选择合适的语言是第一步,但我怀疑大多数人最终只使用一种语言。在我个人的旅程中,我先学了 R,然后是 SQL,再后来是 Python,再后来是 Spark。现在在我的日常工作中,我使用所有这些工具,因为我发现每个工具都有独特的优势(在速度、易用性、可视化等方面)。有些人确实只停留在一个阵营(有些 Python 人从未想过学* R),但是我更喜欢使用现有的东西来创建我的最佳数据解决方案,并且使用多种数据语言有助于我与不同团队的协作。

正如机器学*的状态所指出的,我们面临着在数据团队中支持多种语言的挑战,跨语言工作的一个不利方面是我会把一种语言与另一种语言混淆,因为它们可能有非常相似的语法。考虑到我们拥有一个多种语言共存的数据科学生态系统,我很乐意并排写下这四种语言中的三种常见数据转换操作,以便阐明它们在语法层面的比较。将语法放在一起还有助于我在数据科学工具箱中更好地协同它们。希望对你也有帮助。

四种语言的三种数据操作

数据科学的前景是广阔的,我决定在这篇文章中关注最大的共同点。没有正式的统计数据支持,我想当然地认为:大多数数据科学工作都是基于表格数据;常见的数据语言有 SQL,Python,R 和 Spark(不是 Julia,C++,SAS 等。).

SQL 有一长串的方言(hive,mysql,postgresql,casandra 等等),我在这个帖子里选择 ANSI-standard SQL。纯 Python 和 Base R 能够操作数据,但是在这篇文章中我选择 Pandas 作为 Python,Tidyverse 作为 R。Spark 有 RDD 和数据帧,我选择专注于数据帧。Spark 在 Pyspark 和 Sparklyr 中都有 API,我这里选择 Pyspark,因为 Sparklyr API 和 Tidyverse 很像。

三种常见的数据操作包括筛选、聚合和连接。这三个操作允许您剪切和合并表格,导出平均值和百分比等统计数据,并为绘图和建模做好准备。由于数据争论消耗了大量的数据工作时间,这三种常见的数据操作应该占数据争论时间的很大一部分。

1。使用标准过滤表格

包含和排除在数据处理中是必不可少的。我们保留相关的,丢弃不相关的。我们可以用一个词来称呼包容和排斥:过滤。过滤器在表格数据中有两个部分。一个是过滤列,另一个是过滤行。使用这篇文章中著名的虹膜数据,我在下面列出了四种语言的过滤操作。

Question: What is the sepal length, petal length of Setosa with petal width larger than 1 ?# SQLselect Sepal_Length, Petal_Length from Iris where Petal_Width > 1 and Species=’setosa’;# PandasIris[(Iris.Petal_Width > 1) & (Iris.Species==’setosa’)][[‘Sepal_length’,’Petal_Length’]]# TidyverseIris %>% 
 filter(Petal_Width > 1, Species==’setosa’) %>%
 select(Sepal_Length, Petal_Length)# PysparkIris.filter((Iris.Petal_Width > 1) & (Iris.Species==’setosa’)).select(Iris.Sepal_Length, Iris.Petal_Length)

Pandas 使用括号来过滤列和行,而 Tidyverse 使用函数。Pyspark API 是借熊猫和 Tidyverse 两者之所长而定的。正如你在这里看到的,Pyspark 操作与熊猫和 Tidyverse 有相似之处。SQL 和往常一样是声明性的,显示出它的签名“从表中选择列,其中行符合标准”。

2。按组导出汇总统计数据

创建计数、总和及平均值等汇总统计数据对于数据探索和特征工程至关重要。当分类变量可用时,按某些分类变量对汇总统计数据进行分组也很常见。

Question: How many sepal length records does each Iris species have in this data and what is their average sepal length ?# SQLselect Species, count(Sepal_Length) as Sepal_Length_Count, avg(Sepal_Length) as Sepal_Length_mean from Iris group by Species; # Pandas
aggregated=Iris.groupby(by=’Species’,as_index=False).agg({‘Sepal_Length’: [‘mean’,’count’]})
aggregated.columns = [‘_’.join(tup).rstrip(‘_’) for tup in temp1.columns.values]# Tidyverse
Iris %>%
 group_by(Species) %>%
 summarize(Sepal_Length_mean=mean(Sepal_Length), Count=n())# Pyspark
from pyspark.sql import functions as FIris.groupBy(Iris.species).agg(F.mean(Iris.sepal_length).alias(‘sepal_length_mean’),F.count(Iris.sepal_length).alias(‘sepal_length_count’))

这个例子很好地说明了为什么我会对这四种语言感到困惑。编写“group by”有四种略有不同的方法:在 SQL 中使用group by,在 Pandas 中使用groupby,在 Tidyverse 中使用group_by,在 Pyspark 中使用groupBy(在 Pyspark 中,groupBygroupby都可以,因为groupby是 Pyspark 中groupBy的别名。groupBy看起来更真实,因为它在官方文件中使用得更频繁。

在聚合方面,Python 在这里非常不同。第一,它使用一个字典来指定聚合操作。第二,它默认使用 group by 变量作为索引,你可能不得不处理 multiindex。

3。连接表格以将功能放在一起

大数据工作的一个标志是将多个数据源集成到一个源中,用于机器学*和建模,因此 join 操作是必不可少的。有一个可用的连接列表:左连接、内连接、外连接、反左连接和其他连接。以下示例中使用了左连接。

Question: given a table Iris_preference that has my preference on each species, can you join this preference table with the original table for later preference analysis?# SQLselect a.*, b.* from Iris a left join Iris_preference b on a.Species=b.Species;# Pandaspd.merge(Iris, Iris_preference, how=’left’, on=’Species’)# Tidyverseleft_join(Iris, Iris_preference, by=”Species”)# PysparkIris.join(Iris_preference,[‘Species’],”left_outer”)

这真的很神奇,我们有很多方法来表达相同的意图,在编程语言和自然语言中。

数据争论的备忘单

语言丰富是福也是祸。对于社区来说,在未来对跨语言的公共数据操作的 API 进行标准化可能不是一个坏主意,这可以消除摩擦并增加可移植性。到目前为止,我调查了 Pandas、Tidyverse、Pyspark 和 SQL 中的 filter、aggregate 和 join 操作,以突出我们每天最常处理的语法细微差别。上面的并排比较不仅可以作为一个备忘单来提醒我语言的差异,还可以帮助我在这些工具之间进行转换。在我的 git 库这里有这个备忘单的一个更简洁的版本。此外,你可能会发现其他特定语言的备忘单很有帮助,它们来自 Pandas.org、R Studio 和 DataCamp。

与熊猫的数据角力:链接

与 dplyr 和 tidyr 的数据角力:链接

python for Data Science py spark:链接

如果你想在我的小抄里增加额外的数据运算对,那就连上吧!

最后,通过制作一个来学*如何使用命令行应用程序!

原文:https://towardsdatascience.com/finally-learn-how-to-use-command-line-apps-by-making-one-bd5cf21a15cd?source=collection_archive---------8-----------------------

冒着疏远很多读者的风险…我是和 GUI 一起长大的,所以我从来不需要学*终端的方式!在当今友好用户界面的社会中,这是被社会所接受的,除非你从事软件工程……哎呀!

Manager — “Oh this is easy, just use this command line app”, Me — ”Yes…the command line… I’ll use that…”

找回我的软件工程街头信誉

我已经通过从 Stack-Overflow 复制和粘贴完整的命令行操作走了很远,但还没有足够舒适地“正确”使用命令行应用程序。最终让我喜欢上它的是当我偶然发现一个非常方便的 python 库,叫做arg parse,它允许你为你的 python 脚本构建一个漂亮健壮的命令行界面。

本教程对如何使用 argparse、进行了深入的解释,但我还是要回顾一下关键的开眼器 :

argparse 是标准 python 库的一部分,所以打开你的代码编辑器,跟着做(你不需要安装任何东西)!

帮助

每个命令行 app 最有用的部分!

# inside a file called my_app.py**import** **argparse**
parser = argparse.ArgumentParser(description="*Nice little CL app!*")
parser.parse_args()

上面的代码什么也不会做,除了默认情况下你有帮助标志!

在命令行中,您可以运行:

python my_app.py --help

或者

python my_app.py -h

您将得到如下输出:

usage: my_app.py [-h] **Nice little CL app!** optional arguments:-h, --help  **show this help message and exit**

看起来很酷,对吧?但是等一下,当你使用 argparse 到添加更多功能(见下文)时,这个帮助输出将自动填充你如何使用你的应用程序的所有指令!

必需的参数

假设你想让你的应用程序接受一些变量,我们只需使用parser.add_argument()函数,并给我们的参数一些标签(在这种情况下是“名称”):

import argparse
parser = argparse.ArgumentParser(**description**="*Nice little CL app!*") parser.add_argument("***name***", **help**="*Just your name, nothing special*") args = parser.parse_args()
print("*Your name is what?* " + args**.name**)

注意我们是如何添加帮助文本的!现在,当我们运行python my_app.y -h时,我们会获得所有应用程序的详细信息:

usage: my_app.py [-h] name **Nice little CL app!** positional arguments:name        **Just your name, nothing special** optional arguments:-h, --help  **show this help message and exit**

很酷,但是让我们用python my_app.py来运行我们的应用程序

usage: my_app.py [-h] namemy_app.py: error: too few arguments

没错!自动输入检查!

现在让我们运行python my_app.py "Slim Shady"

Your name is what? Slim Shady

相当光滑!

可选参数

也许你想让某人告诉你更多关于他们的事情?在使用parser.add_argument()函数时添加双破折号将使该参数可选!

import argparse
parser = argparse.ArgumentParser(**description**=”*Nice little CL app!*”)
parser.add_argument(“*name*”, **help**=”*Just your name, nothing special*”) parser.add_argument("***--****profession*”, **help**=”Y*our nobel profession*”) args = parser.parse_args()
print(“*Your name is what?* “ + args.name)if args.profession:
    print(“*What is your profession!? a* “ + args.profession)

如果要为该参数传递一个变量,只需在要传递的变量前指定双虚线参数名称:

python my_app.py "Slim Shady" **--profession "gift wrapper"**

这给了你:

Your name is what? Slim ShadyWhat is your profession!? a gift wrapper

或者可以不用,毕竟是可选的!

python my_app.py "Slim Shady"

仍然给你:

Your name is what? Slim Shady

并且在运行时再次神奇python my_app.py -h:

usage: my_app.py [-h] [--profession PROFESSION] name **Nice little CL app!** positional arguments:name                      **Just your name, nothing special**optional arguments:-h, --help                **show this help message and exit**--profession PROFESSION   **Your nobel profession**

旗帜

也许你只是想让一些很酷的事情发生。将action="*store_true*"添加到您的parser.add_argument()函数中,您就有了一个标志参数:

import argparseparser = argparse.ArgumentParser(**description**="*Nice little CL app!*")
parser.add_argument("*name*", **help**="*Just your name, nothing special*")
parser.add_argument("*--profession*", **help**="*Your nobel profession*") parser.add_argument("*--cool*", **action**="*store_true*", **help**="*Add a little cool*") args = parser.parse_args()
print("*Your name is what?* " + args.name)cool_addition = " *and dragon tamer*" if args.cool else ""if args.profession:
    print("*What is your profession!? a* " + args.profession + cool_addition)

它非常简洁,您只需将标志的名称放入您的命令中,如下所示:

python my_app.py "Slim Shady" --profession "gift wrapper" **--cool**

转眼间。

Your name is what? Slim ShadyWhat is your profession!? a gift wrapper and dragon tamer

记住,你不必使用它,它只是一面旗帜:

python my_app.py "Slim Shady" --profession "gift wrapper"

还是会给:

Your name is what? Slim ShadyWhat is your profession!? a gift wrapper

看看帮助命令python my_app.py -h:

usage: my_app.py [-h] [--profession PROFESSION] [--cool] name **Nice little CL app!** positional arguments:name                      **Just your name, nothing special**optional arguments:-h, --help                **show this help message and exit**--profession PROFESSION   **Your nobel profession**--cool                    **Add a little cool**

我只是假设从现在开始你和我一样对此感到满意。

简易格式

揭开了困扰我很久的神秘的一个角色的争论。仅仅通过在你的parser.add_argument()函数中添加一个以单个破折号为前缀的单个字母,你就可以得到相同参数的超短版本:

import argparseparser = argparse.ArgumentParser(**description**="*Nice little CL app!*")
parser.add_argument("*name*", **help**="*Just your name, nothing special*")parser.add_argument("-p", "*--profession*", **help**="*Your nobel profession*")parser.add_argument("-c", "*--cool*", **action**="*store_true*", **help**="*Add a little cool*")args = parser.parse_args()
print("*Your name is what?* " + args.name)
cool_addition = " *and dragon tamer*" if args.cool else ""
if args.profession:
    print("*What is your profession!? a* " + args.profession + cool_addition)

这样就不用输入:

python my_app.py "Slim Shady" --profession "gift wrapper" --cool

您只需键入:

python my_app.py "Slim Shady" -p "gift wrapper" -c

您将得到相同的输出:

Your name is what? Slim ShadyWhat is your profession!? a gift wrapper and dragon tamer

这反映在帮助文本中(python my_app.py -h):

usage: my_app.py [-h] [--profession PROFESSION] [--cool] name**Nice little CL app!**positional arguments:name                           **Just your name, nothing special**optional arguments:-h, --help                      **show this help message and exit**-p PROFESSION, --profession PROFESSION   **Your nobel profession**-c, --cool                      **Add a little cool**

a perfect little command line app!

你现在有了一个完美的小命令行应用程序,希望你能更舒服地找到命令行应用程序!

只要记住--help

** [## ZackAkil/超级简单命令行应用程序

超级简单的命令行应用程序代码“终于学会如何使用命令行应用程序...通过制造一个!”

github.com](https://github.com/ZackAkil/super-simple-command-line-app)**

最后,欧盟让你控制你的银行数据

原文:https://towardsdatascience.com/finally-the-eu-is-giving-you-control-of-your-banking-data-57f0ee424a3d?source=collection_archive---------4-----------------------

消费者和企业的朋友。银行和美国的敌人?

什么是 PSD2,它将如何帮助我?

不,这不是 R2D2 的表弟。PSD2 是欧盟银行指令的第二个版本,其主要目的是保护消费者。现在我们都知道银行立法通常不被认为是令人兴奋的,但 PSD2 将在 2018 年到来,以撼动系统,让银行客户控制他们的财务数据,并让企业有机会在金融服务中竞争。通过 PSD2,您将能够允许获得许可的第三方金融服务提供商访问您的银行信息(在明确同意的情况下),他们可以使用这些信息来分析您的支出并为您提供预算建议,或者引导您使用更便宜的抵押贷款或更高利息的储蓄账户。第三方也将能够提供跨越国界延伸到整个欧盟和欧洲经济区的支付服务,这意味着消费者可以更快地验证和更少的费用。

所以如果你想象你想成为一个商人,在整个欧盟销售产品。或者想从一个欧洲国家搬到另一个欧洲国家。你马上就能做到这两点。您不需要一个新的外国银行账户,因为您可以允许您的财务数据跨境共享,并在整个欧盟范围内进行支付。而且你的身份和名声很容易被验证。

在本文中,我们将了解为什么需要 PSD2,它是如何工作的,它对消费者、企业和银行意味着什么,以及它将如何影响欧盟和美国。

第三方提供商有两种新的许可证类型

账户信息服务提供商(AISP)—这些服务提供商可以在一个地方为用户提供一个或多个支付账户的汇总信息,帮助消费者更好地管理他们的财务。这可以包括交易历史、往来账户余额、储蓄账户、直接借记和其他存款和支付。

支付启动服务提供商(PISP)—这些服务有助于使用网上银行进行支付。这可以是账户之间的在线资金转账、直接借记、信用转账以及通过借记卡或信用卡进行的交易等。当谈到避免信用卡费用和其他交易成本时,这是一个游戏规则的改变者。

我们为什么需要 PSD2?

第一个指令 PSD1 是在 2008 年金融危机前起草的。不出所料,自那以后,世界发生了很大变化。在政治上,由此产生的紧缩政策和高失业率加剧了欧盟的动荡。在经济上,欧盟增长落后。在数字方面,非洲大陆没有大公司来挑战美国的公司,这意味着当我们从美国购买数字和技术产品和服务时。因此, 欧盟的现金充斥着美国的账户,有价值的数据源源不断地流入美国的服务器,而美国的数据保护法对消费者的友好程度要低得多。PSD2 的不可告人的动机是解除管制,让欧盟的数字企业获得竞争优势——并迅速提振欧盟经济。

据报道,2008 年金融危机之后,欧盟领导人也对银行拥有的权力感到不满。凭借对客户数据的独家访问权,他们是唯一能够通过向客户出售金融服务来赚钱的人,而这往往意味着高额费用。这种对客户数据的垄断在 2015 年为欧盟银行赚取了约 1280 亿€,占其零售银行收入的四分之一。这些高额费用的另一个原因是过时和昂贵的行政和安全系统。每年都有数百万人正式投诉他们的银行。金融科技和区块链公司最*在欧盟的成功证明,向第三方开放金融服务将意味着更多的竞争、创新机会和更好的安全性——同时降低消费者的成本

金融科技并不新鲜

70%的欧盟客户使用应用程序进行网上银行业务,40%的客户使用软件进行移动支付。Sofort、iDEAL 等金融科技公司完成了荷兰和德国超过一半的在线支付业务。在英国,你可以通过朋友的电话号码向他们支付小额款项。然而,如果金融科技公司能够获得客户交易信息,它们还可以提供许多其他服务。目前,大多数银行都配合这些数据请求,但它们可能会响应缓慢,有时甚至会完全阻止这些请求。PSD2 将强制要求共享数据,并建立能够实现实时交易的系统。消费者和企业的巨大胜利。

金融科技只会越来越大。根据毕马威的数据,2016 年对金融科技的投资总额为 247 亿美元。随着私营部门发展 2 在该部门创造更多机会,这一数字今年可能会超过。

安全呢?

所有第三方提供商的安全措施都很严格。他们必须得到许可、保险、监管和监督。例如,帮助公司跟踪工作流程和发票的芬兰初创公司 Holvi 被芬兰金融监管局监管并许可为支付机构,在整个欧盟范围内运营。它和传统银行一样由同一权威机构监管,并为欺诈损失提供保险。所有的客户资金也与公司资产分开存放,所以在破产的情况下,你的钱是安全的,可以随时提取。保护消费者是这项指令的重点。

随着人工智能的改进,欺诈将更容易被发现。这将为零售商和商家节省数十亿欧元的损失,避免因不正确的欺诈检测而导致的网上虚假下降。虚假拒绝还会导致许多顾客的流失,因为据估计,大约三分之一付款被拒绝的用户不会再回到在线零售商那里。通常情况下,失去业务的成本超过了欺诈带来的潜在损失。

不仅仅是公司被检查。PSD1 指令的一个重要变化是需要 SCA、强客户认证。每次您想要使用这些第三方服务之一时,您都必须完成一个更强大的两步认证,该认证包括以下三个组件中的两个组件的组合:

  1. 你拥有的东西——例如手机或物联网设备,如 PINsentry 读卡器
  2. 一些你知道的东西,比如一个别针、个人信息或秘密信息
  3. 你是什么样的人——指纹或面部识别等生物识别技术

公司还需要承担责任,通过加密、混淆、root 和越狱保护、设备绑定和密钥保护等方法保护消费者数据。欧盟本身也将需要开发区块链式的分布式账本基础设施,用于身份验证和交易认证。这些技术可能已经很难实现,但更难让用户友好,这就是为什么银行应该寻求金融科技公司的帮助

PSD2 对银行意味着什么?

周围有一些可怕的统计数据;高盛已经加入进来,并估计传统银行可能会损失多达 4.7 万亿美元的收入,这有利于金融科技公司。然而,大多数金融分析师和评论员似乎都同意,银行应该积极看待 PSD2,将其视为一个创新机会。金融科技可以提供单独的组件,但银行将占据先机,特别是在创建有关身份和数据(他们目前拥有)以及资本(他们目前拥有)的优质实用程序时。

一些银行已经选择接受 PSD2 将带来的变化。西班牙银行 BBVA 已经收购了 Holvi,并将与他们合作提供新的公共设施。其他银行雇佣了专业的研发部门、创新和孵化团队,开始拆分过时的 IT 系统,甚至赞助黑客马拉松。

从使用会计和薪资软件到通过众筹融资而不是获得贷款来筹集资金,中小企业现在在全球范围内运营,并且更加精通技术。对于银行来说,重要的是满足中小企业不断变化的需求,并保持金融创新的领先地位,以避免竞争对手在开始使用第三方提供商时获得优势或失去与客户的联系。Facebook Messenger 计划提供一项服务,允许用户通过其社交网络向朋友支付小额款项。如果脸书每月 20 亿活跃用户中的每一个人都注册这项服务,并输入他们的银行账户信息,那么与数百年来传统银行来之不易的客户基础相比,它可能会在非常短的时间内拥有世界上最大的金融消费者网络之一。

从法律上讲,银行将被要求允许第三方访问数据,但仍要对这些信息的安全性负责。他们还将负责为这些新的竞争对手提供便利的余额检查、报表检查和支付初始化。

它将如何工作?

将银行及其数据连接到第三方的最广泛认同的解决方案是使用 API,即应用程序编程接口。它本质上是一种将一个服务器、移动应用程序或网站插入另一个服务器、移动应用程序或网站,并允许它们相互通话,同时仍然独立工作的方式。在这种情况下,it 可以控制银行希望接收数据请求的方式,以及金融应用程序设计人员希望接收数据的方式,以便最好地与客户沟通。通常,大多数大型商业网站都希望对他们的代码保密,因为他们不希望开发者窃取他们花了很多钱开发的代码。然而,许多人已经意识到,通过向开发者发布他们代码的某些部分,他们通常会得到更好的产品和服务的回报。API 是他们公开的代码的一部分。因此,银行将能够从开发人员社区获得许多新功能,开发人员也有机会在一些昂贵的专业代码和一个巨大的平台上进行构建,以推广他们的工作。

API 还有助于解决如何连接银行、金融科技公司、零售商、社交网络和任何其他计划提供金融服务的人的新生态系统的问题。银行目前已经拥有专有的 IT 系统,这些系统可能会也可能不会连接到云基础设施。考虑到安全性和法规,将整个结构迁移到云中是不安全的。但是,当需要相互协作的操作数量只会不断增加时,集成新的和不同的组件也是如此。随着越来越复杂的系统一个接一个地被开发出来,其结果几乎肯定意味着昂贵且耗时的技术债务。

因此,答案似乎在于混合集成,它使用一个与当前银行内部已经建立的系统相连接的云系统。新的金融科技合作伙伴将能够通过互联网立即加入核心结构,而不需要耗时的入职。通过整合云系统,银行还将受益于即时增加的容量,这对于 PSD2 将带来的实时数据和交易的新需求和增加的需求将是无价的。

荷兰正在发生什么?

除了上述所有好处,该指令在荷兰尤其令人兴奋,因为荷兰是许多金融科技初创公司、孵化器和加速器的所在地。随着英国退出欧盟的迅速临*,许多公司正在寻找英国以外的地点。海牙和鹿特丹等荷兰城市是有吸引力的选择,阿姆斯特丹已经是几家金融科技初创公司、许多顶级以太坊开发商和 BitPay 欧盟总部的所在地。

荷兰金融科技初创公司 Adyen 是整个欧盟获得资金最多的公司之一。其当前价值为 23 亿美元。该公司在一个系统中提供了从信用卡到 Apple Pay 的 250 种不同的支付选择,提供了一种“无摩擦的支付体验”。客户包括网飞、LinkedIn、Spotify、优步、Etsy 和 Groupon。

在阿姆斯特丹,已经有一个强大的技术生态系统,这使它成为 PSD2 改变金融科技和其他几个行业的完美场所。从高速宽带和 LoRaWAN 物联网网络到政府主导的计划、创业孵化器和加速器,以及致力于创新的大学和研究人员。

几周后,EIT Digital 将在该市开设一个金融科技创新中心,由市政府、CWI(数学和信息学中心)、ING 银行、飞利浦和 TNO(荷兰应用科学研究组织)提供支持。该中心相信“投资数字业务对荷兰知识经济非常重要”,将专注于金融区块链技术、人工智能和网络安全领域的研究、教育和创新。

PSD2 会影响美国银行业吗?

简短的回答是没有。它仅适用于在欧盟内部进行的部分支付交易。然而,私营部门司 2 将实施所谓的“一条腿伸出”政策。这意味着一旦资金被记入欧盟内的实体账户,该指令将对支付服务提供商产生影响。对于对外支付,支付服务提供商必须遵守 PSD2,直到欧盟的清算账户被借记。

更长的答案是肯定的,尽管是间接的。这与该指令的竞争性有关。欧洲在个人数据保护方面一直采取比美国更进步的立场,如果你考虑到 2006 年针对谷歌的“被遗忘权”裁决等案例,美国通常会将欧盟列为“反大企业技术”。

目前,Visa 和 Mastercard 等美国金融公司已经在全球和欧盟铺设了支付基础设施。如果一个公司或消费者想要使用这些框架,他们必须付费。如果欧盟可以使用 PSD2 来创建计划中的强大验证和直接帐户到帐户支付系统,美国的系统将变得缓慢、昂贵,并且与欧洲电子商务无关。欧盟将能够改变收费标准,向境外公司收取费用,让他们使用新的基础设施。

机器学*算法可以帮助我们评估金融决策的风险

原文:https://towardsdatascience.com/financial-data-analysis-2f86b1341e6e?source=collection_archive---------15-----------------------

贷款资格预测:探索性数据分析

在本系列的第一部分的中,我展示了一些必要的数据处理,包括:移除常量特征、移除重复特征、移除重复行、移除与 85%缺失值相关的特征>。这些是我们需要在几乎每个数据集上执行的初步步骤。完成上述处理后,我能够移除 60 个不相关的特征,剩下 153 个初始特征中的 93 个。在的第二部分,我手动检查了每一个特征,处理文本并删除了一些不必要的特征。在数据处理和清理结束时,我们有 36 个相关特征。

在这一部分,我对所选择的 36 个特征进行了一些探索性的分析。这些分析包括可视化特征的相关系数,去除高度共线的特征。

让我们从导入库和读取具有所选功能的数据集开始:

import warnings
warnings.filterwarnings("ignore")import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as snsfrom sklearn.utils import shuffle, class_weight
from sklearn import preprocessing
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

读取数据

df_selected = pd.read_csv('./data/df_selected.csv')

特征关联

可视化特征之间的关系是一组数据可能对应于另一组数据的方式之一。特别是在机器学*中,特征相关性的重要性是显著的。它帮助我们识别坏的和高度共线的特征。相关矩阵也可以用于特征工程。在下图中,显示了特征之间的关系:

corr = df_selected.corr()
plt.figure(figsize = (10, 8))
sns.heatmap(corr)
plt.show()

从上面的图中,我们看到解释特性关系有点棘手。所以,我们要具体一点。例如,如果我们想知道特征是如何与目标变量相关的,我们必须编写下面的代码来获得特征与目标变量的相关系数:

corr['loan_status'].sort_values(ascending = False)
                   .to_frame('corr_value')
                   .reset_index()

从上面打印的结果来看,sub_grade 与目标变量贷款状态的正相关性最高,其次是等级、利率等。Fico_range_high 和 Fico_range_low 的负相关性最高。由于 Fico_range_high 和 Fico_range_low 具有几乎相同的相关系数(-0.136),所以我们可以将它们合并,取它们的平均值并删除它们。

df_selected['avg_fico_score'] = (df_selected['fico_range_high'] + df_selected['fico_range_low'])/2.0df_selected.drop(['fico_range_low','fico_range_high'], axis=1, inplace=True)

寻找高度相关的特征

现在,我们有了要素的相关系数矩阵,查找高度共线(高度相关)的要素变得更加容易。使用下面的代码,我找到了共线特性:

funded_amnt           loan_amnt           1.000000
funded_amnt_inv       loan_amnt           0.999996
                      funded_amnt         0.999996
int_rate              term                0.435879
installment           loan_amnt           0.952673
                      funded_amnt         0.952673
                      funded_amnt_inv     0.952653
grade                 term                0.446887
                      int_rate            0.962951
sub_grade             term                0.454138
                      int_rate            0.985559
                      grade               0.976940
total_acc             open_acc            0.689583
acc_open_past_24mths  open_acc            0.482634
                      total_acc           0.428877
mort_acc              home_ownership     -0.477745
pub_rec_bankruptcies  pub_rec             0.642983
tax_liens             pub_rec             0.695931
credit_history        earliest_cr_year   -0.994442
fico_grade            int_rate            0.792840
                      grade               0.821197
                      sub_grade           0.798134

从上面的结果中,我们看到' funded_amnt '和' loan_amnt '有 100%的相关性,这告诉我们,它们本质上是一样的。同样,' funded_amnt_inv '与' loan_amnt '和' funded_amnt '的关联度几乎是 100%。因此,我删除了' funded_amnt ',' funded_amnt_inv '功能。

df_selected.drop(['funded_amnt','funded_amnt_inv'], axis=1, inplace=True)

我还发现以下特性与建模目的无关。因此,我将它们从数据中删除:

df_selected.drop(‘earliest_cr_year’, axis = 1, inplace=True)
df_selected.drop('issue_year', axis = 1, inplace=True)

删除特性后,我们得到了 29 个最相关和最重要的特性以及一个目标特性‘loan _ status’。

分类特征与连续特征

好的,让我们看看这些特征是具有分类值还是连续值。它帮助我们找到合适的建模算法:

cat_features.remove('loan_status')['term',
 'grade',
 'emp_length',
 'home_ownership',
 'verification_status',
 'purpose',
 'initial_list_status',
 'application_type',
 'pub_rec_bankruptcies',
 'disbursement_method',
 'issue_month',
 'issue_year']

我们看到 12 个特征≤14 个唯一值。只有六个要素具有超过 1200 个唯一值。这意味着大多数特征都是绝对的。因此,基于树的算法将是尝试的第一选择。

还有许多其他可以执行的 EDA。但由于时间的限制,我不会做进一步的分析功能。相反,在下一部分中,我将着重于选择一个合适的算法,然后创建一个模型。

系列的下一部分,我将开始创建模型。同时,如果你对这部分有任何问题,请在下面写下你的意见。你可以联系我:

Email: sabbers@gmail.com
LinkedIn: [https://www.linkedin.com/in/sabber-ahamed/](https://www.linkedin.com/in/sabber-ahamed/)
Github: [https://github.com/msahamed](https://github.com/msahamed)
Medium: [https://medium.com/@sabber/](https://medium.com/@sabber/)

机器学*算法可以帮助我们评估金融决策的风险

原文:https://towardsdatascience.com/financial-data-analysis-51e7275d0ae?source=collection_archive---------11-----------------------

贷款资格预测:创建预测模型

本文是构建预测模型系列文章的最后一部分。在前两部分(第一部分第二部分,我展示了如何处理和清理原始数据。然后在的第三部分,我将展示如何执行一些探索性的数据分析(EDA)来理解数据和特性工程。在处理和 EDA 的最后,我们现在有了 30 个最相关的特性,包括目标变量 loan_status。在文章的最后,也是最激动人心的部分,我将展示如何从一个简单的模型开始,然后继续构建一个高精度的复杂模型。在这项工作中,我能够构建一个基于树的 LightGBM 模型,准确率为 87%,而初始的逻辑模型预测准确率为 66%。在接下来的部分中,我描述了用必要的理论和代码改进模型的一步一步的过程。好了,让我们从导入一些必要的库开始。

导入库

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as snsfrom sklearn.linear_model import LogisticRegressionimport lightgbmfrom sklearn.utils import resample
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_validate, KFoldfrom sklearn.metrics import recall_score, roc_auc_score, f1_score
from sklearn.metrics import accuracy_score, roc_auc_score, \ classification_report, confusion_matrix

读取所选功能

df_selected = pd.read_csv(‘./data/df_selected.csv’)df_selected.describe(include = 'all')

看阶级比例

在我们开始任何事情之前,让我们检查一下数据集中的类比率。如果一个类的例子数量很少,而另一个类的例子数量很多,我们就认为数据是不平衡的,我们必须在创建模型之前解决这个问题。以下代码显示了我们使用的数据的类比率:

df_selected.loan_status.value_counts(normalize=True)0    0.783494
1    0.216506
Name: loan_status, dtype: float64df_selected.loan_status.value_counts()
0    358436
1     99048
Name: loan_status, dtype: int64

显然,上面打印的结果显示数据集是不平衡的。1 类(已注销)是少数类别,占全部样本的 21.6%。该数据集中,按时还清贷款的申请人比被取消贷款的申请人更多。这对于机器学*模型来说是一个问题,因为该模型将主要基于具有更多示例的类来学*其参数。因此,模型会偏向多数阶级。要解决不平衡的阶级问题,我们可以使用许多技巧,例如:

(1)分配类权重(2)使用具有交叉验证的集成算法(3)对少数类进行上采样或对多数类进行下采样

在我的另一篇博客([用不平衡数据集提高机器学*模型性能的三种技术](http://In my other blog ('Three techniques to improve machine learning model performance with imbalance datasets') I wrote a blog post describing the above three techniques. In this work, I have tried all the techniques and found upsampling minority class improves the model's generalization on unseen data. I the code below I upsample minority class with Scikit-learn 'resample' method.))中,我解释了这三种技术的细节。我还展示了如何逐步提高模型的性能。在这项工作中,我尝试了所有的技术,发现对少数类进行上采样可以提高模型对未知数据的泛化能力。因此,在本文中,我只关注重采样技术。

对少数民族类进行重采样

处理高度不平衡数据集的一种流行技术叫做重采样。虽然该技术在许多情况下被证明是有效的,以解决不平衡的阶级问题,但是,它也有其弱点。例如,来自少数类的过采样记录会导致过拟合,而从多数类中移除随机记录会导致信息丢失。在向上采样小类和向下采样大类中,我发现带有向上采样的模型在未知数据上表现得更好。下面的代码显示了这种机制:

df_major = df_selected[df_selected.loan_status == 0]
df_minor = df_selected[df_selected.loan_status == 1]df_minor_upsmapled = resample(df_minor, replace = True, n_samples = 358436, random_state = 2018)df_minor_upsmapled = pd.concat([df_minor_upsmapled, df_major])df_minor_upsmapled.loan_status.value_counts()1    358436
0    358436
Name: loan_status, dtype: int64

在上面的代码中,我首先将类分成两个数据帧:1。df_major 和 2。df_minor。然后,我使用 df_minor 将其向上采样到与主类相同的数字,即 358436。请注意,我将替换选项保持为 true。如果我被向下采样,那么我会保持替换选项为假。最后,我将上采样的 minor 类与 major 类连接起来。看看 loan_status 特性的类,它们现在很明显是平衡的。我建议以迭代的方式尝试不同的技术,直到找到更好的模型。

数据标准化

在本节中,我通过去除每个样本的平均值,然后除以标准偏差来重新调整数据。零均值和单位标准差有助于加快模型的优化。我使用了 Scikit-learn StandardScaler 方法。在此之前,我将数据集分为训练和测试部分。以下代码不言自明:

X = df_minor_upsmapled.drop('loan_status', axis = 1)
Y = df_minor_upsmapled.loan_statusxtrain, xtest, ytrain, ytest = train_test_split(X, Y, test_size=0.25, random_state=0)mms = StandardScaler()
mms.fit(xtrain)
xtrain_scaled = mms.transform(xtrain)

现在我们的数据已经准备好了,我继续下一步:构建模型。正如我之前所说,从逻辑回归这样的简单算法开始有助于保持事情的简单,并作为复杂模型的基准。

逻辑回归模型

逻辑回归是一种借用统计学的建模技术。这是第一个算法,应该从复杂模型开始,并不断向复杂模型发展。这种算法相对简单,易于实现,这就是为什么我总是首先从这种技术开始,并记录模型的性能,用于将来复杂模型的基准测试。它帮助我轻松直观地前进。好的,让我们看看逻辑回归是如何执行的:

logisticRegr = LogisticRegression()
logisticRegr.fit(xtrain_scaled, ytrain)LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True, intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1, penalty='l2', random_state=None, solver='liblinear', tol=0.0001, verbose=0, warm_start=False)

在上面的代码中,我用默认的 LR 参数训练模型。下面,我使用训练数据中使用的相同标准化参数均值和标准差来标准化测试数据,然后预测测试数据。

xtest_scaled = mms.transform(xtest)
lr_pred = logisticRegr.predict(xtest_scaled)

为了查看测试数据的性能,我编写了一个名为“evaluate_model”的函数,它打印不同的评估标准:1)准确性,2) ROC-AUC 得分,3)混淆矩阵和 4)详细的分类报告。

最后,让我们看看逻辑回归的表现:

evaluate_model(ytest, lr_pred)Accuracy of the model: 0.66409066053633

Classification report: 
             precision    recall  f1-score   support

          0       0.66      0.68      0.67     89877
          1       0.67      0.65      0.66     89341

avg / total       0.66      0.66      0.66    179218

Confusion matrix: 
[[60846 29031]
 [31170 58171]]

上述预测并不是一个坏的开始,但并不令人印象深刻。模型的精度只是在随机猜测之上一点点。我们看到最简单的模型给出了 66%的准确度。因此,我们还有很多工作要做,以制造一个高效的模型。我们必须选择一个更好的算法并调整其超参数,以使模型优于逻辑回归模型。

如果我们使用下面的代码查看特征的唯一值,我们会看到几乎 60%的特征是分类的,其余的是连续的。显示器看 GitHub jupyter 笔记本

features = pd.DataFrame([], columns = ['feature_name', 'unique_values'])
for i, col in enumerate(df_selected.columns):
    features.loc[i] = [col, len(np.unique(df_selected[col]))]features.sort_values('unique_values')

选择合适的模型是数据科学家面临的另一个挑战。有时,在尝试不同的算法之前,即使是经验丰富的数据科学家也无法判断哪种算法的性能最佳。在我们最终的数据集中,几乎 60%的特征是绝对的。在这种情况下,基于树的模型可能是更好的选择。尽管如此,还是很难预测。如果基于树的算法执行得不太好,我们可以尝试另一种算法,如神经网络。然而,在这个项目中,我将首先尝试基于树的集成技术:bagging(随机森林)和 boosting (LightGBM)算法。好吧,让我们从随机森林开始。

随机森林(RF)模型

随机森林是一种灵活且易于使用的机器学*集成算法。该算法是如此的轻巧和有效,即使没有超参数调整,它也可以产生很好的结果。它也是最常用的算法之一,因为它简单,而且可以用于分类和回归任务。方法的详细内容可以在 Scikit-Sklearn 网页上或者在这篇博文中找到:https://towardsdatascience . com/the-random-forest-algorithm-d 457d 499 fcd。让我们开始建模:

在上面的函数中,我首先定义了超参数。随机森林的重要超参数是估计数和树的最大深度。我更喜欢迭代地寻找最优超参数。在这种情况下,我首先从少量估计量开始,然后慢慢增加。我发现这个手动过程比使用 GridSearchCV 或 RandomSearch 更有效、更直观。还有另一种称为贝叶斯超参数优化的技术,可以用来找到一组合适的超参数。这种方法似乎更有效率和效果。在我的下一个项目中,我会尝试另一个项目。关于该技术的更多细节可以在威廉·科尔森的博客文章“机器学*贝叶斯超参数优化的概念解释”中找到。如前所述,我从最重要的超参数的一个小数值开始,一旦找到最佳值,我就从下一个有影响的超参数开始,依此类推。

好了,是时候看看随机森林在测试数据上的表现了:

evaluate_model(ytest, rfpred, rfpred_proba)ROC-AUC score of the model: 0.8054282761077389
Accuracy of the model: 0.7304177035788816

Classification report: 
             precision    recall  f1-score   support

          0       0.75      0.69      0.72     89877
          1       0.71      0.77      0.74     89341

avg / total       0.73      0.73      0.73    179218

Confusion matrix: 
[[61972 27905]
 [20409 68932]]

哇,拉多姆森林做得更好。几乎 11%的准确率来自逻辑回归,这是一个伟大的成就,证明了基于树的模型在分类数据上表现良好。

因为进一步调整超参数并不能提高模型性能,所以我停止了对随机森林模型的研究。我尝试了其他超参数并增加了 n_estimators,但没有帮助。这些困难帮助我决定使用梯度增强树。因为我不打算进一步使用随机森林,所以让我们检查一下模型的健壮性。找出交叉验证的一种方法。

随机森林模型的交叉验证

交叉验证是在实践中使用独立数据集评估模型及其泛化能力的有效方法之一。如果该模型在不同褶皱上的表现是一致的,那么我们可以说该模型是稳健的并且表现良好。在下文中,我们使用 Scikit-Sklearn 交叉验证方法测试 RF 模型的稳健性:

scoring = [‘accuracy’, ‘recall’, ‘roc_auc’, ‘f1’]scores = cross_validate(rf, X = xtrain_scaled, y = ytrain, scoring = scoring, cv = 10, return_train_score = False, verbose = 10, n_jobs= -1)

正如你在上面的代码中看到的,我使用了四个不同的评估指标(“准确性”、“回忆”、“roc_auc”、“f1”)来判断模型的泛化能力。让我们看看结果:

scores{'fit_time': array([519.01635194, 519.08185387, 518.91476393, 514.854949  ,
        491.86662292, 491.60002613, 492.63204885, 491.53150296,
        296.78954768, 297.04013801]),
 'score_time': array([10.45862293, 10.56293011, 10.65213013, 10.40467215, 10.21855617,
        10.32528472, 10.14684105, 10.33355498,  6.49080539,  6.19442701]),
 'test_accuracy': array([0.72979206, 0.7310196 , 0.73124279, 0.73332589, 0.73371648,
        0.72999163, 0.7343625 , 0.72937785, 0.73207477, 0.73201399]),
 'test_recall': array([0.76737272, 0.77194352, 0.77324415, 0.77840951, 0.77421033,
        0.77122896, 0.77728641, 0.77037422, 0.77174923, 0.77271545]),
 'test_roc_auc': array([0.80477504, 0.80651739, 0.80334897, 0.8090473 , 0.80837787,
        0.80377023, 0.80829186, 0.80413098, 0.80798087, 0.8082303 ]),
 'test_f1': array([0.73977216, 0.74178689, 0.74226804, 0.74502063, 0.74427079,
        0.74087428, 0.74548241, 0.74022496, 0.74248735, 0.74268672])}

上面的代码片段打印出了交叉验证的结果。如果您仔细观察不同的评估指标,您会发现该模型在各个褶皱中表现一致,因此非常健壮。让我们计算更具体的指标,如均值和方差:

print('F1 score# (1) mean: {} (2)variance: {}'.format(np.mean(scores['test_f1']), np.var(scores['test_f1'])))
print('Recall score# (1) mean: {} (2)variance: {}'.format(np.mean(scores['test_recall']), np.var(scores['test_recall'])))
print('Accuracy score# (1) mean: {} (2)variance: {}'.format(np.mean(scores['test_accuracy']), np.var(scores['test_accuracy'])))### mean and variance of the merics:
F1 score# (1) mean: 0.7424874224946193 (2)variance: 3.4239691671447294e-06
Recall score# (1) mean: 0.7728534498486367 (2)variance: 9.340496661280428e-06
Accuracy score# (1) mean: 0.7316917565649772 (2)variance: 2.6660110240196636e-06

很高兴看到每个评估指标都有非常低的方差,这再次证实了模型的稳健性。虽然模型很稳健,但我还不开心。我们需要提高模型性能。接下来,我将尝试一种基于梯度增强树的算法。有许多基于梯度增强树的算法可用,如 XGBoost、LightGBM、CataBoost 等。我发现 LightGBM 速度更快,在分类数据上表现良好。

LightGBM 型号

在上面的代码中,我首先以类似于我在随机森林模型中所做的方式手动找到最佳超参数。我发现模型中最重要的参数是“n 估计量”和“最大深度”。让我们看看模型对测试数据的预测和表现:

### Performance report
ROC-AUC score of the model: 0.9586191656898193
Accuracy of the model: 0.890546708477943

Classification report: 
             precision    recall  f1-score   support

          0       0.93      0.85      0.89     89877
          1       0.86      0.94      0.90     89341

avg / total       0.89      0.89      0.89    179218

Confusion matrix: 
[[75963 13914]
 [ 5702 83639]]

业绩报告似乎很有希望。逻辑回归的准确率提高了 35%,随机森林模型的准确率提高了 23%。我在这里停止优化其他超参数。我大概花了 4 个小时才找到以上两个超参数。现在我使用同样的技术交叉验证来关注模型的稳健性。

如果你看看下面的结果,你会看到 LightGBM 在不同的训练中表现一致,这正是我们想要建立的。我们到了。

--------------- cv: 1 --------------------
ROC-AUC score of the model: 0.9483670270426987
Accuracy of the model: 0.8754963684890869

Classification report: 
             precision    recall  f1-score   support

          0       0.91      0.83      0.87     53472
          1       0.84      0.92      0.88     54059

avg / total       0.88      0.88      0.88    107531

Confusion matrix: 
[[44284  9188]
 [ 4200 49859]]--------------- cv: 2 --------------------
ROC-AUC score of the model: 0.9478880521895745
Accuracy of the model: 0.8756730617217361

Classification report: 
             precision    recall  f1-score   support

          0       0.92      0.83      0.87     53861
          1       0.84      0.92      0.88     53670

avg / total       0.88      0.88      0.88    107531

Confusion matrix: 
[[44633  9228]
 [ 4141 49529]] --------------- cv: 3 --------------------
ROC-AUC score of the model: 0.9490374658331387
Accuracy of the model: 0.8780909691158829

Classification report: 
             precision    recall  f1-score   support

          0       0.92      0.83      0.87     53504
          1       0.85      0.92      0.88     54027

avg / total       0.88      0.88      0.88    107531

Confusion matrix: 
[[44457  9047]
 [ 4062 49965]]--------------- cv: 4 --------------------
ROC-AUC score of the model: 0.9490402272662238
Accuracy of the model: 0.8781188680473538

Classification report: 
             precision    recall  f1-score   support

          0       0.92      0.83      0.87     53958
          1       0.85      0.92      0.88     53573

avg / total       0.88      0.88      0.88    107531

Confusion matrix: 
[[44916  9042]
 [ 4064 49509]]--------------- cv: 5 --------------------
ROC-AUC score of the model: 0.9486846347287888
Accuracy of the model: 0.8762112898725937

Classification report: 
             precision    recall  f1-score   support

          0       0.91      0.83      0.87     53764
          1       0.84      0.92      0.88     53766

avg / total       0.88      0.88      0.88    107530

Confusion matrix: 
[[44671  9093]
 [ 4218 49548]]

在这个项目中,我没有讨论任何关于过度拟合的问题。希望我会写另一篇关于这个话题的博客。

非常感谢您的阅读。我希望你喜欢整个系列。完整的代码可以在 Github 上找到。我很想收到你的来信。如果您发现我在代码中或任何地方犯了任何错误,请随时写下评论。如果你愿意,你可以联系我:

Email: sabbers@gmail.com
LinkedIn: [https://www.linkedin.com/in/sabber-ahamed/](https://www.linkedin.com/in/sabber-ahamed/)
Github: [https://github.com/msahamed](https://github.com/msahamed)
Medium: [https://medium.com/@sabber/](https://medium.com/@sabber/)

机器学*算法可以帮助我们评估金融决策的风险

原文:https://towardsdatascience.com/financial-data-analysis-80ba39149126?source=collection_archive---------12-----------------------

贷款资格预测:数据处理-1

介绍

金融机构/公司已经使用预测分析很长时间了。最*,由于计算资源的可用性和机器学*方面的大量研究,使得更好的数据分析从而更好的预测成为可能。在这一系列文章中,我将解释如何创建一个预测贷款模型来识别更有可能被取消的不良申请人。在一步一步的过程中,我展示了如何处理原始数据,清除不必要的部分,选择相关的特性,执行探索性的数据分析,最后建立一个模型。

作为一个例子,我使用 Lending club loan 数据集。Lending Club 是世界上最大的连接借款人和投资者的在线市场。贷款的一个不可避免的结果是借款人违约。本教程的想法是创建一个预测模型,确定哪些申请人的贷款风险相对较高。为此,我将整个系列分为四个部分,如下所示:

  • 数据处理-1 :在这第一部分,我展示了如何清理和移除不必要的特征。数据处理非常耗时,但是更好的数据会产生更好的模型。因此,为了准备更好的数据,需要进行仔细和非常详细的检查。我将展示如何识别常量要素、重复要素、重复行和具有大量缺失值的要素。
  • 数据处理-2 :在这一部分,我手动浏览从第 1 部分选择的每个特征。这是最耗时的部分,但为了更好的模型,这是值得的。
  • EDA :在这一部分中,我对第 1 部分和第 2 部分中选择的特性做了一些探索性的数据分析(EDA)。一个好的 EDA 需要更好的领域知识。我们需要花一些宝贵的时间来找出这些特征之间的关系。
  • 创建模型 :最后,在这最后但不是最后的部分,我创建模型。创建模型也不是一件容易的事情。这也是一个迭代的过程。我将展示如何从一个简单的模型开始,然后慢慢增加复杂性以获得更好的性能。

好了,让我们开始第 1 部分:数据处理、清理和特征选择。在此之前,你需要从这个链接下载数据集来和我一起编码。

数据处理-1

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings("ignore")

在这个项目中,我使用了三年的数据集(2014 年、2015 年和 2017 年(第一季度))并存储在五个独立的 CSV 文件中。让我们先读文件:

df1 = pd.read_csv(‘./data/2017Q1.csv’, skiprows=[0])
df2 = pd.read_csv(‘./data/2017Q2.csv’, skiprows=[0])
df3 = pd.read_csv(‘./data/2017Q3.csv’, skiprows=[0])
df4 = pd.read_csv(‘./data/2014.csv’, skiprows=[0])
df5 = pd.read_csv(‘./data/2015.csv’, skiprows=[0])

由于数据存储在不同的文件中,我们必须确保每个文件中有相同数量的特征。我们可以使用下面的代码片段进行检查:

columns = np.dstack((list(df1.columns), list(df2.columns), list(df3.columns), list(df4.columns), list(df5.columns)))
coldf = pd.DataFrame(columns[0])

上面的代码是不言自明的,我们首先提取列名,并使用 Numpy 'dstack '对象将它们堆叠在一起。如果你看看 Github 上的 Jupyter-notebook,你会发现它们是一样的。这对我们有好处。我们可以进入下一步了。是时候检查数据的形状了:

df = pd.concat([df1, df2, df3, df4, df5])
df.shape(981665, 151)

我们看到大约有一百万个例子,每个例子有 151 个特征,包括目标变量。让我们看一下特性名称来熟悉数据。必须了解领域,尤其是特性与目标变量之间关系的细节。一夜之间学会并不容易,这就是为什么需要花几天或一周的时间来熟悉数据,然后再进行进一步的详细分析。让我们看看功能名称:

**print(list(df.columns))**['id', 'member_id', 'loan_amnt', 'funded_amnt', 'funded_amnt_inv', 'term', 'int_rate', 'installment', 'grade', 'sub_grade', 'emp_title', 'emp_length', 'home_ownership', 'annual_inc', 'verification_status', 'issue_d', 'loan_status', 'pymnt_plan', 'url', 'desc', 'purpose', 'title', 'zip_code', 'addr_state', 'dti', 'delinq_2yrs', 'earliest_cr_line', 'fico_range_low', 'fico_range_high', 'inq_last_6mths', 'mths_since_last_delinq', 'mths_since_last_record', 'open_acc', 'pub_rec', 'revol_bal', 'revol_util', 'total_acc', 'initial_list_status', 'out_prncp', 'out_prncp_inv', 'total_pymnt', 'total_pymnt_inv', 'total_rec_prncp', 'total_rec_int', 'total_rec_late_fee', 'recoveries', 'collection_recovery_fee', 'last_pymnt_d', 'last_pymnt_amnt', 'next_pymnt_d', 'last_credit_pull_d', 'last_fico_range_high', 'last_fico_range_low', 'collections_12_mths_ex_med', 'mths_since_last_major_derog', 'policy_code', 'application_type', 'annual_inc_joint', 'dti_joint', 'verification_status_joint', 'acc_now_delinq', 'tot_coll_amt', 'tot_cur_bal', 'open_acc_6m', 'open_act_il', 'open_il_12m', 'open_il_24m', 'mths_since_rcnt_il', 'total_bal_il', 'il_util', 'open_rv_12m', 'open_rv_24m', 'max_bal_bc', 'all_util', 'total_rev_hi_lim', 'inq_fi', 'total_cu_tl', 'inq_last_12m', 'acc_open_past_24mths', 'avg_cur_bal', 'bc_open_to_buy', 'bc_util', 'chargeoff_within_12_mths', 'delinq_amnt', 'mo_sin_old_il_acct', 'mo_sin_old_rev_tl_op', 'mo_sin_rcnt_rev_tl_op', 'mo_sin_rcnt_tl', 'mort_acc', 'mths_since_recent_bc', 'mths_since_recent_bc_dlq', 'mths_since_recent_inq', 'mths_since_recent_revol_delinq', 'num_accts_ever_120_pd', 'num_actv_bc_tl', 'num_actv_rev_tl', 'num_bc_sats', 'num_bc_tl', 'num_il_tl', 'num_op_rev_tl', 'num_rev_accts', 'num_rev_tl_bal_gt_0', 'num_sats', 'num_tl_120dpd_2m', 'num_tl_30dpd', 'num_tl_90g_dpd_24m', 'num_tl_op_past_12m', 'pct_tl_nvr_dlq', 'percent_bc_gt_75', 'pub_rec_bankruptcies', 'tax_liens', 'tot_hi_cred_lim', 'total_bal_ex_mort', 'total_bc_limit', 'total_il_high_credit_limit', 'revol_bal_joint', 'sec_app_fico_range_low', 'sec_app_fico_range_high', 'sec_app_earliest_cr_line', 'sec_app_inq_last_6mths', 'sec_app_mort_acc', 'sec_app_open_acc', 'sec_app_revol_util', 'sec_app_open_act_il', 'sec_app_num_rev_accts', 'sec_app_chargeoff_within_12_mths', 'sec_app_collections_12_mths_ex_med', 'sec_app_mths_since_last_major_derog', 'hardship_flag', 'hardship_type', 'hardship_reason', 'hardship_status', 'deferral_term', 'hardship_amount', 'hardship_start_date', 'hardship_end_date', 'payment_plan_start_date', 'hardship_length', 'hardship_dpd', 'hardship_loan_status', 'orig_projected_additional_accrued_interest', 'hardship_payoff_balance_amount', 'hardship_last_payment_amount', 'disbursement_method', 'debt_settlement_flag', 'debt_settlement_flag_date', 'settlement_status', 'settlement_date', 'settlement_amount', 'settlement_percentage', 'settlement_term']

看上面的特征,可能先显得吓人。但是我们将浏览每个功能,然后选择相关的功能。让我们从目标特性“loan_status”开始

df.loan_status.value_counts()Current               500937
Fully Paid            358629
Charged Off            99099
Late (31-120 days)     13203
In Grace Period         6337
Late (16-30 days)       3414
Default                   36
Name: loan_status, dtype: int64

我们看到有七种类型的贷款状态。然而,在本教程中,我们感兴趣的是两类人:1)全额支付的人:支付贷款利息的人;2)冲销的人:无法支付并最终冲销的人。因此,我们为这两个类选择数据集:

df = df.loc[(df['loan_status'].isin(['Fully Paid', 'Charged Off']))]df.shape
(457728, 151)

观察形状,我们会发现现在的数据点是原始数据的一半,但特征数量相同。在手动处理和清理之前,让我们先做一些常规的数据处理步骤:

  • 移除与 85%以上缺失值相关的要素
  • 移除恒定特征
  • 移除重复要素
  • 删除重复的行
  • 移除高度共线的特征(在第 3 部分 EDA 中)

好了,让我们从典型的数据处理开始:

  1. 删除与 90%缺失值相关的特性:在下面的代码中,我首先使用 pandas 的内置方法‘is null()’来查找与缺失值相关的行。然后我将它们相加,得到每个特征的数量。最后,我根据缺失值的数量对要素进行排序,并创建一个数据框以供进一步分析。

在上面的结果中,我们看到有 53 个特征有 400000 个缺失值。我用熊猫滴法去掉这 53 个特征。请注意,在此函数中,我将“inplace”选项设置为 True,“这将从原始数据帧 df 中移除这些要素,而不返回任何内容。

2。移除恒定特征:在这一步,我们移除具有单一唯一值的特征。与一个唯一值相关联的要素无法帮助模型很好地进行概化,因为其方差为零。基于树的模型不能利用这些类型的特征,因为模型不能分割这些特征。识别具有单一唯一值的要素相对简单:

在上面的代码中,我创建了一个函数“find_constant_features”来标识常量特性。该函数遍历每个要素,并查看其唯一值是否少于两个。如果是,这些特征被添加到恒定特征列表中。我们也可以通过方差或标准差来找出常量特征。如果该特征的方差或标准差为零,我们就可以确定该特征只有一个唯一值。print 语句显示五个特性有一个唯一的值。所以我们使用“inplace”选项 true 来删除它们。

3。去除重复特征:重复特征是在多个同名/异名特征中具有相同值的特征。为了找出重复的特性,我从这个堆栈溢出链接中借用了以下代码:

我们只看到一个似乎是复制的特征。我不打算删除该功能,而是等到我们在下一部分做 EDA。

4。删除重复的行:在这一步中,我们删除所有重复的行。我使用 pandas 内置的“drop_duplicates(inplace= True)”方法来执行这个操作:

df.drop_duplicates(inplace= True)

以上四个处理是基本的,任何数据科学项目我们都需要做。让我们看看所有这些步骤之后的数据形状:

df.shape
(457728, 93)

我们看到,执行上述步骤后,我们有 93 个特征。

在本教程的下一部分中,我将浏览每个特性,然后进行清理,并在必要时将其移除。同时,如果你对这部分有任何问题,请在下面写下你的意见。你可以联系我:

Email: sabbers@gmail.com
LinkedIn: [https://www.linkedin.com/in/sabber-ahamed/](https://www.linkedin.com/in/sabber-ahamed/)
Github: [https://github.com/msahamed](https://github.com/msahamed)
Medium: [https://medium.com/@sabber/](https://medium.com/@sabber/)

机器学*算法可以帮助我们评估金融决策的风险

原文:https://towardsdatascience.com/financial-data-analysis-bf4b5e78c45c?source=collection_archive---------9-----------------------

贷款资格预测:数据处理-2

在本系列的最后一部分的中,我展示了基本的数据处理操作,包括:移除恒定特征、移除重复特征、移除重复行、移除与 85%缺失值相关的特征>。这些是我们需要在几乎每个数据集上执行的初步步骤。完成上述处理后,我们最终将特征从 153 个减少到 93 个。在这一部分,我将手动检查每个特性,处理它们并删除不必要的特性。

在最后一部分中,我们将所有数据点存储到一个数据帧“df”中。让我们开始检查数据的形状。

df.shape
(457728, 93)

我们看到现在有 93 个特征。在我们检查每个特性之前,我们需要创建一个用于可视化的绘图函数。我从这个链接借用了下面的函数。

上述函数接受两个参数;第一个是特征名,第二个是布尔变量:特征是连续的还是分类的。如果特征是连续的,那么函数绘制两个子图:(1)特征的分布和(2)基于 loan_status 类的两个箱线图。另一方面,如果特征是分类的,那么第一个子图是计数图,第二个子图基于 group_by loan_status 类。

下面的代码大多是不言自明的。我有时会省略详细的解释。

功能 0–10:

df.iloc[0:5, 0: 10]

First 10 features

功能:贷款金额

### Feature: loan_amnt
-------------------------------len(df.loan_amnt.value_counts())
1415plot_feature('loan_amnt', True)

看起来所有的贷款都不是唯一的。一定量出现几次。可能是这个原因;公司有一定范围或一定额度可以放贷。

功能:期限

### Feature: term
-------------------------------df.term = df.term.str.replace('months', '').astype(np.int)
df.term.value_counts()36    341042
60    116686
Name: term, dtype: int64plot_feature('term', False)

功能:利率

### Feature: int_rate
-------------------------------df.int_rate = df.int_rate.str.replace('%', '').astype(np.float32)
len(df.int_rate.value_counts())
200
plot_feature('int_rate', True)

看起来,那些无力还贷并最终被取消贷款的申请人不得不支付更高的利率。

特征:坡度和路基

看起来等级和子等级与贷款状态具有相同的形状和关系。在这种情况下,我会保留 sub_grade,因为它比等级包含更多信息。

特征:职务

### Feature: emp_title
-------------------------------
len(df.emp_title.value_counts())
128310It looks like emp_title has lots of unique value, which may not strongly be associated with predicted loan_status. Therefore, I delete the feature.features_to_be_removed.extend(['emp_title', 'id'])

11–20 个特征

df.iloc[0:5, 6: 20] 

从右边的图来看,emp _ lenght 似乎不是一个强有力的预测器,并且与贷款状态关系不大。我现在保留这个功能,基于模型性能我们可能会删除它。

功能:Home_ownership

功能:验证状态

verification_status 功能在某种程度上是有区别的,因为来源经过核实的申请人更有可能被注销,这有点复杂。

功能:Issue_d

### Feature: issue_d
### ------------------df.issue_d.value_counts()
Oct-2014    33699
Jul-2014    25974
Jul-2015    23990
Jan-2015    22750
Oct-2015    22431
Nov-2014    21186
Apr-2015    20097
Dec-2015    19106
May-2015    17964
Aug-2015    17492
Apr-2014    17140
May-2014    17133
Aug-2014    16780
Nov-2015    16540
Jun-2015    15304
Jun-2014    15207
Mar-2015    14997
Mar-2014    14988
Feb-2015    14464
Jan-2014    14464
Feb-2014    13945
Sep-2015    13838
Sep-2014     9344
Dec-2014     8283
Jan-2017     5912
Mar-2017     5008
Feb-2017     4241
May-2017     3644
Apr-2017     3431
Jun-2017     2849
Jul-2017     2366
Aug-2017     1863
Sep-2017     1298
Name: issue_d, dtype: int64

“issude _ d”特征是字符串。由于我们正在处理三年的数据,并保持我们的模型独立于年份,所以我只提取月份,然后将它们转换成类别。

df['issue_month'] = pd.Series(df.issue_d).str.replace(r'-\d+', '')
plot_feature('issue_month', False)

看起来,在 12 月份借款的人比在其他月份借款的人更有可能被冲销。确实有趣。

df.issue_month = df.issue_month.astype("category", categories=np.unique(df.issue_month)).cat.codesdf.issue_month.value_counts()
10    56130
5     52330
4     43126
0     40668
8     38741
9     37726
1     36135
7     34993
6     33360
3     32650
2     27389
11    24480
Name: issue_month, dtype: int64df['issue_year'] = pd.Series(df.issue_d).str.replace(r'\w+-', '').astype(np.int)df.issue_year.value_counts()
2015    218973
2014    208143
2017     30612
Name: issue_year, dtype: int64

由于 URL 与 loan_status 无关,我干脆把它去掉。

功能:用途

看样子,目的可以很好的区别对待。例如,为可再生能源贷款的人比为汽车或教育目的贷款的人更有可能被注销。

因为标题和邮政编码有许多唯一的值,所以我简单地将它们从特征空间中删除。

特征:地址状态

“地址状态”特征具有五十个唯一值,因为有五十个状态。如果我们看下面的图表,我们会发现某些州的申请者比其他人偿还的更多。因此,这个特征可能是歧视性的。

21–30 功能

31–40 个特征

df.iloc[0:5, 25: 40]

41–50 个特征

df.iloc[0:5, 35: 50]

51–60 特征

61–70 特征

71–80 特征

81–90 特征

91 至其余特征

df.iloc[0:5, 85:]

移除特征

手动检查每个功能后,我最终有 61 个不相关的。让我们看看选择要删除的功能。

len(set(features_to_be_removed))
61print(features_to_be_removed)['emp_title', 'id', 'url', 'title', 'zip_code', 'issue_d', 'mths_since_last_delinq', 'mths_since_last_record', 'inq_last_6mths', 'mths_since_last_delinq', 'mths_since_last_record', 'total_pymnt', 'total_pymnt_inv', 'total_rec_prncp', 'total_rec_int', 'total_rec_late_fee', 'recoveries', 'collection_recovery_fee', 'last_pymnt_d', 'last_pymnt_amnt', 'last_credit_pull_d', 'last_fico_range_high', 'last_fico_range_low', 'collections_12_mths_ex_med', 'mths_since_last_major_derog', 'acc_now_delinq', 'tot_coll_amt', 'tot_cur_bal', 'total_rev_hi_lim', 'avg_cur_bal', 'bc_open_to_buy', 'bc_util', 'chargeoff_within_12_mths', 'delinq_amnt', 'mo_sin_old_il_acct', 'mo_sin_old_rev_tl_op', 'mo_sin_rcnt_rev_tl_op', 'mo_sin_rcnt_tl', 'mths_since_recent_bc', 'mths_since_recent_bc_dlq', 'mths_since_recent_inq', 'mths_since_recent_revol_delinq', 'num_accts_ever_120_pd', 'num_actv_bc_tl', 'num_actv_rev_tl', 'num_bc_sats', 'num_bc_tl', 'num_il_tl', 'num_op_rev_tl', 'num_rev_accts', 'num_rev_tl_bal_gt_0', 'num_sats', 'num_tl_120dpd_2m', 'num_tl_30dpd', 'num_tl_90g_dpd_24m', 'num_tl_op_past_12m', 'pct_tl_nvr_dlq', 'percent_bc_gt_75', 'tot_hi_cred_lim', 'total_bal_ex_mort', 'total_bc_limit', 'debt_settlement_flag', 'total_il_high_credit_limit']

最后,我放弃上述所有功能:

df_selected = df.drop(list(set(features_to_be_removed)), axis = 1)
df_selected.shape(457728, 36)

在上面的代码中,我们看到有 36 个最终特性为创建贷款预测模型做好了准备。让我们也检查在所选择的 36 个特征中是否有任何缺失值。

如果运行上面的代码,您会看到“dti”和“revol_util”分别缺少 21 和 223 个值。我使用 panda 的 dropna() 方法来删除那些与缺失值相关的例子。

特征编码

是时候对一些分类特征进行编码了。在下面的代码中,我对“目的”、“家庭所有权”、“年级”、“子年级”、“地址状态”进行了编码:

好了,让我们保存包含所选要素的最终数据集。

df_selected.to_csv('./data/df_selected.csv', index = False)

系列的下一部分中,我将进行一些探索性的分析。如果可能的话,做一些特征工程。与此同时,如果您对这部分有任何疑问,请在下面写下您的意见,或者联系我:

Email: sabbers@gmail.com
LinkedIn: [https://www.linkedin.com/in/sabber-ahamed/](https://www.linkedin.com/in/sabber-ahamed/)
Github: [https://github.com/msahamed](https://github.com/msahamed)
Medium: [https://medium.com/@sabber/](https://medium.com/@sabber/)

利用数据科学找到你喜欢的音乐

原文:https://towardsdatascience.com/find-music-you-like-by-using-data-science-1920c4da12f5?source=collection_archive---------6-----------------------

看看 Outlier 的新播客的第一集:数据驱动的讨论!

我很高兴地宣布我们的播客“数据驱动的讨论”正式发布。在数据驱动的讨论中,我们与许多行业的领导者交谈,询问他们如何使用数据来帮助他们的企业取得成功。

在这第一集我采访了 亚历克斯·怀特 。Alex 是 Next Big Sound 的创始人和负责人,该数据集团位于领先的在线音乐服务: Pandora 。音乐是一个竞争激烈的行业。尽管音乐行业是由艺术创造力驱动的,但它也是由数据驱动的。Alex 向我们介绍了获得可靠的音乐数据有多困难,以及数据如何成为竞争优势。

在本次讨论中,我们将回答许多关于该行业的问题,包括:

  • 像 Next Big Sound 这样的服务是如何收集人们对音乐看法的数据的? (3:28)
  • Alex 在评估商业智能工具时寻找什么? (11:49)
  • 妮琪·米娜是如何骗过 Next Big Sound 的高级算法的? (13:35)

听下面这一集:

如果你喜欢这一集并想听更多,一定要给我们留下评论,并在 苹果播客 上订阅数据驱动讨论。

找出名人在推特上谈论最多的话题

原文:https://towardsdatascience.com/find-out-what-celebrities-tweet-about-the-most-6f498d89266b?source=collection_archive---------7-----------------------

使用不到 40 行 R 代码的 WordCloud

猜猜是谁的 twitter 句柄给了这个词 cloud?这里有足够的暗示。你说得对,这是吴恩达在 Coursera 上发布的关于他新的深度学*课程的推文!看到数据运行总是很有趣;不是吗?让我们试着为三位世界领袖创建一个类似的 wordcloud,即。美国总统唐纳德·特朗普、印度总理纳伦德拉·莫迪和俄罗斯总统弗拉基米尔·普京。

单词云是一种数据可视化技术,其中每个单词的大小表明其在相关文本中的频率或重要性(即,单词在语料库中出现的次数越多,单词就越大)

既然您对使用 R 从 twitter 句柄创建一个 wordcloud 感兴趣,我将有把握地假设您已经拥有了这两者,一个您名下的 Twitter 帐户和安装在您机器上的 RStudio。如果没有,现在是时候了😊

你还必须有一个 Twitter 开发者账户,作为提取推文的媒介。如果你需要帮助,这里有一个快速指南

让我们开始吧。我们将采取以下步骤来完成这项任务:

  1. 使用句柄获取 Twitter 数据(2 行代码!)
  2. 为视觉化做准备(真正有趣的部分)
  3. 最后,创建一个单词云(单行代码!)

提取推文

让我们加载必要的库并与 Twitter 建立连接

#Getting tweets from twitter
library(twitteR)
#Twitter-R Authentication
library(ROAuth)
#Text processing
library(stringr)
#Text mining 
library(tm)
#Wordcloud creation
library(wordcloud)#Connect to twitter API using the saved credentials
load("twitter authentication.Rdata")
setup_twitter_oauth(credentials$consumerKey, credentials$consumerSecret, credentials$oauthKey, credentials$oauthSecret)

我们现在去收集一些数据。这里有几件事需要注意-

  1. 一个人只能从关注与 API 相关联的 Twitter 账户的用户那里获得数据。或者,从公共帐户(相对于私有帐户)
  2. Twitter API 限制用户可以从特定时间线获得的推文数量为 3200 条,包括 RTs,即使它被设置为 FALSE。不过,有一些工具可以让你绕过这个限制。在这篇文章中,我们将坚持自己的极限
  3. Twitter API 还对一次可以收集多少条推文有一个速率限制。如果您试图一次收集太多,它可能会失败或返回部分结果。解决这个问题的最好方法是在 API 调用之间引入延迟,这样代码运行时您就不必在旁边了

获取你想查找的人物的 twitter 账号。确保这些是真实的 twitter 帐户,否则会出现错误。
screenName <- c(‘realDonaldTrump’, ‘PutinRF_Eng’, ‘narendramodi’)

使用 twitteR 收集关于这些句柄的信息。
checkHandles <- lookupUsers(screenName)

获取每个句柄的用户数据,并创建一个便于访问的数据框。用这个检查推特和私人账户的数量。删除私人帐户(如果有)。

UserData <- lapply(checkHandles, function(x) getUser(x))
UserData <- twListToDF(UserData)
table(UserData$name, UserData$statusesCount) #Check tweet count
table(UserData$name, UserData$protected) #Check Private Accounts
usernames <- subset(UserData, protected == FALSE) #Public Accounts
usernames <- as.list(usernames$screenName)

接下来,我们从用户时间轴中获取推文列表,将它们转换为数据帧,并在进行另一个 API 调用之前等待 5 分钟。将所有数据帧合并成一个数据帧,对推文进行预处理。请注意,我们将只能获得这些句柄的 3200 条最新推文。特朗普和莫迪发的推特远不止这些。

x <- userTimeline(‘realDonaldTrump’,n=3200,includeRts = FALSE)#Convert tweets list to dataframe
TrumpData <- twListToDF(x)#Wait 5 minutes 
Sys.sleep(300)x <- userTimeline(‘PutinRF_Eng’,n=3200,includeRts = FALSE)
PutinData <- twListToDF(x)
Sys.sleep(300)x <- userTimeline(‘narendramodi’,n=3200,includeRts = TRUE)
ModiData <- twListToDF(x)Trump.df <- data.frame(TrumpData)
Putin.df <- data.frame(PutinData)
Modi.df <- data.frame(ModiData)#Now create a dataframe that combines all of the collected tweets
tweets <- data.frame()
tweets <- Trump.df
tweets <- rbind(tweets,Putin.df)
tweets <- rbind(tweets,Modi.df)

预处理推文

既然我们已经将所有相关的推文放在了一个地方,那么是时候对它们进行预处理了。我这里的意思是,让我们去掉不需要的字符、符号和单词。您不希望文字云中出现图形字符、文章、符号和数字。您可以根据需要跳过这些预处理步骤。

#Convert tweets to ASCII to avoid reading strange characters
iconv(tweets$text, from=”UTF-8", to=”ASCII”, sub=””)#Clean text by removing graphic characters            tweets$text=str_replace_all(tweets$text,"[^[:graph:]]", " ")#Remove Junk Values and replacement words like fffd which appear because of encoding differences            
tweets$text <- gsub("[^[:alnum:]///' ]", "", tweets$text)#Convert all text to lower case            
tweets$text <- tolower(tweets$text)#Remove retweet keyword            
tweets$text <- gsub("rt", "", tweets$text)#Remove Punctuations            
tweets$text <- gsub("[[:punct:]]", "", tweets$text)#Remove links            
tweets$text <- gsub("http\\w+", "", tweets$text)#Remove tabs            
tweets$text <- gsub("[ |\t]{2,}", "", tweets$text)#Remove blankspaces at begining            
tweets$text <- gsub("^ ", "", tweets$text)#Remove blankspaces at the end            
tweets$text <- gsub(" $", "", tweets$text)#Remove usernames 
tweets$text <- gsub("@\\w+", "", tweets$text)

一旦我们对 tweets 进行了预处理,现在让我们为每个句柄创建一个语料库,并删除诸如“my”、“do”、“today”等停用词。

#After preprocessing the data, subset for tweets for each handle
Trump <- subset(tweets, screenName==“realDonaldTrump”, select= text)
Putin <- subset(tweets, screenName== “PutinRF_Eng”, select= text)
Modi <- subset(tweets, screenName== “narendramodi”, select= text)#Create corpus of individual twitter handles 
Trump <- Corpus(VectorSource(Trump))
Putin <- Corpus(VectorSource(Putin))
Modi <- Corpus(VectorSource(Modi))#Remove English Stopwords from the tweets
Trump <- tm_map(Trump, removeWords, stopwords(“en”))
Putin <- tm_map(Putin, removeWords, stopwords(“en”))
Modi <- tm_map(Modi, removeWords, stopwords(“en”))

创建 WordCloud

如果你熬过了所有这些步骤到达这里,你应该得到一个诗意的款待!(宣称即将开始令人兴奋或危险的活动)看我的..

现在我们已经拥有了我们需要的一切,
让我们满足我们的贪婪
把他们发的微博做成云,
就像当初我们同意的那样

一个函数wordcloud()让你定义 wordcloud 创建的参数。输入语料库、要显示的单词的最小频率、云的大小和形状、单词的颜色和顺序、显示的最大单词等。调整这些,玩一玩。

wordcloud(Trump,min.freq = 3, scale=c(6,0.5),colors=brewer.pal(8, “Dark2”),random.color= FALSE, random.order = FALSE, max.words = 110)wordcloud(Putin,min.freq = 4, scale=c(7,0.8),colors=brewer.pal(8, “Dark2”),random.color= FALSE, random.order = FALSE, max.words = 100)wordcloud(Modi,min.freq = 3, scale=c(6,0.5),colors=brewer.pal(8, “Dark2”),random.color= FALSE, random.order = FALSE, max.words = 110)

语法及解释( 来源 ):

wordcloud(words, freq, min.freq, scale, max.words, random.order, random.color, rot.per,colors, ordered.colors,…)
  1. 单词:要在云中绘制的单词
  2. freq:这些词在文本中的出现频率
  3. 最小频率:频率低于最小频率的单词将不会被标绘
  4. scale:长度为 2 的向量,表示单词大小的范围
  5. max.words:要绘制的最大字数;最不常用的词语被删除
  6. random.order:随机排列单词。如果为假,它们将以递减的频率绘制
  7. random.color:从颜色中随机选择颜色。如果为假,则根据频率选择颜色
  8. rot.per:旋转 90 度的比例字
  9. 颜色:颜色词从最少到最多
  10. ordered.colors:如果为 true,则颜色按顺序分配给单词

您可以根据您选择的顺序和颜色向您的单词云添加更多信息。您可以指定非随机颜色(random.color = FALSE ),这将基于频率进行颜色分配,然后使用调色板(来自 RColorBrewer 包的 brewer.pal)为颜色选择一个值,该值按照您喜欢的顺序排列。

你也可以根据他们的情绪给单词标上颜色,比如积极和消极的情绪。这可以通过在数据库中增加一个定义该属性的列来实现,然后用它来定义颜色,如下所示–

wordcloud(df$words,df$freq, min.freq = 3, scale=c(6,0.5), random.color= FALSE, ordered.colors=TRUE, colors=brewer.pal(8, “Dark2”)[factor(df$sentiment)], random.order = FALSE, max.words = 110)

创建云之后,您可能会看到一些不相关的单词或数字,并且没有提供任何附加信息。在这种情况下,你需要再调整一下你的云。例如,当我创建这些云时,我看到‘amp’和‘will’这两个词是特朗普和莫迪的云中出现频率最高的词。我使用了下面的代码行并删除了它们。下面是我做了这些修改后得到的单词云。

#Remove numbers if necessary
#Putin <- tm_map(Putin, removeNumbers)#Remove specific words if needed
#Trump <- tm_map(Trump, removeWords, c(‘amp’,’will’))
#Modi <- tm_map(Modi, removeWords, c(‘amp’,’will’))

Russian President will make America Great again with Indian People 😝

我还创建了一个 GitHub 库,所有代码都在一个地方。那个为阿米塔布·巴坎、桑德尔·皮帅、维拉特·科利和吴恩达创造了文字云

结束语

除了了解一个特定的 Twitter 账号发布的最多的是什么,我们还可以使用 wordclouds 做很多其他很酷的事情。一个这样的例子是对产品的情感分析。使用 hashtag 获取关于产品的所有推文,处理它们以获得有意义的单词并构建云,砰!如果最常用的词是正面的,你就知道你的产品做得很好。

希望你玩推特玩得开心。如需更多此类文章,请关注该出版物,并在下面发表评论以获取问题或建议。

使用自动编码器的相似图像检索

原文:https://towardsdatascience.com/find-similar-images-using-autoencoders-315f374029ea?source=collection_archive---------2-----------------------

Fig 1: Querying a test burger image in a small training set of steakhouse food images

在本文中,我们将解释如何使用自动编码器在未标记的图像数据集中查找相似的图像。除此之外,我们还提供了一个图像相似性推荐系统的 Python 实现,该系统在牛排餐厅的食物图像上进行训练,网址为:

https://github . com/ankonzoid/artificio/tree/master/image _ retrieval

更多我关于深度学*和强化学*的博客、教程、项目,请查看我的 和我的 Github

问:什么是自动编码器?

自动编码器是由编码器和解码器组成的神经网络。目标是用编码器压缩您的输入数据,然后用解码器解压缩编码的数据,以便输出是您的原始输入数据的良好/完美的重建。

问:为什么自动编码器有用?

作为一个黑盒,自动编码器可能看起来毫无用处:如果我们已经有了数据,为什么我们还要费心去重建一个不那么完美的数据副本呢?说得好。但是 autoencoder 的真正价值在于编码器和解码器本身是独立的工具,而不是重建输入数据的联合黑盒。例如,如果我们充分降低编码维度,我们可以指导自动编码器在训练过程中学*数据的最显著特征(并忽略数据的“噪声”),启发式方法是,自动编码器被迫减少其重建误差,限制只有有限的可用自由度,因此自动编码器将优先保留数据的最宏观细节。注意,自动编码器属于无监督学*的范畴,因为基础事实目标是数据本身。训练自动编码器通常通过反向传播来完成,输入数据和重构之间的差异是权重更新的误差在整个网络中传播的原因。

Fig 2: A schematic of how an autoencoder works. An image of a burger is encoded and reconstructed.

好的好的。既然我们可以训练一个自动编码器,那么我们如何将自动编码器用于实际目的呢?事实证明,编码器给出的编码表示(嵌入)是相似性检索的重要对象。大多数原始和高度非结构化的数据,例如您的面部图像,通常嵌入在非人类可解释的向量空间表示中。因此,我们可以使用一个训练有素的编码器将你的面部图像转换为更低维的嵌入,而不是在 RGB 像素空间中费力地操作,这有望成为更有意义的维度,如“图像亮度”、“头型”、“眼睛位置”、“头发颜色”等。利用这种压缩编码表示,嵌入之间的简单向量相似性度量(例如余弦相似性)将在图像之间创建更多人类可解释的相似性。

相似图像检索推荐码

利用我们所描述的通过训练过的编码器(从自动编码器中提取)来使用嵌入图像的方法,我们在这里提供一个简单的具体例子,说明我们如何在数据库中查询和检索相似的图像。如前所述,我们类似的图像推荐系统的代码可以在以下位置找到:

https://github . com/ankonzoid/artificio/tree/master/image _ retrieval

具体来说,我们使用一个小型的训练数据库,包含 5 种常见的牛排餐厅项目类别:牛排、汉堡、沙拉、薯条、芦笋。在下图中,我们展示了牛排餐厅食物嵌入的 t-SNE 可视化(图 3),测试汉堡图像的 top k=5 图像检索(图 4),以及一些训练牛排餐厅食物图像的一些重建图像(图 5)。所提供的算法的性能远非完美,但为任何对深度学*图像检索感兴趣的人提供了一个良好的起点。

Fig 3: t-SNE visualizations of the training steakhouse food item images

Fig 4: Test burger image retrieval from the training set

Fig 5: Steakhouse food item image reconstructions using a convolutional autoencoder

使用 OpenCV 和 Tensorflow 实时查找停车位置

原文:https://towardsdatascience.com/find-where-to-park-in-real-time-using-opencv-and-tensorflow-4307a4c3da03?source=collection_archive---------5-----------------------

用数据做酷事!

介绍

有多少次你开车在停车场转来转去寻找停车位。如果你的手机能告诉你最*的停车位在哪里,那该有多方便啊!

事实证明,这是一个使用深度学*和 OpenCV 相对容易解决的问题。只需要一张停车场的航拍照片。请看下面的 GIF,我的模型突出显示了洛杉矶机场停车场所有可用的停车位,并显示了可用停车位的数量。最棒的是,这一切可以实时工作!

Real time parking spot detection

你可以找到我在我的 Github repo 上使用的代码。

步骤概述

建立停车检测模型有两个主要步骤:

  1. 检测所有可用停车位的位置
  2. 识别停车位是空闲的还是被占用的

由于这里的摄像机视图已经安装,我们可以使用 OpenCV 对每个停车点进行一次性映射。一旦你知道每个停车点的位置,你就可以使用深度学*来预测它是否空置。

检测所有可用停车位的位置

我用来检测停车点的基本想法是,这里所有的停车点分隔线都是水平线,一列中的停车点大致等距。我先用 Canny 边缘检测得到一个边缘图像。我还屏蔽了没有停车位的区域。见下文:

Canny edge detection output

然后我在边缘图像上做了霍夫线变换,画出了它能识别的所有线。我通过只选择斜率接*于零的线来分离水平线。请参见下面的霍夫变换输出:

Line Detection using HoughLines

如您所见,hough lines 在识别停车线方面做得相当不错,但输出并不清晰——许多停车线被多次检测到,而有些却被遗漏了。那么我们如何清理这个?

然后我用观察和直觉从这里开始。使用 hough lines 返回的坐标,我对 x 观察值进行聚类,以确定主要的停车车道。聚类逻辑通过识别检测到的车道线的 x 坐标中的间隙来工作。这让我能够识别这里的 12 条停车道。见下文

Identify parking lanes by clustering x-coordinates from hough lines

如果这一切看起来很复杂,不要担心——我已经在 github 上的 jupyter 笔记本中一步一步地记录了代码。

现在我很清楚所有的停车道在哪里,我通过假设所有的停车位都是相同的大小来识别每个单独的停车位,这是一个合理的假设。我目测了一下结果,以确保尽可能准确地捕捉到斑点之间的边界。我终于能够标出每个停车位了。见下文。

Each parking spot marked out

现在我们完成了——我们可以为每个点分配一个 ID,并将它的坐标保存在字典中。我把这本字典腌了起来,以便以后检索。这在这里是可能的,因为相机是固定的,我们不需要一次又一次地计算每个点在它视野中的位置。

识别该点是否被标记

现在我们有了停车地图,我认为有几种方法可以确定这个位置是否被占用:

  1. 使用 OpenCV 检查一个点的像素颜色是否与一个空停车位的颜色一致。这是一个简单的方法,但容易出错。例如,照明的变化会改变一个空停车位的颜色,这将使这种逻辑在一天中难以工作。此外,如果逻辑可能会将灰色的汽车混淆为空停车位
  2. 使用对象检测来识别所有汽车,然后检查汽车的位置是否与停车位重叠。我尝试了一下,发现可以实时工作的对象检测模型真的很难检测小尺寸的对象。不超过 30%的汽车被检测到
  3. 使用 CNN 查看每个停车点,并预测是否被占用。这种方法最终效果最好

要建立一个 CNN,我们需要有有车和没有车的停车场的图像。我提取了每个景点的图像,并将其保存在文件夹中,然后将这些图像分组为已占用或未占用。我也在 Github 上分享了这个培训文件夹。

由于在尺寸为 1280x720 的图像中有接* 550 个停车点,所以每个停车点的大小只有大约 15x60 像素。请参见以下空位置和已占用位置的示例图像:

Occupied spot

empty spot

然而,由于被占用的位置和空的位置看起来很不一样,这对 CNN 来说应该不是一个挑战性的问题

然而,我只有大约 550 两个类的图像,所以决定使用转移学*的前 10 层 VGG 和添加一个单一的 softmax 层到 VGG 模型的输出。你可以在这里找到这个迁移学*模型的代码。模型的验证准确率达到了 94% 。见下文:

CNN model test and train accuracies

现在,我将停车点检测与 CNN 预测器结合起来,构建了一个停车点检测器。它惊人的准确。

Empty Spot Predictions.

我还在笔记本中包含了在视频流中运行这个的代码。

结论

我惊讶于现在链接不同的工具并使用深度学*来构建实际应用变得如此容易。我在两个下午做了这项工作。

进一步探索的几个额外想法:

  • 如果停车点检测逻辑可以扩展到任何可能使用深度学*的停车地图上,那将非常好。OpenCV 的局限性在于需要针对每个用例进行调优
  • CNN 中使用的 VGG 模型是一个相当重的模型。愿意尝试重量更轻的模型

我有自己的深度学*咨询公司,喜欢研究有趣的问题。我已经帮助许多初创公司部署了基于人工智能的创新解决方案。请到 http://deeplearninganalytics.org/来看看我们。

你也可以在https://medium.com/@priya.dwivedi看到我的其他作品

如果你有一个我们可以合作的项目,请通过我的网站或 info@deeplearninganalytics.org 联系我

使用 Python 中的客户细分找到您的最佳客户

原文:https://towardsdatascience.com/find-your-best-customers-with-customer-segmentation-in-python-61d602f9eee6?source=collection_archive---------1-----------------------

Photo credit: Pixabay

概观

当谈到找出谁是你最好的客户时,老 RFM 矩阵原则是最好的。RFM 代表*期、频率和货币。是一种利用过往购买行为将客户分组的客户细分技术。

RFM 分数计算

最*度(R): 自上次购买后的天数
频率(F): 总购买次数
货币价值(M): 该客户的总消费金额

步骤 1:计算每个客户的 RFM 指标。

Source: Slideshare

步骤 2:将段号添加到 RFM 表中。

Source: Slideshare

第三步:根据最佳客户的 RFM 得分(得分 111)进行排序。

Source: Blast Analytics Marketing

由于 RFM 是基于用户活动数据,我们首先需要的是数据。

数据

我们将使用的数据集与我们进行购物篮分析在线零售数据集时的数据集相同,可以从 UCI 机器学*库下载。

import pandas as pd
import warnings
warnings.filterwarnings('ignore')df = pd.read_excel("Online_Retail.xlsx")
df.head()
df1 = df

该数据集包含一家总部位于英国的注册在线零售商在 2010 年 1 月 12 日和 2011 年 9 月 12 日之间发生的所有交易。

加载数据需要几分钟,所以我保留了一份备份。

探索数据—验证和新变量

  1. 重要列中缺少值;
  2. 每个国家的客户分布情况;
  3. 单价和数量应该> 0;
  4. 发票日期应为< today.
df1.Country.nunique()

38

共有 38 个独特的国家,如下所示:

df1.Country.unique()

数组(['英国'、'法国'、'澳大利亚'、'荷兰'、'德国'、
、'挪威'、'爱尔兰'、'瑞士'、'西班牙'、'波兰'、'葡萄牙'、
、'意大利'、'比利时'、'立陶宛'、'日本'、'冰岛'、【T28 '、'海峡群岛'、'丹麦'、'塞浦路斯'、'瑞典'、'奥地利'、【T29 '、'以色列'、'芬兰'、'巴林'、'希腊'、'香港'、'新加坡'、
、'黎巴嫩'、'阿拉伯联合酋长国'、'沙特阿拉伯'、'捷克'、
、'加拿大'、'未指明

customer_country=df1[['Country','CustomerID']].drop_duplicates()customer_country.groupby(['Country'])['CustomerID'].aggregate('count').reset_index().sort_values('CustomerID', ascending=False)

数据中 90%以上的客户来自英国。一些研究表明,客户群因地理位置而异,因此这里我将数据仅限于英国。

df1 = df1.loc[df1['Country'] == 'United Kingdom']

检查每列中是否有缺失值。

CustomerID 列中缺少 133,600 个值,因为我们的分析是基于客户的,所以我们将删除这些缺少的值。

df1 = df1[pd.notnull(df1['CustomerID'])]

检查单价和数量列中的最小值。

df1 = df1[pd.notnull(df1['CustomerID'])]

0.0

df1.Quantity.min()

-80995

删除数量列中的负值。

df1 = df1[(df1['Quantity']>0)]
df1.shape
df1.info()

(354345,8)

清理完数据后,我们现在处理 354,345 行和 8 列。

检查每列的唯一值。

def unique_counts(df1):
   for i in df1.columns:
       count = df1[i].nunique()
       print(i, ": ", count)
unique_counts(df1)

发票号:16649
库存代码:3645
描述:3844
数量:294
发票日期:15615
单价:403
客户 ID : 3921
国家:1

为总价添加一列。

df1['TotalPrice'] = df1['Quantity'] * df1['UnitPrice']

找出数据中的第一个和最后一个订单日期。

df1['InvoiceDate'].min()

时间戳(' 2010–12–01 08:26:00))

df1['InvoiceDate'].max()

时间戳(' 2011–12–09 12:49:00 ')

由于最*是针对某个时间点计算的,并且最后一个发票日期是 2011 年 12 月 9 日,因此我们将使用 2011 年 12 月 10 日来计算最*。

import datetime as dt
NOW = dt.datetime(2011,12,10)df1['InvoiceDate'] = pd.to_datetime(df1['InvoiceDate'])

RFM 客户细分

RFM 分割就是从这里开始的。

创建一个 RFM 表

rfmTable = df1.groupby('CustomerID').agg({'InvoiceDate': lambda x: (NOW - x.max()).days, 'InvoiceNo': lambda x: len(x), 'TotalPrice': lambda x: x.sum()})rfmTable['InvoiceDate'] = rfmTable['InvoiceDate'].astype(int)
rfmTable.rename(columns={'InvoiceDate': 'recency', 
                         'InvoiceNo': 'frequency', 
                         'TotalPrice': 'monetary_value'}, inplace=True)

计算每个客户的 RFM 指标

解释:

  • CustomerID 12346 的频率为 1,货币价值为 77,183.60 美元,最*时间为 325 天。
  • CustomerID 12747 的频率为 103,货币值为 4,196.01 美元,最*时间为 2 天

让我们检查一下第一个顾客的详细情况。

第一位顾客只购物过一次,购买了一件数量巨大的产品(74,215 件)。单价很低;也许清仓大甩卖。

拆分指标

将指标分割成多个部分的最简单方法是使用四分位数。

  1. 这给了我们详细分析的起点。
  2. 4 段易于理解和解释。
quantiles = rfmTable.quantile(q=[0.25,0.5,0.75])
quantiles = quantiles.to_dict()

创建分段 RFM 表

segmented_rfm = rfmTable

最低的最*,最高的频率和金额是我们最好的客户。

def RScore(x,p,d):
    if x <= d[p][0.25]:
        return 1
    elif x <= d[p][0.50]:
        return 2
    elif x <= d[p][0.75]: 
        return 3
    else:
        return 4

def FMScore(x,p,d):
    if x <= d[p][0.25]:
        return 4
    elif x <= d[p][0.50]:
        return 3
    elif x <= d[p][0.75]: 
        return 2
    else:
        return 1

向新创建的分段 RFM 表添加分段编号

segmented_rfm['r_quartile'] = segmented_rfm['recency'].apply(RScore, args=('recency',quantiles,))
segmented_rfm['f_quartile'] = segmented_rfm['frequency'].apply(FMScore, args=('frequency',quantiles,))
segmented_rfm['m_quartile'] = segmented_rfm['monetary_value'].apply(FMScore, args=('monetary_value',quantiles,))segmented_rfm.head()

RFM 细分市场将客户群分割成一个难以想象的 3D 立方体。不过,我们可以整理一下。

添加一个新列来合并 RFM 得分:111 是我们之前确定的最高分。

segmented_rfm['RFMScore'] = segmented_rfm.r_quartile.map(str) 
                            + segmented_rfm.f_quartile.map(str) 
                            + segmented_rfm.m_quartile.map(str)
segmented_rfm.head()

很明显,第一个客户根本不是我们的最佳客户。

谁是我们的前 10 大最佳客户

segmented_rfm[segmented_rfm['RFMScore']=='111'].sort_values('monetary_value', ascending=False).head(10)

了解更多信息

有兴趣了解更多信息吗?

  1. Kimberly Coffey 有一个优秀的教程关于同一个数据集使用 r。
  2. 丹尼尔·麦卡锡和爱德华·沃兹沃斯的 R 包— 买直到你死—一个演练
  3. 来自 yhat 博客的葡萄酒销售商的客户细分。

创建这个帖子的源代码可以在这里找到。我将很高兴收到关于上述任何反馈或问题。

参考:爆炸分析和营销

查找和管理研究论文:工具和产品调查

原文:https://towardsdatascience.com/finding-and-managing-research-papers-a-survey-of-tools-and-products-9151810d1b4d?source=collection_archive---------12-----------------------

在本帖末尾你可以找到一个 TL;博士与我的建议,最有用的工具,以改善您的工作流程与科学论文。

重大更新(2020):
我们发布了一个可视化查找和探索学术论文的工具。请看我们的
发布博文 获取 连接论文

作为研究人员,特别是在(过度)多产的领域,如深度学*,我们经常发现自己被大量的论文淹没,无法阅读和跟踪我们的工作。我认为其中一个很大的原因是没有充分利用现有的工具和服务,这些工具和服务的目的是让我们的生活更轻松。另一个原因是缺乏一个真正好的产品,在一个界面下满足我们所有的需求,但这是另一篇文章的主题。

最*,我进入了 ML 的一个新的子领域,并对优先排序、阅读和管理相关文件的过程感到非常沮丧……我最终寻找工具来帮助我处理这一过载,并希望与您分享我发现的产品和服务。我们的目标是改善任何从事科学论文工作的人的工作流程和生活质量。

我将主要关注纸张消耗(相对于写作)并涵盖:

  1. 参考管理者(又名纸质图书馆)
  2. 分享知识的社交平台
  3. 自动论文分析以获得额外的元数据(关键词、相关数据集、重要引用等)

参考管理者(又名纸质图书馆)

在这些平台上,你可以创建和组织你过去和未来阅读的清单,添加个人笔记,并与一个小组分享。图书馆与云端同步,这意味着你的论文可以在任何地方查阅。认为 goodreads ,但是对于论文。选择以下选项之一:

  1. 门德利:这不是最好看的产品,但它有一个免费增值的商业模式,并支持多种平台,包括 web、PC、Mac 和移动设备。除了一般的纸质笔记,您还可以直接注释和突出显示 pdf。你要为额外的云存储付费(几百篇论文之后必须的)。
  2. Paperpile :付费订阅(没有免费版),但是看起来感觉很现代。很容易从其他服务中导入你的库。图书馆与你自己的谷歌硬盘同步,这是一个优势。目前只适用于 chrome 浏览器。
  3. Zotero :一个免费增值和开源的实现,你需要为额外的云存储付费。与门德利相似,但用途较少。

还有更多 选项,不过这些都是我试过的,都没问题。如果我不得不选择一个,它将是 Mendeley 的平台通用性和免费增值。

Mendeley’s Interface

ArXiv 增强剂

ArXiv 从 1991 年开始出现,在过去的十年里变化很小,而出版量却急剧增加[1]。很自然,今天我们有不同的要求和需求,从我们的主要仓库的文件。我们想要执行论文分析的算法,我们想要找到实现论文的代码,我们想要一个可以共享信息的社交层,也许我们不想看双栏 pdf。

在互联网上搜索现有的解决方案时,我发现了许多这样的工具:

社会阶层

  1. Shortscience :分享论文摘要的平台;目前超过 1000 摘要和增长。适用于任何具有 DOI 的纸张(因此,比 arXiv 更适用)。
  2. OpenReview :一个透明的论文审核流程,也对公众审核开放,目前仅适用于选定的会议,如 NIPS 和 ICLR。除了官方评论之外,最*许多论文都有来自原作者的积极回应。
  3. Scirate :在 arXiv 的克隆体上添加 like (ehh,“scite”)按钮。添加注释部分。大多不活跃。

寻找论文的代码实现

  1. 代码为的论文:自动将论文连接到实现它们的 github 库,并按 github stars 排序。每篇论文可以有多个未合并的条目。
  2. Github pwc :一种极简主义的方法,自动(?)将 papers 连接到一个代码实现,显示为一个简单的表格。
  3. GitXiv :合作策划项目 feed。每个项目方便地呈现为 arXiv + Github + Links + Discussion。不幸的是这个项目不再维护

Some links from Github pwc

其他的

  1. arXiv-sanity :给 arXiv 改头换面,提供公开的摘要、论文预览和非常基本的社交和图书馆功能。Andrej Karpathy 在业余时间大胆尝试将上述许多想法结合在一起。想法都在那里,但在我看来,实现不够好,不足以成为研究人员的首选工具,而且该项目在过去一年中并不活跃。
  2. arXiv-vanity :将来自 arXiv 的学术论文呈现为可响应的网页,这样你就不必斜眼看 PDF 了。

论文搜索和分析

  1. Google scholar :当今搜索论文、查看论文统计以及引用和参考文献、通过关注作者或论文为新论文设置提醒,以及保留自动推荐的基本库。
  2. IBM 科学摘要器:摘要是通过分析论文的内容,以及它们的结构、章节、段落和关键术语而生成的。它并不总是工作得很好,但它在不断改进,非常适合快速浏览文章。
  3. 语义学者:外部素材聚合的论文语义分析。功能包括:暴露引用和参考文献并衡量其影响,显示论文数字,自动生成关键词(主题),分析作者,在互联网上查找其他资源(例如相关的 youtube 视频)并建议推荐论文。
    AI2 支持的新的伟大努力。最*他们对上面提到的 Paperswithcode 和 arXiv 本身做了一个小的集成。).

Semantic Scholar: author profile page

作者工具

  1. 背页:协作、在线 LaTeX 编辑器。想想写论文的谷歌文档。执行得非常好。
  2. Authorea:21 世纪在线合作撰写论文的一种方式,旨在大部分情况下放弃 LaTeX,支持现代的 WYSIWYG 编辑器。支持内联代码和数据的可复制性、内联公共注释和其他非常有意义的特性。
  3. 代码海洋:基于云的计算再现平台。我的理解是,你上传你的研究作为 Jupyter 环境代码,在线运行它,并复制作者得到的相同的图形/输出。这里有一个的例子(按右上方的 Run)。

Tl;dr —我的推荐

我希望这篇文章至少向你介绍了一种可以改善你工作流程的服务。如果你知道这篇文章中没有提到的有用的工具,请在下面分享给大家。

[1]截至 2016 年 10 月,提交率已增长至每月 10,000 多份。https://en.wikipedia.org/wiki/ArXiv

arXiv submission by Topic, from their statistics page

在小型会议中发现巨大价值

原文:https://towardsdatascience.com/finding-big-value-in-small-conferences-d5178295d773?source=collection_archive---------11-----------------------

你可能已经看到了我之前的帖子,关于什么是 DataScienceGO 2018,它在哪里举行,谁将参加。现在,我们将与您分享它是价格最好的会议的原因。

Check it out!

数据科学的真相

面向专业人士的数据科学和技术会议很常见。在美国和更远的地方有很多人参加。如果你想参加的话,当然不会缺少会议。

我成立了 SuperDataScience,作为一家电子学*公司,为每一位数据科学家和数据爱好者提供有价值的内容。这一切都是为了向数据科学家提供他们可以用来推进其职业生涯的信息。

数据科学家需要做的主要事情之一是建立网络和提高技能。这就是为什么我们设立了data science ego,这是一个价格合理的会议,面向那些寻求将其职业生涯提升到一个新水平的数据从业者。

会议—为什么数据科学家应该参加

参加专业会议是数据科学家建立联系和增加就业能力的重要途径。数据科学是一个发展最快的领域,关于什么是数据科学有很多困惑。即使在行业内,每个数据科学家的工作方式都不一样,每个人都有不同的背景。

数据科学从业者需要相互交流他们是如何成为数据科学家的。他们还需要脱颖而出,而做到这一点的最佳方式就是参加数据科学会议。

问题是,它们很贵。很少有低于 1000 美元的费用,这还只是为了参加活动!如果你必须支付会议期间的差旅费和住宿费,这个数字即使不是三倍,也是两倍。

行业和专业会议是你结识该领域专家、客户、导师、朋友甚至商业伙伴的好地方。你将有机会了解即将到来的趋势、软件和技术突破。您将能够了解行业的陷阱,从专家的主题演讲中学*,并发现行业的秘密。

最重要的是,你将能够避免犯你的同龄人在职业生涯中犯过的错误。你将能够找到你职业生涯的最佳路径。在 DSGO,你的周围都是对数据充满热情和兴奋的人,就像你一样。

DataScienceGO——是什么让它与众不同?

SuperDataScience 的成立是为了让数据科学变得更容易理解。我相信,如果有足够的动力、热情和好奇心,任何人都可以成为数据科学家,这就是为什么我们让我们的会议和课程定价合理——教育应该触手可及。

DSGO 也不例外。它的价格实惠,因此任何对数据科学感兴趣或想成为数据科学家的人都可以做到这一点,而不会倾家荡产。我们希望人们聚集在 DSGO,讨论他们是如何成为数据科学家的,并向新来者解释为什么他们也应该成为数据科学家。

对于崭露头角的数据科学家来说,DSGO 是最有价值的会议之一。对于刚进入这个行业的人来说,这是一个完美的会议,而且比其他会议便宜得多,尤其是对圣地亚哥地区的人来说。

为期三天的会议的全票不到 500 美元(如果你快,会更便宜),如果你是团体旅行,还有折扣。这使得许多刚刚进入这个行业的人都可以使用它。与大多数会议相比,DataScienceGO 更小,更个性化,更平易*人,这也是它成本更低的原因。

好事成双

DSGO 的价格合理,因此,这是一个更加个人化和私密的会议。许多大规模的技术和数据会议让人应接不暇。它们在大型会议中心举行。这不仅使得在演讲者的活动之间导航变得不同,而且几乎不可能见到人并和他们说话。

大型活动是令人惊奇的,但是如果你离开附*就找不到任何人,那么参加活动来促进你的职业发展和建立关系网就没有意义了。DSGO 更加个人化,让你有足够的机会见到你的同龄人和你的偶像。

DSGO 也是一个专门为数据科学家举办的会议,因此,它是针对你的问题和疑问的,特别是那些与你的职业道路有关的问题和疑问。你会给 DSGO 留下很多信息,这些信息会对你和你的职业非常有用。

不到 500 美元,DSGO 是一个方便的,负担得起的会议,为已建立的数据科学家和那些有兴趣开始他们的数据科学职业生涯。你将带着信息、经验、教训和人际关系离开。DSGO 是彻底腾飞的第一步!

还没决定?以下是你应该参加的原因

DSGO 很小,很个性化,是为数据科学家设计的。当我们说“数据科学家”时,我们指的是那些对数据科学感兴趣但尚未投身其中的人,以及那些希望将自己的数据科学职业视为可以不断发展的人。我们希望为每个对数据科学感兴趣的人提供一个学*如何在他们的领域取得战略性进展的地方。

DSGO 2018 大会上,你会听到业内专家(包括我自己)以及那些好奇想了解更多入门知识的人的观点。我们希望你有职业发展、目标和成功。我们为个人和团体提供实惠的价格,我们还为学生提供 50%的折扣,因为我们希望让每个人都有机会参加。

我们还设立了专门的网络午餐,您将获得免费午餐,并有机会与您最喜爱的数据科学家或数据爱好者交流。这 90 分钟的时间是很多会议都没有的宝贵机会。在享用免费午餐的同时,你可以了解事情的本质、陷阱和错误。所以带上你的名片吧!

去 DSGO 2018

我们毫不犹豫地投资于我们的大学教育、我们的笔记本电脑、智能手机和 WiFi 连接。这些都是我们认为对推进我们的生活和事业不可或缺的东西。按照这种逻辑,我们为什么不投资这个机会去参加一个专门针对我们职业需求的会议呢?

数据科学正在成为一个饱和的行业,因此我们需要确保自己脱颖而出。做到这一点的一个简单的方法是把我们自己放在那里,和那些在位置上的人握手,引导我们走向成功。

坐在电脑前是我们工作的主要组成部分,我们从电脑上收集所有的数据和研究。不幸的是,我们无法在舒适的办公椅上学会如何交谈。我们可以学*技术诀窍,但我们不会得到职业建议,也不会与其他数据科学家面对面交流。

寻找 TED 演讲的特点

原文:https://towardsdatascience.com/finding-characteristics-of-ted-talks-911879560146?source=collection_archive---------3-----------------------

今天我想了解一下 TED 演讲的特征分布——它们被用户评价为优美、巧妙还是啰嗦?

为了做到这一点,我用 TED 点击了最新的数据集,其中包括从年初到今年迄今的所有有评级的谈话,将 json 列解析为包含 14 个正面和负面特征的数据框架,从有说服力到有创意到令人讨厌到令人瞠目结舌,然后根据谈话的最大值对这些特征进行归一化(否则观看最多的人也会因为观众基数较大而显得最冗长),并将它们绘制在平行坐标上,以获得它们分布的概览。

平行坐标乍看之下可能不是最容易理解的视图,但它有一个优点,可以清晰地布局多元数据集的分布。这里每条线代表一个谈话,它们与多轴的交点代表不同的特征。

在根据最大属性对每个演讲进行标准化后,我通过关注这些属性在 0.95 到 1 范围内的人,放大到最美丽、勇敢、率真、有说服力和令人讨厌的演讲。

最美丽的谈话很少不鼓舞人心或引人入胜。

最有勇气的谈话往往鼓舞人心,但不那么引人入胜。

最巧妙的谈话往往是鼓舞人心的,引人入胜的,信息丰富的。其中有一个被评为不可信,这是一个 beatjazz 表演。

最有说服力的演讲通常也被认为是信息丰富和鼓舞人心的。

也有一些令人讨厌的,包括一个音乐家的呼吸和音乐表演(可能太前卫了)。

这是我关于数据科学和视觉故事的# 100 日项目的第 61 天。我的 github 上的全部代码。感谢阅读。如果你喜欢,请分享。欢迎新主题的建议和反馈。

用 Python 查找歌曲中的合唱

原文:https://towardsdatascience.com/finding-choruses-in-songs-with-python-a925165f94a8?source=collection_archive---------4-----------------------

如何使用一些非常简单的模式识别找到音乐中的合唱

Popular Song Structure

你有没有觉得现在的歌曲重复了很多遍?

我甚至没有谈论像蠢朋克的这样围绕着单词的歌曲,其中相同的 4 个小节基本上重复了 7 分钟(尽管它超级朗朗上口)。在多种流派中,似乎一旦你录制了一首独唱和合唱,你可以复制/粘贴几次,然后瞧,你就有了一首完整的歌曲。独唱—合唱—独唱—合唱—桥听起来像合唱—合唱的结构一如既往的受欢迎。

事实上,歌曲中的重复是分析它们的一个很有价值的工具。这是我最*在研究用机器学*寻找歌曲结构时偶然看到的一篇论文的主题。这个想法非常简单,而且效果非常好,我认为它值得探索。

大致来说,歌曲结构指的是识别引子-独唱-合唱-桥梁等。当我们听一首歌的时候,我们会自然地认出这些部分。在这篇文章中,我们将特别考虑如何找出歌曲的哪些部分包含副歌或叠句,这是一个比找出整个结构更简单的问题。这有许多应用程序,例如为 iTunes/Google Play 选择歌曲预览,为像 songpop 这样的琐事游戏选择可识别的剪辑,甚至自动生成 DJ 提示点。

这是即将到来的一个小小的预览。您可以跳到结果部分获得更多输出:

算法概述

在高层次上,由于副歌是通常重复次数最多的部分,我们试图找到歌曲中重复次数最多的部分。算法大致如下

  1. 找出歌曲中任何时刻正在播放的音符
  2. 将歌曲的短部分与其他部分进行比较,看哪里有重复的部分
  3. 寻找那些重复多次且连续重复之间有很大间隔的长片段

让我们深入研究一下实现,看看这是如何做到的。假设有一些编程和音乐理论的基础知识,所有代码都可以在https://github.com/vivjay30/pychorus找到并安装

pip install pychorus

正在演奏什么音符

我们需要做的第一件事是把歌曲的 1 和 0 变成有用的东西。最简单的方法是使用频率,因为频率告诉我们存在什么音符(例如,A 是 440 赫兹)。将原始声音信号转换成频率涉及到大量的数学运算,但幸运的是,我们有库来为我们做这件事。为了这篇文章我选了一首经典的流行歌曲, 尖叫和呼喊 靠意志。这绝对是我高中时的最爱。

import pychorus
chroma, _, _, _ = pychorus.create_chroma("scream_and_shout.mp3")

这主要是一个 librosa 库的包装器,做两件事。首先,它使用傅立叶变换将原始波形转换成频率。然后,它使用不同八度的音符频率知识(不同八度的 A 为 440hz、880hz、1760hz 等)来了解任何时刻正在播放的音符。歌曲中任何时刻播放的音符列表称为色谱图。

也许你已经可以从频谱中看出一些歌曲结构了。

Frequencies present at any moment of the song

Notes present at any moment. Lighter means more of that note

最简单的思考方式就像视频帧。声音是连续的,但计算机处理的是离散的数据。这个色谱图每秒大约有 5 帧,每一帧告诉我们在 0.2 秒的音乐片段中播放了什么音符。因为在西方音阶中有 12 个音符,所以每个帧是 12 个元素的向量,其中每个值在 0 和 1 之间。例如,如果我们正在听一个纯音符 A,向量将是[0,0,0,0,0,0,0,0, 1 【T7,0,0],如果音乐完全无声,那么它将全为零。对于一个 4 宋敏,这给出了一个 1200×12 的矩阵。

尽管查看原始频率是可行的,但出于几个原因,我们将其转换为音符。首先,它对不同合唱中的乐器变化提供了更强的鲁棒性。例如,如果最后一个合唱团有一个额外的吉他或更多的鼓,频率可能会非常不同,但实际的音符和和弦将是相似的。此外,处理音符允许我们在更低维度的空间中工作(12 个可能的音符与人类可以听到的 5000 个不同的频率)。

寻找相似之处

现在让我们考虑如何找到长的重复部分。

听听这首歌中的两个不同的合唱部分。我们将专注于检测这些特定的合唱。

First chorus, 0:44–1:00 in the song

Second chorus, 2:30–2:45 in the song

这些部分听起来是一样的,但是我们如何测量呢?

因为我们的歌曲是每个 12 个音符的帧的集合,所以我们需要一个相似性函数来比较任何给定的歌曲帧。如果 V₁和 V₂是歌曲中任意两个实例的 12 个音符矢量,那么我们将使用下面的相似度函数:

直觉:我们首先求向量的差,然后看范数。如果演奏相同的音符,那么差异的范数将接*于 0,如果音符不同,那么这个范数将很大。我们除以√12 使得结果总是在 0 和 1 之间,我们从 1 中减去使得相似的音符得到高分,反之亦然。

我们现在需要做的是迭代所有可能的歌曲帧对,看看哪些是相似的,并寻找具有相似的连续帧的两个区域。形式上,我们可以创建一个矩阵 M ,其中M[x][y]=相似性(x,y) ,使用上面的相似性函数这叫时间-时间相似度矩阵。请参见下面生成它的示例代码。实际上,我们可以用 numpy 广播更快地做到这一点,但是较慢的例子更容易理解

完整的时间-时间矩阵如下图所示。注意一些属性

  1. 它关于对角线对称,因为帧 xy 之间的相似性与帧 y 和帧x:M[x][y]= M[y][x]之间的相似性相同
  2. 对角线全是 1,因为每一帧听起来都完全像它自己:具体来说 M[x][x]=1

Time-Time similarity matrix for the entire song

现在让我们来看看这些合唱部分相交的地方

Time-Time Similarity for a repeated chorus

请注意 x 轴上从 2:30 到 3:00 延伸的黑色对角线,y 轴上从 0:45 到 1:15。这对应于上面播放的第一和第二合唱之间的匹配。

直观地说,如果 0:45–1:15 的片段与 2:30–3:00 的片段相似,那么这意味着 0:45 的帧应该与 2:30 的帧匹配,0:46 的帧与 2:31 的帧匹配,直到 1:15 的帧与 3:00 的帧匹配。希望你能看到重复的部分总是用对角线表示。

“重复部分是时间-时间相似性矩阵中的对角线”

时滞相似矩阵

不幸的是,检测矩阵中的对角线比检测垂直线或水平线更加困难和缓慢。正因为如此,我们可以应用一个简单的线性变换,使重复的和弦显示为水平线,而不是对角线,使以后的处理更容易。这是通过创建时间滞后相似性矩阵来完成的。如果时间-时间矩阵测量帧 x 和 y 之间的相似性,那么时间滞后矩阵测量帧 x 和 y 秒前发生的帧之间的相似性。形式上,时滞矩阵T[x][y]= M[x][x-y]=相似度(x,x-y)。

让我们来看看之前看到的那场合唱比赛。

Time Lag matrix zoomed into the match between first and second chorus

我们的对角线现在变成了水平线。x 轴是一样的,但是现在这条线在 1:45 左右有一个恒定的 y 值。由于 2:30–3:00 的第二次合唱与 0:45–1:15 的合唱相似,所以这条线告诉我们,2:30 的帧与 1:45 之前的帧相似。2:31 的画面与 1:45 前的画面相似…3:00 的画面与 1:45 前的画面相似

综上所述,2:30–3:00 的音乐与歌曲中发生在 1:45 之前的部分相似。这就是为什么我们在 y 坐标 1:45 处有一条从 2:30 到 3:00 的线。

“重复部分是时间滞后相似矩阵中的水平线”

因为我们知道我们正在寻找水平线,我们可以做一些很好的一维去噪和平滑技术来隔离这些线。这基本上是现在的计算机视觉,去噪后可以看到那个合唱交集的结果。

从这个去噪矩阵中,我们可以通过迭代每一行并使用最小检测分数和最小线长度的阈值来容易地识别线(重复部分)。

为了简单明了,我们将在时间-时间空间(对角线)中演示算法的其余部分,但实际上,为了速度和更容易实现,该算法是在时间滞后空间(水平线)中实现的。

计算所有重复的部分

现在我们有了检测歌曲中重复部分的方法,我们需要一种方法来计算合唱重复的次数。理论上,如果合唱在歌曲中出现了 n 次,我们应该有 n 条线代表所有可能的交叉点。我们很少能探测到所有的合唱,但只有少数几个是必要的,以了解合唱团在哪里。请参见下面的动画来计算行数。

Example of finding 9 line segments for 3 choruses in the time-time diagram

在这个例子中,我们显示了 9 条对角线,对应于 3 个彼此匹配的合唱。事实上,有超过 3 个合唱团,你可能会看到不止 9 个突出线。

注意所有检测到的线是如何水平或垂直匹配的。对于每个线段,我们只需在水平和垂直方向寻找其他线段,并根据我们相交的其他线段的数量来得分。为了输出合唱,我们可以选择任何重复的合唱部分,但我们将选择具有最强相似性得分的最多交叉点的部分。(同样,理论上它们都有相同数量的交集,但实际上总有一个交集的相似性得分更高)。

结果

现在是有趣的部分!我们一边寻找至少 15s 的合唱,一边看看算法输出的是什么样的小节。

为了表明它不仅适用于流行音乐,下面是著名的富尔·伊利斯钢琴曲的合唱部分:

为了好玩,我决定在世界各地的蠢朋克上运行它。老实说,一个随机数生成器也会找到这首歌的副歌部分。

这是世界各地时间-时间相似性矩阵的一部分。记住对角线是重复的部分。是的,这是很多重复,尤其是一个 1 分钟的剪辑。

Section of time-time similarity matrix for Around the World

缺点和今后的工作

一个主要的问题是,这种方法对于以不一致的速度录制的音乐不起作用。例如,很多旧音乐,如摇滚,通常是在没有节拍器的情况下录制的,但鼓手会跟上节奏。如果一个合唱比另一个快或慢,那么它通常不会被拾取。

以下是披头士黄色潜水艇在时滞空间的重复合唱。

这条线应该是水平的。然而,第二次合唱明显比第一次慢,这导致线明显向下倾斜。这意味着我们的水平线检测器没有拾取重复,并且我们没有合唱检测。

取而代之,我们采用一种方法,其中我们对矩阵进行阈值处理,并且寻找在 x 轴上具有足够大跨度的连通分量。这只有在我们知道这首歌是在没有节拍器的情况下录制的情况下才能做到。开始时,我们可以使用节拍检测器,查看节拍之间的标准偏差。对于严格定时的歌曲,标准差基本为 0,而自由录制的歌曲标准差要大得多。

这项功能尚未发布,是其他变化中的计划功能,例如可以选择输出哪个合唱团(而不仅仅是得分最高的一个)。

结论

我们从观察到歌曲会自我重复开始,最后用一种快速简单的方法来检测合唱。

这种方法的主要优点之一是,它可以在几秒钟内在 cpu 上运行一首完整长度的歌曲,这与需要更多计算或 gpu 的神经网络方法相反。尽管机器学*模型几乎肯定会做得更好,但这种算法很容易理解,也是对信号处理和音乐模式识别的很好介绍。

我鼓励你尝试在一些歌曲上运行源代码,看看你会得到什么样的结果!

如果有任何问题,也可以随时联系,或者在 twitter 上关注我在【https://twitter.com/vivjay30】T4 的更多项目和更新!我总是很乐意与对人工智能和音乐感兴趣的人交谈和合作。

用 OpenCV 实时查找车道线

原文:https://towardsdatascience.com/finding-driving-lane-line-live-with-opencv-f17c266f15db?source=collection_archive---------2-----------------------

你好,在这个项目中,我将尝试从仪表板摄像头视频饲料找到车道线。一旦我们检测到车道线,我们将在原始视频帧上标记它们并回放。所有这些都将使用 OpenCV 函数在线完成,没有任何延迟。

我们的方法是开发一系列功能来检测车道线。在编写这个函数时,我们将使用一个“样本”图像,一旦我们能够成功地检测到几个“样本”图像上的车道线,我们将把完整的程序合并到一个函数中,该函数可以接受实时馈送图像并返回相同的图像帧,其中车道线高亮显示。所以没有太多的延迟,让我们开始吧。

Sample Image

首先,我们输入样本图像帧。这一行将在最终代码中进行注释,其中“图像”将是由视频捕获发送的帧。

image = cv2.imread('test_images/whiteCarLaneSwitch.jpg')

Greyed Image

为了减轻我们处理器的负担(这在嵌入式系统中是非常稀缺的资源),我们将以图像的“灰度”版本而不是原始的彩色版本来进行所有的图像处理。这有助于用更少的资源更快地执行我们的程序。以下函数将彩色图像转换为灰度图像

grey_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

Image Blurring (Image Smoothing)

接下来,我们将通过模糊图像来去除噪声。图像模糊是通过将图像与低通滤波器核进行卷积来实现的。这对于消除噪音很有用。它实际上删除了图像中的高频内容(例如:噪声、边缘)。所以在这个操作中边缘有点模糊。OpenCV 提供了 4 种不同类型的模糊技术,高斯模糊是最流行的一种。

我们可以选择不同的内核大小,其中结果滤波器将简单地取内核(内核大小的行×列矩阵)区域下所有像素的平均值,并用平均值替换中心元素。同样,5 是一个相当标准的值,并且对我有效。

kernel_size = 5blur_gray = cv2.GaussianBlur(grey_image,(kernel_size, kernel_size),0)

Canny Edge Detection

Canny 边缘检测是一种流行的边缘检测算法。事实上,Canny edge function 还实现了我们在前面步骤中使用的 5x5 核高斯滤波器,但在我接触的许多文献中,它总是建议在 Canny 边缘检测之前实现自己的模糊。边缘检测背后的基本理论是,只要有边缘,边缘两侧的像素在它们的强度之间就有很大的差异(也称为梯度)。首先,在水平和垂直方向上扫描输入图像,以找到每个像素的梯度。在获得梯度大小和方向后,对图像进行全扫描,以去除可能不构成边缘的任何不想要的像素。为此,在每个像素处,检查像素是否是其邻域中的局部最大值。

low_threshold 和 high_threshold 决定检测到的边沿强度。如果梯度高于“high_threshold”,则梯度被视为边缘的一部分。但是一旦检测到边缘,即使下一个像素大于“low_threshold ”,它也会包含在边缘中。

low_threshold = 50high_threshold = 150edges = cv2.Canny(blur_gray, low_threshold, high_threshold)

参考我们的示例图像,很明显,在边缘条件下,尤其是车道线所在的位置,相邻像素之间存在巨大的对比度差异,车道线为白色,相邻道路像素为黑色。

Region of Interest

需要考虑的一点是,我们不想找到图像中的所有边缘。我们只是对找到图像中心区域周围的车道感兴趣。直观上,这是有意义的,因为图像的右上/左上部分的边缘极不可能是车道。查看样本图像,我们可以有把握地说,车道线应该在梯形区域内,图像底部的边缘较宽,图像顶部的边缘越来越窄。

以下四条线标记了我们的边缘检测图像中的感兴趣区域。首先,我们找出图像的大小,其次我们创建梯形的四个角(这一步,和许多其他步骤一样,是一个迭代过程,其中我们需要尝试不同的值来找出最佳情况)。第三,我们用上面的顶点创建梯形,最后我们做一个逐位运算,这样只有在感兴趣的区域内并且被分类为边缘的像素被标记为 1。

imshape = image.shapevertices = np.array([[(0,imshape[0]),(450, 320), (500, 320), (imshape[1],imshape[0])]], dtype=np.int32)cv2.fillPoly(mask, vertices, ignore_mask_color)masked_edges = cv2.bitwise_and(edges, mask)

接下来,我们执行霍夫线变换,以便从上述边缘检测图像中检测一条线。请记住,边也可以是圆形边,但我们在应用中感兴趣的边是车道的直线边。

Hough Line Transform

简而言之,霍夫变换法将一条直线从其传统的 y = mx + b 形式变换为ρ= x * cos(θ)+y * sin(θ)其中ρ是从原点到该直线的垂直距离,θ是该垂直线与水平轴形成的角度。

我们知道一条线(y = mx + b)在 m vs b 图中表示时只是一个点,x,y 框架中的一个点在 m vs b 框架中表示为一条线。

所以我们在图像空间中寻找直线的策略是在霍夫空间中寻找相交的直线。为此,我们将霍夫空间划分为一个网格,并将相交线定义为通过给定网格单元的所有线。在霍夫空间中许多直线相交的地方,我们宣布我们已经找到了描述图像空间中一条直线的点的集合。

我们有一个问题,垂直线在 m 对 b 的表示中有无限的斜率,这就是ρ对θ参数化的需要。

现在图像空间中的每个点对应于霍夫空间中的正弦曲线(rho vs theta)。如果我们取一整行点,它就转化成霍夫空间中的一整串正弦曲线。您可以将霍夫空间中的正弦曲线视为相当于 m vs b 空间中的一条线,它表示图像空间中的一个点。同样,霍夫空间中这些正弦曲线的交点给出了直线的表示。回到我们的代码,我们首先定义霍夫变换的参数,然后调用函数本身。

rho = 2 # distance resolution in pixels of the Hough gridtheta = np.pi/180 # angular resolution in radians of the Hough gridthreshold = 15     # minimum number of votes (intersections in Hough grid cell)min_line_length = 40 #minimum number of pixels making up a linemax_line_gap = 30    # maximum gap in pixels between connectable line segmentsline_image = np.copy(image)*0 # creating a blank to draw lines on

输出“线”是包含检测到的线段的端点的数组。

lines = cv2.HoughLinesP(masked_edges, rho, theta, threshold, np.array([]),min_line_length, max_line_gap)

迭代输出“线”并在空白图像上画线。

for line in lines:
        for x1,y1,x2,y2 in line:
            cv2.line(line_image,(x1,y1),(x2,y2),(255,0,0),10)

在原图上画线,还回来。

lines_edges = cv2.addWeighted(image, 0.8, line_image, 1, 0)return lines_edges

Lane Lines on a single frame

在样本图像上成功检测车道线之后,我们将视频作为输入,检测车道线并回放视频。请注意,这里我处理的是以前录制的视频,但这可以很容易地应用到使用相同 cv2 的现场视频。视频捕捉功能。

首先,我们使用 cv2 创建一个视频对象。视频捕获命令。当‘video _ capture’运行时,我们读取它。Read()函数将返回两个变量,其中第一个变量是布尔值,分别用 true 或 false 值指示读取操作的成功或失败,第二个对象是捕获的帧本身。因此,每当“ret”为真时,我们就获取帧,并简单地将其传递给我们刚刚在上面构建的 processImage 函数。从 processImage 接收的输出显示在捕获帧顶部的车道标记上。

video_capture = cv2.VideoCapture('test_videos/solidWhiteRight.mp4')while (video_capture.isOpened()):
    ret, frame = video_capture.read()
    if ret:
        output = processImage(frame)
        cv2.imshow('frame',output)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break# Release everything if job is finished
video_capture.release()
cv2.destroyAllWindows()

仅此而已。希望这篇文章写得足够好,让你愉快地阅读,并希望学到一两件事。显然,在上述程序中可以实现更多的改进,例如,检查检测线的斜率,以检查检测线是否实际上与车道线一致,并移除异常值。等等。欢迎提出任何改进建议,也欢迎提出有助于我成长的建议。完整的代码与样本图像和视频可以找到这里

如果你喜欢这篇文章,在 Twitter 或 Claps 上关注、转发它,在我继续我的博客世界之旅时,Medium 上的赞会鼓励我写新文章。

直到下一次…干杯!!

找到好的学*率和一个周期的政策。

原文:https://towardsdatascience.com/finding-good-learning-rate-and-the-one-cycle-policy-7159fe1db5d6?source=collection_archive---------1-----------------------

简介

学*速率可能是深度学*中最重要的超参数,因为学*速率决定了要反向传播多少梯度。这反过来决定了我们向极小值移动了多少。小的学*率使模型收敛缓慢,而大的学*率使模型发散。所以,学*率需要刚刚好。

Gradient descent with small(top) and large (bottom) learning rates. Source: Andrew Ng’s Machine Learning course

找到并设定正确的学*速度更多的是尝试和错误。最简单的方法是尝试不同的学*速率,选择一个损失值最小的速率,而不牺牲学*速度。(验证损失对于欠拟合/过拟合也很重要)。

本文对描述不同超参数设置方法的两篇论文进行了简要总结。这篇文章假设读者知道反向传播,梯度下降和超参数。

有没有更好的办法?

在经历 程序员实用深度学*第 1 部分 mooc 时,提到了 Leslie N. Smith 的论文 用于训练神经网络的循环学*率

该论文提到了几个时期的范围测试运行,以找出良好的学*率,其中我们从一些低学*率开始训练,并在每个小批量之后增加学*率,直到损失值开始爆炸。

Learning Rate Increase After Every Mini-Batch

想法是从小学*率(如 1e-4、1e-3)开始,并在每次小批量后增加学*率,直到损失开始激增。一旦损失开始爆发,停止范围测试运行。绘制学*率对损失图。选择比损失最小的学*率低一个等级的学*率(如果损失很低,为 0.1,则开始的好值为 0.01)。这是损失仍在减少的值。论文建议这是模型良好学*率值。

Test run on CIFAR-10 with batch size 512, resnet 56 , momentum=0.9 and weight decay=1e-4. The learning rate ~10⁰ i.e. somewhere around 1 can be used.

这就是我们在每次小批量后更新学*率的方式:

n =迭代次数
max_lr =要使用的最大学*率。通常我们使用更高的值
,比如 10,100。请注意,在范围测试期间,我们可能达不到这个 lr 值。
init_lr =较低的学*率。我们将从这个值开始范围测试。我们使用非常小的值,如 1e-3,1e-4。
设 q 为我们在每次小批量后增加学*率的系数。
下图显示了计算第 I 个小批量后学*率的公式。

一旦我们找到最佳学*率,我们就用它来训练模型。范围测试是非常有用的工具,因为它提供了一种用少量历元运行找到良好学*率的方法。

循环学*率:

该论文进一步建议在完整运行期间在下限和上限之间循环学*速率。传统上,随着学*开始随时间收敛,学*速率降低。那么循环学*率背后的动机是什么呢?

直观上,将学*速率向更高的学*速率振荡是有帮助的。因为较高的学*率可能有助于摆脱鞍点。如果鞍点是复杂的平台,较低的学*率可能无法从鞍点获得梯度。

A saddle point in the error surface (Img Credit: safaribooksonline)

周期是我们从下限学*率到上限再回到下限的迭代次数。周期在时期上可能没有边界,但是在实践中它通常有。步长是周期的一半。所以步长是我们希望学*率从一个界限到另一个界限的迭代次数。

Cyclic Learning Rate(Image: https://arxiv.org/pdf/1506.01186.pdf)

单周期政策

在论文“神经网络超参数的训练方法:第 1 部分—学*速率、批量、动量和权重衰减”中,Leslie Smith 描述了设置超参数(即学*速率、动量和权重衰减)和批量的方法。特别是,他建议应用学*率的一个周期政策。

作者建议做一个周期的学*率 2 步等长。我们使用范围测试来选择最大学*速率。我们使用较低的学*速率作为最大学*速率的 1/5 或 1/10。在步骤 1 中,我们从较低的学*率到较高的学*率,然后在步骤 2 中回到较低的学*率。我们选择这个周期长度略小于要训练的总时期数。在最后剩余的迭代中,我们将学*率消除到低于较低的学*率值(1/10 或 1/100)。

这背后的动机是,在学*过程中,当学*率较高时,学*率作为正则化方法工作,并防止网络过度拟合。这有助于网络避开陡峭的损耗区域,更好地获得平坦的最小值。

CIFAR -10: One Cycle for learning rate = 0.08–0.8 , batch size 512, weight decay = 1e-4 , resnet-56

如图所示,我们从 0.08 的学*率开始,进行 41 个时期的步骤,以达到 0.8 的学*率,然后再进行 41 个时期的步骤,回到 0.08 的学*率。然后我们再做 13 个纪元,以达到学*率下限的 1/10(0.08)。

使用 CLR 0.08–0.8、批次大小 512、momentum 0.9 和 Resnet-56,我们在 CIFAR-10 上的 95 个历元中获得了大约 91.30%的准确度。

循环动量

动量和学*率密切相关。在 SGD 的权重更新方程中可以看出,动量对权重更新的影响与学*速率相似。

作者在他们的实验中发现,当学*速率增加时,减小动量会给出更好的结果。这支持了直觉,即在训练的那一部分,我们希望 SGD 快速进入新的方向以找到更好的最小值,因此新的梯度需要被赋予更多的权重。

实际上,我们选择 2 个动量值。在一个循环中,我们做动量的两步循环,在第一步中,我们从上限到下限减少动量,在第二步中,我们从下限到上限增加动量。根据该论文,这种循环动量给出了相同最终结果,但这节省了用不同动量值运行多个完整循环时间和精力。

用一个周期政策和周期动量,我可以复制论文中提到的结果。其中,该模型在 9310 次迭代中实现了 91.54%的准确性,而使用一个周期,学*率为 0.08-0.8,动量为 0.95-0.80,使用 resnet-56,批量为 512,而没有 CLR,则需要大约 64k 次迭代才能实现这一准确性。(论文达到了 92.0±0.2 的准确率)。

Accuracy vs Iterations

Training and Validation loss vs epochs

这允许我们以更高的学*速率训练模型。在学*率为 0.3–3 的情况下,我们可以通过训练 resnet-56 仅 50 个时期来获得 85.97%的训练准确率。

重量衰减值也很重要。

重量衰减也是一个重要的超参数。重量衰减也作为正则化因子。但是它与学*速度或动量有很大不同,因为作者发现最佳值应该在整个训练过程中保持不变。

Resnet 56 Accuracy after 50 epoch on CIFAR-10 with weight decay = 1e-3(left) vs 1e-5(right)

Resnet 56 training and validation losses after 50 epoch on CIFAR-10 with weight decay = 1e-3(left) vs 1e-5(right)

从上面可以看出,图 1e-3 是非常差的重量衰减值,因为在 50 个时期后,精确度勉强达到 60%,而重量衰减 1e-4 和 1e-5 的精确度分别为 85.97%和 87.78%。(CLR 范围为 0.3–3,动量范围为 0.95–0.8,批量为 512)

作者建议,用不同权重衰减值的 CLR 和循环动量进行组合运行,以同时确定学*率、动量范围和权重衰减。如果不知道什么是正确的重量衰减值,该论文建议首先使用 1e-3、1e-4、1e-5 和 0 这样的值。另一方面,如果我们知道,比如说 1e-4 是正确的值,本文建议尝试三个平分指数的值(3e-4、1e-4 和 3e-5)。

总批量

该论文建议将可装入存储器的最大批量值用作批量。

结论

范围测试方法提供了一种定义的方法,通过少量的运行迭代来找出一个好的学*率值。一个循环和循环动量似乎允许模型以更高的学*速率被训练并且收敛得更快。单周期政策提供了某种形式的规范化。因此,其他形式的监管也需要相应调整。

上面提到的实验很少能在笔记本这里找到。

参考资料:

  1. 训练神经网络的循环学*率
  2. 神经网络超参数的训练方法:第 1 部分——学*速率、批量、动量和权重衰减
  3. 吴恩达的 Coursera 课程
  4. 法斯泰图书馆
  5. 程序员实用深度学*,第 1 部分
  6. https://sgu gger . github . io/how-do-you-find-a-good-learning-rate . html
  7. http://teleported.in/posts/cyclic-learning-rate/
  8. https://sgugger.github.io/the-1cycle-policy.html

如果你喜欢这篇文章,请一定给我一个掌声,并关注我以获取我未来文章的更新。

还有,随时在LinkedIn上联系我或者在Twitter上关注我。

如果你喜欢我的作品,请考虑赞助我,它会帮助我推出更多这样的作品。

利用边缘检测寻找农田土地面积

原文:https://towardsdatascience.com/finding-land-area-of-farm-plots-using-edge-detection-5b070cc05c5a?source=collection_archive---------14-----------------------

为农业目的使用现代技术

我不会特意让我的项目与农业相关。然而,我继续发现图像处理和机器人技术在农田中的应用。也许是许多农场地块的几何一致性,或者是工程和学术界推进这个乡村话题的更大愿望。

在最*的一次假日聚会上,我与一位经济学家进行了交谈,他需要获得不同农场地块大小的数据。对于美国的很多农场来说,这个数据是存在的。然而,获取这些数据通常需要付出高昂的代价。此外,许多外国和发展中国家没有现成的地块面积数据。这个数据很有意思。

幸运的是,有大量卫星图像形式的公开农场数据。把你的视野放在美国中西部的任何一个地区,你一定会发现一片片的农田。这就产生了将图像处理算法应用于农田以确定单个农场所占面积的想法。

A set of farms used to test the algorithm

我选择追求的概念包括使用导数滤波器。这是有意义的,因为它似乎与人类区分土地或形状的方式相匹配。当我们扫描一个物体时,我们使用对比和阴影来确定物体的形状、用途和身份。类似地,导数滤波器可以用于寻找对比区域。如果像素值与其周围像素值之间的差值大于阈值,则用 1 标记,否则用 0 标记。这将创建一个二进制图像,并选择原始图像的边缘。

在此之前,建议对图像应用模糊滤镜。原始图像中有大量的噪声和细节会降低算法的成功率。这可以用任何模糊过滤器来完成,并且鼓励用户实现这种算法实验。由于我主要对去除噪声和微小的细节感兴趣,同时出于对比目的保留了图的颜色,所以我使用了 4x4 中值滤波器。一个标准的高斯滤波器也可以。模糊滤波器之后是灰度图像,以便应用边缘检测。

Blurred and gray scaled farms

实验了三种边缘检测方法来寻找最佳结果。我将简要描述每一种方法及其结果,但是我鼓励好奇的读者自己研究每一种方法以获得更彻底的理解。

第一个被测试的边缘检测滤波器,也可能是最著名的,是 Sobel 滤波器。此滤镜对图像中的每个像素执行渐变检查。内置的 Matlab 函数执行水平和垂直方向的运算,并合并结果。

内置 Sobel 滤波器的 Matlab 返回最干净的结果。最终的图像几乎没有噪声。不幸的是,将过滤后的图像与原始图像进行比较,可以看到许多图之间的分隔线没有被很好地拾取。这一点在农场与相邻地块颜色差异不大的地区尤为明显。可能需要使用 Sobel 滤波器中的值来获得这些更加混合的区域。

测试的第二种方法是 Canny 滤波器。从左侧查看 Canny 滤波器的结果,可以立即看到 Canny 滤波器拾取了更多的边缘。缺点是也拾取了相当多的噪声。考虑到 Canny 算法采用通过幅度阈值函数的像素和通过稍低阈值函数的相邻像素的并集,这是预料之中的。Canny 算法比简单的 Sobel 滤波器更复杂。它还依赖于预先执行的高斯平滑。中值滤波器的使用可能会妨碍最佳结果。

The Laplacian of Gaussian filter returned the best results

测试的最后一个滤波器是高斯的拉普拉斯滤波器。当比例是一个因素时,该滤波器非常适合边缘检测。无论我们使用什么过滤器,我们看到大多数突出的道路被捕获。来自小的农作物阴影或邻*道路的可能的房屋的噪声的标记依赖于滤波器。与道路相比,这些是不同比例的小细节。农场图像的这一特性使其成为高斯拉普拉斯滤波器的理想选择。从测试结果来看,呈现了一个相当理想的结果。找到噪音最少的最大数量的道路。

为了进一步去除图像中的噪声,使用 Matlabs 区域属性函数来去除总像素面积小于平均像素面积值的所有白色区域。当然,这个阈值还可以进一步实验,但是我们发现它在这个测试用例中工作得很好。

反转过滤后的图像,给出标绘土地的区域。然而,道路只有一个像素宽。这为应该分割的区域连接留下了很好的可能性。仅需要单个公共像素来形成两个应该被分割、组合的区域。排除这种可能性,在图像上执行维数为 4 的膨胀正方形。此外,一个像素的黑色边框被添加到整个图像,以识别将图像作为一个区域的地块。

Dilated Image

有了这张图片,寻找每块土地的面积就一目了然了。Matlab 的(或者 OpenCV 的)regionprop 函数可以用来求每个区域的面积。仍有一小块土地不是小块土地。有些是残留的道路或其他细节。为了减少这些面积,我只包括面积大于平均值减去一个标准差的区域。

然后每个区域被着色,其像素尺寸被印在它的点上。结果可以在下图中看到。打印的尺寸是该区域像素的实际数量。除非像素和图像尺寸之间存在已知的比例,否则这些值是没有用的。我知道卫星应用程序,如谷歌地图,往往有一个规模。我让感兴趣的开发人员来实现这个特性。

总的来说,我对结果很满意。该应用程序能够将大部分地块分成各自特定的区域。有一些例外,例如像素值为 47,680 的大橙色部分将两个区域混合在一起。这可以通过调整膨胀值来解决。另一个要考虑的因素是,道路的扩张确实侵蚀了农场的像素区域。为了得到农场更精确的价值,把侵蚀的结果加到农场的总面积上可能是有意义的;未来发展的另一个话题。

Result of our test farm

我想简单地评论一下所探索的另一种方法。代替使用边缘检测来寻找农场,超级像素可以是一种有效的方法。在与前面提到的经济学家探讨了这项任务之后,超级像素被测试并展示了同等的(如果不是更好的)结果。

Another farm example (top) and its result (bottom). Note, larger images need better thresholding strategies.

Github 脚本链接:

[## TimChinenov/农用绘图仪

下面是一个 Matlab 脚本,它使用图像处理来确定图像中农场地块的数量并打印…

github.com](https://github.com/TimChinenov/FarmPlotter)

使用 Twitter 数据查找本地事件

原文:https://towardsdatascience.com/finding-local-events-using-twitter-data-18298f03ead6?source=collection_archive---------12-----------------------

Photo by Giammarco on Unsplash

无人监督的学*

陈亦飞、阿什温·古普塔、Shruthi Krish、Raghav Prakash、王巍的项目

Twitter 是一个社交媒体平台,数百万用户用它来分享自己的生活更新。通常,这些推文是关于用户周围发生的本地事件。尽管新闻机构报道当地的事件,但是新闻机构了解、调查和报道事件所花费的时间是相当长的,尤其是与事件的持续时间相比。相比之下,用户对可能发生的事件的解释会实时上传到 Twitter 上,他们的 Twitter 订阅源的追随者可以在新闻机构广播信息之前了解到事件。

在这个项目中,我们分析来自给定地理区域的推文,以确定某个事件是否已经发生。然后,我们报告与该事件相关的最具描述性的推文。解决这一问题将是一种快速提醒用户其所在区域可能发生事故的方法。我们的方法将数据分成位置桶,识别推文活动中的峰值,然后根据相似性对推文进行聚类。

一.项目概述

  • 目标:给定带地理标签的 Twitter 数据,识别一个本地事件
  • 应用:如果实时完成,用户可以在新闻媒体报道之前得到当地事件的通知。确切的应用因确定的事件类型而异。例如,如果检测到交通延迟,用户可以通过选择替代路线来避免延迟。我们的系统也将能够向新闻站提供信息,以便他们能够进一步调查。

方法概述

  1. 获取并预处理特定区域的推文
  2. 将推文分成位置桶
  3. 发现异常
  4. 定义重大事件
  5. 相应地选择一个标题

这个项目的代码可以在 GitHub 上找到。

东京大学的 Muhammad Khan 和 Danushka Bollegala 进行了使用 tweets 识别事件的研究。台湾国立高雄应用科技大学的钟李洪也进行了类似的研究。

二。数据

背景

在我们的项目中,我们需要在短时间内获得带有地理标签的推文。由于计算上的限制,我们选择分析某个特定地理区域的推文。我们最初的想法是使用 Twitter 搜索 API 从纽约大都市地区收集数据。然而,考虑到我们的时间限制和 Twitter API 的速率限制,收集所需数量的数据是不可能的。我们选择在互联网上找到一个具有以下特征的现有数据集。

相关特征

  • 所有的推文需要来自世界上同一个地区。
  • 我们需要访问每条推文的正文日期发布时间发布
  • 每条 tweet 都必须有一个相关联的地理标签,指定纬度经度

Required information from each tweet. All tweets used in our project are public on Twitter, but this user’s information has been masked for privacy. (Source: Twitter)

我们的数据集

在寻找适合我们项目的数据集时,我们发现绝大多数推文都没有地理标记。这使得找到满足我们所有要求的数据集变得更加困难。然而,经过大量搜索,我们找到了一个来自英国的带有地理标签的推文的数据集。这些推文在 2016 年 4 月的活动中持续了 9 天。

该数据集最初包含大约 170,000 条具有上述特征的地理标记推文。

初始预处理

由于伦敦是英国最大的大都市,我们决定将我们的数据仅限于伦敦及其周边地区发布的推文。我们首先根据纬度和经度缩小数据范围,重点关注在纬度范围 51.3794444 到 51.6275813 和经度范围-0.4598808 到 0.0994444 发布的推文。

在查看了我们的推文的语言分布后,我们从数据集中删除了所有非英语推文。因为我们五个人都非常熟悉英语,所以用其他语言来验证一个事件是否被正确地检测到是很困难的。也有一些 tweets 缺少经度值,因此我们通过用该地区的平均经度填充这些值来完成初始预处理阶段。

三。学*和建模

将推文分成位置桶

在完成数据的初始预处理后,下一步是按位置将数据划分成簇。这些集群是设置推文基线活动的基础。我们希望聚类足够大以包含多个 tweets,但又足够小以用于识别“本地”事件。为此,我们尝试了许多不同的模型,包括 k-means、层次聚类、DBSCAN 和 HDBSCAN。

K-means 的工作方式是首先随机选取 K 个起始点来调用中心点,然后根据哪些点最接*定义的中心来迭代计算新的中心点。这一直持续下去,直到中心点不再移动,并且每个点都在它的最终分区中。在我们的例子中,K-means 没有很好地工作,因为它对噪声没有弹性,并且需要我们指定聚类的数量。此外,k-means 更喜欢绘制直线来划分点,而不是动态绘制形状来聚集点,这对于我们的项目来说并不理想。下面的地图显示了 k-means 如何划分我们的数据,其中每个点代表一条推文,不同的颜色代表不同的聚类。

K-means location clusters

DBSCAN 通过遍历每个点并将预设ε距离内的点添加到同一个聚类中来生成聚类。在找到所有聚类之后,任何小于预定最小值的聚类都被作为噪声丢弃。DBSCAN 解决了 k-means 的两个最大问题,因为它对噪声具有鲁棒性,并且不需要预定义的聚类数。然而,DBSCAN 仍然不是完美的,因为它不能很好地处理变化的密度。运行 DBSCAN 时,伦敦市中心将是一个巨大的集群,而周围地区将有非常稀疏的集群,如下所示。伦敦市中心可能会举办许多当地活动,所以我们希望在市中心内外都能找到较小的集群。

DBSCAN location clusters

HDBSCAN 的工作方式与 DBSCAN 非常相似,但它不需要用户定义的 epsilon,而是根据不同区域的密度分层选择 epsilon。最后,我们决定使用 HDBSCAN,因为它对噪声具有很强的鲁棒性,并且可以处理可变密度的集群。下图显示了伦敦市中心包含至少 20 条推文的集群。这些聚类比 k-means 和 DBSCAN 发现的聚类更集中。

HDBSCAN location clusters

检测异常

使用位置聚类,下一个目标是识别能够反映事件发生高概率的推文集。对于每一个单独的位置桶,我们想要识别具有代表事件的高概率的推文组。在这一步中,我们将连续的时间间隔离散化为特定位置集群的每小时 tweet 活动组。接下来,我们计算每个位置聚类的统计数据,例如每小时推文的平均值和标准差。

下一步是为每小时的推文率建立基于标准差的阈值,以标记包含潜在事件的时间。由于我们想要标记与正常小时数有很大不同的小时数,我们使用平均值的两个标准偏差的阈值(假设正态分布,95%的数据位于两个标准偏差内)。当查看阈值的上限时,使用 0.025 的 alpha 级别,我们能够发现不同位置群集的推文中的尖峰,潜在地对应于给定群集中的事件。下图显示了特定集群位置的每小时 tweet 数据以及阈值。

在一个峰值内找到相似的推文

在检测到 tweets 数量的峰值后,我们首先确定峰值是否是由事件引起的。如果尖峰是由某个事件引起的,那么我们希望找到哪些导致尖峰的推文构成了该事件。峰值可能是由同时发送的不相关的推文引起的,但我们不想将此归类为一个事件。此外,一个事件可能正在发生,但可能有一些不相关的推文充当噪音,不能定义该事件。我们的目标是输出几组 tweet,其中每组对应一个事件,一组中的每条 tweet 代表检测到的事件。

为了做到这一点,我们通过删除 URL、提及、转发和标签来清理每条推文的正文。然后我们对每条推文进行词干分析和标记。接下来,我们将每条 tweet 转换为一个向量,每个词有一个维度,并用字数填充这个维度。然后,我们通过文档词频(TF-IDF)对每个向量进行归一化。最后,使用 DBSCAN 对相似的 tweets 进行聚类。由于每个集群都有属于它的最少数量的推文,所以不是所有的推文都会加入集群。如果聚类后在同一个聚类中有点,我们从结果聚类中选择最大的聚类。这可以确保有足够多的推文是关于同一个主题的,还可以找到哪些推文在内容上是相似的。

Example cluster of tweets defining a potential event

最初,为 DBSCAN 找到合适的ε参数是困难的,因为没有定量地定义找到合适的聚类。经过一番努力,我们决定尝试 HDBSCAN,因为它会根据密度自动找到合适的 epsilon 参数。这种算法执行得不是很好,因为它倾向于将具有相似内容的推文分开,这是有意义的,因为许多推文在 TF-IDF 向量空间中将倾向于靠得很*。最后,我们决定通过观察不同值输出的集群来调整 epsilon 参数。在我们的例子中,值 1.2 似乎工作得很好,但并不完美。我们如何检测事件的细节可以在下面的结果部分找到。

选择摘要推文

我们项目的最后一步是,给定一组与事件相关的推文,确定哪条推文提供了关于事件的简明而有用的信息。为了做到这一点,我们首先对每条推文进行标记化(分割成一个单词列表),并从每条推文中找到内容单词。然后,我们使用评分标准(术语频率-逆文档频率)找到最能概括事件的推文。

为了对 tweets 集进行标记,我们尝试了 NLTK 库中的 Twitter 专用标记器和 spaCy 标记器。Twitter 特定标记器在拆分推文上具有更好的准确性。然而,出于性能原因,我们使用默认的 spaCy tokenizer。更具体地说,由于我们需要使用 spaCy 的实体标记功能(下面解释),使用 spaCy 标记 tweet 更有意义,这样我们就可以直接访问这些功能。

要找到实词,重要的是定义什么是实词。一个快速而非正式的实词定义是一个传达高度信息的词。在 2015 年的一篇论文中。al 指出了三种传达高度信息的实体:数字、名词和主要动词。因此,我们使用 spaCy 的命名实体识别功能来查找标记,并在我们的标记化 tweets 列表中将它们设置为内容词。

在为每条推文找到我们的内容词之后,我们现在需要找到包含最高信息密度的推文。为了做到这一点,我们使用一种称为术语频率-逆文档频率(TF-IDF)分数的度量来对单词进行评分。我们使用这个标准来确定可能的实词列表中的词的“有用性”。由于我们已经在上一节中去除了候选推文中的大部分噪声,我们可以根据内容词在我们的集合中的频率对其进行评分,以找到包含可能对我们的用户有帮助的附加信息的推文。

在对我们的内容词进行评分后,我们就可以找到最大化内容词密度的推文了。本质上,我们试图解决一个优化问题:(1)我们希望找到具有最高内容分数的推文,给定约束条件(2)我们希望最小化用于获得最高内容分数的字数,以及(3)推文不应超过 150 个字。这类优化问题也称为整数规划,是 NP 完全的。为了解决这个整数规划问题,我们使用整数线性规划(ILP ),它使用一个叫做 pymprog 的数学建模库。这个库使得在 Python 中建模、求解、分析、修改和操作线性程序变得简单而高度灵活。

在解决了这个整数规划问题之后,我们得到了一个整数数组,该数组对应于选择了哪些 tweets 来最大化内容分数密度。上一步中显示的集群的最终输出是“Muse rocking the O2!!!@氧气。”

四。结果

确定如何评估准确性很困难,因为数据集没有标记,事件是主观定义的。为了了解我们的项目执行得有多好,我们仔细检查了数据,找到了数据集中发生的所有事件。然后,我们将此与我们的项目发现的事件进行了比较。本质上,我们标记数据集是为了验证的目的。

在强制要求 tweet 峰值必须由至少 10 个事件组成后,我们的模型发现了 26 个潜在事件。6 个尖峰被正确分类为事件,15 个尖峰被正确拒绝,因为它们不对应于事件。我们的模型错误地将四个尖峰分类为事件,并且意外地拒绝了一个尖峰作为事件。

我们正确识别的事件的一个例子是 O2 竞技场的 Muse 音乐会。

我们发现的一个更大规模的事件是女王的生日。

动词 (verb 的缩写)结论

我们这个项目的目标是使用地理标记的推文来识别当地事件。使用现有的数据集,我们将推文分成位置桶,使用 DBSCAN 定义重要事件,并选择最能代表每个事件的标题推文。我们能够识别出一些事件,比如在伦敦 O2 竞技场举行的音乐会和女王的生日。

在这个过程中,我们学到了很多东西;最重要的是我们需要更多的数据!有了更多的数据,我们可以减少噪音,并有希望找到更多的事件,减少错误分类率。除此之外,我们还假设推文通常会被用来报道某种类型的事件。然而,随着越来越多的人使用该平台进行简单的个人更新,情况并非如此。从机器学*的角度来看,我们发现评估无监督问题的性能是具有挑战性的,因为通常没有量化的措施来验证。

未来的工作

将来,我们将从收集更多的数据开始。理想情况下,我们会希望收集更密集区域和不同位置的数据。我们也有办法改进识别异常的方法。我们可以查看基于时间的推文密度,以识别不同长度的事件,让我们有机会区分每小时和一整天的事件。我们还可以尝试改变位置群集的大小。这可以突出显示在不同地理区域发生的事件。

此外,为了报告更好的摘要推文,我们可以通过将与事件相关的所有推文的重要方面拼凑在一起,而不是从现有推文中选择最佳的一个,来找出如何生成新的标题。最后,实时处理推文和定义事件将是这个项目产生有意义的商业影响的最终目标。

寻找魔法:具有潜在狄利克雷分配的聚集原型

原文:https://towardsdatascience.com/finding-magic-the-gathering-archetypes-with-latent-dirichlet-allocation-729112d324a6?source=collection_archive---------2-----------------------

结合纸牌游戏和主题建模

这篇文章在 reddit 上引发了一场有趣的 讨论 ,并被《海岸奇才》的 精选

我使用机器学*完成的最酷的项目之一,围绕着使用一种叫做潜在狄利克雷分配(LDA)的主题建模方法。主题建模仅仅意味着将主题分配给文档。这可能是为一个新闻故事找到一个类别,为一本书找到一个流派,或者为一副纸牌游戏找到一个原型。

我从十二岁左右就开始玩魔法:聚会。我想知道将 LDA 应用于魔术甲板工来发现原型是否有意义。结果令人惊喜!

甲板建筑人工智能

LDA 是一种无监督学*算法,它接受一组文档(甲板列表)和一些主题(原型)作为输入。通过无监督的学*,我的意思是我不会给它任何提示什么牌属于什么原型。我甚至没有试图去描述原型——我只是向它展示了一个甲板水手的集合,并询问原型的数量。

通过 LDA,我们可以发现什么样的卡片与什么样的原型相关联。也许我们要求它用三种原型来描述所有的牌组,它会返回对应于攻击、组合和控制牌组的牌列表。或者,举例来说,如果我们让它找出五个原型,它可能会简单地将卡片分成基本颜色:白色、蓝色、黑色、红色或绿色。

更有趣的是,我们还得到了一个原型中牌的概率分布。这意味着对于每一个原型,都有一对卡片和概率,其中所有的概率自然加起来就是一。继续上面的例子,我们可能会发现蓝色原型中最受欢迎的牌是快照法师,其次是血清幻象,然后是驱散等等。

Draw, go.

解析地寻找分布通常是困难的,并且包括估计难以处理的积分。来自一个叫做贝叶斯推理的学科的方法被用来从我们所知道的信息中得到分布的最佳猜测。在这种情况下,“我们所知道的”是我们的一套甲板货,这有助于我们很好地估计潜在的原型是什么样子的。

通过实例学*

作为统计学和机器学*的一般规则:我们拥有的数据越多,我们就能做出更好的估计。获得好的数据通常是一项困难的任务。因为我们给算法越来越多的甲板看起来像什么的例子,它将变得更好地理解一种格式,它看到更多的甲板清单。

MTG·戴克斯的天使好心为我们提供了这篇文章的数据。我将为本文分析的数据集由最*比赛中的 500 名现代甲板水手组成。

我应该在这里强调,数据是由原始的卡片列表组成的。人工智能不会收到任何关于牌组名称、谁建造了它、在哪里或什么时候玩过等等的信息。只有 500 张 75 张的单子。

确定原型

接下来,我们决定寻找一些原型。如果我们将它设置为 1,那么我们将得到一个包含数据集中所有卡片的原型。如果我们将其设置为 500,那么我们可以预期我们的 500 副牌中的每一副都是一个原型。

要寻找的原型数量是 LDA 的一个超参数。这意味着它是我们在算法执行之前提供给它的一个额外的数字。机器学*的一个不幸方面是超参数优化——这是一个“尝试不同的值,直到你对结果满意”的花哨术语。

低数量的原型,大约 1-20,大部分发现原型具有相同颜色的副牌或使用相似卡片的副牌。这些原型大多可以用“包含山脉和平原的甲板”或“包含流放之路的甲板”等来概括。值在 20-30 左右时,结果大多是好的,但被一个又一个退化原型破坏了,例如,亲和电子混合物。

将原型设置为 30 对我找到已知的原型很有效。

机器学到了什么

让我们来看看被发现的一些原型的前十六张卡片:

For each archetype, the algorithm returns a list of cards and their respective probabilities. These are the probabilities that: an unknown card of a deck, of a given archetype, is a specific card. We can interpret this as indicating how many copies of a given card are usually in a deck of the given archetype. Modern players will recognize archetype 27 as Infect and archetype 26 as Tron.

由于我已经有一段时间没有玩游戏了,我不得不参考 MTG 甲板上的元游戏原型来检查我的结果是否有意义。我要求找到 30 个原型,所以我收到了 30 张带有相关概率的卡片列表。原型本身是未命名的,只有一个与之相关联的整数——我必须自己找出原型的名称。看起来原型 27 和感染很匹配,原型 26 和艾尔德拉兹创匹配。

Which archetype is this?

我以前玩标准版,那时 Skullclamp 无处不在,Arcbound 掠夺者威胁着 meta。在注意到我的老朋友蹂躏者后,我更仔细地检查了原型 13,果然——它是亲和力

为了更好地理解这些数字,请注意 0.031 ≈ 2.3/ 75。这可以解释为一副 75 张的牌中平均有 2.3 张牌是“原型 13”。

但是考虑一下 Blinkmoth Nexus: 0.068 ≈ 4.1 / 75。一副牌中不能有超过四张非基本地的副本!记住,一副牌被建模为原型的混合物:一副牌不太可能被描述为 100%是任何给定的原型。如果人工智能看到一副亲和牌,那么它可能会说这是 97%的原型 13,给 Blinkmoth Nexus 每副牌 4 张牌的预期数量。

我们也可以将顶级卡片的值视为原型中卡片种类的度量。比较亲和力与感染,我们看到前 16 个亲和力卡有更高的概率和,表明这个原型有更多的 4-of staples。

创造性人工智能

关于 LDA 的另一件很酷的事情是,它是一个生成模型。这意味着我们可以用它来创建新的甲板。为此,我们首先选择一个原型,比如说亲和力。然后我们抽取新的卡片,一次一张。给定的卡被添加的概率由其每个原型的卡分布决定。然而,LDA 不知道魔术中的甲板构造规则,所以如果它使甲板非法,我们可能不得不重新做一个样本。

A deck with mixed main deck and sideboard generated from the multinomial distribution defined by the affinity probability vector. I sampled the cards, one at a time, sampling again if I would end up with 5 copies of a card.

该模型可以扩展到区分主甲板卡和餐边柜卡。例如,首先标记在数据集中频繁出现为餐边柜卡片的卡片。然后在主副牌的抽样过程中将这些牌的概率设置为零,对于餐具柜牌则相反。

进一步阅读

如果您想亲自看看如何重现本文中的结果,请参考带有代码的我的笔记本

该方法最初是由 Blei 等人在本文中提出的,但是维基百科的文章也给出了该方法的一个很好的技术概述。

我使用 python 包 gensim 来生成结果,其中有很好的教程和文档。

寻找意义:社会科学中小区域分析的数据问题

原文:https://towardsdatascience.com/finding-meaning-the-data-problem-with-small-area-predictive-analysis-in-the-social-sciences-part-9fba1e2c981b?source=collection_archive---------11-----------------------

更新:好消息!在这方面已经取得了很大进展。请阅读我对这篇文章的回应,因为我将在未来几天发表它们! 下面是 的第一个。

你可以在这里找到这个系列的第 2 部分。

你会在这篇文章中发现什么

  • 为什么我对小区域分析感兴趣…那到底是什么?
  • 所有的数据都在哪里?
  • 为分析准备数据——使用 Pandas 清理和聚合 Python 中不同来源的数据
  • 初步可视化

为什么我对小区域分析感兴趣…那到底是什么?

我曾经是纽约市一所特许学校的教师。我教普通和特殊教育学生高中数学、科学和计算机科学。根据我自己的经历和我同事的经历,我知道这个城市所有五个区的学生的故事。我知道社区健康和环境风险因素在特殊教育项目的学生比例以及学生的整体表现中占很大比重。从轶事经验来看,我发现这些学生无法控制的因素严重影响他们高中毕业以及高中毕业后继续接受教育的机会。

我也知道这种风险因素在城市的不同社区之间有很大的不同。例如,连接曼哈顿和新泽西的乔治·华盛顿大桥是每天最繁忙的桥梁之一。这座桥位于华盛顿高地附*的一个人口密集区,导致了整个城市最高的空气污染率。众所周知,空气污染会导致许多健康和发展问题,尤其是对非常年轻的人。

因此,我开始尝试使用小区域分析来发现教育程度和环境因素以及社区健康指标(如预期寿命、饮酒情况、早产率和许多其他指标)之间的统计显著联系。小区域分析将允许我分析整个城市的趋势如何变化,特别是因为“成为纽约人”的含义变化如此之大,以至于相距仅十个街区的两个家庭之间的生活可能会非常不同。小区域分析背后的想法是帮助确定不同社区的具体需求。

数据都在哪里?

我遇到的第一个问题是寻找数据。我最初开始从任何一个大都市地区(希望是几个)寻找数据,将我需要的数据聚集到适当大小的邻域中,并按适当大小的邻域进行分隔。最初,我希望找到按邮政编码聚合的数据。我搜遍了国家和州政府网站——没有运气。很快很明显,我所寻求的粒度的数据并不容易被公众获得,因为这是社会科学中一个相对的新想法。

最终,我去了我所知道的地方,并专门查看了纽约市,看看他们的政府网站或任何城市倡议是否会有我正在寻找的那种公开数据。最终,我偶然发现了纽约市社区健康调查,该调查将该市分为 59 个社区区,如下图所示。

社区健康调查(CHS)有我正在寻找的教育信息,以及我想要分析的许多公共健康和社区统计数据。然而,我仍然遗漏了许多我希望包括在内的环境风险因素,所以我继续寻找。我发现了大量的环境数据,但很少是按社区跟踪的,因此无法用于我的分析。此外,我可以使用的数据是以与来自 CHS 的数据完全不同的方式建立的。

NYC Community Health Survey Data

NYC Environmental & Health Data Portal

正如您所看到的,环境和健康数据(EH)要混乱得多,实际的相关数据值在三列中的任何一列中(在标有NULL的列之前)。此外,与 CHS 数据中的列标题不同,每个功能名称都使用第三列和第四列之间的组合来列出。显然,我必须找到一种方法来处理所有这些,以创建一个连贯的数据集。

为分析准备数据——使用 Pandas 清理和聚合 Python 中不同来源的数据

我首先必须决定我想看什么因素。在社区卫生服务数据集中,我对人口统计数据不感兴趣,对每个功能从 1 到 59 的排名不感兴趣,对组成前六列的城市和行政区范围的统计数据也不感兴趣。这是一个足够简单的练*来削减这些规格的数据集。

# Eliminating unwanted summary information
CD_CHS_data = raw_CHS_data.iloc[6:,:] # Eliminating data ranking each Community District on each feature by implementing a regular expression filter
CD_CHS_data.drop(list(NYC_data.filter(regex = 'rank')), axis = 1,            
                 inplace=True)

此外,所有的人口统计数据都集中在前面的列中,所以我使用original_CHS_columns = raw_CHS_data.columns.values.tolist()创建了一个列标题列表,删除前 33 列非常容易。

因此,我必须检查 CHS 数据中的NaN值,令我吃惊的是,有许多列都有这样的值,所以我使用下面的代码将它们聚集到一个列表中,发现除了一列(第一列)之外,所有列都只是“可靠性注释”。在以后的数据传递中,我可能会考虑这些,但是我想得到一些基线,所以我简单地删除了“可靠性注释”栏。

# Creating a list of the columns with NaN values
CHS_NaN_columns = []for column in original_CHS_columns:
    if CD_CHS_data.loc[:, column].isna().any():
    CHS_NaN_columns.append(column)# Deleting desired columns
CHS_columns_to_delete = CHS_NaN_columns[1:]
CHS_data_to_merge = CD_CHS_data.drop(columns=CHS_columns_to_delete)

唯一剩下的有NaN值的列是“avertable deaths _ rate ”, 59 个中只有 5 个——不到 10%,所以我决定简单地估算那些有平均值的。在进一步检查数据源和收集技术后,使用不同的方法替换这些值可能是明智的,但同样,获得基线是我当时的首要任务。此外,我知道 EH 数据将花费我更多的时间来准备与 CHS 数据合并。

如前所述,EH 数据集使用两列来描述每个测量或特征。应用一个lambda函数来合并这两列非常简单:

CD_EH_data['labels'] = CD_EH_data.apply(lambda row: ''.join([row[2], row[3]]), axis=1)

更困难的部分是讨论的另一个问题,即实际数据分布在数据集中的三个不同的列中。我用下面的方法着手解决这个问题。

# Because much of the data in many column was words (names of neighborhoods) first it is necessary to convert all the data to numeric data, "coercing" non-numeric data to be represented as NaN
for column in [8, 9, 10, 11]:
    CD_EH_data.iloc[:,column] =  
           pd.to_numeric(CD_EH_data.iloc[:,column], errors='coerce')# Following the pattern observed in the CSV file, the first numeric value starting from the right of the dataframe would be the desired value
def get_value(row):
    if not np.isnan(row[11]):
        value = row[11]
    elif not np.isnan(row[10]):
        value = row[10]
    elif not np.isnan(row[9]):
        value = row[9]
    else:
        value = row[8]
    return value

CD_EH_data['values'] = CD_EH_data.apply(lambda row: 
                                        get_value(row), axis=1)

最后,为了合并这两个数据集,我必须在合并之前用 EH 数据创建一个数据透视表。

# Create the pivot table with desired features
EH_data_to_merge = CD_EH_data.pivot_table(index='ID', 
                                          columns='labels', 
                                          values='values')# Merge the datasets
NYC_data = EH_data_to_merge.merge(CHS_data_to_merge, how='outer', 
                                  left_index=True, right_index=True)

初步可视化

热点图是直观查看数据集中不同要素之间相关性的绝佳方式。下面是使用 sci-kit 的“RobustScaler”缩放每个功能后,使用 seaborn 和 matplotlib 库创建的热图。

该数据集中有许多要素,在下一部分中,我将“放大”查看要素集的几个子集,以对结果进行一些分析。

另一种可视化数据的方法是使用主成分分析,它允许我们通过分解这些特征(使用大量复杂的数学运算)将数据尽可能多地分布在二维图形上,来可视化具有许多特征(每个特征都有自己的维度)的数据。

在这两个图表中,红点代表教育程度最高的社区区域不是高中毕业,黄点代表教育程度最高的区域是高中毕业,可能是大学毕业,蓝点代表教育程度最高的区域是大学毕业或更高。

正如您在上面看到的,标准化每个属性的数据稍微有助于将每个组聚集在一起,尽管还有许多需要改进的地方。

在我的下一篇文章中继续阅读这个项目,第二部分!

利用机器学*发现《权力的游戏》中的死亡模式

原文:https://towardsdatascience.com/finding-patterns-of-death-in-game-of-thrones-using-machine-learning-68cf95d7f1d1?source=collection_archive---------2-----------------------

Valar Morghulis ( 所有人都必须死)是任何 GoT 粉丝最难忘的一句话。几乎每一集都有令人震惊的死亡。大多数角色,包括杰出人物,都遭遇了暴力的结局。但是死亡是随机发生的呢,还是发生在具有相似特征的特定角色身上呢?那些死去的人和那些设法活下来的人之间有某种模式吗?

当你玩权力的游戏时,你要么赢,要么死。

机器学*是一种技术,它允许计算机找到隐藏的洞察力,而无需显式编程去哪里寻找。它从足够多的过去的例子中学*来预测未来。在这个项目中,我将机器学*应用于 Kaggle 上的《权力的游戏》数据集,以识别影响角色死亡的特征。(数据集基于《冰与火之歌》这本书,而非该剧。)

因为真正的粉丝看书。

数据集

该数据集包括总共 27 个特征(标题、性别、文化、年龄、贵族、在每本书中的出现、死亡关系的数量、受欢迎程度等)。)大约 2000 个字符。它还描述了角色在第五本书(《与龙共舞》)结束时是生是死。

功能选择

在将分类特征转换成数字特征后,我总共有 685 个特征。然后,我使用带有线性支持向量分类器的 SelectFromModel 来选择最佳的 32 个特征。

交叉验证和超参数优化

我将数据集分为训练集和测试集(80–20)。具有 10 重交叉验证的线性 SVC 在测试集上提供了 0.76 的准确度。调整内核参数将精确度提高到 0.78。优化的随机森林分类器进一步提高了 0.82 的精度。

方法性能

我使用 TP(真阳性,即正确预测的死亡人物)、FP(假阳性,即活着的人物预测死亡)、TN(真阴性,即正确预测的活着的人物)和 FN(假阴性,即死亡的人物预测活着)的比率来测量精确度、召回率和 f 分数。

我的模型的预测结果是:

+--------+-----------+--------+---------+
| Labels | Precision | Recall | F-Score |
+--------+-----------+--------+---------+
| Alive  | 93%       | 85%    | 86.5%   |
| Dead   | 47%       | 70%    | 63.5%   |
+--------+-----------+--------+---------+

重要特性

在随机森林中使用特征重要性度量,发现以下特征贡献最大(从贡献最大到贡献最小排序):

  1. 与角色相关的死亡角色的数量
  2. 《乌鸦的盛宴》中的人物形象
  3. 《与龙共舞》中的人物形象
  4. 角色的性别
  5. 《权力的游戏》中的人物形象
  6. 性格的高贵
  7. 《刀剑风波》中的人物形象
  8. 角色的头衔(社会地位)
  9. 角色所属的房子
  10. 《国王的冲突》中的人物形象
  11. 角色的受欢迎程度

探索特征与死亡的关系

Is there a relationship between survival and number of dead relatives?

Does appearing in more books relate to survival?

Does belonging to a noble family make you prone to death?

How does house relate to survival? (Only houses with more than 10 members have been considered.)

做好准备,冬天来了!更多的死亡和情节曲折也是如此。虽然我们只能等待冬天的风来看看接下来会发生什么,但这一分析可能会帮助我们做好准备。因为黑夜是黑暗的,充满了恐惧。

我将收集更多的数据,并对上述结果进行进一步的分析,以预测未来书籍中人物的命运。你可以在 Github 上找到我的代码,并在 Twitter 上与我联系,讨论一些很酷的想法。让我们的极客来展示我们对这本书和这个节目的热爱吧。

除非他杀光他们…

用 BOW,TFIDF 和 Xgboost 寻找相似的 Quora 问题

原文:https://towardsdatascience.com/finding-similar-quora-questions-with-bow-tfidf-and-random-forest-c54ad88d1370?source=collection_archive---------4-----------------------

photo credit: Pixabay

Google 长期以来在索引和信息检索中使用 TFIDF 来计算给定关键字对给定页面的重要性

Quora 是一个问答网站,它的用户社区以意见的形式提问、回答、编辑和组织问题。

2018 年 9 月,Quora 报告月度用户达到 3 亿。每个月有超过 3 亿人访问 Quora,所以很多人问重复的问题也就不足为奇了,也就是说,这些问题有着相同的意图。比如像“我怎样才能成为一个好的地质学家?”以及“我该怎么做才能成为一名伟大的地质学家?”是重复的问题,因为它们都有相同的意图,应该只回答一次。

Quora 非常努力地消除重复问题,但是 NLP 是一个非常困难的问题。有这么多方法来描述同一个意思,看看上面的例子就知道了。Quora 用户提供了很大的帮助,合并了类似的问题,比如:

source: Quora

在这篇文章中,我们将开发一个机器学*和 NLP 系统来分类问题对是否重复,我们从一个带有 Xgboost 的模型 BOWTF-IDF 开始。

BOW 和 TF-IDF 是人们在信息检索中最常用的两种方法。一般来说,支持向量机和朴素贝叶斯更常用于分类问题,但是,因为它们的精度依赖于训练数据,所以 Xgboost 在这个特定的数据集中提供了最好的精度。XGBoost 是一个梯度增强框架,已经变得非常流行,尤其是在 Kaggle 社区中。因此,我决定使用这个模型作为基线模型,因为它设置简单,易于理解,并且有合理的机会提供体面的结果。我们的基线模型将允许我们快速获得性能基准。如果我们发现它提供的性能不够充分,那么检查简单模型的问题可以帮助我们选择下一个方法

数据预处理

Quora 重复问题公共数据集包含超过 40 万对 Quora 问题。在我们的实验中,我们将数据随机分为 70%的训练样本和 30%的测试样本。

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inlinedf = pd.read_csv('quora_train.csv')
df.dropna(axis=0, inplace=True)
df.groupby("is_duplicate")['id'].count().plot.bar()

Figure 1

这些职业并没有完全平衡,但这并不坏,我们不会去平衡它们。

在清理文本之前,我们预览几个问题对,以确定如何清理它们。

df.drop(['id', 'qid1', 'qid2'], axis=1, inplace=True)
a = 0 
for i in range(a,a+10):
    print(df.question1[i])
    print(df.question2[i])
    print()

Figure 2

你可能已经注意到我们在文本清理方面有很多工作要做。经过一些检查,一些尝试和来自的想法 https://www . ka ggle . com/Currie 32/the-importance-of-cleaning-text,我决定对文本进行如下清理:

  • 不要删除停用词,因为像“什么”、“哪个”和“如何”这样的词可能有强烈的信号。
  • 不要词干。
  • 去掉标点符号。
  • 纠正错别字。
  • 将缩写改为其原始术语。
  • 删除数字之间的逗号。
  • 将特殊字符转换为单词。诸如此类。

clean

清理文本后,我们再次预览这些问题对。

a = 0 
for i in range(a,a+10):
    print(df.question1[i])
    print(df.question2[i])
    print()

Figure 3

好多了!

特征工程

一段时间以来,我们在对单个文本进行分类方面很有经验——但是对文本之间的关系进行精确建模的能力相对较新。这里我使用 Panda 的concat函数将来自问题 1 和问题 2 的两个文本对象连接成一个。scipy.sparse.hstack用于水平堆叠稀疏矩阵(按列)。

词袋+ Xgboost 模型

这种后续策略(计数矢量器)被称为单词包。通过单词出现次数来描述文档,而完全忽略单词在文档中的相对位置信息。它对文档进行标记,计算标记的出现次数,并以稀疏矩阵的形式返回它们。

Xgboost 与以下参数一起使用,这些参数是根据验证数据中的性能选择的:

max_depth=50
n_estimators=80
objective='binary:logistic'
eta=0.3

bow_xgboost

Figure 4

字级 TF-IDF + Xgboost

TF–IDF是两个统计量的乘积,术语频率和逆文档频率,它是当今最流行的术语加权方案之一。

我们将 tf-idf 归一化应用于出现计数的稀疏矩阵,从单词级、n-gram 级和字符级。

word_tfidf_Xgboost

Figure 5

关于特征工程的一个微妙之处是,它需要知道我们在实践中很可能不知道的特征统计。为了计算 tf-idf 表示,我们必须基于训练数据计算逆文档频率,并使用这些统计来缩放训练和测试数据。在 scikit-learn 中,在训练数据上安装特征转换器相当于收集相关的统计数据。然后,可以将安装好的变压器应用于测试数据。

N-gram 级 TF-IDF + Xgboost

N_gram_tfidf_Xgboost

Figure 6

人物等级 TF-IDF + Xgboost

character_tfidf_Xgboost

Figure 7

我们的最高验证分数是 0.80,对初学者来说一点也不差!

到目前为止,我们最好的 Xgboost 模型是字符级 TF-IDF+Xgboost,重复问题的召回率,即我们的模型能够检测的重复问题占重复问题总数的比例是 0.67。这对于手头的问题至关重要,我们希望检测并尽可能多地消除重复问题。

考虑到这一点,我们将开发一个 word2vec 和 Xgboost 模型,看看这个结果是否可以改进,这将是下一篇文章的

这篇文章的 Jupyter 笔记本可以在 Github 上找到。周末快乐!

用 Word2Vec 和 Xgboost 寻找相似的 Quora 问题

原文:https://towardsdatascience.com/finding-similar-quora-questions-with-word2vec-and-xgboost-1a19ad272c0d?source=collection_archive---------4-----------------------

photo credit: Pixabay

如何使用自然语言处理来识别任何文本数据集中的相似记录

上周,我们探索了使用 BOW、TFIDF 和 Xgboost 识别相似文档的不同重复数据删除技术。我们发现传统的方法如 TFIDF 可以取得一些令人印象深刻的结果。这也是谷歌长期以来在索引和信息检索中使用 TFIDF 来计算给定关键词对给定页面的重要性的原因之一

为了继续我们的学*之旅并增长我们的技能,今天,我们将探讨如何使用不同的方法解决相同的匹配和重复数据消除问题,同样,我们将把重复数据消除作为分类器的扩展来处理。我们开始吧!

数据

Quora 重复问题对的任务是确定一对问题是否具有相同的含义。数据包含一对问题和一个由人类专家标记的基本事实标签,标记这对问题是否重复。请注意,这些标签是主观的,这意味着并非所有人类专家都同意这一对问题是否重复。因此,这些数据应被视为有根据的,而不是 100%准确的。

df = pd.read_csv('quora_train.csv')
df = df.dropna(how="any").reset_index(drop=True)
a = 0 
for i in range(a,a+10):
    print(df.question1[i])
    print(df.question2[i])
    print()

Figure 1

计算单词移动者的距离

WMD 是一种允许我们以一种有意义的方式评估两个文档之间“距离”的方法,不管它们有没有共同点。它使用单词的矢量嵌入。它将两个文本文档之间的差异度量为一个文档的嵌入单词需要“行进”以到达另一个文档的嵌入单词的最小距离。让我们看一个例子,下面的问题对被标记为重复:

question1 = 'What would a Trump presidency mean for current international master’s students on an F1 visa?'
question2 = 'How will a Trump presidency affect the students presently in US or planning to study in US?'question1 = question1.lower().split()
question2 = question2.lower().split()question1 = [w for w in question1 if w not in stop_words]
question2 = [w for w in question2 if w not in stop_words]

我们将使用 word2vec 预训练的谷歌新闻语料库。我们将这些加载到一个 Gensim Word2Vec 模型类中。

import gensimfrom gensim.models import Word2Vec

model = gensim.models.KeyedVectors.load_word2vec_format('./word2Vec_models/GoogleNews-vectors-negative300.bin.gz', binary=True)

让我们用 wmdistance 方法计算这两个句子的 WMD。记住,这两句话表达的是同一个意思,在原 quora 数据中被标注为重复。

distance = model.wmdistance(question1, question2)
print('distance = %.4f' % distance)

距离= 1.8293

这两个句子之间的计算距离相当大。这就把我们带到了规范化的大规模杀伤性武器。

标准化 word2vec 向量

当使用 wmdistance 方法时,首先规范化 word2vec 向量是有益的,这样它们都具有相等的长度。

model.init_sims(replace=True)
distance = model.wmdistance(question1, question2)
print('normalized distance = %.4f' % distance)

归一化距离= 0.7589

正常化后,距离变小了很多。

再来一对试试,这次这两道题不重复。

question3 = 'Why am I mentally very lonely? How can I solve it?'
question4 = 'Find the remainder when [math]23^{24}[/math] is divided by 24,23?'question3 = question3.lower().split()
question4 = question4.lower().split()question3 = [w for w in question3 if w not in stop_words]
question4 = [w for w in question4 if w not in stop_words]distance = model.wmdistance(question3, question4)
print('distance = %.4f' % distance)

距离= 1.2637

model.init_sims(replace=True)
distance = model.wmdistance(question3, question4)
print('normalized distance = %.4f' % distance)

归一化距离= 1.2637

归一化后,距离保持不变。WMD 认为第二对没有第一对相似。成功了!

模糊的

我们已经介绍了 Python 中模糊字符串匹配的一些基础知识,让我们快速浏览一下 FuzzyWuzzy 是否可以帮助我们解决问题重复数据删除问题。

from fuzzywuzzy import fuzzquestion1 = 'What would a Trump presidency mean for current international master’s students on an F1 visa?'
question2 = 'How will a Trump presidency affect the students presently in US or planning to study in US?'
fuzz.ratio(question1, question2)

53

fuzz.partial_token_set_ratio(question1, question2)

100

question3 = 'Why am I mentally very lonely? How can I solve it?'
question4 = 'Find the remainder when [math]23^{24}[/math] is divided by 24,23?'
fuzz.ratio(question3, question4)

28

fuzz.partial_token_set_ratio(question3, question4)

37

基本上,Fuzzywuzzy 不认为第二对问题是相似的。那很好。因为根据人类评价,第二对是不相似的。

特征工程

首先,我们创建几个函数来计算 WMD 和归一化 WMD 以及单词到向量的表示。

wmd_normWmd_sent2vec

我们将创建的新功能包括:

  • 单词的长度。
  • 字符的长度。
  • 问题 1 和问题 2 之间常用词的长度。
  • 问题 1 和问题 2 之间的长度差。
  • 向量 question1 和 question2 之间的余弦距离。
  • 城市街区(曼哈顿)矢量问题 1 和问题 2 之间的距离。
  • 向量 question1 和 question2 之间的雅克卡距离。
  • 向量问题 1 和问题 2 之间的堪培拉距离。
  • 向量 question1 和 question2 之间的欧几里德距离。
  • 向量 question1 和 question2 之间的闵可夫斯基距离。
  • 向量问题 1 和问题 2 之间的 Bray-Curtis 距离。
  • 向量问题 1 和问题 2 的偏度和峰度。
  • 大规模杀伤性武器
  • 标准化大规模杀伤性武器

所有的距离计算都可以通过使用scipy.spatial.distance函数来完成。

new_features1

word 2 虚拟建模

我们将使用 word2vec 预训练的谷歌新闻语料库。我下载并保存到“word2Vec_models”文件夹中。然后,我们将这些加载到一个 Gensim Word2Vec 模型类中。

model = gensim.models.KeyedVectors.load_word2vec_format('./word2Vec_models/GoogleNews-vectors-negative300.bin.gz', binary=True)
df['wmd'] = df.apply(lambda x: wmd(x['question1'], x['question2']), axis=1)

归一化 Word2vec 建模

norm_model = gensim.models.KeyedVectors.load_word2vec_format('./word2Vec_models/GoogleNews-vectors-negative300.bin.gz', binary=True)
norm_model.init_sims(replace=True)
df['norm_wmd'] = df.apply(lambda x: norm_wmd(x['question1'], x['question2']), axis=1)

获取问题 1 和问题 2 的向量,然后计算所有距离。

new_features2

Xgboost

Xgboost

Figure 2

我们创建的所有新功能的 Xgboost 实现了 0.77 的测试准确性,低于字符级 TF-IDF + Xgboost 的 0.80,但是,我们能够将重复问题的召回率从 0.67 提高到 0.73,这是一个显著的改进。

Jupyter 笔记本可以在 Github 上找到。祝你一周工作顺利!

参考:

https://www . LinkedIn . com/pulse/duplicate-quora-question-abhishek-thakur/

寻找创业公司——在早期风险投资基金中担任新数据科学家的工作笔记

原文:https://towardsdatascience.com/finding-startups-notes-on-work-as-a-new-data-scientist-in-an-early-stage-vc-fund-7e994c8f390e?source=collection_archive---------18-----------------------

(合著 【保罗·迈因豪森】 )

上个月,我作为一名数据科学家加入了早期风险投资基金 Montane Ventures ,在班加罗尔工作。我加入 Montane 是因为有机会与几家伟大的初创公司一起研究有趣的数据和技术问题,也因为我喜欢早期初创公司与小团队一起开发产品时的信噪比。

我的一部分时间将花在 Montane 已经投资(或正在合作投资)的初创公司上;帮助他们提升数据科学成果和能力。我还会花时间做风险投资分析师更传统的工作:帮助寻找和识别投资的创业前景。

风险投资通常是为了支持那些以雄心勃勃和创新的方式使用技术的公司。Montane Ventures 的团队认为,风险投资本身的工作可以通过雄心勃勃的创新技术得到改善。随着技术和数据科学的使用在过去几十年中以各种方式发展,如果我们以二三十年前投资者的方式确定有前途的投资,那将是奇怪的。这是我被雇佣的很大一部分原因;这是我将与团队紧密合作的事情。

让数据科学软件成为风险投资的有效工具本身就雄心勃勃且困难重重(世界上还有其他几个基金或多或少地公开参与了类似的努力)。在 Montane,我们正在探索将数据科学融入风险投资的多种方式。这篇文章是为了追踪我们的一些想法,特别是关于使用数据科学来帮助我上面确定的第二个主要职责所涉及的内容:确定投资的初创公司。

在这篇文章的剩余部分,我将

  1. 解释风险投资如何受益于数据科学,
  2. 描述我们使用的数据为什么以及如何产生。
  3. 概述数据科学可以应用的两个主要领域,以及
  4. 分享我们关于数据科学将如何增加价值的一些具体假设

投资不容易

那么为什么需要数据科学来寻找创业公司进行投资呢?从外面看,风险投资似乎很容易:投资者有资本;大多数(全部?)创业公司要资本;投资者只需要选择谁得到它,然后进行投资。

只是没那么简单。想象一下,投资者有一定的时间来完成他们所有的工作。现在减去他们筹集新资本、管理基金以及与已经投资的公司合作所需的时间。我们剩下的时间让他们去寻找新的投资项目。用这种基本方式来表达有助于明确我们的目标:有效利用时间。我们甚至可以把它变成一个非常简单的等式:

I = T — (R+P)

其中:
I 是分配给对初创公司进行新投资的时间,
T 是可用的总时间,
R 是行政管理基金和筹集新资本所需的时间,
P 是与基金的投资组合合作并支持该投资组合(已投资的初创公司)所需的时间。

该基金需要在寻找投资的初创企业中进行分配。比方说,如果每年有 10 家初创公司准备融资,那么你可以为每家初创公司分配大约 10%的时间(或更少),决定支持哪家,然后专注于你选择的 1 或 2 家初创公司。有超过 10 家初创公司在寻求投资。有几百或几千个。创业公司的数量是造成这一分配问题的部分原因。

图片是澄清问题的另一个有用的工具。下图从概念上将投资决策过程建模为一系列依次更小的子集:

由于被投资的创业公司是你所知道的创业公司的一个子集,最终投资子集的质量受到初始群体质量的制约。

现在要澄清的是,没有人知道一个生态系统中初创公司总数的准确规模(让我们以印度为例——我们暂且不谈生态系统本身的流动性和难以划分的问题)。但是我们可以把理论上的总人口看作是我们分配问题的数据集。第一个挑战是收集我们的数据集(并保持其最新),它将保持真实人口总数的样本,并希望尽可能接*它。我们将这部分问题称为扫描

继续说印度的创业生态系统,这一估计认为印度的科技创业公司数量约为 4750 家。我们将以这个数字为起点。由于市场的不断变化,初创公司是一个有趣的库存问题。他们只在特定的时间点筹集资金,如果你是一个专注于特定阶段的基金,那么你真的只能在每个初创公司作为初创公司存在的时间子集(他们筹集资金的间歇时间段)的子集(例如 A 轮)投资该初创公司。

我们希望我们的数据集中有尽可能多的创业公司,因为这是我们要从中选择的样本。如果有一些我们应该考虑投资的初创公司不在我们的初始人口数据集中,我们就会遇到数据收集和样本偏差的问题。

如果有一些我们应该考虑投资的初创公司不在我们的初始人口数据集中,我们就会遇到数据收集和样本偏差的问题。

下一步是选择我们将花时间仔细考虑的创业公司子集。我们将这部分问题称为过滤。我们希望我们的过滤功能尽可能好:避免误报(我们让初创公司通过了过滤,然后花太多时间考虑它们是否很适合我们的基金)和漏报(没有通过过滤但实际上具有良好投资潜力的初创公司)。

接下来的两节概述了扫描和过滤问题。

扫描

为 VC 开发数据科学软件并不是为了自动化 VC(先明确一点!).投资者做的很多事情不会被机器取代。投资者在长期任期内培养的个人关系会带来内向推荐,这通常是老牌风险投资基金的一大优势。总的来说,内向流量(联系投资者而不是相反的创业公司)是风险投资渠道的重要组成部分。除了个人推荐之外,入站流量还受到来自在线和离线媒体的一般声誉的驱动,如故事、采访和资金公告。正是风险投资的在线存在,使得基金能够被寻找投资的初创公司发现。

我们不想取代以上任何一个。我们只是认为,将过滤数据集局限于入站会给我们留下一个有缺陷的数据集——一个不包含和不具有代表性的实际创业人口样本。

除了通过集客活动寻找创业公司,互联网和在线资源已经是任何投资者寻找过程的重要组成部分。局限性在于,对许多投资者来说,搜索过程大多是手动的。投资者会阅读创业新闻和社交媒体等,并发现他们决定跟进以进行进一步调查的创业公司,或者指派分析师或合伙人进行跟进。数据科学可以帮助建立一个补充的搜索过程,使我们的过滤数据集尽可能全面。

收集数据的互联网来源可以分为几类。

  • 聚合网站是最直接、最重要的来源。他们以结构化的格式呈现数据,并努力做到尽可能全面和详细。更开放的两个最著名的网站是 CrunchbaseAngellist 。像 Tracxn 这样的网站是付费/订阅网站和服务的好例子。
  • 资金公告是另一个强大的来源。这些网站没有聚合网站那么结构化,但通常是融资活动的第一份公开文件。印度的 VCCircle 是一个发布半结构化融资公告的网站。你的故事又是一个。
  • 加速器/孵化器是早期创业公司的良好来源。如果只有一两个,您可以很容易地手动跟踪它们。然而有很多这样的并且他们每隔几个月就有新的一批;理想情况下,你不希望每隔几个月就必须记得手动检查每个网站,以找到关于一家初创公司的信息。

并非所有信息都可以在网上获得。然而,初创公司会在网上分享自己的信息有三个原因,我们可以在网上高效地找到这些信息:

  1. 他们需要筹集资金,他们希望投资者找到他们
  2. 他们需要招聘,他们希望员工找到他们;
  3. 他们需要销售,他们希望顾客找到他们

任何新公司都会在这三个动机中的至少两个下运作。

过滤

一旦我们有了未来 6(或 N)个月内可能成为投资目标的所有初创公司的数据集,下一个任务就是筛选它们。

投资的大部分筛选和最终决策都必须借助人类投资者的专业知识和洞察力来完成。我们不期望让软件来做投资的最终决定。因此,我们的目标应该更加明确。我们制定了两个,我们仍然认为假设,而不是结论性的目标:

  1. 能够对创业公司进行更系统的比较,而不是对每一家创业公司进行简单的是或否的决定。
  2. 在投资过程的早期,要注意危险信号或需要密切关注的领域。

1。在初创公司之间进行更系统的比较,而不是对单个初创公司做出孤立的是或否的决定,是有价值的。

这第一个目标是我们通过反思我们的投资经验而制定的。每个初创企业的投资过程通常看起来是有序和分散的。在你没有深入投资尽职调查过程的时候,你会定期会见和评估初创公司。一旦你决定一家初创公司看起来很有趣,你通常会开始花更多的时间和他们在一起,考虑他们的论点和商业模式。随着你花更多的时间在一家初创公司上,你有更少的时间进行介绍会议和对其他初创公司的探索性评估。你在一家初创公司呆的时间越长,它就越偏离另类投资,比较就变得不那么频繁和有用。

这可以被建模为一种隧道过程,你越深入隧道,就越难与其他创业公司进行比较;因为你在考虑这个创业公司的所有细节和背景。

这种方法有一些缺陷,因为投资者并没有真正做出是否投资的决定。他们已经筹集到了资金,人们认为他们会进行投资。真正的问题是,是投资(时间和注意力以及最终的资本)创业公司 E 还是创业公司 F(或者创业公司 G……)。这总是一个权衡。虽然你必须评估所有支持和反对投资创业公司 E 的理由,但分析应该尽最大可能包括对现有的替代投资进行明确和系统的比较。在整个投资过程中,这种比较应该尽早、定期地进行。

2。在投资过程中尽早意识到危险信号或需要密切关注的领域。

当我们发展了我们的假设和建立了我们的原型过程,我们喜欢识别非常真实的、具体的和特定的例子来说明我们可以给投资过程增加的价值。对于我们的第二个假设,我们将分享一个在班加罗尔真实创业的例子。请注意,这并不是要谴责或批评某个特定的创业公司。只是有时候学*来源于明确承认和关注不幸的故事。

2015 年和 2016 年是许多金融科技初创公司在印度成立和获得资金的时期。那个时期的创业公司之一是班加罗尔的一家名为 Finomena 的公司。他们受到了很多关注,并得到了活跃在印度的一家主要全球风险投资基金的支持,有一段时间,他们被认为是该领域最知名的初创公司之一。到 2018 年,他们已经关闭了。虽然 Finomena 关闭的确切原因并不为公众所知,但在社区内部,人们认为存在领导问题以及资本和财务管理问题。当风投决定投资一家公司时,这是他们渴望避免的结果。

那么,数据科学如何在收集和识别信息方面发挥作用,而这些信息可以通过分析来帮助及早发现这些问题呢?举个例子,Finomena 的员工在 Glassdoor 上的评论表明了管理层的问题,也可能是公司文化的问题。在评估中,前员工和管理层之间不断提出同样的抱怨和反复的争论是一个警告信号。一旦你的数据管道建立起来,这是一个简单的步骤,自动扫描 Glassdoor 的数据集中的任何公司,并快速过滤危险信号。

提醒一下,不是所有的危险信号都会出现在任何特定的地方。初创公司可以在网上的个别地方人为粉饰自己的形象。尽管有操纵公众形象的能力,但仍有一个很好的理由来系统地、定期地扫描网上信息来源,并将这些信息纳入你的决策过程。

结论

在 Montane,我们仍处于开发这一领域工作的早期阶段。我们很高兴能成为其中的一员,并将数据科学的工具和方法带入 VC 的世界。我们将继续发展我们的思维,并通过这些帖子分享我们的工作实例。因此,如果你有兴趣将技术和数据科学引入风险投资,请继续关注!

寻找食物的模式

原文:https://towardsdatascience.com/finding-the-pattern-of-food-a462b3ce5910?source=collection_archive---------12-----------------------

继续上一篇关于食物和营养的文章,今天我想找到与不同季节、节日和主题相关的常见食材。

为了做到这一点,我对 Epicurious recipe 数据应用了关联规则,以基于 3 个度量来找到相关的项目集:它们出现得相对频繁(支持),一个项目经常与另一个项目一起出现(置信度),以及它们出现得比偶然更频繁(提升)。

food associated with different seasons

在矩阵视图中,关联子集被分组。我们看到季节性产品,如春天的芦笋,秋天的红薯,还有季节性饮料,如冬天的热饮。

food associated with major festivals

就节日食物而言,在一个简洁的视图中,它显示了从新年前夜的香槟、7 月 4 日的后院烧烤到圣诞节的可食用礼物等各种食物。

这方面的一个用例是,食谱网站可以将他们的季节性食谱与谷歌搜索食品趋势进行比较,以了解用户的新需求。

当放大一个节日时,人们可以观察到更多细节。

然后,我们还可以了解与某种食物相关的配料和饮食,如快餐和便餐:

A salad/couscous kinda mood

开胃菜:

some cheese, some tomato, some seafood

甜点:

all the sweet things

此外,由于双重标记的性质(一个配方同时标记一个项目及其父项目,如果有的话),我们实际上可以使用它来分组标签,达到类似的聚类效果:

这是我关于数据科学和视觉故事的# 100 日项目的第 55 天。我的 github 上的全部代码。感谢阅读。欢迎新主题的建议和反馈。

在命令行中查找 2017 年美国大学排名中的学院百分比(第二部分 grep 和 wc)

原文:https://towardsdatascience.com/finding-the-percent-of-colleges-in-the-us-university-ranks-2017-at-the-command-line-part-ii-grep-5db6d59f76a1?source=collection_archive---------5-----------------------

Image adopted from the unsplash.com

各位编码员好!欢迎回到我的系列课程数据科学@ Bash Shell 。在上一课中,我们学*了如何预览数据集( unirank.csv )。您应该从下面的网页下载数据,因为我们已经稍微简化了数据,让我们将数据保存为:unirank.csv

wget https://www.scientificprogramming.io/datasets/unirank.csv

数据集预览

现在让我们进行我们的第一个分析:要列出数据文件中包含短语“college”的所有行,我们需要向您介绍命令grep(全局正则表达式打印)。简而言之,grep允许您浏览文件中的所有行,但只输出那些匹配模式的行。在我们的例子中,我们希望找到数据集中包含“college”的所有行。

我们是这样做的:

$ grep -i "college" unirank.csv | csvlook

这里,grep 命令有两个命令行参数:第一个是模式,第二个是我们要在其中搜索该模式的文件。如果运行此命令,您应该会看到一些包含字符串“college”的行:

Institutes containing “colleges” in the unirank.csv data set

请注意,我们已经设置了-i选项,使匹配案例变得不敏感。还有,发现逻辑误将两所大学认定为学院!因为他们的名字包含字符串(“学院”)。因此,在数据分析中使用grep时,尤其是在做出决定之前,你需要小心谨慎!

找到大学的百分比

对于这一步,我们需要引入管道的概念,这是 Bash shell 中最强大的特性之一。管道用竖线符号(|)表示。本质上,管道允许您将一个命令的输出转发到另一个命令的输入,而不必将中间输出保存到文件中。

我们想把grep的输出给另一个命令,它可以告诉我们这个输出有多少行。事实证明,有一个命令可以让我们做到这一点:wc代表单词计数,用于计算给定输入中有多少单词,但最常用的是与-l选项一起使用,它将计算输入中的行数。所以让我们从计算unirank.csv文件中总共有多少行开始:

$ wc -l unirank.csv232 unirank.csv

现在我们来数一下学院的数量,让我们用管道把我们所学的东西集合起来:

$ grep -i "college" unirank.csv | wc -l8

grep 的输出——文件中包含“学院”的行——被传递给wc -l,它将计算文件中的行数。注意,我们没有在wc -l命令中指定文件名;我们不需要这么做,因为我们通过管道将数据传输到wc -l,所以它不需要从文件中读取数据。

所以在这个数据集中,((8-2)/232) x 100% = 2.5% institutes 来自美国高校。我们仔细地扣除了两个错误识别的学院。 下集再见

阅读 上一课(第一部分)🚶

[这个项目是‘学* Bash Shell 和 Linux 中的数据’课程的一部分。]

[## 使用 Bash Shell 学*实用的数据科学

描述 Bash 可能不是处理所有类型数据的最佳方式,但是经常会出现这样的情况

科学编程](https://school.scientificprogramming.io/course/learn-practical-data-science-with-bash-shell/2?/learn-bash/)

寻找纽约时报畅销书的趋势

原文:https://towardsdatascience.com/finding-trends-in-ny-times-best-sellers-55cdd891c8aa?source=collection_archive---------20-----------------------

每个作家都梦想全职写作,但可悲的事实是,大多数作家挣的钱都不够养活自己,更不用说养家了。如果你登上了《纽约时报》畅销书排行榜,你将写作作为职业的机会将会更高,尤其是如果它在排行榜上停留了许多周,因为《纽约时报》畅销书排行榜与图书销售密切相关。那么,有什么诀窍可以让这一切发生吗?我对《纽约时报》2008 年至 2016 年的畅销书排行榜做了一些分析,看看我是否能找到任何重要的趋势。

选择类别/流派

如下图所示,悬疑/惊悚小说和普通小说在畅销书排行榜中所占的比例一直高于其他任何类别。请注意,这并不意味着这些类别的书一定更有可能成为畅销书,但是确实表明这些类别比其他类别卖得更好,因此这些类别的书有更大的机会成为畅销书。

一般小说是相当广泛的,但包括任何小说,不能被归类到任何其他子类。这可能意味着生活片,文学,和其他一般的小说。它也被称为主流小说。

性别差距?

畅销书排行榜显示,男性和女性接*分榜。合著的书肯定不那么普遍了,但仍然占据了很大的比例,尽管其中一个合著者通常已经是畅销书了。名单上的大多数书只有一个作者。

赢家拿走大部分产业

詹姆斯·帕特森以他的名字出现 408 次而雄踞榜首。这包括他和别人合著的书。他的第一本书出版于 1976 年,直到 1993 年,他的第八部小说才登上畅销书排行榜。他现在是纽约时报畅销书排行榜上书籍最多的吉尼斯世界纪录保持者。

约翰·格里森姆在 1989 年出版了他的第一部小说,但是是他在 1991 年出版的第二部小说让他登上了畅销书排行榜。

这些排名前 20 位的作者占据了畅销书排行榜的 29%,而在分析的 8 年时间跨度中,610 位作者占据了另外的 71%。一个作者出现在榜单上的平均时间是 13 周,中位数是 5 周。大多数作者只在名单上呆了一周。

什么书最受欢迎?

另一方面,这些是最常出现在清单上的书。《帮助》是凯瑟琳·斯托克特第一部也是唯一一部出版的小说,《所有我们看不见的光》是安东尼·杜尔第二部出版的小说。两者都可以归类为一般小说,以历史为题材。

一本书在榜单上停留的平均周数是 5 周,中位数是 3 周。和作者一样,大多数书只能在榜单上停留 1 周。

书名的趋势

假设你已经写完了你的小说,和一个出版商签了一本书,现在正为封面和书名而紧张。某些书名比其他的表现好吗?

起始词

清单上的大多数书都不是以“A/An”或“the”开头,但根据你写作的体裁,“The”通常是标题中的第一个词(参见动作/冒险或宗教小说)。

起始词真的有影响吗?一些出版商强调要让书名“谷歌化”。人们很容易找到你的书吗?

使用“A”或“The”可能会对图书在图书馆或实体店中按字母顺序的位置造成一些混乱,或者可能会抑制人们对标题的本能反应。(作者的假设。)

使用“of”

另一组要看的是使用介词" of "的书,以及有多少书的书名后面有一个" the "。如下所示,列表中的大多数书都没有使用介词,即使使用了,也不会经常使用“the”。

结论

如果一本书上了畅销书排行榜,它很可能是一个作者写的悬疑/惊悚或普通小说。标题可能不会以“A”或“The”开头,也不会包含“of”。

即使你的书登上了榜单,也很可能只会停留 3 到 5 周,而且在这 8 年的时间跨度中,大多数作者总共只会在榜单上停留 5 周,尽管每位作者在榜单上的平均周数被那些似乎一直生活在榜首的名人向上倾斜了。

不幸的是,用于这种分析的数据不包括一本书写得有多好,它是如何营销的,或许多其他因素,这些因素无疑对图书销售非常重要。Erica Verillo 在她的帖子中说得很好

归根结底,最成功的作家遵循了自己的想法、灵感和灵感。

但是,如果你有选择,选择一个喜欢惊悚片或主流小说的缪斯。

用神经网络寻找川普

原文:https://towardsdatascience.com/finding-trump-with-neural-networks-4419468e0624?source=collection_archive---------5-----------------------

当总统发微博时,我们怎么知道谁是真正的键盘后面的人?有了训练有素的神经网络,我们也许能找到答案。

在 2018 年 3 月之前,唐纳德·特朗普(Donald Trump)在担任总统期间曾使用未经授权的个人安卓手机。虽然这让他的工作人员感到焦虑,但对于记者和研究人员来说,这对于区分总统本人的话和白宫工作人员的话特别有用。有了 Twitter 的 API——Twitter 为任何想要利用其数据的人提供的网关——提供每条推文的“来源”信息,就可以合理地假设,如果“来源”是 Android,那就是纯特朗普。

然而,正如你从下面的图表中看到的,该图表按照推文频率(y 轴)绘制了推文的月份(x 轴),在 2017 年 3 月左右,Android 的活跃度下降,iPhone 的活跃度上升。

Chart showing Tweet activity for “@realDonaldTrump@ split by source.

正如白宫社交媒体主任小丹·斯卡维诺(Dan Scavino Jr .)透露的那样,特朗普已经在 3 月中旬搬到了 iPhone。媒体猜测这一变化是出于安全考虑,个人机器人规避了白宫的机构管理。虽然对白宫工作人员来说是好事,但(不)预期的后果也意味着特朗普本人写的推文现在与他的工作人员在 POTUS 账户上写的推文混在一起。由于 Twitter 已经成为白宫沟通的一个关键组成部分,加上美国总统任期内的异常事态,能够区分总统本人和他的工作人员的推文变得相当重要。输入计算解!—一个经过训练的神经网络,可以仅通过推文文本识别特朗普创作的推文。

在我们开始之前…

首先,应该指出的是,这种建模纯粹是一种练*。我喜欢技术转移和学*新技能的借口。有时候,这些借口会变成我学生的完整论文和新课程,但通常它们会被卡在一个数字抽屉里。类似的练*已经使用其他机器学*技术完成了,我鼓励任何感兴趣的人去阅读关于它的

然而,对于这个特定的项目,我将看看我们是否可以训练一个神经网络,纯粹通过推文的文本来识别特朗普。神经网络是计算机模拟,其运行方式类似于我们大脑的工作方式。它们拥有高度互联的人工神经元,可以根据流经它们的数据来适应和改变自己。对于这个网络的数据,我使用了特朗普推特档案,该档案提供了从 2009 年开始的特朗普账户推特的储存库。不幸的是,数据归档似乎已于 2018 年 1 月停止,但我们将利用我们在练*中获得的信息进行工作。对于有编程头脑的人来说,详细描述代码的记事簿是可用的,但我的目的是给非程序员的社会科学家一个这些过程如何工作的要点,以便他们可以在自己的项目中考虑它们。

检查数据

首先,我将 2015 年、2016 年和 2017 年的精简数据集加载到一个数据框架中,删除所有转发,因为这些转发将包含并非来自特朗普或他的工作人员的文本。你可以加入 2018 年的数据集,但它将于 1 月中旬结束。

An example of the data after loading into the Pandas DataFrame

首先,我快速浏览了一下数据,看看账户上使用了哪些类型的资源及其活动。在整个综合数据集中,该账户的前三大来源是 Android、iPhone 和 Twitter 网络客户端,尽管最后一个似乎在特朗普宣布参加 2015 年 6 月总统大选之前最活跃。查看 Twitter 网络客户端的几个例子,并不完全清楚网络客户端上的人是唐纳德还是助手。

ICYMI,@IvankaTrump 的 int。在@TODAYshow 上讨论@Joan_Rivers &选手在@学徒 NBChttp://t.co/Em7bgj10SM上的竞争

“@nanaelaine7 @realDonaldTrump 只有你能让它再次伟大。你的计划是现实中唯一的计划。特朗普让美国变得伟大”

。@megynkelly 最*说不能被川普拉拢。她各方面都那么一般,谁他妈想追求她!

事实✔️on“红线”在叙利亚:人权委员会“我不在那里。”事实:2012 年 8 月划定的界限。人权委员会 Secy 的状态,直到 2 月 13 日。https://t.co/4yZjH3TR5B

目前还不清楚这些人是应该被排除在数据之外,还是应该被归类为特朗普或工作人员。对于这个练*,我让他们作为工作人员,因为我们的主要假设是特朗普从 Android 发推文,但稍后返回并尝试其他分类会很有趣。

我们已经知道,特朗普是在 2017 年 3 月的某个时候转向 iPhone 的,因此值得深入研究并定位 Android 变暗的确切日期。利用熊猫对时间序列数据进行重新采样的奇妙能力,我将数据重塑为 2017 年 2 月至 4 月期间每天的推文计数,并按来源进行拆分。

Graph demonstrating Trump’s Android phone finally went dark on the 8th March 2018 (…kind of).

从图表中我们可以看到,一般来说,Android 手机的最后一次使用是在 2018 年 3 月 8 日。来自 Android 的两条推文在 3 月 25 日再次出现,但似乎无关紧要,因此为了简单起见,我们将忽略它们,因为从 4 月到数据集结束,不再有 Android 推文出现。

在此基础上,我将数据一分为二,iPhone 前和 iPhone 后的数据。对于 iPhone 之前的数据,我们可以假设任何 Android 推文都是特朗普,任何其他推文都是员工。对于后 iPhone 时代的数据,我们不能再做这样的假设。这意味着我们需要训练我们的神经网络模型来区分 iPhone 前数据上的特朗普和工作人员推文,然后使用该模型来预测 iPhone 后数据上的来源。轻松点。

像数字一样的神经网络——大量的数字

训练网络的第一步是使单词对它来说是可理解的。我们通过将来自 Python 库“Scikit Learn”的 TFIDF 矢量器与整个文本数据相匹配来实现这一点。这个阶段基本上创建了一个小模型,记录所有推文中的每个独特的词,以及它在数据中的流行程度。我们将这个模型放在手边,因为我们将需要它将我们不同的文本数据集转换成神经网络可以理解的数字模式。矢量器的工作原理是将一串文本转换成一个非常宽的电子表格,每个文档占一行,每个可能的单词占一列。计算的值可以是单词在文档中出现的次数,1 或 0 表示它是否出现过,或者在 TFIDF 的情况下,是基于单词对该文档的重要性的分数,同时考虑文档本身和数据集中的所有其他文档。下面用《爱丽丝梦游仙境》中的两段摘录和 TFIDF 单词分数的两行数组演示了这一点。

但是它是怎么“知道”的呢?!—训练神经网络

神经网络进行分类的方式是,通过向它们提供大量数据示例来训练它们,最重要的是,向它们提供模型应该预测的预期输出或标签。对于每个例子,模型将其预测与“正确”标签进行比较,对自身进行调整,然后再次尝试。训练继续进行,直到尽可能接*正确预测训练数据的所有实例的分类的理想情况。在我们的例子中,我们为模型提供了大量的推文,对于每条推文,我们都告诉模型它是特朗普的推文还是员工的推文,直到它的预测非常接*正确的类别。

通常,经过多次迭代训练后,神经网络模型在将其预测与预期结果进行匹配时会变得非常准确,但实际上,我们想知道它对从未见过的推文的分类预测会有多好。我们可以通过保留一定比例的训练数据来评估神经网络做出这些预测的效果,以便这些推文永远不会被训练中的模型看到。然后,我们要求模型预测推文作者,并根据我们已经分配的类别检查其预测。对于我建立的最终模型,结果是一个模型在预测它见过的训练数据中的标签方面的准确率为 97.6%,在预测它从未见过的推文中的准确率为 76.8%。然而,人们不只是建立一个模型。首先你建立 120 个模型!

为您选择正确的神经网络…

通常,在处理文本数据时,机器学*的改进来自对训练数据的更好管理,例如在我们的情况下,要么只关注 iPhone 和 Android 推文,要么考虑特朗普是否也要对其他平台的推文负责。我们也可能会考虑是否更好地预处理文本(清除噪音,正确识别表情符号,删除网址等)。)可能是个不错的决定。然而,也可能这些噪声元素实际上是模型的最大信息量。在我们的例子中,在清除了推文中的网址、标签和表情符号后,我发现模型的准确性下降了 20%左右,这表明正是这些特征有助于识别。

然而,构建和使用神经网络的一个关键部分是选择你的网络有多少层,每层有多少个节点。这些不一定是可以通过算法选择的东西,它们因数据而异。一个建议是在不同数量的层和节点的不同模型形状上运行试验。对于每个模型形状,您都要多次训练和评估模型,每次都使用训练数据的不同子集。对于每个模型形状,取其试验的平均分,并查看哪个模型在小块训练数据上表现最好。正如您在评估了 120 个独立构建的模型后所看到的,最好的结果是模型 010,这是一个包含 4 个隐藏层的神经网络,其中每个隐藏层包含 1000 个节点。请注意,简单地增加节点和层并不一定会提高预测能力,正确的模型“形状”通常取决于您正在处理的数据。

Making this Graph required building and training 120 different neural networks. You’d think it would look more impressive.

大结局:找到特朗普

在确定了要使用的最佳模型形状(1000 个节点的 4 个隐藏层)后,我们建立了一个全新的模型,并用我们所有的训练数据训练它,并转向我们迄今为止被忽视的特朗普改用 iPhone 后的推文数据集。在这种情况下,我们没有“正确”的标签,因为我们不再确定哪些推文来自特朗普的手机,哪些来自他的工作人员,因为它们都来自 iPhone 平台。我们使用原始的 TFIDF 矢量器转换文本,并将其提供给模型,要求它为我们提供预测;工作人员还是特朗普?。就活跃度而言,我们可以看到该模型在推文之间有相对均匀的划分,在某些日子工作人员的预测活跃度更高,而在其他日子特朗普的预测活跃度更高。

Trump and his staff put the work in equally. It’s a fair division of labour.

考虑到该模型在未公开数据上的准确率约为 77%,我们有必要单独检查推文,看看我们认为该模型在定性层面上的表现如何。从每个类别中随机抽取 10 个样本,为我们提供了一个很好的概览。对于特朗普撰写的那些预测的推文,我们看到了许多感叹号,许多强调的强烈措辞,一些反民主党的诽谤和许多与老狐狸和朋友的互动。工作人员发布的推文通常带有一个 URL,更多的是以详细描述的方式发言,并喜欢感谢和祝贺各种公民的努力。对于每个预测,您可以看到模型对自己的预测有多有信心,1 表示绝对有信心,0 表示没有信心。

预测川普推特

预测员工推文

对任何政治家来说,让多人通过一个被认定为一个人的账户“说话”会让公众很难搞清楚他们选出的官员到底是谁。对于那些希望让这些波兰人承担责任的人来说,这也增加了不确定性,因为他们可以振振有词地声称,他们一开始就没有写那条有问题的推文。然而,至少根据这个模型,这是 100%的特朗普,有 100%的信心。

如果你对自己摆弄神经网络感兴趣,或者想知道我是如何建立模型的细节,这种转移的代码是 ,可作为 Jupyter 笔记本

埃塞克斯大学的 ESRC 人权、大数据和技术项目 为这一转移提供了部分支持。

这项工作得到了经济和社会研究委员会的支持[批准号 ES/ M010236/1]

在 scikit-learn 中微调分类器

原文:https://towardsdatascience.com/fine-tuning-a-classifier-in-scikit-learn-66e048c21e65?source=collection_archive---------0-----------------------

很容易理解,许多机器学*问题受益于作为其最佳性能度量的精确度或召回率,但实现这一概念需要详细过程的知识。我最初几次尝试为回忆(灵敏度)微调模型很困难,所以我决定分享我的经验。

这篇文章来自我的第一个 Kaggle 内核,我的目的不是构建一个健壮的分类器,而是想展示优化分类器的实用性。在下图 A 中,目标是将决策阈值向左移动。这最大限度地减少了假阴性,这在为本文选择的数据集中尤其麻烦。它包含 357 个良性和 212 个恶性乳腺活检图像的特征。假阴性样本相当于错过了恶性肿瘤的诊断。数据文件可以在这里下载。

The goal of this post is to outline how to move the decision threshold to the left in Figure A, reducing false negatives and maximizing sensitivity.

使用 scikit-learn,针对召回调整分类器可以(至少)通过两个主要步骤来实现。

  1. 使用[GridSearchCV](http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html)通过搜索最佳超参数并保留具有最高召回分数的分类器来调整您的模型。
  2. 使用精确回忆曲线和 roc 曲线调整决策阈值,这是一个更复杂的方法,我将详细介绍。

首先加载必要的库和数据。

通过统计diagnosis列可以找到阶级分布。b 代表良性,M 代表恶性。

B    357
M    212
Name: diagnosis, dtype: int64

转换类别标签,并将数据分成训练集和测试集。使用stratify=Truetrain_test_split导致训练集和测试集之间的一致类别分布:

# show the distribution
print('y_train class distribution')
print(y_train.value_counts(normalize=True))print('y_test class distribution')
print(y_test.value_counts(normalize=True))y_train class distribution
0    0.626761
1    0.373239
Name: diagnosis, dtype: float64
y_test class distribution
0    0.629371
1    0.370629
Name: diagnosis, dtype: float64

既然已经准备好了数据,就可以构建分类器了。

第一个策略:使用 GridSearchCV 和 scoring 参数优化灵敏度。

首先建立一个通用分类器并设置一个参数网格;随机森林有许多可调参数,这使它适合于GridSearchCVscorers字典可以用作GridSearchCV中的scoring参数。当多个分数通过时,GridSearchCV.cv_results_将返回所提供的每种分数类型的评分标准。

下面的函数使用 GridSearchCV 根据param_grid中的参数组合来拟合几个分类器。来自scorers的分数被记录下来,最佳模型(由refit参数评分)将被选择并“改装”成完整的训练数据,供下游使用。这也对伸出的X_test进行预测,并打印混淆矩阵以显示性能。

包装器功能的要点是根据所选择的评分标准类型快速重用代码以适合最佳分类器。首先,试试precision_score,它可以限制误报的数量。这不太适合最大灵敏度的目标,但允许我们快速显示针对precision_score优化的分类器和针对recall_score优化的分类器之间的差异。

grid_search_clf = grid_search_wrapper(refit_score='precision_score')Best params for precision_score
{'max_depth': 15, 'max_features': 20, 'min_samples_split': 3, 'n_estimators': 300}

Confusion matrix of Random Forest optimized for precision_score on the test data:
     pred_neg  pred_pos
neg        85         5
pos         3        50

param_grid中每个参数组合的精度、召回率和准确度分数都存储在cv_results_中。这里,pandas 数据框架有助于可视化每次分类器迭代的得分和参数。这是为了表明,尽管分类器之间的准确率可能相对一致,但很明显,准确率和召回率之间存在权衡。按精度排序,最好的评分模型应该是第一条记录。这可以通过查看第一条记录的参数并将其与上面的grid_search.best_params_进行比较来检查。

results = pd.DataFrame(grid_search_clf.cv_results_)
results = results.sort_values(by='mean_test_precision_score', ascending=False)results[['mean_test_precision_score', 'mean_test_recall_score', 'mean_test_accuracy_score', 'param_max_depth', 'param_max_features', 'param_min_samples_split', 'param_n_estimators']].round(3).head()

该分类器针对精度进行了优化。为了比较,为了显示GridSearchCV如何选择最佳分类器,下面的函数调用返回一个为召回优化的分类器。网格可能与上面的网格相似,唯一的不同是召回率最高的分类器将被重新调整。这将是癌症诊断分类问题中最理想的度量,在测试集混淆矩阵上应该有更少的假阴性。

grid_search_clf = grid_search_wrapper(refit_score='recall_score')Best params for recall_score
{'max_depth': 5, 'max_features': 3, 'min_samples_split': 5, 'n_estimators': 100}

Confusion matrix of Random Forest optimized for recall_score on the test data:
     pred_neg  pred_pos
neg        84         6
pos         3        50

再次复制生成结果表的相同代码,只是这一次最好的分数将是recall

results = pd.DataFrame(grid_search_clf.cv_results_)
results = results.sort_values(by='mean_test_precision_score', ascending=False)results[['mean_test_precision_score', 'mean_test_recall_score', 'mean_test_accuracy_score', 'param_max_depth', 'param_max_features', 'param_min_samples_split', 'param_n_estimators']].round(3).head()

第一种策略没有为recall_score产生令人印象深刻的结果,与为precision_score优化的分类器相比,它没有显著减少(如果有的话)假阴性的数量。理想情况下,在设计癌症诊断测试时,分类器应尽可能减少假阴性。

策略二:调整决策阈值,确定操作点

precision_recall_curveroc_curve是可视化分类器中灵敏度-特异性权衡的有用工具。它们有助于告知数据科学家在何处设置模型的决策阈值,以最大化灵敏度或特异性。这被称为模型的“工作点”。

理解如何在 scikit-learn 中微调分类器的关键是理解方法.predict_proba().decision_function()。这些返回样本被预测在一个类中的原始概率。这是与调用.predict()方法返回的绝对类预测的一个重要区别。

为了使这种方法适用于 scikit-learn 中的所有分类器,要知道有些分类器(如 RandomForest)使用.predict_proba(),而有些分类器(如 SVC)使用.decision_function()RandomForestClassifier的默认阈值是 0.5,所以以此为起点。创建一个名为y_scores的类概率数组。

y_scores = grid_search_clf.predict_proba(X_test)[:, 1]# for classifiers with decision_function, this achieves similar results
# y_scores = classifier.decision_function(X_test)

为分类器生成精确召回曲线:

p, r, thresholds = precision_recall_curve(y_test, y_scores)

这里的adjusted_classes是一个简单的函数,用于返回上面计算的y_scores的修改版本,只是现在将根据概率阈值t分配类别标签。下面的另一个函数绘制了相对于给定阈值t的精度和召回率。

多次重复执行该功能,每次改变t,调整阈值,直到出现 0 个假阴性。在这次特别的运行中,我不得不一直降到 0.29,然后将假阴性降低到 0。

precision_recall_threshold(p, r, thresholds, 0.30)pred_neg  pred_pos
neg        79        11
pos         1        52

查看精确度和召回率之间权衡的另一种方式是将它们一起绘制为决策阈值的函数。

# use the same p, r, thresholds that were previously calculated
plot_precision_recall_vs_threshold(p, r, thresholds)

最后,ROC 曲线显示,为了实现 1.0 的召回,模型的用户必须选择一个允许某些假阳性率> 0.0 的操作点。

fpr, tpr, auc_thresholds = roc_curve(y_test, y_scores)
print(auc(fpr, tpr)) # AUC of ROC
plot_roc_curve(fpr, tpr, 'recall_optimized')0.9914046121593292

感谢跟随。针对特异性和敏感性调整模型的概念应该更加清晰,并且您应该能够轻松地在您的 scikit-learn 模型中实现这些方法。我很想听到改进代码和/或分类器的建议。

像老板一样在 Python 中微调 XGBoost

原文:https://towardsdatascience.com/fine-tuning-xgboost-in-python-like-a-boss-b4543ed8b1e?source=collection_archive---------0-----------------------

XGBoost(或 eXtremeGradientBoosting)不再被引入,它在太多的数据科学竞赛中被证明是相关的,如果你刚刚开始使用它,它仍然是一个很难微调的模型。

为什么微调是关键?因为如果你有大数据集,你对 5 个不同的参数进行简单的网格搜索,每个参数有 5 个可能的值,那么你将有 5⁵= 3125 次迭代。如果一次迭代需要运行 10 分钟,那么在获得参数之前,您将有超过 21 天的等待时间(我不说 Python 崩溃,不让您知道,并且您在意识到它之前等待了太长时间)。

在这里,我想你首先正确地完成了你的特性工程工作。特别是分类特征,因为 XGBoost 不接受输入中的分类特征。

1.列车测试分割、评估指标和提前停车

在进行参数优化之前,先花些时间设计模型的诊断框架。

XGBoost Python api 提供了一种方法,通过增量树的数量来评估增量性能。它使用两个参数:“eval _ set”——通常是训练集和测试集——以及相关的“eval_metric”来测量这些评估集上的误差。

绘制结果的时间:

在分类误差图上:看起来我们的模型学*了很多,直到 350 次迭代,然后误差非常缓慢地减少。这反映在测试集上,当迭代次数从 350 增加时,我们不一定看到性能。有了这个,你已经可以考虑在 350 棵树后进行切割,并为将来的参数调整节省时间。

如果你不使用 scikit-learn api,而是使用纯 XGBoost Python api,那么还有提前停止参数,它可以帮助你自动减少树的数量。

2.是时候微调我们的模型了

当您还没有运行任何模型时,从哪里开始呢?

  1. 为关键输入填充合理的值:
    learning _ rate:0.01
    n _ estimators:100 如果你的数据量很大,1000 如果是中低的
    max _ depth:3
    子样本:0.8
    col sample _ bytree:1
    gamma
  2. 运行 model.fit(eval_set,eval_metric)并诊断您的第一次运行,特别是 n_ 估计器参数
  3. 优化最大深度参数。它表示每棵树的深度,即每棵树中使用的不同特征的最大数量。我建议从一个低的 max_depth (例如 3)开始,然后递增 1,当增加它没有性能增益时停止。这将有助于简化您的模型,避免过度拟合
  4. 现在玩一下学*率和避免过拟合的特性:
    learning_rate :通常在 0.1 到 0.01 之间。如果你关注的是性能,并且有足够的时间,在增加树的数量的同时,逐渐降低学*速度。
    子样本,这是每棵树用于构建该树的行数百分比。我建议不要取出太多行,因为性能会下降很多。取 0.8 到 1 之间的值。
    colsample_bytree :每棵树使用的列数。为了避免一些列在预测中占据过多的份额(就像在推荐系统中,当你推荐了购买最多的产品而忘记了长尾理论),去掉一个适当比例的列。如果您有许多列(尤其是如果您进行了一次热编码),则值为 0.3 到 0.8;如果您只有几列,则值为 0.8 到 1。
    gamma :通常被误解的参数,它作为一个正则化参数。要么 0,要么 1,要么 5。

你可以走了!

参数 base_score 什么都没给我。要么是和收敛没关系,要么是不知道怎么用。

3.其他备注

查看 feature_importance 表,并确定解释超出其应有范围的变量。你的数据可能有偏差!你的模型和参数都不相关。

比较两个模型的预测,其中一个模型比另一个模型多使用一个变量。具体比较预测不同的数据(预测类不同)。

请记住,在实际项目中,如果您今天将 XGBoost 模型工业化,明天您将希望改进该模型,例如通过向模型添加新的特性或简单地添加新的数据。为了比较这两个模型,绘制属于类别 1 的概率(风险= proba > 50%),如下所示:

你会知道你的新型号与旧型号相比如何,它们哪里相似,哪里不同。同样,绘制两个 feature_importance 表,并比较两个模型中最相关的要素。

我希望这篇文章对你有用,如果有用,考虑至少给 50 次掌声:)

基于全卷积网络的指纹去噪和修复

原文:https://towardsdatascience.com/fingerprint-denoising-and-inpainting-using-fully-convolutional-networks-e24714c3233?source=collection_archive---------13-----------------------

By Jeremy Yap on https://unsplash.com/

指纹是主要的身份识别手段之一,因为两个人拥有相同指纹的概率估计为 640 亿分之一。这意味着能够准确有效地处理和匹配指纹对是一项宝贵的资产。这就是这个项目的动机,在这个项目中,我们试图从噪声失真的观察中提取一个干净的指纹图像。

所有图像都包含某种形式的噪声。这种噪声可能是由于采集设备、压缩方法或应用于图像的处理造成的。这促使研究人员研究去噪和修复等方法和工具来缓解这个问题。它们被用作预处理步骤,为目标任务(可能是分类、分割、匹配……)准备图像。在我们的例子中,最终目标是提高指纹错误接受率或错误拒绝率。

深度学*,特别是深度卷积神经网络的最新进展,通过展示学*有噪图像到“干净”图像之间的映射的能力,实现了去噪和去噪,并改进了现有技术。

在这篇文章中,我们将使用一种类似于 U-Net [1]的架构,并展示它可以成功地应用于去噪和盲修复。

数据

http://chalearnlap.cvc.uab.es/challenge/26/description/

我们将使用的数据集由 chalearn challenge 的组织者提供,由 84k 合成指纹图像组成,这些图像是使用 Anguli:合成指纹生成器生成的。然后,通过添加随机变换(模糊、亮度、对比度、弹性变换、遮挡、划痕、分辨率、旋转)和背景图像,人为地降低这些图像的质量。
目的是从退化的观测数据中提取干净的指纹图像。我们使用平行数据集(噪声图像、指纹图像)作为模型训练的(输入、输出)。

模型

所用的架构如上图所示,与[1]中介绍的架构相似(除了我们填充输入而不是镜像边沿)。这种架构的一个重要优点是,在对像素进行预测时,它能够考虑更广泛的背景。这得益于上采样操作中使用的大量通道。
U-Net 的另一个重要特征是跳跃连接,因为它们通过减少消失梯度问题使训练更容易。

在代码中,它看起来像这样:

处理

输入图像的处理如下:

  • 归一化:像素强度除以 255,因此它们在(0,1)范围内。
  • 重新调整大小:由于最大池化,网络期望输入图像的每个维度可被 2⁴整除。
  • 数据扩充:仅在训练期间执行。随机翻转(水平或垂直或两者)、随机剪切、随机平移(水平或垂直或两者)、随机缩放、随机对比度变化、随机饱和度变化、随机旋转。

培养

我们使用 Adam optimizer,初始学*率为 1e-4,每次验证损失稳定超过 3 个时期时,学*率降低 0.5,如果验证损失在最后 5 个时期没有改善,则停止学*。
在 1070 GTX 卡上使用 Keras 和 Tensorflow 后端完成实施。

结果

这种方法在所有三个指标上得到最好的结果(【Mae】psnrssim )。尽管我们只在损失函数中使用了 MAE,但它似乎是其他两个指标的良好代理。
作为比较,rgsl888 使用了与我们相似的架构,但增加了扩张卷积以扩展网络的感受域。hcilab 使用分层方法,sukeshadigav 使用基于 M-Net 的卷积神经网络。

在这篇文章中,我们训练了一个深度神经网络,对指纹图像的噪声版本进行像素级预测,以消除噪声。我们展示了类似 U-Net 的架构可以在 Chalearn 竞赛的所有三个指标上取得最佳结果。

这里有代码:https://github.com/CVxTz/fingerprint_denoising

[1] Olaf Ronneberger、Philipp Fischer 和 Thomas Brox。生物医学图像分割的卷积网络。

2017 年金融科技交易所将重点放在数据上

原文:https://towardsdatascience.com/fintech-exchange-2017-puts-the-focus-on-data-db2ee3b9cfa1?source=collection_archive---------6-----------------------

上周,包括我在内的数百名金融和科技专业人士齐聚芝加哥,参加 Barchart 第三届年度金融科技交易所(FinTech Exchange)会议。该活动专注于专门针对市场和交易的技术。每年的主题都在演变,以反映及时的主题。正如 Barchart 首席执行官 Mark Haraburda 在 John Lothian 新闻简报中分享的那样,今年的内容是“关注数据、数据交付方式、数据存储方式、数据分析和可视化方式以及替代数据空间中的新型数据。”

虽然与会者和演讲者来自各地,但芝加哥的存在是最强的——不仅因为会议在那里举行,还因为芝加哥已经成为金融科技创新的中心。

如果人们需要一个提醒,说明芝加哥已经在全球金融科技领域取得了重要地位,他们马上就能得到。哈拉布尔达在欢迎辞中指出,德勤最*将芝加哥列为全球金融科技中心的第五名。这是芝加哥第一次上榜,这是一个强大的首次亮相,这座风城的排名领先于除纽约、硅谷、伦敦和新加坡之外的所有城市。

如果这一事实不足以让与会者相信 TT 的家乡是金融科技领域的“en fuego ”,来自芝加哥的闪电圆桌会议主持人提供了大量证据。虽然他们代表了从全球交易所到软件初创公司的各种公司,但他们都专注于为我们的行业提供数据相关的创新。

但是并不是所有的演讲者都来自芝加哥。总部位于西雅图的 Tableau 的 Vaidy Krishnan 的开场主题演讲重点关注大数据。根据 Krishnan 的说法,虽然构建将数据带到最前沿的仪表板很重要,但当你深入表面之下并问“为什么?”时,数据的真正价值才显现出来他断言,是这个简单的问题,而不是数据本身,激发了新的见解。但他警告说,大多数分析工具并不是为了让你探索下一层问题而设计的。他的建议是:选择一个具有仪表板功能的分析平台,该平台将挖掘其所在位置的数据,并超越仪表板指标来回答那些意想不到的问题。

来自 CME Group 的 Julie Menacho 谈到了交易所的几项数据相关计划,特别是应用程序和数据中心服务,以及专注于 CME 数据业务和市场数据分发的合作伙伴关系。最引人注目的是,她描述了该交易所新推出的基于云的数据服务。从 1970 年开始,超过 450 的历史数据以及来自非传统来源的替代数据(如卫星、信用卡交易和社交媒体)现在可以通过云轻松访问,从而为投资决策提供信息。

来自 Enova 的肖恩·奈史密斯(Sean Naismith)教授了另一个与数据相关的话题:预测分析。奈史密斯表示,自 Enova 于 2004 年成立以来,分析一直是这家在线贷款公司的“心脏和灵魂”,Enova 自称是芝加哥最早的金融科技公司之一。他讲述了客户对即时答案的需求如何推动该公司建立了一个名为 Colossus 的实时决策管理系统。他解释说,这样一个系统需要三个组成部分——业务规则、预测模型和优化例程——并分享了 Enova 在建造 Colossus 时学到的六个值得注意的经验。其中包括:深刻理解客户体验及其留下的数据。

Vertex Analytics 的吉姆·奥斯汀获得了最具娱乐性演示奖。Vertex 的平台通过提供扫描和利用实时和交易后交易数据的工具,帮助交易公司管理当今监管环境的复杂性和雷区。奥斯汀利用了金融科技交流恰逢带孩子上班日这一事实。他让一群学龄儿童和他一起上台,扮演场内交易者和电子交易者的角色。他赢得了当天最大的笑声和推特上的大量喜爱。干得好,吉姆。

DataRobot 的贾斯汀·迪克森(Justin Dickerson)给数据主题又增加了一层。他专注于自动机器学*(AML),这属于更大的(也是人们谈论最多的)人工智能(AI)类别。DataRobot 通过利用云使分析建模变得更加容易。迪克森透露,在这家成立五年的公司基于云的机器学*平台上,已经建立了超过 1.3 亿个预测模型。他的信息很有说服力:你最好关心机器学*。这不仅仅是因为它能够快速识别业务问题/趋势,具有大规模“学*”的内在能力,并且几乎每天都在变化,还因为您的竞争对手将会使用它。

最后两位演讲者,Nadex 的 Tim McDermott 和 TopstepTrader 的 Michael Patak,来自非常不同的公司。Nadex 是一个受监管的交易所,提供二元期权交易,而 TopstepTrader 的使命是为新交易者提供资金。尽管这两家公司乍看之下几乎没有相似之处,但麦克德莫特和帕塔克传达了一个共同的信息。两人都断言,交易的未来在于零售。麦克德莫特说,该交易所正在努力吸引散户投资者,解决他们对成本和恐惧的担忧,调整市场时间和其他时间框架,并使新交易者更容易进入市场。Patak 说“所有的眼睛都盯着零售”,他的重点是通过教育扩大公司的用户群。看看他们的预测能否实现将会很有趣。

感谢 FinTech Exchange 2017,我现在变得更聪明了,对专注于数据的技术和公司也更加好奇了。我们的行业产生和消耗的数据量可能是巨大的,但芝加哥和其他地方正在发生创新爆炸,可以帮助以更高效和更有利可图的方式处理和管理这些数据。我希望 2017 年的许多演讲者明年将带着更新返回 FinTech Exchange。

要了解更多金融科技交易所的关键信息,请查看 Twitter 上的 @FinTechChicago#FTX17 流。

2018 年的金融科技——墨西哥浪潮

原文:https://towardsdatascience.com/fintech-in-2018-the-mexican-wave-f1ef59e7cc84?source=collection_archive---------10-----------------------

席卷拉丁美洲的工业革命

墨西哥超过了 300 家金融科技初创公司的门槛,巩固了其作为拉丁美洲第二大金融科技生态系统的地位

仅在 12 个月内,125 家新的金融科技创业公司在墨西哥诞生,巩固了墨西哥作为拉丁美洲地区主要金融科技生态系统之一的地位,主要受以下领域增长的驱动:金融机构的企业技术、交易&资本市场、财富管理和替代评分、身份和欺诈。

金融部门目前正处于深刻的变革和创新过程中,这一过程的主要特点是使用新技术。这种颠覆性的浪潮始于伦敦或新加坡等稳固而成熟的市场,在过去几年中已经扩展到几乎全世界,在拉丁美洲,它正在迅速发展,并正在改变我们所知的金融世界。

Finnovista 之前对拉丁美洲主要金融科技生态系统进行的研究结果证明了该地区金融部门的稳固转型。在过去几年中,我们见证了该地区大多数金融科技生态系统的增长率约为 50%。迄今为止,芬诺维斯塔已经发表了对 【阿根廷】巴西智利哥伦比亚厄瓜多尔西班牙的研究 以及关于在拉丁美洲运营的外国创业公司的特定雷达(**** Fintech Radar 外国创业公司 )和关于金融普惠(fin tech for Inclusion Radar))。 当前的分析代表了 Fintech Radar Mexico 与 泛美开发银行 合作的更新,其第一版于 2017 年 7 月发表。********************

过去几个月,墨西哥采取了重大举措来推动金融科技创新生态系统,并将自己定位为潜在的全球金融科技中心之一。仅在一年前,在该分析的第一个版本中,该国成为该地区最大的金融科技生态系统,拥有 238 家初创公司。在新版 Fintech Radar 中,墨西哥的 Fintech 生态系统增长到了 334 家 Fintech 初创公司,这使得该国落后于巴西,根据 2018 年 6 月发布的上一份Fintech Radar Brazil,巴西是该地区最大的 fin tech 生态系统,有 377 家初创公司。因此,墨西哥巩固了其作为拉丁美洲第二大金融科技生态系统和该地区金融创新主要驱动力之一的地位。墨西哥的生态系统目前比哥伦比亚大 2.5 倍,哥伦比亚是该地区第三大金融科技生态系统,有 124 家创业公司,比阿根廷大 3 倍多,比智利大 4 倍多。

这表明在过去的 12 个月中,墨西哥金融科技生态系统中的创业公司数量增长了 96 家,年增长率为 40% ,略低于该地区其他主要生态系统的年增长率,如巴西增长了 48%,哥伦比亚增长了 52%,阿根廷增长了 56%,尽管高于智利去年增长的 22%。然而,与其他国家相比,墨西哥的死亡率较高,为 12%,而巴西为 14%。这反映出墨西哥有 29 家创业公司在过去几年中停止了运营,因此,同期该国出现了 125 家新的创业公司。与其他金融科技生态系统相比,较低的增长率以及较低的死亡率也可能反映了该国金融科技行业的整合阶段,更多处于更高级发展阶段的创业公司正在整合其商业模式。

目前,墨西哥的六个主要细分市场是:

  • 支付和汇款,占 75 家初创公司总额的 23%
  • 贷款,占 74 家创业公司总数的 22%
  • 企业财务管理,占 45 家初创企业总数的 13%
  • 个人理财,占总数的 11%,有 36 家初创公司
  • 众筹,有 30 家初创公司,占总数的 9%
  • 面向金融机构的企业技术,占总数的 7%,有 23 家初创公司。

在这项分析中,其余五个新兴领域都不到已识别初创企业总数的 6%:

  • 保险,占总额的 6%
  • 财富管理,占总额的 3%
  • 替代得分、身份和欺诈,也占总数的 3%
  • 交易和资本市场,占总数的 2%
  • 数字银行,占总数的 1%。

如果我们将这些结果与前一版的 Fintech Radar Mexico 进行比较,我们会发现主要 Fintech 细分市场之间的微小变化。支付和汇款、贷款、企业财务管理、个人财务管理和众筹仍然是创业公司数量中最重要的部分。唯一的区别是,这一次,支付和汇款部门成为美国最大的金融科技部门,有 75 家初创公司,贷款部门略有落后,有 74 家初创公司。

然而,当查看所有金融科技细分市场在过去 12 个月中的增长率时,我们可以看到增长率最高的细分市场通常不是该国创业公司数量最多的细分市场。在这个新版本中,以下部分经历了特别强劲的增长:

  • 金融机构的企业技术,从 10 家增加到 23 家,增长了 130%
  • 交易和资本市场,从 3 到 6 家初创公司增长了 100%
  • 另类评分、身份和欺诈,从 6 家增加到 11 家,增长了 83%
  • 财富管理,从 6 到 10 家初创公司增长了 67%。

与此同时,墨西哥四大金融科技生态系统在过去 12 个月中也经历了超过 30%的高增长率:支付和汇款(增长 42%)、贷款(37%)、众筹(36%)和企业财务管理(29%)。尽管在美国的 11 个金融科技领域中,没有任何一个领域出现负增长,但我们确实发现了两个领域的增长速度比其他领域慢:保险,增长率为 27%,个人金融管理,在过去 12 个月中增长了 6%。

另一方面,值得注意的是,数字银行领域出现了 5 家金融科技初创公司,因为在上一期墨西哥金融科技雷达中,该领域没有初创公司。正如我们在巴西已经观察到的那样,该细分市场在一年内增长了 147%,多达 16 家初创公司,我们不断发现更多的数字银行解决方案,试图适应新的市场需求,从而接*新一代。

如果我们将墨西哥金融科技细分市场的分布与拉丁美洲的其他两个主要生态系统(巴西和哥伦比亚)进行比较,我们会发现这三个国家拥有相同的主要金融科技细分市场,但略有不同:支付和汇款、贷款和企业财务管理。支付和汇款现在是这三个国家中最大的部分,这反映了我的移动设备在进行交易时变得越来越重要。在其他两个细分市场中观察到了细微的差异,因为贷款细分市场是墨西哥和哥伦比亚的第二大生态系统,而在巴西则位于第三位,这可能是受该国该细分市场面临的监管限制的影响。

我们认为,在过去 12 个月里,墨西哥和巴西在金融科技领域的增长趋势方面存在重大差异。正如我们已经提到的,面向金融机构的企业技术这一细分市场在墨西哥的增长率最高,有 13 家初创公司,而在巴西,这一细分市场一年内只有 5 家新的初创公司,这可能反映了墨西哥金融机构对将金融科技解决方案纳入其业务的开放程度更高。另一方面,保险部门的增长率差异也值得注意,因为在巴西,该部门在 12 个月内增长了 73%,而在墨西哥,该部门的增长率限制在 27%,这表明该部门在墨西哥处于早期发展阶段,这可能是受 WeeCompany 首席执行官 Jesús Hernández 指出的“不愿意冒太大风险”的保守形象的影响。这种较慢的增长率反映了墨西哥保险技术部门的停滞,而此时该部门正在经历世界其他地区的增长和转型过程。墨西哥显然需要高效且无处不在的创新保险服务,因此墨西哥最具创新性的保险公司将利用这一机会整合 InsurTech 创新,无论是墨西哥还是外国的解决方案,正如西班牙初创公司【Bdeo】已经与墨西哥重要的保险公司一起推出了视频理赔工具。

为了对墨西哥的金融科技生态系统进行更深入的分析,对该国 110 家金融科技初创公司进行了一项关于不同业务方面的调查。

收集的信息表明,墨西哥城是大多数墨西哥金融科技初创公司的创办城市,有 61%的人提到了它们的起源城市,其次是瓜达拉哈拉,9%,蒙特雷,6%,梅里达,4%,普埃布拉,2%。关于国际化,83%的公司声称只在墨西哥运营,而 17%的公司确认在国外运营。我们发现,与该地区最大的金融科技生态系统巴西相比,墨西哥的国际化率较低,巴西的国际化率为 30%,仍远远低于该地区国际化率最高的阿根廷的 48%。

当分析已经开始国际化进程的初创公司的主要目的地国家时,我们观察到 62%的国际扩张发生在拉丁美洲和加勒比海地区,38%的墨西哥金融科技初创公司已经扩张到该地区以外,是巴西的两倍。

哥伦比亚成为墨西哥金融科技初创公司的主要目的地,其中 30%在该国运营,其次是智利和秘鲁,每个国家都是 17%墨西哥金融科技初创公司的目的地,以及巴西,其中 9%的墨西哥金融科技初创公司已经扩张。另一方面,我们还观察到洪都拉斯、巴拿马或哥斯达黎加等加勒比国家是主要目的地,这反映了墨西哥金融科技初创公司如何将其业务国际化到仍处于早期发展阶段的生态系统,因此在开发较少的市场中寻找机会。

除了拉丁美洲和加勒比海地区,美国和加拿大是墨西哥金融科技初创公司的下一个目的地,这些公司决定将活动扩展到其他大陆,因为 19%的公司已经在这里运营。与此同时,11%的金融科技初创公司在欧洲运营,8%的墨西哥金融科技初创公司已经扩展到亚洲。

墨西哥金融科技雷达的这一新版本展示了关于墨西哥金融科技生态系统成熟度的重要结果,因为我们观察到,78%的受访金融科技初创公司已经处于高级阶段,超过了巴西注册的 66%。具体来说,31%的人声称已经处于增长和扩张阶段,而 47%的人表示已经准备好进行扩展。其余 22%仍处于早期阶段,主要是准备用于商业发布的测试版本,因为 16%的受访金融科技初创公司声称处于这一阶段。

然而,尽管墨西哥的金融科技生态系统处于高度成熟的阶段,并且正如我们在巴西等该地区其他重要生态系统中所看到的那样,大多数接受调查的初创公司在员工数量方面仍然很小,因为其中 54%的公司声称拥有 1 至 10 名员工,而只有 8%的公司拥有 50 名以上的员工。

从公司的年龄来看,墨西哥的 Fintech 生态系统主要由年轻的创业公司组成,因为 85%的公司不到 5 年。具体来说,45%不到 2 岁,31%出生于 3 至 4 年前,9%出生于 4 至 5 岁。与此同时,只有 15%的被调查创业公司成立超过 5 年

根据 世界银行 的数据,37%的墨西哥成年人口拥有官方银行账户,这意味着墨西哥的银行化率约为 63%,高于该地区的平均水平(51%)。然而,我们可以再次看到,银行服务不足和没有银行服务的消费者和中小企业市场仍然是墨西哥金融科技初创公司的主要目标市场,这是我们 Finnovista 称为金融科技包容性的细分市场。具体而言,54%的墨西哥金融科技初创公司将他们的产品和/或服务瞄准了这一细分市场,这一比例自 2017 年以来有所增加,当时 46%的墨西哥金融科技初创公司被确定将他们的服务瞄准了这一细分市场。另一方面,有趣的是,要强调的是,这一比例高于该地区其他主要金融科技生态系统,因为在巴西,35%的初创公司将其解决方案瞄准金融科技领域,哥伦比亚为 45%,阿根廷为 41%,智利为 40%。

当被问及用于创建其产品和服务的主要技术时,墨西哥 Fintech 初创公司最常用的三种技术是:大数据和分析(25%)、API 和开放平台(17%)以及移动和应用(15%)。我们再次看到开放银行在不同实体的产品和服务之间的联系方面获得的重要性,所有参与者都在利用传统金融实体拥有的大量数据和信息,另一方面,金融科技方面的技术创新能力也在改善他们的客户服务。这一过程反映了金融实体如何与行业中的新参与者进行更深入的合作,这些新参与者通过适应消费者的新需求来获得市场份额。

在回答融资问题的 110 家墨西哥金融科技初创公司中,64%的公司声称过去获得过第三方公司的资金,这表明了外部资金来源在该国创业项目发展中的重要性。然而,墨西哥金融科技初创公司仍在筹集少量外部资金,40%的公司表示收到的资金不到 10 万美元,而只有 7%的公司声称筹集了超过 100 万美元,低于巴西注册的金额,巴西 13%的金融科技初创公司筹集了超过 100 万美元。然而,在过去几年中,我们已经看到墨西哥金融科技初创公司的重要投资轮次,例如由贷款平台 Konfio 筹集的8900 万美元 轮次,由 Vostok Emerging Finance 牵头;the700 万美元 由 Curu 募集,QED 投资人领投;或者是由 ePesos 融资的600 万美元 轮,由 Santander Innoventures 牵头。

当在墨西哥金融科技初创公司中确定主要资金来源时,正如在巴西发生的那样,天使投资者成为最重要的资金渠道,因为同意分享这些信息的初创公司中有 27%通过这些方式筹集了资金。与其他生态系统不同,大多数墨西哥金融科技初创公司(20%)仍在转向封闭的资金来源,即所谓的3f:朋友、家人和傻瓜。另一方面,加速和孵化计划也是墨西哥金融科技初创公司的重要替代资金来源,因为其中 14%的公司声称参与了类似的计划。具体来说,在墨西哥,我们发现加速计划 Startupbootcamp FinTech 墨西哥城 ,以及规模计划startup boot camp Scale fin tech,两者都由 Finnovista 运营。最后,还值得注意的是风险投资公司在墨西哥金融科技生态系统中的重要性,因为 18%的墨西哥初创公司声称从当地基金筹集了资金,12%来自外国基金。

最后,当被问及他们的融资计划时,墨西哥 71%的金融科技初创公司表示他们目前正在寻找资金,其中 71%在这个过程中提供股权,20%通过收购债务来实现。

最终外卖

正如我们在 Finnovista 之前进行的研究中看到的那样,金融科技创新浪潮现在是一种全球现象,据估计,银行业面临着因金融科技初创公司而损失高达 4.7 万亿美元收入的潜在风险。拉丁美洲也未能幸免于这场革命,过去在一些市场上是孤立的创新,现在是整个地区的普遍趋势。这一波金融创新在这个 51%的人口仍然没有银行账户的地区尤其重要,换句话说,他们被排除在正规金融系统之外,因为金融科技解决方案通过提供从汇款平台或数字支付到智能手机的各种解决方案,将自己定位为这部分人口的替代者。

然而,为了实现该行业的稳定增长、发展和接受,仍有一些关键因素必须考虑和解决,例如在监管或行业开放方面所做的努力。从这个意义上说,在 2018 年 3 月通过监管金融科技机构的法律(通常称为金融科技法)成为该地区第一部法律和全球参考后,墨西哥成为了先锋。这项新法律的目标是通过一个立法框架来监管所有被称为金融科技机构(FTI)的平台,从而提供更大的法律确定性,并创建一个法律框架,确保金融科技初创公司与传统金融和银行机构之间的公平竞争。

金融科技行业存在适当和量身定制的监管是该国行业大多数主要参与者所接受的必要性,因为正如在伦敦或新加坡等其他整合生态系统中所看到的那样,它增加了该行业的清晰度,从而推动了创新解决方案的进一步增长和整合。然而,我们面临着这些新法规的风险,如墨西哥的金融科技法,导致过度监管的市场,从而减缓甚至阻碍更大的金融创新。在墨西哥,新的法律规定,电子支付机构必须通过独立的第三方评估遵守“这些机构根据上述规定必须遵守的关于信息、电子手段的使用和持续运作的安全措施”的情况。这一过程高度依赖区块链技术,因此高度依赖提供这些技术要求的外国公司,这些技术要求在墨西哥和该地区其他地方尚未被广泛采用。

最后,因为我们发现自己正处于技术金融全球化的时代,所以新的监管不应该局限于一个国家的情况。拉丁美洲国家必须考虑到国际领域,学*其他国家的最佳做法,以及最终阻碍进一步创新和新商业模式的主要障碍。通过这种方式,该地区将能够在国际市场上实现更大程度的整合,同时将拉丁美洲国家定位为外国公司的目的地生态系统,并将为该地区的初创公司打开扩张之门。

参考

见原帖:芬兰人

首先创建一个常识基线

原文:https://towardsdatascience.com/first-create-a-common-sense-baseline-e66dbf8a8a47?source=collection_archive---------1-----------------------

当你着手解决一个数据科学问题时,很容易一头扎进去,开始构建模型。

不要。首先创建一个常识基线。

如果你不了解任何数据科学,常识基线就是你如何解决问题。假设你不知道监督学*,无监督学*,聚类,深度学*,随便什么。现在问问你自己,我会如何解决这个问题?

有经验的从业者经常这样做。

他们首先对数据和问题进行一些思考,对什么是好的解决方案有一些直觉,并考虑应该避免什么。他们与可能一直手动解决问题的业务最终用户交谈。

他们会告诉你,常识性的基线不仅实现简单,而且通常很难超越。即使数据科学模型超过了这些基线,它们也是以微弱的优势超过的。

我们将看三个例子,从直接营销的一个问题开始。

你在一家服装零售商工作,有一个客户数据库,其中包含了过去一年中从你这里购买过东西的每个客户的信息。你知道他们买了什么,花了多少钱,还有一些人口统计信息。

您想要发送一封邮件,宣传您最新的春季服装系列,并且您有足够的预算从数据库中向多达 100,000 名客户发送邮件。

你应该挑选哪 10 万个客户?

您可能渴望创建一个训练和测试数据集,并学*一些监督学*模型。也许是随机森林或者梯度推进。甚至是深度学*

这些都是强大的模型,应该放在你的工具箱里。但首先,问自己这个问题:“如果这些方法都不存在,我必须靠自己的智慧生活,我将如何挑选最好的 10 万名客户?”。

常识告诉我们,你应该在数据库中挑选最忠诚的客户。毕竟,如果有人会找到感兴趣的邮件,这些客户会*。

你如何衡量忠诚度?直觉上,一个忠诚的顾客可能会买很多东西,花很多钱。这样你就可以计算出每个顾客在过去一年里花了多少钱,和你一起购物了多少次。

如果你这样做,看看数据,你会发现它很好地抓住了忠诚度。但你也会注意到,它挑选的客户在上半年是忠诚的,但在下半年似乎从地球上消失了。

您可以通过查看顾客最*如何与您一起购物来解决这个问题。如果消费和购物频率相似,昨天与您一起购物的客户比 11 个月前购物的客户对您更有价值。

总而言之,对于每个客户,您可以计算

  • 他们在过去 12 个月里和你一起度过的时光
  • 过去 12 个月的交易数量
  • 自上次交易以来的周数

您可以根据这三个指标对客户文件进行划分,并相应地对客户列表进行排序。

挑选前 100,000 名客户。

恭喜你!你刚刚发现了古老的*因-频率-货币(RFM) 启发式方法,一种久经考验的直销方法。

如果你想知道在十分位数列表中 R、F 或 M 哪个更重要,那么 R 被认为是最重要的

RFM 方法易于创建、易于解释和易于使用。最棒的是,效果出奇的好。经验丰富的直销从业者会告诉你,即使更复杂的方法击败了 RFM,它们之间的差距也会比你想象的小得多,会让你怀疑复杂的东西是否值得努力。

接下来是产品推荐区的一个例子。

你工作的零售商有一个电子商务网站,你被要求建立一个产品推荐区,将显示在主页上。

它需要个性化——如果访问者以前来过你的网站,你需要利用你对他们的任何了解来推荐适合他们兴趣的产品。

关于这个主题的整本书(示例示例)已经写好了,GitHub repos ( 示例示例)随时准备为您服务。你应该深入研究矩阵分解吗?

你也许应该在某些时候,但不是第一件事。您应该首先创建一个常识基线。

你能向访问者展示的最简单、最相关的东西是什么?

畅销产品!

当然,它们不是个性化的。但是,畅销产品之所以成为畅销产品,是因为有足够多的访问者购买它们,所以从这个意义上来说,至少有合理比例的访问者会发现它们是相关的,即使它们不是专门为它们选择的。

此外,你无论如何都需要准备好畅销商品,因为你需要一些东西展示给你没有数据的首次访问者。

挑选畅销书很简单。确定一个时间窗口(过去 24 小时,过去 7 天,…),确定一个指标(收入、浏览量等)。),决定重新计算的频率(每小时,每天,…)。),编写查询并将其放入一些自动化中。

你可以用简单的方法调整这个基线,让它变得有点个性化。例如,如果您记得访问者在上次访问中查看的产品类别,您可以简单地从这些特定类别中(而不是从所有类别中)选择最畅销的产品,并在推荐区域中显示它们。在前一次访问中浏览了女装类别的访问者可以在当前访问中看到女装的畅销商品。

明确地说,上面描述的“调整”将涉及开发工作,因为你需要在访问中“记住”信息。但是,如果您计划构建并交付基于模型的个性化推荐,无论如何都需要这样做。

我们的最后一个例子来自零售价格优化。

作为一家服装零售商,你销售季节性商品,例如毛衣,这些商品需要在每个季度末从商店中清理出来,以便为下一季的产品腾出空间。降低这些季节性产品的价格以刺激购物者购买,这是业内的标准做法。

如果你折扣太少,你会在季末有剩余的商品,你将不得不以残值处理掉。如果你打折太多,你会卖完产品,但失去赚更多钱的机会。

在行业中,这种平衡行为被称为清仓优化或降价优化。

关于如何使用数据科学技术建模和解决这个问题,有大量的文献(例如,参见牛津定价管理手册中的第 25 章)。披露:是我写的)。

但是,让我们首先考虑如何创建一个常识基线。

假设您手头有 100 件毛衣,当前季节还剩 4 周。你可以一周改变一次价格,所以你有四次机会做某事。

本周该不该降价?

嗯,首先,这取决于如果你保持价格不变,你认为在接下来的 4 周内你能卖出多少台。

我们怎样才能对此有所了解呢?我们能做的最简单的事情就是看看上周卖出了多少台。

假设我们卖出了 15 台。如果接下来的 4 周与上周相似,我们将售出 60 台,到本季度结束时仍有 40 台未售出。

不太好。显然降价是理所应当的。

零售商有时使用折扣阶梯——20%折扣、30%折扣、40%折扣…——降价必须在阶梯上。最简单的做法是走到阶梯的第级第级,即将下周的价格打八折。

快进一周。假设你上周卖出了 20 台。您现在还剩 80 个单位,还有 3 周时间。如果在接下来的三周内保持相同的销售速度(例如每周 20 台),您将在剩余的三周内售出 60 台,在季末还有 20 台未售出。所以,你又下了一个台阶,把折扣提高到 30%。

你明白了。每周重复,直到赛季结束。

不同的产品可能遵循不同的折扣路径,这取决于它们的销售率对折扣的反应。在下面的例子中,B 项比 a 项需要更多的折扣刺激。

这个常识基线可以用非常简单的 if-then 逻辑来实现。与上面的个性化推荐示例一样,它可以被调整(例如,不是仅使用上周的销售单位作为未来几周的“预测”,而是取最后几周的平均值)。

有了基线,您现在就可以向前迈进,尽您所能在这个问题上投入所有的数据科学火力。但是,将您所做的一切与常识基线的结果进行比较,以准确衡量努力的回报。

在许多问题领域,古老的 80-20 原则仍然有效。常识性的基线通常会让你很快达到 80%。

随着你在这个问题上投入越来越多的数据科学,你会看到更多的价值,但速度会越来越慢。现在,根据您的具体情况,您可能会决定采用复杂的方法来提取最后的价值。但是你应该对增量成本和收益有一个清晰的概念。

最终,常识基线会保护你免受由理查德·费曼著名描述的危险。

第一个原则是你不能欺骗自己——而你是最容易被欺骗的人。

构建数据科学模型可能非常令人愉快,并且很容易让人误以为您复杂的、精心创建和调整的模型比实际情况更好(从成本/收益角度来看)。

常识基线快速传递价值,保护你免受自我伤害。让它们成为一种*惯。

有一种不同的方式来思考这个问题——提升建模——它考虑了给客户发送邮件的增量*效果。

在 Nodeflux 作为人工智能研究科学家的第一次实*

原文:https://towardsdatascience.com/first-internship-as-ai-research-scientist-at-nodeflux-ea4a339d03f?source=collection_archive---------10-----------------------

大二学生实*的机会很少,至少在我家附*是这样。我的动机是获得新的经验,了解校园生活是什么样的。通过这篇文章,我将讲述我自己,Nodeflux,以及我作为数据科学家的实*经历,后来从注册到最后经过 2 个月的实*,我的实*经历修改为人工智能研究科学家。

我的一般背景

我的名字是丹迪·瑙法尔迪。在我写这篇文章的时候,我即将开始我在 ITS 信息学系的第三年。我的高中背景是一个喜欢学*数学和物理的书呆子。大概我选择信息学专业就是为了避开生物和化学。在校园里,我总是有兴趣学*新的东西,这可能是我决定不再继续竞争编程 lol 后的“数据科学”之旅的开始。

Nodeflux

你可能从未听说过 Nodeflux。这是一家非常年轻的初创公司,位于雅加达,专注于智能视频分析服务。利用各种知识,你可以从中央电视台的视频流。他们的一些产品是高速公路休息区的车辆计数器,在' mudik '期间确实帮助了很多人,使用人脸识别技术的员工考勤机,以及 2018 年亚运会的视频监控系统也使用人脸识别技术。他们的口号是“扩展视野,超越想象”。检查他们的网页

实*前:我如何到达这里

在我的第四个学期,我决定我必须在我的下一个假期实*,以获得新的经验和知识。于是,我开始主要在 IT 创业上寻找实*信息。我在寻找软件工程师的职位。有一次,我 2012 届的学长 Mas Fika 在我的部门脸书小组分享了关于 Nodeflux 实*机会的信息。我不太了解 Nodeflux,之前我只知道 2013 届的 Mas Rizok 不是我们系唯一在 Nodeflux 工作的校友。我只知道他们做 AI 的东西,专注于计算机视觉技术。当时,Nodeflux 面向软件工程师、web 开发人员和 devops 工程师开放职位。我只是认为这是一个机会,我必须申请这一个。

首先,我只是把我的简历发到海报中提供的邮箱。接下来是技术任务。它包括一些与不同领域相关的问题,就像职位空缺一样。所以有一些面向对象的问题,CSS 和 Javascript 的东西,linux 的理解,和机器学*的东西。有很多问题要在 3 天的期限内完成。除了一些我以前从未听说过的 devops 之外,它们都很简单。之后,被选中的候选人将与 Nodeflux 的一些工程师进行在线面试。最初的几个问题之一是我对什么职位感兴趣。我一片空白,忘了有哪些职位空缺。我只是说我对软件工程和机器学*的东西感兴趣(他们的海报里没有发表,lol) 。问了一些问题后,问题开始聚焦在 web 开发和数据科学上。有人问我更喜欢 web dev 还是 data scientist,我选择了 data scientist,因为这家公司的专长是人工智能,我认为这将是扩展我知识的一个非常好的机会。几周后,我得到了这个职位。耶!!

日常实*

首先,你需要知道这里的数据科学家不是那种以商业为导向的工作。我们更像人工智能工程师或人工智能研究科学家或机器学*工程师,他们专注于使用人工智能来创造产品或增强产品。有趣的事实是,这里没有数据科学家职位的员工,只有人工智能工程师和人工智能研究科学家。在我实*期间,我有 2 个导师,Mas Rizok(人工智能工程师)和 Mas Alvin(人工智能研究科学家)。第一天,我被要求学*容器概念和 Docker,因为它在这里被大量用于容器化开发环境和产品部署。然后,我得到了一个在整个实*期间要完成的项目,就是制作一个能够从一个人的正面照片预测年龄和性别的模型。查看我的项目这里

With one of my mentor, Mas Rizok (Informatics ITS 2013)

我做这个项目的过程是起起伏伏的。挑战之一是处理这种“脏”数据集,即 IMDB-Wiki 数据集。它包含大量标签错误数据。我花了大约 3 天时间浏览了 20,000 张图片(只有全部部分清理过的数据集的 1/10 ),并设法丢弃了其中的 2000 张,而这实际上只是全部数据的一小部分。让我开心的一件事是获得大量的计算能力。起初,我获得了使用 2 个 GTX 1080Ti + 2 个 16 核英特尔至强的服务器的权限,然后更改为使用 Tesla V100 的 AWS 实例。它们真的很快,我从来没有机会使用这么大的计算能力。

我在这里学到了很多新的技术和方法。它们是人脸检测、人脸对齐、制作双输出模型、多重处理和多线程。在我实*之前,我从来没有处理过这种不适合内存的数据,有一天,我刚刚用完了所有 60 GB 的可用内存,因为我的笨脑袋,然后我学会了如何根据需要加载数据,并通过多处理最小化 I/O 开销。这个项目也是我的第一个项目,我给了很多文件。我试图让其他人也能复制它。在这里,我也熟悉自己阅读论文作为参考,因为他们真的是很好的参考。我在这里学到了很多新东西,直到我可以说我的大部分代码对我来说都是新事物。

后来,当我完成了模型的制作。我的导师要求我建立一个端到端的系统,以实时视频流作为输入来推断模型。在那里,我学会了如何在线程中分离作业,以实现实时视频处理。我还集成了排序跟踪器,后来我知道它使用卡尔曼滤波器作为其主要结构。研究了一下卡尔曼滤波器,我意识到我的线性代数和统计&概率课是值得的。是的,我在实*期间学到的很多新东西实际上是我在校园里所学的东西的实现(操作系统课程、线性代数课程、统计&概率课程,还有其他一些)。

在这里,我形成了一些价值观,它们真的帮助我度过了第一次实*。它们是:

  • 好奇心:永远要有学*新事物的精神,让它们引导你克服你真正的问题。多搜索,多阅读
  • 自信:新的挑战总会向你走来,你必须确保你能做到。坚强的意志真的有帮助。
  • 耐心:在你的旅程中可能会遇到障碍,你必须有耐心保持在你的轨道上并始终如一。以后你将能够克服这些问题。

With some of other intern, CEO, and employee. From top left to bottom right: Guntara (SE Intern), Atina (SE Intern), Kak Ilham (SE), Kak Meidy (CEO), Chasni (Web Dev Intern), Dani (AI Intern), Nanda (DevOps Intern), Adi (DevOps Intern), Kevin (SE Intern), Daniel (SE Intern), Me, Kak Anggun (Talent Management)

结论

在实*期间,我得到了所有我想要的东西。我学到了新的东西,认识了伟大的人,向最优秀的人学*,并且能够与他人讨论我的想法。Nodeflux 是一家年轻的初创公司,发展非常迅速。我会把它推荐给任何喜欢体验新事物,解决挑战,当然也想了解更多人工智能的人。这里所有的人都是伟大的人,他们热爱自己的工作,热爱自己的工作。我想感谢 Nodeflux 给我这个好机会,因为这是我的第一次实*,真的很有趣。

Our “Agustusan” event

卡格尔的第一枚银牌

原文:https://towardsdatascience.com/first-silver-medal-on-kaggle-d41819182ec9?source=collection_archive---------5-----------------------

Fig 1. Camera Model Identification Challenge

问题陈述:摄像机型号识别

面临的挑战是建立一种算法,通过使用图像中固有的痕迹来识别哪种相机模型捕捉了图像。数据集中的图像来自 10 种不同的相机型号,如下所示:

  • 索尼 NEX-7
  • 摩托罗拉摩托 X
  • 摩托罗拉 Nexus 6
  • 摩托罗拉 DROID MAXX
  • LG Nexus 5x
  • 苹果 iPhone 6
  • 苹果 iPhone 4s
  • HTC One M7
  • 三星银河 S4
  • 三星 Galaxy Note 3

解决这个问题对犯罪调查有很大的影响,调查人员可以识别拍摄图像的相机,这有助于验证镜头。

受训模特

ImageNet 模型(如 ResNet、DenseNet 模型)经过微调,可以对前面提到的 10 种不同的摄像机进行分类。微调 ImageNet 权重和训练分类器只不过是迁移学*!!

Fig 2. Transfer Learning

转移学*直觉

假设一个人正在努力学*如何骑自行车/滑板车。

场景 1: 他/她已经知道如何骑自行车,现在他/她正在学*骑滑板车。

场景 2: 他/她正在从头开始学*骑滑板车。

在哪个场景中涉及的学*更多?🤔

显然在第二个场景中正确!

由于这个人是从零开始学骑踏板车,他/她必须学会如何平衡踏板车,*惯不同的功能,如刹车或加速等..这需要花很多时间去学*。而一个已经知道如何骑自行车的人可以在学*骑自行车/踏板车时很容易地转移他的知识。

这同样适用于从零开始训练图像分类器,而不是使用 ImageNet 权重并用较低的学*速率微调权重来训练分类器。

以下是我们在本次比赛中使用的几个模型,并给出了相应的准确度分数。

注:所有模型都用 ImageNet 模型权重初始化。

Fig 3. Accuracy for different models & settings.

作为一个团队,我们提交了大约 63 份作品&最后 3 份作品的最高投票使我们在私人排行榜上排名第 43 位,是的,我们获得了第一枚银牌!!

观察结果&竞赛要点:

  • 仅仅微调顶层效果并不好。在卷积神经网络中,所学*的特征是非常特定于任务的,对于这个竞赛分类也是如此,它不是基于图像中存在的内容,而是基于图像中的图片质量、模糊度、噪声模式等.. 因此,对用低学*率的 ImageNet 权重初始化的整个模型进行微调对于这场比赛是必要的。
  • 与传统的机器学*模型相比,深度学*模型需要大量数据。增加更多来自 Flickr 的训练样本,准确率提高了 4 - 5%。

Fig 4. Performance of DL & ML models with increasing data.

  • 数据集清洗至关重要(移除 Flickr 数据集中主要来自 moto_x mobile 的不良训练样本)。
  • 通过增加类别权重来处理类别不平衡(每个类别约占训练集的 10-15%,Moto X 除外,它仅占训练集的 3%)。
  • TTA(测试时间增加)在私人排行榜上增加了 1.1%的准确率。
  • 合奏 作品!!我们对我们最好的 3 个模型进行了最大投票,这是我们在比赛中的最后一次提交&我们的私人得分增加了大约 0.8%。

如果没有安德烈亚斯·托鲁比亚、伊万·罗马诺夫和格莱布分享来自 Flickr 的额外数据集的想法,获得银牌是很困难的。

如果您有任何想法、意见或问题,请在下面留下评论或在 LinkedIn 上联系我们。

我发表的一些博客:

关注我上 阅读更多此类博客。

团队成员:

[## Rajesh Shreedhar Bhat -数据科学家-印度沃尔玛实验室| LinkedIn

Rajesh Shreedhar Bhat 是班加罗尔沃尔玛实验室的数据科学家。他的工作主要集中在…

www.linkedin.com](https://www.linkedin.com/in/rajeshshreedhar)

苏拉布·赫姆卡:https://www.linkedin.com/in/saurabhkhemka

https://www.linkedin.com/in/vignesh-s-53424847

潘卡杰·夏尔马:https://www.linkedin.com/in/pankaj-sharma-ab1016a7

Python 数据科学的第一步— NumPy

原文:https://towardsdatascience.com/first-step-in-data-science-with-python-numpy-5e99d6821953?source=collection_archive---------2-----------------------

我读到过学*的最好方法是写博客。既然我学*数据科学已经有一段时间了,我想为什么不试一试呢。这就是了。我的第一篇博客。

现在,网上有很多优秀的资源,人们可以从中学*。但是,当您刚刚开始时,可用资源的数量会让您有些不知所措。特别是在数据科学领域,你可以找到所有这些热门词汇,如数据科学、人工智能、机器学*、深度学*等等。它变得令人困惑——从哪里开始呢?

如果你像我一样,你会发现一些使用数据科学或人工智能的很酷的应用程序,你会迫不及待地开始自己构建这些应用程序。你将开始学*基础知识,但很快就无法决定如何将它们整合在一起,最终会感到沮丧。我对任何新手的建议是要有耐心。不要看得太远,只关注眼前的事情。一般来说,数据科学或编程是一门艺术,你需要一步一步来。我还没到,但我在努力。

最重要的是开始;第二重要的是坚持下去。

毫无疑问,学*基础知识很重要。但是如果你不能解决任何真正的问题,学*又有什么意义呢?我相信无论你何时学*,你都必须有一个最终目标。我在这篇文章中的目标是尝试解决问题;非常简单的问题,但仍然是问题。从问题到解决方案,分享数据科学第一步的一些基础知识——NumPy。

等等,什么是 NumPy?

NumPy 代表数字 Python。正如文档所述,NumPy 是使用 Python 进行科学计算的基础包。它用于对数组执行数值运算。NumPy 在大小、速度和功能性方面都优于 python list。关于 python list 和 NumPy 数组比较的详细描述可以在这个链接中找到。

在开始使用 NumPy 之前,它需要安装在您的系统中。您可以使用 pip 或 anaconda 安装它。本文中的代码使用 Python3 和随 anaconda 安装的 NumPy。我不会对安装进行详细说明。如何安装 NumPy 见此链接

说够了。让我们进入正题。

你可以在下面的链接中找到这篇文章的完整代码。

[## bajracharya-kshitij/numpy

numpy -在解决问题的同时学* numpy 基础知识

github.com](https://github.com/bajracharya-kshitij/numpy)

在我们开始使用 NumPy 或任何其他包执行任何种类的计算之前,第一步总是导入包。所以,还是导入 NumPy 吧。

import numpy as np

这里,我们给 NumPy 取一个更短的名字— np。这就是所谓的混叠。从今以后,每当我们需要从 NumPy 包中访问任何方法时,我们将使用' np '来这样做。参见此链接了解更多关于混叠的信息。

我们不是要解决问题吗?

是的。现在我们已经导入了 NumPy,我们可以用它来执行各种计算。那么,现在让我们来定义第一个问题。

问题 1

给你 5 个不同半径和高度的圆柱形容器,高度从 5 厘米到 25 厘米不等。找出
a)每个容器可以容纳的水的体积,
b)所有容器可以容纳的水的总体积,
c)哪个容器可以容纳的最高体积和多少,
d)哪个容器可以容纳的最小体积和多少,
e)容器可以容纳的水的体积的平均值、中间值和标准偏差是多少?

这是基本的算术。我不需要 NumPy 来解决这个问题。

你当然不知道。Python 包是为解决更复杂的问题而构建的,并且能够解决更复杂的问题。但是这里的目的只是给出 NumPy 如何工作的一个基本概念,以便这些技术以后可以应用于更大规模的问题。我只是不想吓跑那些新手。

解决方案 1

首先,我们需要 5 个圆柱形容器的半径和高度。半径和高度的值被定义为在 5 和 25 cm 之间。我们先用变量来定义这些。

no_of_items = 10
lower_limit = 5
upper_limit = 25

项目的数量是 10,因为我们需要 5 个容器中的每一个都有 2 个值——一个是半径,另一个是高度。

稍微提个醒。与网上其他关于 NumPy 的资源不同,这些资源遵循特定的模式或不同属性或方法引入的顺序,本文不会这样做。因为我们的目标是解决手头的问题,所以我们将向前推进,按照有助于我们解决问题的顺序引入概念。所以,这一切都是随机的。说到这里,我们来生成一些随机数。

np.random.seed(0)
values = np.random.randint(lower_limit, upper_limit, no_of_items)

上面有三个参数——下限 5、上限 25 和项目数 10。这个执行的结果是values将被分配一个由 5 到 25 之间的 10 个随机数组成的 NumPy 数组。这是创建 NumPy 数组的一种方法。注意,这里下限是包含性的,上限是排他性的。所以,25 永远不会出现在数组中。np.random.seed是一种有趣的方法。它有一个参数(上面的 0 ),它的作用是返回一组随机数。有趣的是,不管你什么时候执行上面的代码块——现在,午饭后或者一年后——你总是得到相同的随机数集合。相比之下,如果从上面的代码块中删除np.random.seed,每次执行都会得到不同的随机数集合。我在这里使用 0 作为种子,但是您可以使用任何整数;你得到的只是一组不同于我的随机数。

:也有其他方法产生随机数。np.random.randint生成整数。如果需要浮点数,可以用np.random.randnp.random.randn。这些你可以自己去探索。

如果你现在打印出values,你会得到这样一个 NumPy 数组

array([17, 20,  5,  8,  8, 12, 14, 24, 23,  9])

这里我们可以看到,有一个单独的开始和结束方括号。这说明values是一个一维数组。为了进一步验证这一点,您可以使用values.ndim,它返回值1,表示values是 1D。现在,为了验证数组中实际上有 10 个条目,我们可以使用values.size,它返回数组的长度10。此外,要找出列表中包含什么类型的值,您可以使用values.dtype,在这种情况下,它将返回dtype('int64'),表示数组包含整数。

接下来,我们通过使用返回(10,)values.shape来看看这个数组的形状。这里逗号分隔每个维度上的项目数。由于values是 1D,逗号后面没有数字。这些只是熟悉 NumPy 的一些属性。让我们回到问题上来。

所以,我们需要圆柱体的半径和高度,但是现在我们只有一个简单的数字数组。让我们重新组织一下,使数字成对出现,每个气缸一个。为此,我们使用reshape方法。

no_of_rows = 5
no_of_columns = 2
containers = values.reshape(no_of_rows, no_of_columns)

reshape 方法将 NumPy 数组的形状更改为我们指定的任何维度;唯一的要求是沿着每个维度的项目数的乘积等于项目总数。在这里,我们将values转换成一个 5 行(每个容器一行)2 列(一列表示半径,另一列表示高度)的 2D 数组,并将其存储在containers中。现在,如果你打印出containers,你会看到如下所示。

array([[17, 20],
       [ 5,  8],
       [ 8, 12],
       [14, 24],
       [23,  9]])

正如我们所见,有两个左右方括号,所以这是一个 2D 数组。使用containers.ndim验证这一点。现在形状也变了。试试containers.shape,你会看到它返回(5,2)

现在我们有一个 2D 数组,让我们分开半径和高度数组。为此,我们将使用切片。这里我们只处理两列,所以切片会非常简单。关于切片的深入细节,请参见本教程。

假设第一列代表半径,第二列代表高度。我们来切片containers

radius = containers[:,0]

这定义了我们只取所有的行(:)和第一列(0)。同样,对于高度,我们取所有的行(😃,只取第二列(1)。

height = containers[:,1]

现在我们有了半径和高度的所有值,我们终于可以计算圆柱体的体积了。你可能知道,圆柱体的体积可以这样计算:

volume = np.pi*(radius**2)*height

如果我们现在打印volume,它会返回一个数组,如下所示

array([18158.40553775,   628.31853072,  2412.74315796, 14778.05184249,14957.12262374])

只用一行代码,它就计算出了所有 5 个圆柱体的体积。这里,我们只取了一个包含 5 个元素的 1D 数组。NumPy 能够快速高效地执行多维数组计算,每个维度上有成百上千个项目。这就是 NumPy 的力量。

现在,为了找到所有圆柱体中包含的水的总体积,我们可以简单地将上述数组中所有圆柱体的体积相加。

total_volume = volume.sum()

总容积也可以用另一种方法计算,不用计算单个气缸的容积。方法是计算半径和高度的点积。

radius_squared = np.square(radius)
dot_product = np.dot(radius_squared, height)
total_volume_by_dot_product = np.pi*dot_product

total_volumetotal_volume_by_dot_product都给出相同的结果。点积在这里有效,因为半径平方和高度都是一维的。对于二维矩阵,它必须满足第一个矩阵的列数必须等于第二个矩阵的行数的要求。因此,如果两个 2D 矩阵具有相同的维数,在执行点积之前,有必要使用np.transpose()方法找到其中一个矩阵的转置。

现在,要找到哪个圆柱体能容纳最大体积的水,我们可以使用max方法,这个圆柱体在数组中的索引可以通过使用argmax方法找到。

max_volume = volume.max()
index_of_max_volume = volume.argmax()

类似地,我们可以使用min方法来查找最小体积,使用argmin方法来查找圆柱体在数组中的索引。

min_volume = volume.min()
index_of_min_volume = volume.argmin()

最后,我们可以计算圆柱体体积的平均值、中间值和标准偏差。

volume_mean = np.mean(volume)
volume_median = np.median(volume)
volume_standard_deviation = np.std(volume)

问题 2

从 1 到 25 的 25 张牌随机平均分配给 5 个人。找出每个人的纸牌总数,这样对于第一个人来说,总数是第一张纸牌的价值减去其余纸牌的总数;对于第二个人,总和是第二张牌的值减去其余牌的总和,依此类推。纸牌总数最大的人将获胜。找出赢家。

解决方案 2

这次我们需要从 1 到 25 的 25 个数字。在问题 1 中,我们通过使用np.random.randint方法生成了一个 NumPy 数组。现在,让我们看看生成 NumPy 数组的第二种方法。这次我们将使用arange方法。请注意,这是一个安排,而不是安排。

numbers = np.arange(1,26)

np.random.randint方法一样,下限是包含性的,上限是排他性的。如果没有定义下限,将导致 NumPy 数组从 0 开始。我们还有一个用于arangestep参数,如果定义的话,它将在开始和结束限制之间产生step的倍数。此时,如果您选中numbers,您将得到下面的数组。

array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25])

现在我们有了从 1 到 25 的卡片,让我们在分发之前洗一下。为此,我们使用np.random.shuffle

np.random.shuffle(numbers)

现在,如果我们看一下numbers,我们将得到一个类似这样的数组。

array([12, 22, 20, 19, 3, 23, 21, 17, 11, 1, 4, 5, 16, 9, 14, 10, 6, 18, 15, 8, 25, 2, 13, 7, 24])

这只是可能的方式之一。这是因为shuffle方法在每次运行时都会改变numbers的顺序。你的将会完全不同。

太好了。我们已经洗牌了。现在让我们把它们平均分配给 5 个人,每人 5 张卡片。

reshaped_numbers = numbers.reshape(5,5)

看起来像这样。

array([[12, 22, 20, 19,  3],
       [23, 21, 17, 11,  1],
       [ 4,  5, 16,  9, 14],
       [10,  6, 18, 15,  8],
       [25,  2, 13,  7, 24]])

5 张卡片,每张 5 个人,排列成 2D 矩阵。完美。现在,我们需要做的就是找出每个人的总数。为此,添加对角线元素并减去其他元素。因此,第一个人的总和将是12-22-20-19-3,第二个人的总和将是-23+21-17-11-1,以此类推。要做到这一点,我们需要一个矩阵,它的对角线元素和上面的一样,但是其他元素都是无效的。首先,让我们用单位矩阵得到对角线。

对“我”的一只眼睛使整个世界变瞎。嗯,除了对角线。

为了生成一个单位矩阵I,我们使用了eye方法。由于I是方阵,我们只需要一个自变量。在这种情况下,我们需要一个 5x5 的矩阵。

I = np.eye(5)

这会生成下面的单位矩阵。

array([[1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.]])

现在,如果我们将reshaped_numbersI相乘,一个元素接一个元素的乘法将只保留对角线元素,并删除所有其他元素。

diagonal_matrix = np.multiply(reshaped_numbers,I)

所以,diagonal_matrix看起来会像下面这样。

array([[12.,  0.,  0.,  0.,  0.],
       [ 0., 21.,  0.,  0.,  0.],
       [ 0.,  0., 16.,  0.,  0.],
       [ 0.,  0.,  0., 15.,  0.],
       [ 0.,  0.,  0.,  0., 24.]])

接下来,我们需要否定的非对角线元素。要做到这一点,我们只需要一个对角线上为 0,其他地方为-1 的矩阵。如果我们从单位矩阵I中减去一个单位矩阵U就可以得到。U是全 1 的矩阵。U不需要是一个正方形矩阵,所以我们需要定义行数和列数。

U = np.ones((5,5))

所以,U现在看起来像

array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])

请注意,ones的参数是一个元组(5,5 ),而不像reshape和其他方法那样只有 5,5。还有一个类似的zeros方法,生成一个给定形状的全零矩阵。现在,让我们生成我们需要的矩阵。

I_minus_U = I - U

当我们从单位矩阵中推导出单位矩阵时,我们得到下面的矩阵。

array([[ 0., -1., -1., -1., -1.],
       [-1.,  0., -1., -1., -1.],
       [-1., -1.,  0., -1., -1.],
       [-1., -1., -1.,  0., -1.],
       [-1., -1., -1., -1.,  0.]])

对角线是 0,其余是-1。我们再次执行reshaped_numbersI_minus_U的逐元素乘法,以获得我们需要的矩阵。

negative_diagonal_matrix = np.multiply(reshaped_numbers,I_minus_U)

negative_diagonal_matrix现在看起来是这样的。

array([[  0., -22., -20., -19.,  -3.],
       [-23.,   0., -17., -11.,  -1.],
       [ -4.,  -5.,   0.,  -9., -14.],
       [-10.,  -6., -18.,   0.,  -8.],
       [-25.,  -2., -13.,  -7.,   0.]])

现在,我们需要做的就是使用add方法将diagonal_matrixnegative_diagonal_matrix结合起来。

combined_matrix = np.add(diagonal_matrix, negative_diagonal_matrix)

元素相加的结果是combined_matrix看起来像这样。

array([[ 12., -22., -20., -19.,  -3.],
       [-23.,  21., -17., -11.,  -1.],
       [ -4.,  -5.,  16.,  -9., -14.],
       [-10.,  -6., -18.,  15.,  -8.],
       [-25.,  -2., -13.,  -7.,  24.]])

最后,剩下要做的就是对combined_matrix执行逐行加法。

sum_matrix = combined_matrix.sum(axis=1)

这里,axis=1执行逐行加法。如果需要按列添加,请使用axis=0

最后,您将得到一个矩阵,其中包含每个人的总和,如下所示。

array([-52., -31., -16., -27., -23.])

数字最高的就是赢家。为了找到赢家的指数,我们使用argmax

winner = np.argmax(sum_matrix)

更新:

正如@ Payal Bhatia 在她的回复中提到的,上述内容在技术上是列方式的添加,而不是行方式的添加。乍看之下,我们似乎在做逐行加法,而这正是我们想要的。但是,NumPy sum 的工作方式比这要复杂一些。点击下面的链接可以更直观地了解 NumPy sum 是如何工作的。

[## 理解数字总和

如果你不清楚 NumPy 是什么或者它是如何工作的,请先看看这篇文章。

towardsdatascience.com](/understanding-numpy-sum-1587eec69527)

问题 3

给你一根 5 米长的绳子。将绳子分成 9 段,每段长度相等。

解决方案 3

我们需要在等距离的点切断绳子,这样就有 9 个部分。所以,除了startend点,我们还需要 8 点;一共 10 分。

start = 0
end = 5
no_of_points = 10

为了找到等距点,我们使用linspace方法。

np.linspace(start, end, no_of_points)

这将为我们提供下面的数组。

array([0\.        , 0.55555556, 1.11111111, 1.66666667, 2.22222222,
       2.77777778, 3.33333333, 3.88888889, 4.44444444, 5\.        ])

所以,除去数组中的第一个和最后一个条目,剩下的就是绳子必须被切断的点,这样我们就有 9 个等长的部分。

linspace常与arange混淆。arange通过使用第三个参数作为一个步骤,生成一个从头到尾(排除)的 NumPy 数组。linspace通过使用第三个参数作为两端之间要计算的点数,生成一个 NumPy 数组,该数组包含从开始到结束(包括)的等距点。

我想做很酷的东西,不是这个。

当然,这篇文章没有包含任何花哨的可视化效果,也没有介绍任何可以展示的酷模型。但是,NumPy 是所有即将出现的酷东西的基本构件。此外,这篇文章并没有涵盖所有关于 NumPy 的知识。但是现在你很擅长自己探索。这是这篇文章的结尾,但也是数据科学中其他一切的开始。

在下一篇文章中,我们将关注数据科学中的另一个基础包——熊猫。

[## 开始走数据科学之路(上) :熊猫系列

既然我们已经迈出了数据科学的第一步,

towardsdatascience.com](/beginning-to-walk-the-data-science-road-part-1-pandas-series-920e2237c336)

关于卡格尔的初步想法

原文:https://towardsdatascience.com/first-thoughts-on-kaggle-326a6c4dc005?source=collection_archive---------6-----------------------

大约两周前,我报名参加了我的第一个 Kaggle 竞赛,即梅赛德斯-奔驰绿色制造竞赛。我的代码可以在这里找到,我尝试的日志可以在这里找到。以下是我对 Kaggle 的第一印象:

学*曲线

进入大赛,我唯一的机器学*知识来自麻省理工的入门课(6.036)。因此,我惊喜地发现,卡格尔竞赛对那些之前经验很少的人来说是完全可以参加的。这很大程度上是由于 Kaggle 的内核,它允许更有经验的 Kaggle 用户与其他人公开分享他们的代码。内核甚至允许那些完全不熟悉机器学*的人在排名中具有竞争力— 通过简单地复制代码,任何人都可以取得与 Kaggle 老手不相上下的结果。

我发现,在我尝试改进内核代码的过程中,我收到了关于机器学*中多个概念的简要介绍,其中许多概念我希望在未来写得更透彻:

  • 梯度增强树
  • 超参数调谐
  • 降维:主成分分析,独立分量分析,tSNE,逻辑主成分分析,TSVD,GRP,SRP
  • 过度拟合、K 倍交叉验证、非折叠预测
  • 集合、堆叠和平均
  • Sklearn 型号:套索、ElasticNet 等。
  • 基本特征选择和特征工程
  • 可能性编码(赛后)

在我看来,这个比赛是一个快速“边做边学”的好方法。很难在网上找到任何其他像 Kaggle 这样有助于学*数据科学概念的资源。

排行榜的不可预测性

从最终排名的大规模调整可以看出,公共排行榜对于预测私人排行榜来说完全不可靠:几乎所有在比赛中领先的人最终都下降了数百个排名。然而,即使是交叉验证也被证明是无用的:我的最终模型,用 5 重 CV 评估,并不比我在第四天制作的严重过度拟合的 XGBoost 模型表现得更好。

Public and Private LB scores for my 36 submissions — a few past models made it over the bronze cutoff!

最后,事实证明有可靠的方法来测试一个模型——尽管在大多数情况下,参赛者(包括我)对评估他们模型的表现不够彻底。

Kaggle 的竞赛社区

对于 Kaggle 的社区,我只有积极的话要说。用户提交的关于比赛的内核和线程大大鼓励了参赛者之间的合作。在比赛期间,许多用户在公开论坛上一起工作,改进彼此的模型并讨论数据集的属性。本次比赛是参赛者共同努力的众多成果之一,通过排行榜探测,从测试数据集中发现了 32 个 y 值。

结论

我发现参加这次比赛非常愉快!虽然我的最终排名(~ 1400 名)有点令人失望,但比赛非常有趣,让我学到了很多东西,我计划将来在 Kaggle 上更加活跃。如果您有任何反馈,请告诉我——也许更多关于 Kaggle 的报道将很快出现。😃

2017 年应用数据科学的第一个周末

原文:https://towardsdatascience.com/first-weekend-at-applied-data-science-2017-23c86415c1b8?source=collection_archive---------16-----------------------

本周末,学生们学*了应用数据科学课程中教授的许多机器学*技术的基础知识。他们温*了线性代数、统计学和复杂性理论。此外,他们还学*了 Python 中的自动化测试,以及如何编写可读和可维护的测试,以获得信心并促进代码协作。

最大的收获是对我们在这门课中所做的所有工作背后的理论有了一个真正清晰而简明的理解。正如 Thibaut 提到的,你可以在不参加这个周末的情况下获得对这个项目 85%的理解,但是有了它,你就有了能够更深入地探索这些概念的基础知识。这样当你面临一个问题时,你就可以理解它背后的理论,并提出一个更新颖的解决方案。那是我的关键外卖。

从我的背景(没有任何强大的数学经验)来看这些材料是非常令人生畏的,但我现在知道了我需要在接下来的两周内学*的关键技术,并积累了一些工作知识。

为了让我理解这个理论,将我们所做的应用到现实世界的例子和工作案例中是非常有用的。在本课程之外,我正在处理一个大数据问题,但我们没有数据科学团队来探索它。因此,我将从这个周末开始思考我们在开发解决方案时忽略的一些事情,以及我们如何从不同的角度看待这个问题。

Rupert Prescot,产品经理

我真的很期待即将到来的回归模块和覆盖神经网络的最后一个周末。但是你需要掌握数学才能达到目的——这是我们都在努力的。

Suresh Gangaiah,计算机科学毕业生

一些关键要点。当谈到特征向量和特征值时,Thibaut 把它们框起来,作为描绘矩阵和得到足迹的一种方式。我喜欢承认每种技术对你有什么帮助的想法。在这种情况下,您希望了解以后需要的某些特征。他在会议中也有一个关于规范的线索,这是一个很好的方式来加强这个概念的重要性。

安东·苏斯,经济学家

如果您希望提升您目前的技能,了解前沿的行业方法,并在数据科学领域开始职业生涯, 现在就申请在 2018 年加入我们。

机器学*简介:使用 TensorFlow 对 Kaggle 数据集应用逻辑回归

原文:https://towardsdatascience.com/fitting-a-machine-learning-model-to-a-kaggle-dataset-with-tensorflow-c79356936858?source=collection_archive---------10-----------------------

Machine Learning can create complexly beautiful systems. Source: Pixabay.

经过几天的特征工程和探索性分析,机器学*是完美的甜点。

如果你一直关注我以前的帖子,你已经读过这个,和这个,在那里我分析了这个 Kaggle 数据集。我查看了奥运会项目及其参与者的历史,将分析缩小到几个方面:

  • 赢得奖牌。
  • 随着时间的推移,女性和男性的参与情况。
  • 给定性别,每个运动项目运动员的身高和体重统计。

最后,我提到使用数据开发机器学*模型可能会很有趣。

让我想到的是看到运动员的体重和身高与他们在生物学上是男是女之间的强烈关联。这让我想到,应该有可能将运动员性别的预测建模为一个分类问题。

因此,在我的第一篇机器学*文章中,我们将看看如何预测奥运会运动员的性别(为了简洁起见,从现在起我将使用单词 sex 来指代生物性别)。为了实现这一点,我们将用我们能找到的最好的特征来建模这个问题。
我们将使用 TensorFlow 构建模型。

在这第一部分中,我们将看一个简单的逻辑回归,它实际上实现了比我预期的更好的性能。在接下来的文章中,我们可能会关注更复杂的模型,比如深度神经网络。然而,我坚信,在事情变得更复杂之前,我们应该从用我们可能使用的最简单的模型来解决问题开始。

虽然我将添加相关的代码片段,但我鼓励你跟随笔记本上的这个 GitHub 项目,尤其是如果你想试验代码并实际运行它的话。

但首先,几个定义。

机器学*

机器学*是人工智能的一个分支。它包含各种算法,但它们的共同点是能够从输入中“学*”。

它们通常需要大量的数据才能真正学到东西,但如果训练得当,它们会非常强大。在机器学*可以解决的许多问题(图像合成、欺诈预防、推荐系统)中,许多都属于分类的范畴:为建模数据的某个样本分配一个或多个标签。在这种特殊情况下,我们将为数据的每个样本(每个运动员)分配一个标签(男性或女性)。

逻辑回归

早在古代(50 年代),英国统计学家大卫·考克斯发明了一种算法,在给定某些变量的情况下预测事件的概率。

在给定上下文的情况下,逻辑回归为二元事件分配一定的概率(从 0 到 1)。为了使用它,我们将首先创建输入向量,其中每个向量对应于一名运动员,向量的每个字段是该运动员的一个(数字)特征(例如,他们的体重或身高)。
然后,我们将尝试预测其中一个字段为 1 或 0 的概率(例如,在我们的例子中,1 可能意味着女性和男性)。

它通过以下方式做到这一点

  • 在输入要素中执行仿射变换,即,将它们乘以一个矩阵,并向乘积中添加一个偏差向量。我们称矩阵和偏差向量的元素为“权重”。
  • sigmoid 函数组合该运算,该函数将整个实数域中的数字“处理”成介于 0 和 1 之间的(仍然是无限的)数字。这给了结果一个概率的概念。
  • 代价函数惩罚模型(在我们的例子中,我们将使用交叉熵):如果我们希望模型学*某样东西,我们将不得不惩罚它没有学*它..
  • 找到成本函数(我们希望最小化)的梯度作为模型权重的函数。
  • 向相反方向稍微更新权重,由称为“学*率”的常数指示,以便在下一次迭代中降低成本函数。

这个循环反复执行,多次迭代整个输入集。这些迭代中的每一次都被称为“时期”。

最终,该函数收敛到一个值,该值通常是成本函数的局部最小值。然而,这并不能保证是一个全球最小值。

这整个过程被称为“训练”模型。模型训练完成后,我们将通过测量其准确性来了解它的表现:它做出的预测中有多少是正确的,除以它总共做出的预测数。用统计学术语来说,在整个预测集合中,模型有多少真阳性和真阴性。

在这个小小的介绍之后,我鼓励你进一步阅读维基百科,也许是一本书。我特别喜欢奥莱利版。

变脏:预处理数据。

我们终于可以从本文中实用、有趣的部分开始了。为了让模型消费数据,我们必须首先决定 CSV 的哪些列是相关的,并将它们转换成数值。这包括像“运动”这样的分类特征。

保留正确的列

对于这个特殊的问题,我认为我们实际上能找到的有用的栏目只有身高、体重、参加过的运动、性别。我还会添加每个运动员的名字,因为我们可能希望检查他们的独特性。

我们不希望参加一个以上项目的运动员使我们的数据有偏差。为了避免这种情况,我们只为它们中的每一个选择一行。我假设他们的体重和身高在不同的项目之间不会有太大的差异,而且也没有太多的运动员每次都尝试不同的运动。为了挑选出独特的运动员,我们将使用我们的数据框架的 groupby 方法,并将称为独特的方法。

我们看到,现在我们的数据集中有* 10 万名独特的运动员,他们从事 55 种不同的运动。

分类列的一键编码

具有 55 个不同分类值的列对于机器学*模型来说是难以消化的。正因为如此,我们将对它使用一次性编码。这意味着我们将把一个有 55 个可能不同值的向量,变成 55 个二进制向量。听起来很复杂?手工编码会有点麻烦。幸运的是,熊猫有一个内置的方法来保护我们。这是一个热门的编码片段。

就像这样, df_one_hot_encode 是一个 54×100k 的矩阵,每行只有一个非零值,这个值总是 1。 drop first 参数使其丢弃其中一个类别,因为“所有列都是 0”本身可能就是一个类别。

转换为 NumPy 数组

编码完成后,我们向其中添加身高和体重列,当然还有我们的标签。

最后,我们将完全放弃数据帧,转而使用 NumPy 数组,因为 TensorFlow 接受矩阵作为输入。我马上承认我不像对熊猫那样精通数字。如果以下任何一行太难看,请告诉我,我会修改它们。

这是我们将数据帧转换成矩阵的方法:

我的热心读者可能想知道为什么我真的放弃了体育专栏。老实说,我尝试了几种不同的方法,但运动只会给模型增加噪声。如果有人能想出巧妙使用它们的方法(可能通过相关性将它们分组为几个集群,但我今天没有尝试),请分叉该项目并这样做。我很想看到有趣的结果。

我正在做的另一件有争议的事情是使用两列,一列用于男性(二进制),一列用于女性(1-男性)。为了对多个列进行回归,我们将使用 softmax 转换,这是针对多类分类问题的 sigmoid 的推广。它以依赖的方式给每个类分配一个概率,所以它们加起来都是 1。这可能有些矫枉过正,但这将使修改这段代码来预测更广泛的类别变得非常容易(比如,预测体育…?)以后。

实际机器学*:Tensorflow 中的逻辑回归。

定义我们的模型

任何不导入配置文件的好 TensorFlow 程序都是从官僚主义开始的。我保证会好起来的。

在这里,我们定义模型的输入数量(每个特征一个)和输出数量(2 个,一个男性,一个女性)。我们还设置了学*率(每次下降时梯度将“跳跃”多远),定义了模型并初始化了权重变量。

值得注意的一件有趣的事情是 TensorFlow 变量是延迟求值的:它们不会有任何值,直到我们在一个会话中运行它们。打印它们只会显示它们是 tf 变量,而不会实际得到值。这允许许多优化,例如许多加法和减法可以压缩成一个。

在下面的片段中,我们将讨论如何训练和评估机器学*模型。

我们定义精确度,并设置一个优化器(梯度下降)。我们还添加了成本函数(所有输入的交叉熵的平均值)。训练我们的模型

最后,这个美丽的片段实际上开始了训练,我们可以看到我们的逻辑回归在起作用。

注意我们如何简单地在每个时期迭代输入,并运行优化器。由于 TensorFlow 函数是惰性的,我们必须通过从 tf 调用 run 来初始化它们。Session,并在一个 feed_dict term 中传递它们的变量值(在起床遇到一些麻烦后,它们最终被初始化)。

在每个时期结束时,我们打印精确度,这是我们一直试图优化的指标。

请注意,我们在与训练数据集完全不同的数据集上测量准确性。这样做是为了避免过度拟合:机器学*模型可能会开始简单地记住它的输入,并在被问及时重复给你,而不是实际学*从数据中进行归纳。我想象的方式是用三次多项式拟合一条线上的几个点:当然它会拟合它们,但是问它另一个点可能在哪里,它可以指向线外的任何地方。

结论和见解

这是整个代码介绍,但现在让我们做一些实际的数据科学。

我首先运行训练,用所有 56 个输入输入模型。结果相当糟糕,准确率低于 60%。这个模型基本上只是猜测每个人都是男性。因此,它的表现只能达到允许的等级不平衡(70%的运动员是男性)的水平。不仅如此,在预测女运动员的少数情况下,它通常是错误的。我的理论是,过于稀疏的体育投入只会增加噪音。

我去掉了它们,尝试了一个非常简单的模型,它只关注身高和体重。它过拟合数据的速度如此之快,以至于在一个时期内就预测了 100%的雄性。你自己试试,你会发现这是真的。

起初我认为我一定是初始化变量错误或什么的,所以我传递给它一个全女性的训练集。然后它开始预测 100%是雌性,所以很明显它实际上是在学*。

我试着将数据标准化,我终于看到了一些结果。然而,这比再次预测所有男性好不了多少。

最后,我求助于一个老把戏。我给模型添加了新的非线性特征:不仅包括体重和身高,还包括它们的比例、乘积、正方形和立方体,所有这些都是标准化的。
模型达到了 76%的准确率。这意味着在某些情况下必须正确地猜测两性(比我今天所做的任何事情都要好),实际上比随机猜测要好很多。

为了生成这些特性,我使用了下面的代码片段:

我希望你喜欢这个对机器学*这个巨大世界的小小介绍。将来,我们可能会用一个完全不同的模型来解决这个问题(提示:深入思考),也许会用一种更直观的方式来观察模型的表现。

像往常一样,代码可以在 GitHub 项目的上获得。如果你想改进它,或者添加任何其他功能,请随意。我的准则就是你的准则。

如果你觉得这篇文章的任何部分不够清楚,或者有更好的解释方法,请告诉我。你的反馈对我很有帮助,意义重大。
如果你是机器学*的新手,我希望你觉得这篇介绍有用,或者至少有趣。我也希望很快能再见到你。

关注我获取更多数据科学和机器学*教程。如果你还没有这样做,请在 twitter 上关注我,看看我什么时候写一篇新文章。

原载于 2018 年 9 月 18 日www . dataden . tech

每个数据科学家都应该阅读的五本与数据科学无关的书

原文:https://towardsdatascience.com/five-books-every-data-scientist-should-read-that-are-not-about-data-science-f7335fb1f84f?source=collection_archive---------3-----------------------

我在 2010 年为华盛顿大学(UW)的一个班级写了第一行 R 代码。当我意识到编码比电子表格强大得多时,我就着了迷。在过去的十年里,我见证了“数据科学”一词的广泛使用,也见证了大数据、商业智能、分析以及现在的人工智能等术语的兴衰。

我在 UW 大学上的课是“计算金融”,就像今天的深度学*课一样,很容易就挤满了一个相当大的演讲厅。当时,金融危机对每个人都记忆犹新。对于工程师来说,这是一个不太微妙的信息;如果你想得到一份高薪工作,那就进入金融行业,成为一名定量分析师,就像今天的数据科学一样。在商业运作中直接使用数学的概念非常有趣,不仅用于决策支持,还用于实时决策。然而,金融危机也暴露出,即便是最复杂的模型,也不足以应对现实世界的混乱局面。

许多人认为,金融危机的核心是一个获得诺贝尔奖的微分方程;布莱克-斯科尔斯期权定价模型。这个模型被用来衡量巨额投资的风险,却没有理解其内在的局限性和隐含的假设。这种技术上的盲目为灾难性的经济损失创造了条件。

今天,有抱负的数据科学家被鼓励学*一系列令人难以置信的建模技术。每一种方法,比如线性回归,都有自己的一套哲学,你通过它的使用内在地认同它(知道或不知道)。这就产生了一批准备部署模型的新员工,他们并不了解实际发生了什么。年轻的社区没有解决技术盲问题,而是参与了关于工具的代理争论(R vs. Python!).

为了帮助解决这个问题(我也深受其害),我提供了一份简短的阅读书目,从哲学上帮助数据科学家做好准备。此外,在部署模型之前,他们会激发关于模型的技术假设的问题。这个列表并不详尽,书中的主题从有趣到激烈。金融工程的影响力很大,因为它比其他任何学科都更能培养出通用数据科学家。

  1. Incerto: 这本书是纳西姆·塔勒布的作品集,其中最著名的是《黑天鹅》,在我看来最好的是《反脆弱》。塔勒布是现代最伟大的风险、不确定性和定量建模问题的思想家。他也是一个推特巨魔,因为他叫出了那些“聪明但白痴”的 IYI 人。从背景来看,他是一名移民衍生品交易员,后来成为了数学哲学家。你要么爱他,要么恨他,因为他会在他所有的作品中不断挑战你的假设。如果他写了什么,你应该马上把它放在你的阅读清单上。

  1. 《财富》公式:麻省理工学院早期诞生的一个公式(凯利标准)的故事,该公式被认为是大量金融成功的背后原因。你将了解信息论之父(克劳德·香农)以及后来在埃德·索普的《击败庄家》中出名的算牌骗局的开端。索普现在被认为是量化对冲基金的教父。最重要的是,这本书展示了如何一个好的模型不能永远被忽视,但坏的模型可以烧伤你。这个故事也是历史上第一次计算机科学和数学合作解决现实世界的问题(只是碰巧是为了赌博)。这个故事是数据科学行业创建 60 年前的一个伏笔。

  1. 混沌——造就一门新科学:最年轻的科学的详细历史。既是混沌的历史,也是对这一主题的通俗易懂的回顾。这本书将让读者了解我们模拟现实世界的能力的局限性。由于非线性过程的性质,今天开发和部署的许多深度学*模型无法真正理解。这本书将帮助你理解这些局限性。此外,对伯努瓦·曼德尔布罗个人生活和工作的全面回顾使其成为任何数据科学家的必读之作。詹姆斯·格雷克是一位了不起的作家,他还有许多其他优秀的书籍可以添加到你的阅读清单中。

  1. 暗池:一个程序员永远改变了股市交易的故事。如今,预测模型被部署在高频交易领域,决策以纳秒级的速度做出。这本书讲述了这个隐藏但强大的生态系统的创建过程。这个故事的奇妙之处在于,它阐明了当你知道一些代码时,许多问题是如何解决的。它还表明,创造真正的价值是做真正创新的事情,而不是依赖于现有的假设。有时候你必须有点疯狂才能解决难题。

  1. 不会消亡的理论:贝叶斯公式和贝叶斯统计的历史以及它的竞争对手,频率主义者。统计的历史和关键技术主题的简单语言评论使这本书至关重要。您将了解历史上一些最伟大的人物,如 Pierre Laplace 和 R.A. Fischer,以及他们的哲学如何在几个世纪内塑造了世界的数据方法。

这五本书虽然不详尽,但将有助于为研究现实世界问题的数据科学家建立哲学基础。不要重蹈 10 年前宽客们的覆辙。寻求从哲学上理解技术和模型,而不仅仅是机械地理解,我们的职业将变得无价

我在联合国数据科学实*的五个教训

原文:https://towardsdatascience.com/five-lessons-from-my-data-science-internship-at-the-united-nations-58d2da17f07f?source=collection_archive---------9-----------------------

当我听说联合国开发计划署全球脉动的工作时,我认为这简直是电影里的情节。社会影响数据科学听起来是我能用数学做的最酷的事情。

我在人生的不同阶段培养了对数学、经济学和计算机科学的热情。在加州大学洛杉矶分校,我不得不整天戴着不同的帽子,在撰写数学证明、研究经济理论和编写计算机程序之间转换。直到今年夏天,我一直在分别追求这三个令人兴奋的领域。

以下是我在联合国全球脉动实验室(PLJ)工作期间,从研究、数据、经济和我自己身上学到的一些经验。

1.你几乎可以把每个问题都归结为一个数学问题

我不得不在一周内对数亿个数据点实现聚类算法,对机器学*一无所知。幸运的是,我是一名数学专业的学生——我的数学背景确实有助于我从头开始理解所使用的算法。

some of the 345678938241861414201280 plots I had to look at

例如,理解主成分分析(PCA)背后的线性代数在我解释 R 中漂亮的可视化以决定特征选择时是有回报的。当 PCA 的概念被描述为“通过代数方法识别几何相似性的机制”(Jauregui,2012) ,或者,我认为它是映射数据指向由协方差的特征向量确定的最重要的‘方向’(相关性?)数据集独立变量的矩阵。这些概念对我来说是有意义的,因为它们背后的数学是有意义的。

我对数学有了更多的欣赏,因为我已经将它们应用到了现实生活的项目中。这就像我上个季度的‘为什么’时刻(为什么我需要正交化特征向量?为什么会有一百万个特征值定理?等等。)都得到了回答——这些都是无价的启示。

但是现实生活中的问题不仅仅是数学问题。还有许多其他层次的活动部件需要考虑。

2.使(表面上的)对立面相交

我从未见过像 PLJ 这样多元化的团队。我在 quant 研究团队工作,但我经常参加社会系统团队的研讨会和讲座,内容涉及城市规划、海洋生物学和社会经济调查以及许多其他主题。

PLJ 的研究展示了公共部门数据科学研究的两个领域是如何深深交织在一起的。这场名为“机器学*评估贫困”的黑客马拉松式活动聚集了全国各地备受尊敬的研究人员,进行了为期 3 天的数据探索和分析,以了解更多关于印度尼西亚贫困的信息。看着统计学家和计算机科学家与社会科学家和政府官员在同一个研究项目上工作,并见证他们的专业知识相互借鉴,令人深思。

让看似不相关的领域的专家参与进来,对我来说是一种富有洞察力的实践。在向实验室提交我的项目时,我在社会系统项目经理的建议下定性地定义了我的分析的目标和影响。他们的建议指导我完善我的研究目标,并考虑我的发现对政策制定者的影响——一些我戴着数学家帽子也不会想到的事情。

这是我实*期间最喜欢的经历之一,甚至可能是整个领域的经历:将不可能的点连接起来,并赋予它们一些概率

3.开放数据,开放创新,开放政府…

我们生活在一个分享就是关爱的世界。分享知识创造协同效应和市场效率。当我们将创新和数据交给合适的人时,它们最为重要。

我是通过 quant 研究团队的其他成员的工作了解到开放政府的概念的,他们为印度尼西亚开放政府工作,并在印度尼西亚城市进行数据开放的测量。我对印度尼西亚作为一个新兴经济体成为一个更加开放的经济体所取得的进步感到惊讶。像 Satu Data Indonesia、BappenasRI、Jakarta Smart City 等组织和许多其他组织都是该实验室的密切合作者,他们的工作也极大地启发了我关于机构层面“开放”的想法。

how cool is this!??

我了解到,这种开放性需要通过内部和外部各种利益相关者之间的合作和沟通对话来培养。由于分享知识(尤其是关于分享什么、如何分享、为什么我们应该分享的对话)往往被低估,因此还有许多工作要做。为了高效和多产地实施大数据工具,需要一个强大的大数据基础设施,并且理想情况下应将其视为一种公共产品。

4.握手和交接

也就是说,“强大的授权实体(解读:公共部门)之间的握手,允许将权力移交给那些有希望、雄心、灵感和想法的人(解读:私营部门),让我们的国家变得更好”。我是在阅读安尼什·乔普拉的《创新的国度》时产生这个想法的,这本书是我一直以来最喜欢的书之一。书中讨论的观点帮助我理解了技术在公共部门的潜力,以及政府作为推动技术发展的工具所扮演的角色。如上所述,拥有一个开放的政府是一种方法。

我开始明白这句话在实验室的实际含义。虽然 UN Global Pulse 不是一家私营公司,但该组织采用了相关技术和与大多数初创公司类似的好奇心态。然而,该团队有责任倡导技术,并将其与现有的政府/社会结构相结合。PLJ 与政府密切合作,为决策建立数据驱动的平台。这项任务需要多种多样的技能,以始终如一地应对各种激励措施,并委派不同学科领域的任务,所有这些都建立在相互信任的基础上。不容易。这需要承诺和尊重,以及高水平的专业技术。这在技术上和社会上都具有挑战性。

5.战胜你的恐惧和不安全感(冒名顶替综合症太真实了!)

我是实验室里最年轻、经验最少、技术最差的人,最初让我感到恐惧和不安全。与此同时,我感到非常幸运和谦卑,每天都能从如此优秀和热情的同龄人那里学*,我选择拥抱这种感觉。

我转向生产力和乐观来减少我的冒名顶替综合症。我孜孜不倦地倾听、提问、超前研究并坚持不懈,直到找到合适的答案并解决问题。谷歌搜索东西,不怕问,永不放弃让我找到了正确的地方。

我个人发现,持续改进的最好*惯之一就是让自己走出舒适区。关键是在这个过程中保持坚强和集中。

这篇文章只是对我的经历的简单回顾,这些经验只是我在数据科学之旅的起点。我一直热爱数学和创造性的问题解决方法,但我知道我渴望在我的职业生涯中坚持一个目标,为社会公益和/或经济发展做出贡献。当我的个人价值观与团队的使命一致时,我每天早上去上班都会感觉很好。

参考资料:

杰夫,你好。"线性代数中的主成分分析."Math.union.edu,2012 年 8 月 31 日,www.math.union.edu/~jaureguj/PCA.pdf.

我在 HARA 大学数据科学实*的五个教训

原文:https://towardsdatascience.com/five-lessons-learned-from-my-data-science-internship-at-hara-f9a5bcb53a51?source=collection_archive---------12-----------------------

对于社会影响来说,还有什么比数据科学更酷的呢?不多,但通过基于区块链的数据交换的数据授权,将印度尼西亚农业置于聚光灯下,已经足够接*了。介绍 HARA。

Okay the screen capture doesn’t do justice for all the coolness here: https://haratoken.io, or read HARA Token’s medium here: https://medium.com/@HARAToken

给我印象最深的是 HARA 是如何以创业的心态和精力应对经济发展的宏伟使命的:

HARA 的使命是创造一个繁荣的农业经济,让数据成为农业的新商品。通过智能合约使用区块链,HARA 透明和可追踪的数据交换确保每个参与者都有动力提供可靠的数据。

实*是我第一次接触到与其他数据科学家和软件工程师一起在初创公司工作。我有了一个最酷的机会,在 Dattabot 的 HARA 数据科学团队工作了六周,从事一个计算机视觉项目。以下是我在研究数据、区块链科技对社会的影响以及新兴经济体中的初创企业生态系统时学到的一些经验。

1.各种景点

计算机视觉和数字图像处理对我来说是新的领域——我以前从来没有把图像当作数据。我们怎么可能使用面向对象编程来分析一幅图像呢?我们如何在分解数据后综合洞察?什么样的数据会被编码并对我们人类有用?

我被存储在数字图像处理基础中的数学优雅和严谨惊呆了。直方图表示图像强度,矩阵表示过滤器,梯度向量表示边缘。一个非常有趣的概念是边缘和轮廓,这对我们人类的视觉系统非常重要。其主要思想是,人类可以通过其轮廓明确地分辨出一个物体:我们可以通过一阶导数的概念(梯度),通过沿特定方向的局部强度变化来描述边缘,一阶导数是相对于空间距离的变化量。

Gradient based image detection, a fundamental concept to HOG-based algorithm I implemented for my custom object detector

另一个令人兴奋的时刻是当我看到关于线性卷积的一节时,它是图像处理中线性滤波器的基础。我在概率论中彻底研究过卷积,在信号处理中也听说过,但从没听说过它在数字图像处理中的应用。我在独立随机变量和的上下文中理解卷积,从两个或多个简单的求和/积分中梳理出一个更困难的求和/积分,或者更一般地说,是两个函数在一个扫过另一个时有多少重叠的度量

Watch here: https://www.youtube.com/watch?v=N-zd-T17uiE

我一点也不知道卷积可以用来消除“噪声”像素,并为图片创建平滑效果。

From convolving random variables to convolving image pixels

正如首席数据科学家马斯·维斯努(Mas Wisnu)用他自己的话说:“数学主义”。

我花了几个小时来分析数字图像处理中的微积分和线性代数,这真的给了“一张图片胜过千言万语”这句话另一层含义。我现在看数字图像,我看到数据。

2.学*如何学*

HARA 数据科学团队中的每个人都有数学背景,但背景非常多样化。所以我们有很多关于数学的辩论,但更多的时候,我是从失败的一方开始。我有一些同事的行业经验和数学知识,我想迎头赶上。我需要找到一种在工作中融入主动学*的方法。

作为一名数学专业的学生,我通过经典的教科书路线学*数学:指定阅读、*题集、讨论。在我的整个实*期间,我接受了挑战,要采取一种不同的学*方法,一种更加以问题为导向和好奇心驱动而不是理论驱动的方法。我同时阅读了几本不同的教科书,搜索了 Stack Overflow、Math StackExchange、YouTube 教程……我的任务要求我研究新的、前沿的方法和算法,并从那时起解构其背后的数学。我的重点是从里到外研究相关的主题——基础和微妙之处——尽可能高效地解决我遇到的问题。理解工具背后的数学原理与调整或定制它们以适应我的项目是相关的。

此外,通过我们随意的交谈和辩论,我遇到了许多其他感兴趣的话题。这真的很有趣——我没有机会谈论频率主义者与贝叶斯统计、股票市场和金融工程、天体物理学、数据科学的高尚应用(以及许多其他有趣的话题!)日常。这些讨论让我保持头脑清醒,缩短了工作时间。

3.数据民主化

当我读到 Dattabot 和 HARA 时,给我留下最深印象的是该公司民主化数据的愿景:“通过一次一个字节的数据赋予数十亿人权力”。

我支持开放数据,开源项目,让每个人都可以访问数据。今天,在你的个人电脑上设置 Python、R、C++和用几行代码编写机器学*程序很容易。随着物联网的兴起,生成数据、用云存储存储数据以及其他许多简化数据收集的技术进步也变得更加容易。

然而,数据项目始于我们人类为解决问题或学*洞察力而强加的问题。人们将数据和工具转化为信息和知识。像 HARA 这样的平台激励人们(数据提供者、数据鉴定者、数据购买者……)接受以数据为中心的决策和操作,是引领数据民主化革命的关键。

帮助每个人访问和理解数据的想法被称为数据民主化。数据民主化意味着打破孤岛,随时随地提供所需的数据访问。

-创新企业

今天,数据民主化的想法听起来可能是乌托邦和理想主义的,但我认为 HARA 及其平台可以通过迎合相关利益攸关方的激励,推动印度尼西亚食品和农业产业向正确的方向发展。

4.弄脏你的手和脚。一路。

在夏初,我告诉自己,我想在数据科学方面有所建树。夏末,我感觉自己一头扎进了数据科学的流沙中。从好的方面来说。

我带着 2 个小时的 Python 经验来到我的办公桌前,我立即被分配了一个项目,为印度尼西亚国民身份证创建自定义对象检测器。然后,该探测器将用于帮助验证农民从 HARA 移动应用程序提交给数据交换的照片。

第一周,我一头扎进了数字成像和机器学*的教科书和论文中,在我的浏览器上一直有至少一百个标签。我专注于逐步解决 bug 和问题,并快速获得正确的答案,以跟上其他团队成员(参见第 2 课!),到最终独立推进项目。

对我来说,被我周围的人才吓倒太容易了,但是我已经学会了接受一种对我的工作不自私的心态。最重要的是,我希望项目和我的团队取得成功,为此我不怕弄脏自己的手。

5.STEM 中的女性(不存在)

Haha, I do two kinds of modeling for HARA

HARA 工程团队主要是男性。我是数据科学团队中唯一的女性。在决定从事 STEM 职业后,我已经熟悉了女性在该领域的代表性不足。我从事的每一项数据科学工作,对我来说这个问题都变得更加真实。我参与的每一项任务都成为我争取 STEM 平等机会的机会。我的个人使命是通过我的个人工作倡导科学、技术、工程和数学领域的女性,并帮助其他女性在科学、技术、工程和数学领域增强自身能力。更多关于这个话题的内容,期待另一篇中型文章!

今年夏天,我非常幸运地参加了两次实*,每次实*都让我学到了关于数据科学对社会影响的有意义的课程。这很困难;有些日子,我不得不在周末或在家工作,不得不牺牲闲暇时间,一天中的大部分时间我都在学*等等。然而,每一次奋斗都证明是值得的,我也越来越喜欢我所做的事情。

参考资料:

"介绍卷积:直觉+卷积定理."介绍卷积:直觉+卷积定理,YouTube,2018 年 4 月 21 日,【www.youtube.com/watch?v=N-zd-T17uiE.

麦凯、伊恩等人数字图像处理的原理:基本技术。斯普林格伦敦,2009 年。

潘纳曼,埃利奥特。"初学者指南:数据民主化|文章|首席数据官."文章|创新|创新企业,2016 年 9 月 1 日,channels . the Innovation Enterprise . com/Articles/初学者-数据民主化指南。

PT Mediatrac 系统。"基于区块链的全球透明数据交换."haratoken.io/. HARA 令牌

五分钟到你自己的网站

原文:https://towardsdatascience.com/five-minutes-to-your-own-website-fd0b43cbd886?source=collection_archive---------9-----------------------

(Source)

如何使用 GitHub Pages 和 Jekyll 开始创建自己的完全免费的博客

建立自己的网站在几个层面上都是有益的。有机会向朋友、家人和潜在的雇主展示你的作品,有机会为制作某样东西而自豪,有机会根据自己的喜好设计(非常小的)一部分网页。

虽然 Medium 是开始写博客的一个很好的选择,因为有限的功能让专注于写作,但最终,像我一样,你会希望自己的网站成为你工作的中心位置。幸运的是,我们生活在一个充满创造力的伟大时代,你可以使用免费工具在几分钟内建立一个网站。

在这篇文章中,我们将看到如何使用 Jekyll 站点生成器和 GitHub 页面来构建和发布一个简单的博客,而不需要编码。如果你想了解最终产品,你可以看看我的(工作进展)网站

Jekyll 和 GitHub 页面

Jekyll 是一个简单的静态站点生成器。这意味着它获取纯文本文件,并将其呈现为一个网站,然后可以通过 web 托管服务提供给 web。这项服务的一个选项是 GitHub Pages,免费的“通过 GitHub 托管和发布的网站”

使用 Jekyll + GitHub Pages,您网站的源文件位于 GitHub 存储库中,该存储库会自动发布到 web 上。基本上,Jekyll 将存储库中的文本文档转换成一个网站,然后该网站由 GitHub 托管。你唯一要担心的是写文章和编辑一些文本文件,让事情看起来像你想要的那样。正如杰基尔设计理念所述:

Jekyll 不会妨碍你,让你专注于真正重要的事情:你的内容。

你可以按照 GitHub 上的这个指南建立一个新的空白网站。然而,如果你想尽快制作一个简单的博客,一个更好的选择是 fork(GitHub 术语,意思是复制)Jekyll Now 资源库,它已经构建了一个博客布局并准备发布。

分叉后,进入你的账户下的存储库设置,把名字改成username.github.io

Fork the Jekyll Now repository and change the name to username.github.io

几分钟后,您就可以在浏览器中导航到 username.github.io,并看到您的新网站发布在网络上!它还不是真正属于你的,但是你可以通过几个步骤来修复它。

Default Jekyll Now website

通过克隆存储库并在您喜欢的文本编辑器中打开它们,您可以在本地编辑任何网站文件。然后,当你提交并推送你的更改到 GitHub 时,网站会自动更新。然而,我强烈推荐在线散文编辑器,而不是本地编辑。

散文编辑

散文让你更容易看到你所有的文件,快速做出修改,并在你保存后提交和推送到 GitHub。你必须向 GitHub 认证散文,然后才能开始改进你的博客。例如,要开始个性化网站,请编辑_config.yaml文件:

Editing _config.yaml in Prose editor.

点击保存后,可以在线看到这些更改。

Website after making changes to config file.

写博客文章

Jekyll 中的所有博客帖子都是用 Markdown 编写的,这是一种轻量级语言,可以转换成 HTML 或许多其他格式。它非常容易学*,在网络上无处不在,并且提供了很多机会来定制你的文章,这是你在媒体上做不到的。

你网站上的文章位于_posts/文件夹中,当你编辑并保存散文文件时,你可以看到它们出现在你的博客上。遵循命名惯例:date-title.md,你的帖子将自动出现在你的网站上,并正确命名和标注日期。

Editing Markdown document in Prose (left) and post as is appears on website (right).

如果你已经在 Medium 上发布了文章,你可以使用这个 Chrome 扩展或者这个命令行工具将它们转换成 Markdown。转换并不完美,但稍加编辑,你就可以将你的中型作品快速导出到你的博客中。这是我写的一篇关于从现有的媒体文章到降价的文章,解决了我发现的几个问题。

更进一步

你自己的网站的好处是你可以控制事物外观的每个方面,并添加任何你想要的功能。首先在存储库中挖掘文件,并查看 Jekyll 文档。例如,要更改字体和样式,请编辑style.scss文件,要启用帖子评论等功能,请编辑_config.yaml。你甚至可以通过像 Hover 这样的网站域名注册商购买一个自定义域名,并遵循这个指南。

Jekyll 的好处是,如果你只想专注于写作,你可以保留默认设置,这样你就会有一个干净、像样的博客。如果你想做出改变,那么你想走多远就走多远。例如,我在我的关于页面的中添加了一个动态代码编辑器,让它更有趣:

Live coding editing on my about page.

结论

如果你因为担心时间和成本而迟迟不写博客,那么现在是时候开始了。使用 GitHub Pages 和 Jekyll,你可以在五分钟内免费拥有自己的博客!

提醒一下,这些步骤是:

  1. Jekyll Now 存储库转到您的 GitHub 帐户。
  2. 将回购更名为username.github.io。您的网站现已发布。
  3. 散文在线编辑器中对网站文件进行更改,并保存以更新网站。从改变_config.yaml开始,在_posts/添加你的降价帖子。
  4. 通过阅读文档、查看其他网站或尝试,尽可能地扩展/定制网站

对于那些已经拥有中型文章的人来说,这里有一个将它们转移到 Markdown 的指南。如果你不知道,那么这里有一些关于写数据科学项目的帮助。最后,走出去,建立一个属于你自己的网站!

一如既往,我欢迎评论和反馈。可以通过 Twitter @koehrsen_will 或我的个人 GitHub pages 网站 willk.online 找到我。

NPS 客户情感分析的五个实际应用案例

原文:https://towardsdatascience.com/five-practical-use-cases-of-customer-sentiment-analysis-for-nps-a3167ac2caaa?source=collection_archive---------0-----------------------

玛娅·安杰洛曾经说过:

“人们会忘记你说过的话,会忘记你做过的事,但人们永远不会忘记你带给他们的感受。”

麦肯锡最*的一项研究结果表明这对企业意味着什么:在积极的客户体验之后,超过 85%的客户购买了更多。在一次消极的经历之后,超过 70%的人减少了购买。因此,弄错这一点可能会被证明是一项代价高昂的工作。

与其依赖假设,企业如何确切地知道是什么让客户感觉他们正在接受优质服务?

答案在于对客户情绪的深度分析。如果客户关于如何提高指标的反馈没有被战略性地用来做出积极的改变,那么跟踪 NPS ( 净推广者得分)这样的简单指标是毫无意义的,即使与收入有直接的联系。在这篇文章中,我们揭示了客户情绪分析不仅仅是分配一个积极/消极的标签。此外,我们解释了如何深化这一分析,并从结果中实际受益。

NPS 还不够吗?

NPS 等原始指标提供了某种程度的客户情绪意识。然而,研究表明NPS 过于宽泛,遗漏了许多关于顾客感受的有用细节。甚至在调查客户不高兴的具体原因之前,许多诋毁者仍然可以积极地谈论他们所接受的服务的要素。推销者可以详述他们不喜欢的元素,尽管他们整体上喜欢这项服务。

通过更准确地分析情绪,特别是发现人们真正不高兴的事情,你可以更专注于什么会有所不同。一个贬低他人但积极表达的人不太可能告诉全世界他们的问题。热情的人会。

什么是情感分析?

最常见的情感分析指的是给一段文本分配一个度量,该度量详细描述了所述文本是积极的还是消极的。这个度量也被称为极性,因为它返回一个范围从+1(极正)到-1(极负)的一维值。通过使用阈值,可以将评论分成定义好的类别:正面、负面或中性。无论情绪是否受到抑制,分数都需要标准化,以消除人们表达自己的方式的特殊性。

一个算法是如何做到这一点的?最简单的算法使用字典来查找哪个单词或短语表示哪个情感。如果一条短信说“你所需要的是”,它会将其标记为积极的。如果一条短信说“我仍然没有找到我要找的东西”,它就标记为否定。这种字典或基于知识的方法在某种程度上是有效的。然而,使用机器学*的高级算法可以捕捉细微差别。例如,“血腥的”如果用在短语“血腥的优秀”中,实际上可能是一个积极的指示。这些算法从大型数据集学*,这些数据集通常已经由人们根据什么构成积极和消极进行了分级。

使用机器学*的高级算法可以捕捉细微差别,例如“血腥”实际上可能是一个积极的指标,如果用在短语“血腥的优秀”中

使用相同的原理,基于字典和机器学*的方法也可以确定更具体的情绪,如沮丧、愤怒或快乐。

准确性取决于测试数据集与用于开发字典或机器学*模型的数据集的相似程度。如果数据集之间没有什么共同点,那么两者的表现都会很差。

客户情绪分析为什么不一样?

将情感分析应用到客户所说的话上有点困难,原因有两个:他们说了多少,以及他们如何说话。

第一个区别很容易理解:评论和 NPS 评论通常是简短的文本片段。这意味着每段文本在决定其分类时只提供了很少的信息。大多数算法被设计成处理像新闻文章这样的大块文本。他们可能不做顾客评论。

第二,客户写支持票的方式与他们回复调查或给朋友写脸书帖子的方式不同。在支持票的情况下,它们将(希望)更真实,而脸书邮报将是非正式的,不太具体。如果使用相同的分析,那么分配给每个人的情感将会不太准确。重要的是使分析适合于介质。

为什么顾客情绪的各个方面很重要?

客户情绪本身并不总是有用的,因为它并没有描述为什么客户会有这种感觉。客户对什么特别满意或不满意?为了找到答案,企业需要识别顾客评论的方面。例如,在酒店中,这些方面可能是“客户服务”、“房间大小”或“清洁度”。

如何在代码框架中使用方面和情感分析类别的示例

更深入的分析也能发现具体的反复出现的主题。比如‘早餐面包不够’或者‘客房服务太慢’。这些很重要,因为它们更容易理解和执行。确定这些主题是可操作的洞察力的圣杯。它将有针对性地有效改善客户服务。

方面和主题提取的困难在于识别人们可能引用同一事物的许多不同方式。例如,当谈到“酒店房间的清洁度”时,顾客可能会使用“干净”、“整洁”、“肮脏”、“满是灰尘”等词语,以及“看起来像垃圾场”、“可以在地板上吃东西”等短语。一个有效的客户情绪分析练*不仅要捕捉情绪,还要捕捉企业收到的每条客户反馈的各个方面和主题。

客户情绪分析有哪些用例?

你对收集情感感兴趣,你能用它做什么?这里有 5 个用例,将增强您的客户体验战略。

Google Shopping 使用的一个示例界面,用于显示客户评论中各方面的观点。

1.以个人为目标来改善他们的服务

通过抓住对你的产品或服务有强烈负面感觉的客户,客户服务可以有针对性地处理他们的问题。想象一下一个顾客留下了一个负面评价 -0.95 的愤怒。无论是通过个人接触还是通过优先处理他们的票证,行动都有助于缓和局势。如果 Dick 's Sporting Goods 能够识别那些在退货过程中真正有问题的人,他们就能确保客户服务优先考虑他们。

2.随着时间的推移跟踪客户情绪

跟踪与业务特定方面相关的客户情绪比只跟踪 NPS 更有效。分析可以解释为什么 NPS 评分发生了变化;或者如果分数没变,可能在哪些方面发生了变化。在上面的迪克体育用品的例子中,值得跟踪的具体方面是“客户服务”和“退货政策”。

3.确定特定的客户群是否对你的公司有更强烈的感觉

当与人口统计和其他定量数据配对时,就有可能细分客户群并孤立地观察他们的情绪。例如,消费较少的顾客感觉更消极(因此这是他们增加消费的障碍)还是退货政策问题来自迈阿密的顾客而不是纽约的顾客?

4.跟踪产品或服务的变化如何影响客户的感受

随着业务的变化,客户情绪也在变化。发布营销活动或新闻稿,改变产品的界面或价格结构都会产生影响。跟踪客户情绪可以衡量这一点。

分数的变化可以表明变化是否在情感上引起了客户的共鸣并且是成功的。跟踪情绪会帮助你迅速改正任何错误。

如果你知道每个回应的方面和主题,你也可以回答这样的问题:人们对产品价格上涨的负面反应持续了多久,或者他们真的喜欢增加的新功能吗?如果迪克体育用品公司推出一项以竞争性价格为重点的活动,他们会清楚地看到人们是否反应良好。

5.确定你的关键推动者和诋毁者

客户可能会对你业务的许多方面发表评论,但是哪些方面会影响你的 NPS 分数呢?一点点数据科学会帮你回答这个问题。通过将方面与促进者和贬低者相关联,可以显示哪一个对原始 NPS 分数的影响更大。

深信不疑?以下是你可以开始的方法

希望现在,你已经在问如何将情感分析应用到你自己的客户反馈中。第一件也是最重要的事情是收集数据。虽然有很多公司专门收集客户反馈,但即使是像通过调查猴子进行调查或使用 Zendesk 等客户服务软件的内置功能这样简单的事情也能产生大量有趣的数据。

接下来是分析:为每个评论分配情感分数并确定关键方面。您可以通过手动阅读和编码评论,或者通过使用专注于客户情绪分析的软件或产品来实现这一点。

最后,使用分析结果来实施我们关于如何改善客户体验的五条建议。仪表板和报告可用于将这些新信息呈现给需要查看的人。

posted @ 2024-10-13 15:18  绝不原创的飞龙  阅读(302)  评论(0)    收藏  举报