评估机器学习模型性能的各种方法
因为找准了还不够。
在这篇博客中,我们将讨论检查我们的机器学习或深度学习模型的性能的各种方法,以及为什么要使用其中一种来代替另一种。我们将讨论以下术语:
- 混淆矩阵
- 准确(性)
- 精确
- 回忆
- 特征
- F1 分数
- 精确回忆或 PR 曲线
- ROC ( R 接收者 O 操作者 C 特征)曲线
- PR 对 ROC 曲线。
为了简单起见,我们将主要讨论二进制分类问题,比如说我们必须找到一张图片是猫还是狗。或者患者患有癌症(阳性)或被发现健康(阴性)。需要明确的一些常见术语有:
真阳性(TP) :预测阳性和实际阳性。
假阳性(FP) :预测为阳性,实际为阴性。
真否定(TN) :预测否定,实际否定。
假阴性(FN) :预测阴性,实际阳性。
所以让我们开始吧!
混淆矩阵
它只是上述参数的一个矩阵形式的表示。更好的可视化总是好的:)
精度
判断一个模型最常用的指标,实际上并不是一个明确的性能指标。当阶级不平衡时,情况会变得更糟。
以癌症检测模型为例。实际上患癌症的几率非常低。假设 100 个病人中,90 个没有患癌症,剩下的 10 个实际上患了癌症。我们不想错过一个患有癌症但未被发现的患者(假阴性)。检测每个人是否患有癌症的准确率高达 90%。这个模型在这里什么也没做,只是给出了所有 100 个预测中没有癌症。
我们当然需要更好的选择。
精度
阳性实例占 总预测阳性 实例的百分比。这里的分母是从整个给定数据集得到的正的模型预测。把它当成是找出’模型说对了有多少是对的’。
召回/灵敏度/真阳性率
阳性实例占 总实际阳性 实例的百分比。因此,分母( TP + FN) 这里是数据集中存在的阳性实例的实际数量。把它当作找出’当显示正确的时候,模型错过了多少额外的正确的。
特异性
中的负实例占总实际负 实例的百分比。因此,分母( TN + FP) 这里是数据集中存在的否定实例的实际数量。它类似于回忆,但转移是在否定的情况下。比如找出有多少健康的患者没有患癌症,并被告知他们没有患癌症。这是一种衡量等级的方法。
F1 得分
它是精度和召回率的调和平均值。这需要两者的贡献,所以 F1 分数越高越好。请注意,由于分子中的乘积,如果一个值变低,最终的 F1 分数会显著下降。因此,如果正面预测实际上是正面的(精确度),并且没有错过正面而预测它们是负面的(回忆),那么模型在 F1 分数中表现良好。
一个缺点是,精确度和召回率同等重要,根据我们的应用,我们可能需要一个比另一个高,F1 分数可能不是它的精确度量。因此,加权 F1 分数或查看 PR 或 ROC 曲线会有所帮助。
PR 曲线
*是各种阈值下的精度和召回率之间的曲线。*在下图中,我们有 6 个预测值,显示了它们在不同阈值下各自的精度-召回曲线。图的右上部分是我们获得高精度和召回率的理想空间。基于我们的应用,我们可以选择预测值和阈值。PR AUC 就是曲线下的面积。其数值越高越好。
ROC 曲线
ROC 代表接收机工作特性,该图是针对不同阈值的 TPR 和 FPR 绘制的。随着 TPR 增加,FPR 也增加。正如您在第一张图中看到的,我们有四个类别,我们希望阈值使我们更接近左上角。在给定的数据集上比较不同的预测值(这里是 3 个)也变得很容易,如图 2 所示,可以根据手边的应用选择阈值。ROC AUC 就是曲线下的面积,它的数值越高越好。
PR 对 ROC 曲线
这两个指标被广泛用于判断一个模型的性能。
用 PR 还是 ROC 哪个?
答案在于真正的否定。
由于精确召回方程中没有 TN,它们在不平衡类中很有用。在阶级不平衡的情况下,当消极的阶级占多数时。该度量标准没有太多地考虑占多数的否定类别的大量真实否定,从而对不平衡提供了更好的抵抗力。当阳性类别的检测非常重要时,这是很重要的。
我喜欢检测癌症患者,这有很高的不平衡,因为在所有被诊断的患者中很少有人患有癌症。我们当然不希望漏掉一个未被发现的癌症患者(回忆),并确保被发现的人患有癌症(精确)。
由于考虑到 TN 或 ROC 方程中的负类,当这两类对我们都重要时,这是有用的。像猫狗的探测。真实否定的重要性确保了两个类都被赋予了重要性,就像 CNN 模型在确定图像是猫还是狗时的输出一样。
结论
要使用的评估标准在很大程度上取决于手头的任务。很长一段时间,准确性是我使用的唯一衡量标准,这确实是一个模糊的选项。我希望这篇博客对你有用。那都是我这边的。随时建议改正和改进。
机器学习中的矢量化实现
介绍
在机器学习领域,高级玩家需要编写自己的成本函数或优化算法来实现更定制的模型,而不仅仅是使用现有的机器学习库。为了充分利用当今计算机的计算能力,算法实现的现有技术是对所有计算进行矢量化。这允许您实现并行计算,例如充分利用 GPU 的处理器。本文介绍了机器学习矢量化的实现。本帖使用的所有代码都可以在我的 github 中找到。
先决条件:Numpy 数组
我们将在 numpy array 的矢量化过程中使用的最重要的工具。注意,我们不使用 numpy 矩阵,因为 numpy 矩阵是严格的二维矩阵。实际上,numpy 矩阵是 numpy 数组的子集。因此,为了方便起见,我们总是使用 numpy 数组。这里回顾一下 numpy 数组算法,以便更好地理解后面的内容。下面是如何定义 numpy 数组:
# import numpy
import numpy as np# define two numpy arrays
a = np.array([[1,2],[3,4]])
b = np.array([[1,1],[1,1]])print(a)
>>> array([[1, 2],
[3, 4]])
print(b)
>>> array([[1, 1],
[1, 1]])
Numpy 数组加法
# addition
print(a + b)>>> array([[2, 3],
[4, 5]])
Numpy 数组减法
# substraction
print(a - b)>>> array([[0, 1],
[2, 3]])
Numpy 数组乘法
注意,如果直接使用’ * ‘乘法,这不同于称为点积矩阵乘法。两个数组之间的’ * '操作只是将相同位置的元素相乘。
# multiplication:
print(a * b)>>> array([[1, 2],
[3, 4]])
Numpy 数组点积
我们使用 numpy 的点函数来实现矩阵乘法。一个如此方便的方法是通过使用**“@”符号**,它以完全相同的方式工作。
# matrix multiplication
print(np.dot(a,b))>>> array([[1, 2],
[3, 4]])# matrix product alternative
print(a@b)>>> array([[3, 3],
[7, 7]])
Numpy 数组维数
这里我们展示了两个例子,展示了 dimension 如何在 numpy 数组中工作。请注意,在第一种情况下,它是一个一行三列的数组,而在第二种情况下,它是一个三行一列的数组。
# numpy array with one row
a = np.array([1,2,3])
print(a.shape)>>> (3,)# numpy array with three rows
b = np.array([[1],[2],[3]])
print(b.shape)>>> (3, 1)
Numpy 数组索引和切片
对于 2D numpy 数组,当我们在表示为 A 的数组中切片一个元素时,我们可以使用 A[i,j],其中 I 是行索引,j 是列索引。如果想选择一整行 I,使用 A[i,:],类似地对于选择一整列 j 使用 A[:,j]。
# Define an 3x3 2d array
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(a)>>> array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])# select first element in the array
print(a[0,0])>>> 1# select first row of the array
print(a[0,:])>>> array([1, 2, 3])# select second coulumn of the array
print(a[:,1])>>> array([2, 5, 8])
先决条件:线性回归成本函数
在这一节中,我们将回顾线性回归的一些概念及其数学表达式。由于我们需要使用这些公式来实现梯度下降算法,在下一节,看看如何实现矢量化。
线性回归的假设定义为:
线性回归的成本函数定义为:
成本函数对每个θ的导数定义为:
在梯度下降的每次迭代中,我们使用以下等式更新所有θ:
资料组
我们使用的数据集是来自 UCI 机器学习资源库的“波士顿住宅”。它使用了房屋面积大小、建造年份等特征。来预测波士顿地区的房价。数据如下所示:
我们的数据集有 506 个条目,我们将其表示为条目数 m。特征数 n=14,包括我们初始化为全 1 的截取特征。见下文:
# Insert X0 Column
Xd = df.drop(columns=['MEDV'])
Xd.insert(0, 'X0', 1)
Xd.head()
# numpy array format
X = Xd.values
y = df.MEDV.values# sample size
m = len(df.index)
print(m)>>> 506# number of features
n = X.shape[1]
print(n)>>> 14
对于循环垂直向量化
在本节中,我们通过对线性回归应用梯度下降算法,对 for 循环和矢量化方法进行逐步比较。我们在线性回归部分比较了每个公式实现的运行时间。
我们将所有 thetas 初始化为 1:
# Initialize theta
theta = np.ones(n)print(theta)
>>> array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
假设实现:For 循环
为了实现线性回归的假设功能,如果我们使用 for 循环,可以使用下面的代码来实现:
# hypothesis for the first sample
hypo = 0
for j in range(n):
hypo += theta[j]*X[0,j]
为了获得每个样本的假设,我们需要一个列表来存储它,并需要另一个 for 循环来迭代所有样本:
%%time
# hypothesis for all the samples
all_hypo = []
for i in range(m):
hypo_i = 0
for j in range(n):
hypo_i += theta[j]*X[i,j]
all_hypo.append(hypo_i)>>> Wall time: 4 ms
我们可以看到运行时间是 4 ms,这并不太疯狂,因为这个实现足够简单,数据集也很小。
结果显示为:
假设实现:矢量化
每个样本的假设可以使用以下公式进行矢量化:
为了实现将所有样本作为一个列表的假设,我们使用下面的数组点积:
代码实现非常简单明了:
%%time
# matrix format
hypo = X@theta>>> Wall time: 0 ns
我们可以发现,它只需要很少的时间来计算,甚至可以不显示。计算结果如下所示。与 for 循环结果相比,我们可以看到我们获得了完全相同的结果。
成本函数实施:For 循环
基于我们从假设中获得的结果,我们需要另一个循环来迭代所有样本以计算成本函数。
%%time
# cost function
cost = 0
for i in range(m):
hypo_i = 0
for j in range(n):
hypo_i += theta[j]*X[i,j]
cost_i = (hypo_i - y[i])**2
cost += cost_i
cost = (1/(2*m))*cost>>> Wall time: 4 ms
运行时间为 4 ms,结果显示如下:
print(cost)>>> 1.399752908228425
成本函数实现:矢量化
基于假设的矢量化,我们可以很容易地将成本函数矢量化为:
代码实现仍然非常简洁:
%%time
# cost function
cost = (1/(2*m))*np.transpose((X@theta - y))@(X@theta - y)>>> Wall time: 0 ns
同样,这种矢量化计算是即时的。计算结果与 for 循环结果相同:
print(cost)>>> 1.3997529082284244
派生实现:For 循环
计算成本函数对指定θ的导数,编码如下:
dev_sum = 0
for i in range(m):
hypo_i = 0
for j in range(n):
hypo_i += theta[j]*X[i,j]
dev_i = (hypo_i - y[i])*X[i,k]
dev_sum += dev_i
dev_sum = (1/m)*dev_sum
为了计算所有θ的导数并输出一个列表,我们需要另一个 for 循环迭代所有列:
%%time
# derivation
dev_list = []
for k in range(n):
dev_sum = 0
for i in range(m):
hypo_i = 0
for j in range(n):
hypo_i += theta[j]*X[i,j]
dev_i = (hypo_i - y[i])*X[i,k]
dev_sum += dev_i
dev_sum = (1/m)*dev_sum
dev_list.append(dev_sum)>>> Wall time: 47 ms
运行时间为 47 ms,随着循环的增多,for 循环和矢量化的时间成本差异开始变得显著。
for 循环的推导结果是:
print(dev_list)>>> [0.9999999999999983,
0.07814620360307895,
-0.11042922261438312,
0.2620302340552936,
0.05504439083525137,
0.23892542562534522,
-0.06454255823702795,
0.2611634394125097,
-0.1453677181065729,
0.43106386997897883,
0.38303455280215737,
0.16591512402899725,
-0.09920797306076046,
0.1835280968258358]
派生实现:矢量化
关于每个θ的成本函数的推导可以矢量化为:
成本函数对所有θ的推导可矢量化为:
代码实现仍然非常简洁:
%%time
dev = (1/m)*np.transpose(X)@(X@theta - y)>>> Wall time: 999 µs
直接比较是 999μs vs . s . 47 ms,以下是矢量化计算结果:
print(dev)array([ 1\. , 0.0781462 , -0.11042922, 0.26203023, 0.05504439, 0.23892543, -0.06454256, 0.26116344, -0.14536772, 0.43106387, 0.38303455, 0.16591512, -0.09920797, 0.1835281 ])
两种方法的结果也是一样的。
将一切放在一起:优化
在本节中,我们使用我们之前开发的所有实现,并编写一个梯度下降迭代来比较这两种方法。
梯度下降:用于循环
为了获得下降优化结果,我们将迭代次数设置为 10 万次。为了实现梯度下降算法,我们需要嵌套四个 for 循环。学习率被设置为 0.0005,θ被初始化为全 1。代码如下所示:
%%time
a = 0.0005
theta = np.ones(n)cost_list = []for itr in range(100000):
dev_list = []
for k in range(n):
dev_sum = 0
for i in range(m):
hypo_i = 0
for j in range(n):
hypo_i += theta[j]*X[i,j]
dev_i = (hypo_i - y[i])*X[i,k]
dev_sum += dev_i
dev_sum = (1/m)*dev_sumdev_list.append(dev_sum)
theta = theta - a*np.array(dev_list)
cost_val = cost_loop(theta)
cost_list.append(cost_val)>>> Wall time: 1h 15min 58s
总运行时间为 1 小时 15 分钟。以下是我们获得的最小成本。我们还提供了一个曲线图,显示了成本函数相对于迭代的变化。
print(cost_val)>>> 0.017663350184258856
梯度下降:矢量化
矢量化梯度下降的实现非常干净优雅。
%%time
a = 0.0005
theta = np.ones(n)cost_list = []for i in range(100000):
theta = theta - a*(1/m)*np.transpose(X)@(X@theta - y)
cost_val = cost(theta)
cost_list.append(cost_val)>>> Wall time: 1.75 s
矢量化方法具有如下最小成本函数值。同样,提供了关于迭代的成本变化:
print(cost_val)>>> 0.017663350184258835
我们可以看到两种方法的最小成本值几乎完全相同。但是使用矢量化的算法实现时间为 1.75 秒,而使用 for 循环的算法实现时间为 1 小时 15 分钟。
结论
这里有一个图,显示了实现相同算法并使用完全相同的学习速率和初始θ值的两种方法的运行时间差异。这两种方法达到了同样的精度。然而,矢量化方法花费了 1.75 秒,而 for 循环花费了 4558 秒。矢量化方法比 for 循环方法快 2600 倍。
矢量化方法的时间复杂度为 O(s),其中 s 为迭代次数。相比之下,for 循环方法的时间复杂度为 O(snm*n),其中 s 是迭代次数,m 是数据集样本数,n 是数据集特征数。在这种情况下,我们的数据集足够小,m=506,n=14,但是我们观察到时间复杂度的巨大差异。为大数据成像,这种差异会有多大。由于 noway 的计算机和 GPU 是由成千上万个“核心”组成的,我们甚至可以有多个 GPU 或使用一个计算机集群,我们需要充分利用这些计算能力。方法是通过并行计算实现你的算法。因此,在我们的机器学习算法中使用矢量化是提升算法并节省大量训练时间的关键。矢量化是我们需要考虑的一个很好的方法,值得花时间去研究。
栅格向多边形的矢量化
如果有免费的库,我绝不会开始写任何矢量化代码。
然而,最近我作为技术负责人参与了一个与几何和光栅矢量化相关的有趣项目。我需要计算各种形状的复杂投影。我从一个“干净”的数学解决方案开始,很快以大量与多边形三角剖分相关的计算结束——O(log n!).我花了一周的时间才发现自己真的遇到了麻烦——在真实的场景中,这个过程只持续了几分钟。然后,我决定将我们的目光转向离散化(正如在开始时声明的那样),我做了这项工作,并得到了矩阵形式的结果。那天是星期五,结果需要在下周一公布。但是以向量的形式。
我在 R 包中搜索光栅矢量化,发现T5包,因为函数 rasterToPolygons 看起来不错,我们认为它可能为多边形产生了太多的点。因为没有必要的 R 包,所以我需要创建自己的。嗯,仍然有半个周末,我们做了一些 C++编码,并创建了这个函数,它一步就完成了工作。
这是带有飞地和不允许飞地的选项的初始位图,结果如下:
来自火山数据集的示例:
library(fasteraster);
library(datasets);
inp = volcano; res = raster2vector(volcano, 120, 200, 20); image(inp, col = rev(grey.colors(100)), useRaster = TRUE)
plot(0, type = "l", xlim = c(0, nrow(inp)), ylim = c(0, ncol(inp))) a = lapply(res, function(x) lines(rbind(x, x[1,])))
生产:
你可以在这里找到源码包:faster raster _ 1 . 0 . 4 . tar和 Linux 64 二进制:faster raster _ 1 . 0 . 4 _ R _ x86 _ 64-PC-Linux-GNU . tar新鲜版本权自克兰:https://cran.r-project.org/package=fasteraster
附言(同 postscript);警官(police sergeant)
对于个人问题,请在 Linkedin 或脸书联系我,有时我会在那里发布一些关于人工智能的简短新闻和想法。如果你在人工智能方面有需求,或者你需要建立一个数据科学咨询团队,请联系我
反向传播的矢量化实现
在之前的帖子中,我们解释了反向传播背后的基本原理以及神经网络是如何工作的。在本帖中,我们将解释如何利用优化的数学库来加速学习过程。
“向量化”(简化)是重写一个循环的过程,这样它不是处理数组的单个元素 N 次,而是同时处理数组的几个或所有的元素**。**
让我们从一个数据集的例子开始,这个数据集在一个特定的城市出售了 1000 套房子。对于每栋房子,我们有 5 个信息:它的面积,房间数量,建造年份,支付的价格和代理费。目标是训练一个模型,根据前 3 个特征预测价格和代理费。
Dataset example
让我们考虑一个简单的线性前馈模型,具有 6 个权重(W11,W12,W13,W21,W22,W23),其中:
- 价格= W11。面积+ W12。NbRooms + W13。年
- 费用= W21。面积+ W22。NbRooms + W23。年
正如前面更详细解释的那样,机器学习的目标是找到这 6 个权重的哪个值最符合最接近数据集真实输出的模型输出。我们从随机初始化权重开始。然后,我们向前传播以计算预测价格和代理费。通过将结果与来自数据集的真实价格和费用进行比较,我们可以获得误差的梯度,以便稍后反向传播,并相应地更新权重。
一个简单的实现如下所示:
https://gist . github . com/Assad/EC 33987 c 6273293 af 2f 648572 fa 85 a3d
然而,数据集上的这种顺序 for 循环太慢,并且没有利用 CPU 和 GPU 中的现代并行性。
为了获得高性能,我们需要将数据集转换成矩阵表示。如果我们采用基于列的表示,来自数据集的每个输入都被复制到矩阵中的一列。
- 我们的权重矩阵将是一个 2 行 x 3 列的矩阵。
- 我们的输入矩阵将是一个 3 行 x 1000 列的矩阵。
- 我们的输出矩阵将是一个 2 行 x 1000 列的矩阵。
我们正在寻求解决的线性模型可以用以下基于矩阵的形式表示:
Matrix or a vectorized-form of: Weights x Inputs = Outputs
这种表示起作用的原因是因为这正是矩阵乘法的运行方式:
Matrix multiplication
Matrix-multiplication: a row i of the first matrix is multiplied by a column j of the second matrix to calculate the value of the cell (i , j) of the output
有了矢量化实现,以前需要 1000 次迭代的 for 循环现在只需很少的高性能矢量化运算即可完成,如下所示:
Predictions = Matrix.Multiply(Weights, Inputs)
Error = Matrix.Substract(Predictions, Outputs)
在大数据集上,使用 GPU(有些有 1000 个内核),我们可以期待在**数千倍的加速!**在 CPU 上,有很多实现高性能矩阵运算的高级数学库,比如 openBLAS 。
向量化前向传播简单明了,它遵循模型定义。挑战在于误差反向传播的矢量化。
- 有了数字,如果我们通过一个函数 f 传递一个数字 x 得到y = f(x)****f的导数f’给我们 y 的变化率,当 x 变化。
- 对于矩阵,我们需要使用 雅可比矩阵 ,这是一个由关于输入矩阵的不同元素的偏导数组成的矩阵。
背后的理由是固定输入矩阵中的所有元素**,除了一个元素**,其中我们向其添加一个小增量 𝛿 ,并查看输出矩阵中的哪些元素受到影响,影响到哪个比率,并将它们相加在一起。我们对输入矩阵的所有元素都这样做,我们在输入端得到它的梯度矩阵。因此它具有相同的形状(行数和列数)。
考虑下面的矩阵运算。RxP=S,(以及计算输出 S 的前 3 个元素的前 3 个等式)
等式 1: s11 = r11.p11 + r12.p21 + r13.p31(红色输出)
等式 2: s12 = r11.p12 + r12.p22 + r13.p32(绿色输出)
等式 3: s21 = r21.p11 + r22.p21 + r23.p31(黄色输出)
假设我们在输出 S 处已经有了梯度矩阵δS,我们想将其反向传播到输入 R (分别为 P )以计算δR(分别为。δP)。由于 r11 只参与 s11 和 s12 的计算(红绿不黄),我们可以预计只有 𝛿s11 和 𝛿s12 反向传播到 𝛿r11 。
- 为了找到 𝛿s11 的反向传播的速率,我们相对于 r11 对等式 1 进行部分求导(并认为其他一切为常数),我们得到 p11 的速率(另一种解释方式:在 r11 中的小变化,将被 s11 中的 p11 因子放大)。
- 通过对 𝛿s12 和等式 2 做同样的事情,我们得到 p12 的速率。
- 如果我们试图将 𝛿s13 反向传播到 r11 ,并且相对于 r11 推导等式 3,我们得到 0,因为等式 3 根本不依赖于 **r11。**另一种理解方式:如果我们有一个错误或 s21,在 r11 上无法做任何事情来减少这个错误。由于 r11 不参与 s21 的计算!这同样适用于 S 矩阵的所有其他元素(s21、s22、s31、s32)。
- 最后,加起来,我们得到 𝛿r11=𝛿s11.p11 + 𝛿s12.p12
通过对矩阵 R 的所有元素做同样的处理,我们得到如下结果:
- 𝛿r11=𝛿s11.p11 + 𝛿s12.p12
- 𝛿r12=𝛿s11.p21 + 𝛿s12.p22
- 𝛿r13=𝛿s11.p31 + 𝛿s12.p32
- 𝛿r21=𝛿s21.p11 + 𝛿s22.p12
- 𝛿r22=𝛿s21.p21 + 𝛿s22.p22
- 𝛿r23=𝛿s21.p31 + 𝛿s22.p32
- 𝛿r31=𝛿s31.p11 + 𝛿s32.p12
- 𝛿r32=𝛿s31.p21 + 𝛿s32.p22
- 𝛿r33=𝛿s31.p31 + 𝛿s32.p32
如果我们仔细观察该模式,我们会发现我们可以将其转化为矢量化矩阵乘法,如下所示:
**ΔR = ΔS x Transpose(P)**
类似地,如果我们按照相同的过程反向传播到 P,我们得到下面的等式:
**ΔP = Transpose(R) x ΔS**
每个神经网络层由几个数学运算组成。如果我们设法在向前和向后传递中用矩阵运算来定义每个数学运算,我们在学习中得到最大加速。
在第一步中,每个矩阵 M 必须被一个伴随矩阵δM增加,以在返回的路上保持其梯度。
第二步,每个矩阵运算都必须定义自己的向前和向后运算。例如:
在创建了这个数学运算的矢量化库之后,我们可以使用这个库来链接运算,并创建层、激活函数、损失函数、优化器。反向传播将被自动定义为每层中使用的数学函数的回调栈(或计算图)。这就是 Tensorflow 在一定程度上的工作原理。
我们可以将完整的机器学习过程视为一堆抽象的**😗*
An abstraction of machine learning library stack
原载于 2018 年 6 月 1 日【medium.com】。
矢量让你看到 3D 眼镜看不到的东西?
警告:我假设你知道矢量是什么。如果没有,请在评论区告诉我,我会尽力另发一篇帖子。原因是,你要么知道向量,要么不知道。句号。因此,至少 500 字的解释是必须的,根据我的资格是一个单独的职位。
在之前一篇关于降维的文章中,我谈到了降维将如何帮助我们快速得出一些结论。我也提到过,我们将在后面的文章中讨论数学,现在我们来谈谈向量!是的,向量在降维方面很有用:)。事实证明,线性代数在研究像 PCA、SVD 等机器学习技术时非常有用。如果您对这些术语不熟悉,可以将线性代数视为删除不需要的数据、压缩图像、检测图像边缘等的有用工具。我打算很快就这些话题进行写作,并承诺让它们变得更简单。
如果你没有看过我之前的帖子,你可以查看这里的。虽然这不是理解这篇文章的先决条件,但在着色之前,你会先画一个草图。有些人喜欢直接着色!;)
让我们先熟悉一些术语,如跨度、线性组合等。
你可以在下面看到一个向量的跨度。在我们的例子中,两个向量(v⃗和 w⃗)的“跨度”只不过是 v⃗和 w⃗的线性组合的表示,也就是说,你将 v⃗和 w⃗组合起来,得到一个合成向量 x⃗.
I know that’s confusing!
因此,简单地说,跨越就是将按比例缩放的向量相加,产生一个覆盖高维空间的合成向量。看下面的 gif 图片来理解我的意思。
缩放矢量??只是乘以标量,结果向量要么压缩要么拉伸!
因此,矢量 v⃗在大小为“a”的方向上移动,而另一个矢量 w⃗在与 v⃗正交的另一个方向上作用,大小为“b”。所以,通过改变大小,你可以看到这两个向量可以覆盖几乎所有的空间!这也叫向量空间。这些标量在特定的方向上拉伸或挤压矢量。
看下面的 gif 图片,看看整个矢量空间被缩放矢量覆盖的结果。请记住,这里我们有两个维度。想象一架飞机在 3D 情况下被覆盖。我不知道你如何形象化(几何)4D 等等;).然而,事实证明这些向量可以帮助我们处理几何学限制的更高维度。我们将在后面的文章中看到这是如何发生的。
这就是多个向量的线性组合是如何容易地被想出来的。
一个例子应该让我们清楚地记住这一点。我们试图说,上面的‘a’和‘b’的任何组合都会把我们带到向量 av⃗ + bw⃗.
比方说,
使用 v⃗和 w⃗的线性组合的最终向量是 x⃗,其中
向量的值会是什么样子,
上述等式意味着,
这是一个两个未知数的线性系统,我们有两个方程,因此我们可以得到一个解,即我们可以找到 a 和 b。花一些时间来计算这些值(提示:这很容易!).
上述方程的解是,
现在,让我们说,你想找到得到矢量 x⃗=[0 ^ 6]的线性组合是什么?
答案很简单,方程式是,
因此,代入上述值后,最终方程将为:
现在,这可能看起来没有什么魔力,因为我故意举了一个简单的例子,你可以试着做一些难的,你仍然可以得到答案!
我们可以把这个想法扩展到任何维度,我把它作为家庭作业留给你们。但是,让我给你一点提示,看看这个等式在 3D 的情况下会是什么样子。
让我们来看一个向量的 3D 演示。为了直观地理解,红色向量在 x、y、z 方向上分别移动了 5 个单位、8 个单位、3 个单位。
a=5, b=8, c=3 in the x, y, z axis respectively.
我希望这能让事情变得简单,并帮助你思考更高的维度!
这就是这篇文章的内容。尽管对这些方程大谈特谈,我还是要证明这些向量在机器学习中的用处。我们将在随后的帖子中涉及更多关于向量的主题,并最终将所有的点连接起来,以显示线性代数对于机器学习是多么有用!
下次见,机器学习快乐!😃
车辆检测和距离估计
Udacity SDCND
开车时,要做两件非常重要的事情:a)保持在你的车道上 b)避开其他车辆。为此,我们需要知道车道在哪里,其他车在哪里。自动驾驶汽车也是如此,因此 Udacity 的家伙们决定,自动驾驶汽车 Nannodegree 的最后两个项目。在我以前的帖子中,我已经谈到了如何找到车道线,并使其对光线变化和噪声具有鲁棒性。这篇文章解决了在图像上找到车辆并估计它离我们的车的距离的问题。
该项目的目标/步骤如下:
- 提取用于分类的特征
- 构建和训练分类器
- 滑动车窗,在图像上识别汽车
- 过滤掉假阳性
- 计算距离
- 在视频上运行管道
这里用到了《高级寻巷》中的一些部分,所以如果你对更深入的描述感兴趣,你可以在这里阅读我之前的帖子。
所有的代码和训练数据都可以在 这个 Github 库 中找到
汽车分类器
我们需要做的第一件事是创建一个分类器来区分汽车和非汽车。为此需要数据集,我已经使用了 Udacity 提供的数据集。(下载:车辆、非车辆)。该数据集是 KITTI vision 基准套件和 GTI 车辆图像数据库的组合。GTI 汽车图像分为远、左、右、中近。汽车和非汽车的例子如下:
Car images from left to right: 1)KITTI, 2)GTI Far 3)GTI Near 4)GTI Left 5)GTI Right
Non-car images
要建立一个分类器,首先必须识别特征。将要使用的特征是直方图、全图像和 HOG-s 的混合。
提取特征
彩色空间
在颜色编码的意义上,颜色空间与图像的表示有关。有些编码更适合一种用途,但不适合其他用途。例如,从硬件的角度来看,RBG 很好,因为它是如何捕捉和显示像素的( Bayer filter 就是一个很好的例子),但它没有捕捉人类感知颜色的方式,而这对于分类任务很重要。对于汽车分类的任务,我确信没有一个规定的颜色空间是最好的。所以只能通过试错来选择。我所做的是,我已经建立了分类器,基于 HOG、颜色直方图和完整图像,然后改变颜色空间,直到我在测试集上获得最佳分类结果。也许我是从上到下描述问题,但是颜色空间对于解释和可视化特征是非常重要的。经过一番试用,我发现 LUV 色彩空间效果最好。它具有发光分量 L,以及两个( u 和 v )色度分量。该颜色空间始终给出更好的分类结果。
作为特征的子采样和归一化图像
第一个也是最简单的特征是二次抽样图像。再次,通过尝试和检查分类结果,二次抽样图像的大小被选择为 20×20。此外,图像是伽玛标准化。这是在观看 YouTube解释猪的视频时产生的想法。据说,对图像求平方根可以使其标准化,并获得均匀的亮度,从而减少阴影的影响。我试了一下,它在分类上有了微小的改进。因为这是一个非常简单的操作,所以它保留在我的代码中,因为它提供了额外的健壮性。在归一化和二次采样之后,图像被整形为矢量而不是矩阵。原始图像归一化转换成 LUV 的有:
**
Car images from left to right: 1) Original 2) Normalized 3) LUV color space**
颜色直方图
第二组特征是颜色直方图。最初,我试图只使用发光通道 L 的直方图。汽车可以有不同的颜色,所以省略色度通道对我来说是一个自然的选择。经过一些测试后,我发现包括所有三个颜色通道的直方图提高了几个百分点的测试精度,这可以产生很大的差异。基于测试精度选择直方图中的仓数量,128 个仓产生最佳结果。以下是之前显示的图像的直方图示例:
Histograms of all three channels
猪
最后,但可能是最重要的特征是梯度方向直方图——HOG。围绕 HOG 的主要思想是基于使用一些边缘检测器计算的每个像素的方向来计算直方图。边缘上的像素比边缘上的像素对直方图的贡献大得多。图像被分成多个单元,并且对于每个单元,方向被分箱。所以猪基本上显示了每个细胞的主导方向。你可以在这个 YouTube 视频中找到关于这头猪的详细信息。计算凸起的图像大小为 64x64。每个单元的像素数量是 8,而每个块的单元数量是 1。方向的数量是 12。HOG 是在归一化图像的所有三个通道上计算的。我对这些参数进行了大量测试,最终发现这是最佳选择。我在选择时考虑的是以这种方式生成的特征的数量以及在测试集上获得的准确性。当使用这组参数时,每个通道总共创建了 768 个特征。如果每个块的单元数增加到 2,则每个通道的特征数会增加到 2352。当每块使用 2 个单元时,分类精度的提高并不显著,所以我选择每块使用 1 个单元。此外,我还尝试了增加每个单元的像素数,在这种情况下,大量信息会丢失,精度会下降,而降低每个单元的像素数会增加特征的数量。每个通道的图像可视化 HOG 为:
HOG of a car
HOG of a non-car
训练分类器
使用的分类器是线性支持向量分类器。数据集是通过遍历车辆和非车辆的图像并计算这些图像的特征而获得的。接下来要做的是缩放特征,这对任何机器学习算法都非常重要。之后,数据集被分成训练集和测试集,其中测试集占所有数据的 10%。使用 C=1e-4 训练分类器,其中该特征是基于训练和测试集的精度选择的。如果两个精度之间的差异很大,则训练过拟合数据,因此降低了 C 。当测试精度较低但与训练精度相同时,出现了欠拟合,因此增加了 C 的值。在测试集上获得的最终准确度为 99.55% 。训练完成后,分类器和定标器被酸洗并保存,以便在处理来自摄像机的图像时可以重复使用。
在图像/视频上寻找汽车
在图像和视频中寻找汽车的管道非常相似。事实上,在视频中寻找汽车遵循的是在静态图像中寻找汽车的相同流程,只是增加了一些功能。为此,将首先描述单个图像的流水线。
滑动窗户
首先要做的是在屏幕上滑动窗口,并尝试识别在定义的分类器上产生正面命中的区域。将要滑动的窗口总是大小为 64x64,重叠 75%。在某些情况下,汽车可能大于 64x64 像素,因此为了涵盖这些情况,整个图像被缩小。结果,在原始图像和 5 个缩小的图像上搜索汽车,选择这些图像使得原始图像上的汽车的尺寸为 80×80、96×96、112×112、128×128 和 160×160。对于每个缩小的图像,只计算一次 HOG,如果有汽车,则在测试每个窗户时使用 HOG 的子区域。滑动窗口后,为每个窗口计算的整批特征被分类。这是一个原始图像的例子,2 个搜索汽车的区域和检测到汽车的区域:
****
Search region for cars of dimension from left: 1) 64x64, 2) 160x160 pixels. The dimension of the car is calculated with respect to original image
****
Images from left: 1) Original image 2)image with detected cars
计算热图和识别汽车
由于对同一辆汽车有多次检测,所以必须以某种方式对车窗进行分组。在这种情况下,将使用热图。热图中的每个像素包含包含该像素的已识别汽车的窗口数量。热图中像素的值越高,它越有可能是汽车的一部分。热图的阈值为 1,这消除了任何可能的错误汽车检测。之后,连接的组件被标记,边界框被计算。生成的图像是:
Images from left 1)Heatmap 2)Thresholded 3) Heatmap Labels
道路拆除
这样做的原因是,我们想估计我们前面多远是确定的汽车。在我们之前的项目中,我们发现了透视变换,它将路面映射到图像上,使我们能够测量距离。透视变换假设被变换的物体是平面的,所以为了精确地测量距离,我们需要一个在路面上的点。使用边界框下边缘的中点来测量距离。移除路面,以便对被识别汽车的后轮进行测量。为此,找到边界框的最后 8 行的中间颜色。超过 20%的点远离中间颜色的从底部开始的第一条线被认为是边界框的新的底部边缘。在下图中,颜色为“远”的点用紫色表示。
**
Images from left 1)Original 2)Points near in color 3)Cropped**
估计距离
在检测到的车辆周围的矩形被绘制之前,车道线被识别。另外,我们会试着估计离车的距离。一旦我们获得了边界框及其底边的中点,使用透视变换,我们就可以从高级车道寻找项目中计算出它在扭曲图像上的位置。我们不需要扭曲整个图像,而只需要重新计算扭曲图像上的单个位置。在该图像上,像素位置和以米为单位的距离之间存在直接的相关性,因此计算出的中点位置和图像底部之间的距离乘以每个像素的米数就代表了我们的汽车和我们检测到的汽车之间的距离。通过观察帧与帧之间的距离变化,我们可以计算汽车的相对速度,将两帧之间的差异乘以每秒帧数和 3.6,将其转换为每小时公里数,而不是每秒米数。检测到汽车的图像和测量距离的扭曲图像是:
****
Images from the left 1) Detected cars 2) Warped image
关于透视变换的更多信息,请阅读 我之前的帖子 。
最后一步就是在一张图片上画出所有的东西。最终结果如下所示:
Final result
在视频中寻找汽车
对于视频,管道遵循应用于单个图像的基本管道。此外,由于时间维度,应用了一些额外的过滤。以下是所做的工作:
- 当计算热图时,使用所有已经检测到的汽车的边界框。这些边界框被认为是汽车已经在该地点被识别。这有助于避免已经识别的汽车闪烁和松动。
- 边界框是最后 21 帧的平均值
- 如果在连续 5 帧中没有发现汽车,则它已经消失。新车,需要在 5 个连续的帧中被发现,才能被绘制并被认为是现有的。
管道在提供的视频上运行,效果很好。不会出现错误检测或无法识别现有车辆的情况。视频结果是:
讨论
所描述的管道对所提供的视频非常有效,但需要在变化的照明条件下对更多的视频进行彻底的测试。我发现有趣的是,在项目视频中有一部分,两辆车被归类为一辆。第一辆车部分遮挡了第二辆车,但它仍被归类为一辆车。车没有消失,只是被遮挡了。必须找到关于这个问题的更强有力的程序。
计算到汽车的距离工作得很好,甚至比我预期的还要好。然而,当道路表面的颜色改变时,仍然存在一些问题,从识别的边界框的底部移除道路给出了错误的读数。此外,速度是相当跳动的,所以它也必须被过滤,但即使在这种形式下,它也可以给出检测到的汽车是否正在接近或远离我们的信息。
最后一点就是这个程序非常耗时。平均每次迭代大约需要 1.4 秒(Ubuntu 16.06,2 个英特尔酷睿 i7–4510 u CPU @ 2.00 GHz,8GB DDR3)来检测汽车和车道。它远不是实时的,因此它可以在真正的自动驾驶汽车中使用。通过分析,我注意到大约 50%的时间用于计算直方图。这段代码需要优化,可能需要用 C/C++重写。
车辆检测和跟踪
“只要有摄像头,你绝对可以成为超人”。埃隆·马斯克在 TED 演讲。
这是 Udacity 的自动驾驶汽车工程师纳米学位项目 第一学期的期末项目 。源代码和更详细的技术文章可以在 GitHub**上找到**
目标
编写一个软件管道,从汽车上的前置摄像头识别视频中的车辆。
在我的实现中,我使用了深度学习方法来进行图像识别。具体来说,我利用卷积神经网络(CNN)的非凡能力来识别图像。
然而,手头的任务不仅仅是检测车辆的存在,而是指出它的位置。事实证明,CNN 也适用于这类问题。在 CS231n 课程 中有一个专门针对本地化的 讲座 ,我在我的解决方案中采用的原则基本上反映了该讲座中讨论的区域提议的思想,并在诸如fast R-CNN等架构中实现。
主要思想是,由于存在二进制分类问题(车辆/非车辆),模型可以以这样的方式构建,即它将具有小训练样本的输入大小(例如,64×64)和在顶部的 1×1 的单特征卷积层,其输出可以用作分类的概率值。
训练了这种类型的模型后,输入的宽度和高度维度可以任意扩展,将输出层的维度从 1x1 转换为纵横比近似匹配新的大输入的地图**。**
本质上,这在某种程度上相当于:
- 将新的大输入图像切割成模型初始输入尺寸的正方形(例如,64×64)
- 在每一个方块中探测目标
- 将得到的检测结果拼接回去,将与源输入中的相应正方形相同的顺序保存到一个图中,其边的纵横比近似匹配新的大输入图像的纵横比。
Consider each of these squares to be processed individually by its own dedicated CNN, producing a 4x20 detection map
数据
Udacity 为学生提供了训练分类器的强大资源。 车辆 和 非车辆 已使用KITTI vision benchmark suite的样本进行训练。
最终的模型在检测项目视频中的白色雷克萨斯时遇到了困难,所以我用大约 200 个样本增加了数据集。此外,我使用了与 项目 2 中相同的随机图像增强技术对交通标志进行分类 ,从项目视频中产生了大约 1500 幅车辆图像。用于训练、验证和测试的车辆图像总数约为 7500 张。显然,每个样本都被水平翻转过,使数据集膨胀了 2 倍。结果,我有大约 15000 个数据点。
Class IDs are vehicles and non-vehicles
增加了相同数量的非车辆图像作为反面例子。
Typical vehicle and non-vehicle samples with their corresponding labels
模型
我从Max Ritter的实现中借用了构建网络顶部的技术,他显然采用了相同的方法。
已经测试了许多具有不同复杂性的模型架构,以获得最终的模型。
我开始从 VGG16 架构转移学习,权重在 ImageNet 上训练。VGG 是一个伟大的和经过充分测试的架构,ImageNet weights 显然认为它应该对车辆的功能有所了解。我添加了我的顶级单特征二元分类器并对模型进行了微调。正如所料,它产生了相当高的测试精度,大约为 99,5% 。VGG 的另一面是它相当复杂,使得预测的计算量很大。**
然后,我测试了一些不同层数和形状的定制 CNN 配置,逐步降低复杂性并评估测试精度,最终得到了只有大约 28,000 个可训练参数的模型,测试精度仍然约为 99.4% :
**Epoch 5/5
607/607 [==============================] - 48s - loss: 0.0063 - acc: 0.9923 - val_loss: 0.0073 - val_acc: 0.9926
Evaluating accuracy on test set.
test accuracy: [0.0065823850340600764, 0.99373970345963758]**
将模型的复杂性降低到极致对预测的计算成本和过拟合都有好处。虽然数据集可能看起来不太大,但很难假设 28000 个参数的模型可能能够记住它。此外,我还积极利用辍学来进一步降低过度适应的风险。
该模型已经使用 Keras 和 TensorFlow 后端实现和训练。
样本预测结果:
使用训练好的模型进行车辆检测
视频流中的原始帧如下所示:
严格来说,它不是原创的,因为它已经受到了不失真的影响,但这值得一个属于它自己的故事。对于手头的任务,这是要由车辆检测管道处理的图像。
车辆检测的感兴趣区域从顶部起大约第400个像素开始,垂直跨越大约 260 个像素。因此,我们有一个尺寸为260×1280的感兴趣区域,从垂直方向的第400 个像素开始。
这就把顶层卷积层的维度从(?,1,1,1) 到**(?,25,153,1)** ,其中 25 和 153 是预测的微型图的高度和宽度尺寸,反过来,最终将投影到原始高分辨率图像上。****
车辆扫描流水线包括以下步骤:
- 获取感兴趣的区域(见上文)
2。使用训练好的 CNN 模型生成检测图:
****3。应用置信度阈值生成二值图:
预测非常两极化,即对于车辆和非车辆点大多坚持一和零。因此,即使是置信度阈值的中点 0.5 也可能是一个可靠的选择。为了安全起见,我坚持使用 0 .7
4。用scipy.ndimage.measurements
包的label()
功能标记获得的检测区域。这一步可以勾勒出标注的边界,从而有助于在构建热点图时将每个检测到的“孤岛”保持在其要素标注的边界内。
这也是被检测车辆 的第一近似值。
****5。将检测点的特征标签投影到原始图像的坐标空间,将每个点转换成 64x64 的正方形,并将这些正方形保持在特征的区域边界内。
为了说明这种点到平方的转换投射到原始图像上的结果:
6。创建热图。上图中重叠的方块实际上是在积聚“热量”。
7。再次标记热图,为实际车辆的边界框生成最终的“岛”。这个特定热图的标记创建了 2 个检测“孤岛”。很明显。
8。将热图的标记特征保存到标记列表中,这些特征将被保存一定数量的后续帧。
****9。最后一步是获得车辆的实际边界框。[**OpenCV**](http://opencv.org)
提供了便捷的功能cv2.groupRectangles()
。正如在文档中所说:“它使用矩形等价标准将所有的输入矩形聚类,该标准将具有相似大小和相似位置的矩形组合在一起。”正是需要的。该函数有一个groupThreshold
参数,负责“最小可能矩形数减 1 ”。也就是说,它不会产生任何结果,直到历史积累了至少该数量的帧的边界框。
视频实现
我已经将车辆和车道检测 合并到一个单独的管道中,生成一个包含车道投影和车辆边界框的组合镜头。
反光
我彻底研究了将 SVM 分类器应用于 HOG 特征的方法,该方法涵盖了项目课程,但我仍然非常自信地认为深度学习方法更适合车辆检测任务。在我开始提到的一个讲座中,猪只只从历史的角度来看。此外,还有一篇 论文 认为 DPMs (那些基于 HOGs )可能被认为是某种类型的卷积神经网络。
花了一些时间来弄清楚如何导出一个模型,当扩展它以接受全尺寸感兴趣区域的输入图像时,该模型将产生可靠分辨率的检测图。
即使是我最终选择的微型模型,也需要大约 0.75 秒才能在 2014 年中期的 3GHz 四核 i7 MacBook Pro 上生成 260x1280 输入图像的检测图。也就是每秒 1.33 帧。
致谢
我想亲自感谢 David Silver 和 Oliver Cameron 为 Udacity 的自动驾驶汽车 Nanodegree 项目开发的精彩内容,以及所有 Udacity 团队提供的非凡学习体验。
车辆检测和跟踪
在这个车辆检测和跟踪项目中,我们通过滑动窗口在视频管道中检测可能包含车辆的潜在盒子,使用支持向量机分类器进行预测以创建热图。然后,热图历史被用于在识别车辆之前过滤掉误报,方法是在它周围画一个边界框。
Vehicle Detection Sample
车辆检测项目
该项目的目标/步骤如下:
- 对图像的标记训练集执行定向梯度直方图(HOG)特征提取,并训练分类器线性 SVM 分类器
- 或者,您还可以应用颜色变换,并将入库的颜色特征以及颜色直方图添加到 HOG 特征向量中。
- 注意:对于前两步,不要忘记规格化你的特征和随机选择用于训练和测试。
- 实施滑动窗口技术,并使用您训练的分类器在图像中搜索车辆。
- 在视频流上运行管道(从 test_video.mp4 开始,然后在完整的 project_video.mp4 上实施),并逐帧创建重复检测的热图,以剔除异常值并跟踪检测到的车辆。
- 估计检测到的车辆的边界框。
使用了 jupyter/iPython 数据科学笔记本,可在 github 完整项目报告 — 车辆检测项目笔记本上找到(注意交互式 ipywidgets 在 github 上不起作用)。由于笔记本变得相当大,我将一些代码提取到 python 文件 utils.py(提取函数,加载助手),features.py(特征提取和类),images.py(图像和窗口切片处理),search.py(保存搜索参数类),boxes.py(窗口和框类)和 detection.py(协调图像处理的主车辆检测类)。该项目是用 python 编写的,使用了 numpy 、 OpenCV 、 scikit learn 和 MoviePy 。
方向梯度直方图(HOG)
通过一点试错,我找到了一组猪参数。
HOG 特征提取和参数
创建了一个函数 extract_hog_features ,它采用 64x64x3 的图像数组并返回一组特征。这些是并行提取的,它依次使用 HogImageFeatures 类。
由于 hog 算法主要集中在灰度图像上,我最初使用 Y 通道的 YCrCB 颜色空间(用于表示灰度图像)。然而,我发现它在检测阶段的选择性不够。因此,我使用了所有 3 个颜色通道。为了减少特征的数量,我增加了每个单元格的 HOG 像素的数量。我在我的笔记本中使用了一个交互功能,找到了一个 32 的方向设置,它显示了车辆的独特特征。样本如下。
Training Vehicle HOG Sample
最终的参数设置使用了color_space = 'YCrCb'
、orient = 32
、pix_per_cell = 16
和hog_channel = 'ALL'
。使用颜色直方图特征进行了实验,但是它减慢了特征提取,并且后来增加了检测到的假阳性的数量。根据下面的可视化图形,您可以看到 Cr 和 Cb 色彩空间具有可检测的 hog 特征
Sample HOG Channel Output form a video window slice
分类器训练
一旦从 car ( GTI 车辆图像数据库和 Udacity Extras)和 not _ car(GTI)图像集中提取出 HOG 特征(无彩色 Hist 或 Bin 空间)。然后,它们被堆叠并转换为浮动在车辆检测笔记本中。
然后使用 Sklearn 鲁棒定标器对特征进行定标,结果如下。
实验发生在分类器实验笔记本中的 LinearSVC ( 支持向量机分类器)、RandomForest 和 ExtraTrees 分类器之间。选择 LinearSVC 是因为 10 个标签的预测时间为 0.00228 秒,而其他两个标签的预测时间约为 0.10 秒。
滑动窗口搜索
构建推拉窗
在这个项目中,选择了四种尺寸的窗户——32x 32、48x48、64x64 和 128x128,并以不同的深度透视放置在图像的右下方,以覆盖道路。较大的窗户靠近驾驶员,较小的窗户靠近地平线。x,y 的重叠设置在 0.5 和 0.8 之间,以平衡更好的覆盖需求和生成的盒子数量——目前为 937 个。滑动窗口的方框越多,每个视频图像的计算就越多。
分类器示例和优化
使用 Python 异步方法和 VehicleDetection 类中的 asyncio.gather 在搜索的并行化上花费了一些时间。在对每个窗口进行特征提取和预测之前,该搜索提取每个大小的搜索窗口的有界框图像并将其缩放到 64×64。
搜索hot_box_search
返回分类器预测包含车辆的热盒阵列。
这些方框重叠在一起,用于创建一个 255 的二维热点图。为了消除初始误报,保持计数> 4。在应用另一个阈值之前,热图被标准化
heatmap = apply_threshold(heatmap, 4)
heatmap_std = heatmap.std(ddof=1)
if heatmap_std != 0.0:
heatmap = (heatmap-heatmap.mean())/heatmap_std
heatmap = apply_threshold(heatmap, np.max([heatmap.std(), 1]))
将这个阶段重新绘制到图像上
热图有一个历史记录
然后作为输入输入到 Scipy 标签中,该标签具有链接维度的模糊二进制结构,给出
最后,在每个框上应用方差过滤器,如果对于一个检测到的标签框,方差< 0.1 (its just a few close points0 or if multiple with a variance < 1.5 (more noise).
Video Implementation
Vehicle Detection Video
The 忽略 GitHub 上的项目 VehicleDetection mp4,包含结果( YouTube Copy )
跟踪车辆检测
scipy . ndimage . measurements . label函数的一个很好的特性是,它可以处理 3d 数组,给出 x,y,z 空间中的标签。因此,当使用热图历史的数组作为输入时,它在 x、y、z 中标记连接。如果返回的标记框没有在至少 3 个(热图历史最大值-2)z 平面中表示,则它被拒绝为假阳性。结果是,车辆在保存的热图历史中被跟踪。
讨论
当构建这个管道的时候,我花了一些时间来并行化窗口搜索。我发现这样做很可能不会提高整体性能。图像必须连续处理,在生成视频时,我的 cpu 没有得到充分利用。
事后看来,我应该用一个大范围的搜索来探测车辆,然后用一个更小范围的搜索来探测最后已知的位置。可以以更大的间隔或者当车辆检测丢失时运行大重量搜索。
如果车辆在汽车的左侧或中间,我的管道将立即失效。我怀疑卡车、摩托车、骑自行车的人和行人不会被检测到(因为他们不在训练数据中)。
基于前置摄像头的车辆检测和跟踪
Udacity 自动驾驶工程师 Nanodegree —学期 1,作业 5。
目标
这是为 Udacity 自动驾驶汽车工程师 Nanodegree 第一学期的第五次也是最后一次任务创建的报告。挑战在于创建一种算法,利用前置摄像头获取的视频来检测道路上的其他车辆。
这是 Github 库。
特征抽出
为了检测车辆或任何其他物体,我们需要知道它们与相机拍摄的其他图像有何不同。颜色和渐变是很好的区分因素,但最重要的特征将取决于对象的外观。
颜色单独作为一个特征可能是有问题的。依赖于颜色值(或颜色直方图)的分布可能最终在图像的不需要的区域中找到匹配。渐变可以提供更强大的演示。它们在围绕中心的特定方向上的存在可以解释为形状的概念。然而,使用梯度的一个问题是,它们使签名过于敏感
HOG 方向梯度直方图
HOG 是一种计算图像局部梯度方向出现次数的计算机视觉技术。如果我们计算每个像素的梯度
大小和方向,然后将它们分组为小单元,我们可以使用这个“星形”直方图来建立该单元的主要梯度方向。
“Star” histogram of gradient directions
这样,即使很小的形状变化也会保持签名的唯一性。各种参数,如方向箱的数量、网格(单元)的大小、单元的大小、单元之间的重叠,对于微调算法非常重要。
HOG、色彩空间、空间和彩色宁滨参数
在最终的特征提取函数中,我们对 YCrCb 应用了颜色变换。然后,我们将装箱的颜色特征向量、颜色向量的直方图与 HOG 特征向量连接起来。对所有颜色通道进行 HOG 计算。
color_space = ‘YCrCb’
spatial_size = (16, 16) # Spatial binning dimensions
hist_bins = 32 # Number of histogram bins
orient = 9 # HOG orientations
pix_per_cell = 8 # HOG pixels per cell
cell_per_block = 2 # HOG cells per block
hog_channel = “ALL” # Can be 0, 1, 2, or “ALL”
训练分类器
一旦提取了特征,就该建立和训练分类器了。课程中介绍的方法是建立一个分类器,可以区分汽车和非汽车图像。然后,这个分类器通过对小块进行采样而在整个图片上运行。每个补丁然后被分类为汽车或非汽车。
数据集
为了训练分类器,我使用了车辆和非车辆示例的标记数据。这些示例图像来自 GTI 车辆图像数据库、KITTI vision 基准套件和从项目视频本身提取的示例的组合。
数据被随机打乱后分成训练集和测试集,以避免数据中可能出现的排序效应
。
训练基本上是为训练集中的每幅图像提取特征向量。这些向量和它们各自的标签(汽车或非汽车)提供给训练算法,该算法迭代地改变模型,直到预测和实际标签之间的误差足够小。(或者在多次迭代后误差停止减小。)
归一化特征向量的大小
在开始训练分类器之前,我们将特征向量归一化为零均值和单位方差。这是必要的,因为基于颜色的特征和基于渐变的特征之间存在大小差异,这可能会导致问题。
# Fit a per-column scaler
X_scaler = StandardScaler().fit(X)# Apply the scaler to X
scaled_X = X_scaler.transform(X)
支持向量机分类器
正如课程中所建议的,我们使用支持向量机对数据进行分类。我们也实现了一个决策树分类器,但是准确性看起来不太好,所以我们决定继续微调 SVM。
3.26 Seconds to train SVC...
Test Accuracy of SVC = 0.9926
滑动窗口方法
既然我们已经训练了分类器,我们将不得不在帧中搜索汽车。前提是我们在图像中定义小块,然后对每个小块运行分类器。然后,分类器将决定该小块是否“是”汽车。
在滑动窗口技术中,我们在图像上定义一个网格,并在其上移动以提取训练的特征。分类器将在每一步给出预测,并判断网格元素是否包含汽车特征。
鉴于图像的视角,远离汽车摄像头的物体会显得较小,而靠近的汽车会显得较大。因此,网格细分根据图像上的位置考虑不同的大小是有意义的。我们也不考虑地平线以上的任何区域,忽略有天空、山脉和树木的区域。
跟踪问题
不足为奇的是,分类器将返回大量的假阳性。这些区域没有汽车,但是图像中的照明或纹理会欺骗分类器称其为汽车。对于自动驾驶汽车应用程序来说,这显然是一个大问题。假阳性可能导致汽车改变方向或启动刹车,这是事故的潜在原因。
为了过滤掉误报,我们记录每一帧的所有检测的位置,并与在后续帧中发现的检测进行比较。检测的群集很可能是一辆真实的汽车。另一方面,在一帧中出现而在下一帧中没有再次出现的检测将是误报。
热图和边界框
搜索find_cars
返回分类器预测包含车辆的热盒阵列。我们创建了一个热图来识别重叠盒子的集群。使用apply_threshold
,我们可以移除假设的误报。
import collections
**heatmaps** = collections.deque(maxlen=10)
def process_frame(source_img): out_img, boxes = find_cars(source_img, ystart,
ystop, scale, svc,
X_scaler, orient, pix_per_cell,
cell_per_block, spatial_size,
hist_bins, False) current_heatmap =
np.zeros_like(source_img[:,:,0]).astype(np.float)
current_heatmap = **add_heat**(current_heatmap, boxes)
**heatmaps.append**(current_heatmap)
heatmap_sum = sum(heatmaps)
heat_map = **apply_threshold**(heatmap_sum, 2)
heatmap = np.clip(heat_map, 0, 255)
labels = label(heatmap)
labeled_box_img = draw_labeled_bboxes(source_img, labels)return labeled_box_img
上面的例子是针对单个帧的。如前所述,我们要考虑时间顺序,以避免一次性考虑。我们使用了一个deque
数据结构来保存最后 10 帧的盒子。
管道和视频
总结我们的整体跟踪渠道:
- 处理带标签的数据集以定义训练和测试集。
- 从数据集图像中提取特征。
- 训练分类器。
- 对于每个视频帧:使用滑动窗口技术运行搜索,并过滤掉误报。
Generated video
考虑
值得注意的是,一些检测到的是高速公路对面的汽车。虽然这不是一件坏事,但我们可以通过缩小考虑范围来避免它们。
当汽车进入视频帧时,检测会有一点延迟,这种情况可以通过调整平均框计算中考虑的帧数来解决。
最近使用深度神经网络的技术可以通过提高准确性、减少假阳性的发生和提高性能来改善特征检测。微小的 YOLO 似乎是一种常见的方法。
Janai 等人(2017) 发表了一份关于技术如何改进以及仍需解决的挑战的评估。
这是一个总结第一学期的伟大项目。我可以看到我从使用 OpenCV 寻找车道的第一个任务中学到了多少,我期待着在第二学期学到更多。感谢出色的 Udacity 团队让这一切成为可能。
基于机器学习和 HOG 的车辆检测和跟踪
我进入了 Udacity 自动驾驶汽车 Nanodegree 的第一个学期,我想分享我关于第一学期最终项目的经验,即车辆检测和跟踪。完整的代码可以在这里找到。
介绍
这个项目的基本目标是应用 HOG 和机器学习的概念从仪表板视频中检测车辆。等一下?机器学习和 2018 年的物体检测?听起来过时了,不是吗?当然,利用卷积神经网络的深度学习实现,如 YOLO 和 SSD,在这方面表现突出,但如果你是这一领域的初学者,最好从经典方法开始。所以让我们开始吧!!
收集数据
对于任何机器学习问题来说,最重要的是带标签的数据集,这里我们需要两组数据:车辆和非车辆图像。这些图像取自一些已经可用的数据集,如 GTI 和 KITTI Vision 。图像大小为 64x64,看起来有点像这样:
Figure 1. Vehicle Images
Figure 2. Non Vehicle Images
提取特征
一旦我们得到了数据集,下一个明显的步骤就是从图像中提取特征。但是为什么呢?为什么不能把图像原样喂给机器学习分类器?我的朋友,如果我们这样做,将需要很长时间来处理图像,只是提醒一下,我们不是在这里向 CNN 提供图像,这毕竟不是一个深度学习问题!
明白了,但是如何提取特征呢?如果你想从图像中提取特征,有三种好方法。
- 颜色直方图- 最简单直观的方法就是从图像的各个颜色通道中提取特征。这可以通过绘制各种颜色通道的直方图,然后从直方图的箱中收集数据来完成。这些箱给了我们关于图像的有用信息,并且在提取好的特征方面非常有帮助。
Figure 3. Color Histograms for Vehicle Image
Figure 4. Color Histograms for Non Vehicle Image
2.空间宁滨- 彩色直方图确实很酷,但是如果图像的特征如此重要,那么为什么我们不能使用某种 numpy 函数来提取所有的特征呢?在这一点上你肯定是正确的。我们可以通过使用 numpy.ravel()展平图像来提取图像中的所有信息。但是等一下,让我们做一些计算,图像大小是 64x64,它是一个 3 通道图像,所以提取的特征总数是 12,288!!单个图像中接近 12k 的特征不是一个好主意!所以这里空间宁滨来图片!如果我说,一个 64x64 的图像提供的信息和 16x16 的图像提供的信息是一样的呢?当然有一些信息丢失,但我们仍然能够从图像中提取出好的特征!因此,如果我将 numpy.ravel()应用于 16x16 的图像,我将只能获得 768 个特征!
Figure 5. Spatial Binning Intuition
- **HOG(梯度方向直方图)——**上面讨论的特征提取技术很酷,但肯定比不上 HOG。HOG 实际上拍摄了一幅图像,把它分成不同的块,在块中我们有细胞,在细胞中我们观察像素并从中提取特征向量。单元内的像素被分类到不同的方向,并且块内特定单元的结果向量由最强向量的幅度决定。注意——这里我们不计算某个像素在某个特定方向上的出现次数,而是对该像素在该特定方向上的大小感兴趣。阅读更多关于猪这是一个很好的链接。
Figure 6. HOG with 9 orientations. CPB(Cells Per Block) PPC (Pixels Per Cell)
这里只需要注意一点。OpenCV HOG 返回 HOG 图像和特征向量,但是 image.ravel()的长度不等于特征向量长度。这是因为 HOG 在内部执行一些计算,减少数据中的冗余,并返回优化的特征向量。此外,您在图像中看到的行数越多,意味着它将返回更多的特征。
生成数据集和数据预处理
好了,酷,现在我们知道如何提取特征,所以我们将处理所有图像的这些步骤?是的,你是对的,但是没有必要使用上述所有方法的所有功能。让我们暂时只使用 HOG,忽略颜色直方图和空间宁滨。
让我们决定提取特征的 HOG 参数。经过多次尝试,我决定采用以下方法:
- 方向- 9
- 每块电池- 2
- 每个单元格的像素- 16
- 色彩空间- YUV
酷,用这些参数通过 HOG 函数运行图像后,最终的参数大小是 972,非常酷!
数据预处理 现在我们的特性已经准备好了,下一步是预处理数据。不要担心,sklearn library 总是在那里帮助完成这些任务。我们可以执行以下预处理:
I)混洗数据
ii)将数据集分成训练集和测试集
iii)数据的标准化和缩放(数据集的拟合和变换)
这里要注意的非常重要的一点是,在步骤(ii)之后,我们必须拟合和转换数据,但是我们不应该拟合测试集中的数据,因为我们不希望我们的分类器将峰值偷偷带入我们的数据中。
训练分类器
嗯,特征提取,数据预处理!接下来呢?是的,现在轮到我们的分类器了。你可以选择分类器,但是有很多分类器可供选择:
- 支持向量机
- 朴素贝叶斯
- 决策图表
我决定用支持向量机,因为它们和 HOG 有很好的兼容性。现在在 SVM,我们有 SVC(支持向量分类器),在这里,我们也可以选择不同的核和不同的 C 和γ值。
我在线性核和 rbf 核上训练我的分类器。线性核花费大约 1.8 秒来训练,测试精度为 98.7%,而 rbf 核花费大约 25 分钟来训练,测试精度为 98.3%。我决定使用带有默认参数的 LinearSVC,仅仅是因为它运行时间更短,而且比 rbf 内核更精确。
推拉窗
酷我们的分类器现在训练有素,它将有 99%的时间能够正确预测车辆和非车辆。那么下一步是什么?好吧,下一步是将分类器应用到你的图像中,以便找到汽车在图像中的确切位置!
但是首先你需要决定各种重要的参数。第一件事是从哪里开始搜索汽车,显然你不应该在天空中搜索汽车,因此你可以忽略图像的上半部分,所以基本上确定一个地平线,在这个地平线下你将搜索你的汽车。第二件重要的事情是你要找的窗口大小是多少,两个窗口应该重叠多少?这取决于你的输入图像长度,因为这里是 64x64,所以我们将只从 64x64 的基本窗口大小开始。下一件重要的事情,也是这里要注意的非常重要的一点是**,你在地平线附近搜索较小的汽车,当你走向仪表板摄像头时,你搜索较大的汽车**。这是因为如果汽车靠近地平线,它们就越小,因为它们远离你的汽车,而靠近的汽车则相反。
但是我应该增加多少窗口大小和多少重叠?那要看你的眼光了。我决定使用 4 种不同尺寸的窗户。在下面的图片中,我将尝试用相应的窗口大小来说明我的搜索区域。
Figure 7. My Choice of Window Sizes with Overlap and Y coordinates
Figure 8. Window Size 64x64 Coverage
Figure 9. Window Size 80x80 Coverage
Figure 10. Window Size 96x96 Coverage
Figure 11. Window Size 128x128 coverage
我的总窗口大小为 470!因此,一旦我们定义了我们将搜索的所有滑动窗口,下一步就是逐个窗口提取所有补丁的特征,并运行我们的分类器来预测找到的窗口是否是汽车。请记住,我们在从 64x64 图像提取的特征上训练我们的模型,因此对于大小不同的窗口,我们需要首先将它们的大小调整为 64x64,以保持特征相同。让我们看看我们的分类器是如何工作的。
Figure 12. Refined Windows after running the classifier.
热图
因此,我们能够检测滑动窗口,但有一个问题。这么多窗口相互重叠,如何画出最终的包围盒?答案是热图。我们将创建一个与原始图像大小相同的空白黑色图像,对于所有已识别的优化窗口,我们将为优化窗口的整个区域增加一个像素值。这样,我们将得到具有不同强度的区域,其中公共区域是最强的。然后,我们可以应用一个阈值来裁剪最终的图像,并获得最终盒子的坐标。
Figure 13. Heatmap drawn after increasing the pixel intensities of refined windows
Figure 14. Final Image After applying the threshold
Figure 15. Testing Pipeline On a New Image
好吧,太酷了,就这样?嗯,是也不是!当您在更多的测试图像上运行代码时,还有一个问题。
Figure 16. Applying Heatmap on some more Images
正如你所观察到的,在我们的图像中检测到了一些误报,从左车道驶来的车辆也被检测到,那么我们如何解决这个问题呢?首先我们需要观察这个问题是如何出现的?我们的分类器有 98.7%的准确率。我们总共有 470 扇窗户。因此,在生成的窗口中,我们将有大约 6 个窗口是误报的。如果最终热图图像中的阈值较低,这些窗口可以出现在任何地方。因此,要解决汽车驶入另一条车道的问题,一些误报可以通过提高阈值来解决。在我的例子中,我将阈值设置为值 4,但是阈值设置还是取决于许多因素,使用的色彩空间,SVM 精度等等。
求平均值
我们现在差不多完成了!管道处理图像的效果非常好,但是如果你要对来自视频流的图像运行管道,还是有一个问题。最终检测到的框将变得非常不稳定,无法提供流畅的体验,在某些帧中框可能会消失。那么解决办法是什么呢?解决方案非常直观,存储所有从前 15 帧检测到的细化窗口,并平均当前帧中的矩形。此外,你需要调整阈值到一个更高的水平。通过这样做,最终的边界框看起来不那么抖动,并提供一个平滑的流程。我在项目视频上尝试了我的管道,结果有点像这个。
一些提示和技巧
- 如果您在视频上运行管道时处理时间过长,请先尝试缩小窗口。
- 如果处理时间仍然很长,请尝试减少提取的要素数量。
- 如果你有一个包含 10,000 张图片的测试集,你的特征大小是 8000,即使测试集的准确率超过 95%,SVM 也不会达到标准。使用具有“rbf”内核或 reduce 特征的 SVM。
- 如果管道运行仍然需要很长时间,请尝试跳过一半或三分之二的帧。它会加速。记住,我所说的跳过帧是指跳过对帧的处理,并将该帧的细化窗口设置为从存储在某个数据结构中的前 15 帧中收集的矩形。
你可以在这里观察最终的视频输出。
当然,视频并不完美,但我很高兴最终的输出。有较少的滞后,也没有检测到来自其他方向的汽车。还有。我正在研究 YOLO 和 SSD 方法,并将很快写下从中得到的经验。万岁!!第一学期结束了,是时候自我反省了,也为第二学期感到非常兴奋。
基于支持向量机(SVM)的车辆检测
下面是从视频中成功检测到汽车的输出视频:
分析:
我已经完成了 Udacity 自动驾驶汽车项目的车辆检测项目。在这里,我试图提供使用支持向量机(SVM)检测车辆的详细分析。
在此之前,为了理解使用 SVM 实现车辆检测,我们需要知道一些术语:
图像特征提取:
我做的第一件也是最重要的事情是从图像中提取特征。图像中有许多可以提取的特征,这些特征可以帮助训练我们的分类器。通过仅从称为特征描述符的图像中提取有用的信息来表示图像。我用于车辆检测的一个重要的 T4 特征描述符是猪:
梯度方向直方图(HOG):
形状是表征任何物体的重要参数之一。HOG 是一种特征描述符,用于根据对象的形状来表征对象。该技术计算图像提及部分中每个梯度方向的直方图(出现次数)。但是等等,到底什么是渐变定向???正如我们所知,每张图像都有颜色和亮度。这些性质的方向变化可以称为梯度取向。以下是特征提取的逐步过程,其中也包括 HOG:
- 提取图像的空间特征:
调整图像大小后,我们仍然保留了图像的所有特征。因此,我们调整了图像的大小,有了它的帮助,我们的代码会运行得更快,而不会丢失任何信息。这可以在打开 cv 函数 cv2.resize()的帮助下完成。
2。图像色彩空间转换:
将图像转换到特定的色彩空间以从所选色彩通道中提取信息:
我们可以将图像转换为以下任何色彩空间:
RGB、HSV、YCrCb、YUV、LUV、HLS
例如,如果你想识别一个物体在阴影下的图像,我们可以使用它们的一些属性,如图像的亮度或饱和度,来更有效地对一些阴影下的车辆进行分类。这可以通过使用 HLS 色彩空间通道来完成。
3。颜色直方图提取:
我们借助函数 numpy.histogram()获取图像的颜色直方图。这在存储图像的不同特征时非常重要。
4。猪:
如上所述,HOG 是我在特征提取过程中使用的最后一步。我为 hog 使用的函数是 HOG()。下面是图像的 hog 特征的可视化:
Hog feature of a car
特征提取完成后,现在开始训练我们的分类器。我用过 rbf SVM(支持向量机中的径向基函数)。早些时候,我尝试使用线性 SVM 模型,但由于准确性较低,我的代码在许多地方无法检测到车辆。使用 rbg SVM 将我的准确率提高到 99.13 %。
使用滑动窗口检测汽车:
既然分类器被训练,我们使用滑动窗口概念。对于车窗的每个区域,我们应用图像分类器来检查是否在该区域检测到车辆。请注意,汽车的大小将根据汽车离我们的汽车有多远而有所不同。下面是一个这样的例子,由于汽车与中央摄像机的距离不同,汽车尺寸也不同:
因此,我使用了 3 个不同大小的矩形窗口,它们将贯穿整个图像并检测汽车,如果有的话。我选择的窗口尺寸是 64x64、96x96 和 128x128。如果有汽车出现在窗口,我们将窗口位置保存到一个变量中。实施之后,我仍然面临两个问题:
- 单个汽车图像的窗口太多:
虽然在图像的某些部分检测到了汽车,但是还有许多窗口在检测汽车。下面是我为图片中的两辆车准备的窗户:
Multiple windows
我的目标是只有一个窗口,而不是这么多的窗口。
2。误车检测(误报)
False positive
现在是项目的最后一部分,**热图。**我创建了所有汽车检测的热图,对于每个检测,我将热图[window_img]增加 1。现在,在热图的帮助下,我将只保留一个窗口,而不是一辆车的多个窗口。此外,我将拒绝一些窗口的基础上,一些阈值。这是我的热图中具有多个(重叠)窗口的图像的外观:
以下是应用热图后的结果图像:
Detected cars from an image
虽然汽车被正确地检测到,但我仍然觉得这个视频有一些局限性。处理这段视频花了大约 30 分钟。此外,这在我们有其他物体(如行人)的其他场景中可能并不完美。在接下来的日子里,我一定会尝试 YOLO 来提高准确性!!
通过图像处理识别外部环境中的车辆
这是我 2015 年为伯南布哥大学做的科学研究的结果。
这个研究项目旨在协助开发一个低成本的本地系统,不依赖于外部条件就能监控十字路口的车辆流量。使用数字图像处理技术来识别车辆,并在需要的情况下做出决策。在一个简化的方法中,提出了在城市环境中检测车辆的计算方法。本文中的解决方案已经用 VisualStudio C++实现,并使用 OpenCV 库来实现识别。针对两种类型的条目提出了解决方案:图像和视频。图像中侦察车辆的算法结果更接近本研究的目标。然而,还提出了一种在视频中使用识别算法的解决方案。
在文献中有不同的方法探索车辆的检测和识别。可以在已处理的对象和初始数据库的对象之间进行比较,也可以获得优化场景减法和使用连续帧之间的对称差的结果。
还有混合方法,除了计算机视觉之外,还寻求其他方法来优化识别和检测,例如使用基于激光的传感器。
也可以使用感兴趣区域的分割和选择技术、车辆的检测和识别以及阴影的去除技术,集中于使用静态摄像机的方法,目的在于主动交通监控。在体积计数的方法中,我们可以突出那些使用静态监控摄像机的方法。
神经网络应用于车辆检测。但是神经网络有两个主要问题:不能保证达到全局最小值,第二个问题意味着它定义了代表真实世界的数据集,并且没有理想的神经网络模型。模糊逻辑测量用于检测车辆。光强度值用作漫射测量。当强度值落在某个范围内时,必须使用失真的测量来确定它是否是车辆。
首先,我使用基于级联分类器的 Haar 特征来检测对象。这个特性最初是由保罗·维奥拉提出的,后经雷纳·林哈特改进。一个分类器(即具有相似 Haar 特征的工作驱动分类器的级联)由特定对象(即人脸或汽车)的数百个样本视图组成,这些样本视图被称为正样本,它们的大小相同(例如,20x20),负样本是相同大小的任意图像。
在分类器被训练以应用于感兴趣的区域(与训练期间使用的大小相同)之后。如果该区域可能显示对象(即面部/汽车),则分类器产生“1”,否则产生“0”。要在图像中搜索对象,您可以在图像中移动搜索窗口,并使用分类器检查每个位置。分类器被设计成可以容易地“调整大小”,以便能够定位不同大小的感兴趣的对象,这比调整图像本身的大小更有效。因此,为了在图像中找到未知大小的物体,检查过程应该在不同的比例下进行几次。
几个分类器用于测试。有些被证明在某些特定位置对汽车有效,但没有一个被证明在正常交通情况下有效。
Vehicle Recognition using Haar feature
Vehicle Recognition using Haar feature
Vehicle Recognition using Haar feature
由于发现的分类器的结果不完全令人满意,因此需要训练一个分类器来满足这项工作的需要。但是没有用于训练分类器的数据库。有必要创建一个数据库,其中包含各种位置的汽车图像。
该项目的最初想法是开发一种工具来实时计算车辆的体积。然而,由于开发一个通用计数项目非常复杂,为了使实现可行,做了一些简化。这些简化涉及图像、风景和物体的获取。
图像采集:必须通过读取之前存储的视频文件来执行,因为算法没有足够的计算效率来处理实时视频。
场景:它最好是静态的,虽然系统能够很好地处理平滑的运动,但关键是摄像机的位置要确保它能够提供赛道的最佳视图。这种场景的选择旨在避免遮挡的发生,并简化图像分割和对象处理的过程。
对象:对对象进行了概括,即所有对象都被视为车辆。由于我们使用了特定的场景和视频,这是一个有效的概括,它允许更简单的识别过程。
OpenCV 库用于图像处理和分割。对于操作,使用了库的基本功能,允许图像的读取、访问、写入和呈现。
分割包括利用图像的某些属性的技术,以便根据要解决的问题将图像细分成组成图像的区域或对象。在这种情况下,将视频的每一帧细分成两种类型的区域:场景和运动物体。检测这些对象的简单方法是从当前帧中减去场景图像。
Original
MOG2
Binary Image
Result
在不同环境和更高分辨率的视频中的结果不如图 4、5、6 和 7 中呈现的结果令人满意。
作为这个算法的一个应用。提出了一种交通控制算法的组成。这种合成识别双向运动,选择两者中感兴趣的区域,并通过像素计数返回到交通流量更多的区域。计数可以根据地点、时间、车流量和各种其他情况而变化。最简单的解决方案是绘制信息图,并将其分为几类:密集流量、正常流量和少量流量,然后根据这些预定义的信息,做出释放或抑制流量的决定。
该系统在 VisualStudio C ++中开发,使用 Intel 的 OpenCV 库。使用的 OpenCV 版本是 2.4.10。实验结果在由单个摄像机制作的实时视频中进行了演示。测试是在英特尔酷睿 i5–2.60 GHz 笔记本电脑上进行的,该笔记本电脑配有 4,000 GB 内存和 Windows 8.1。
高速车辆以及如何追踪它们
成为自动驾驶汽车工程师之路:第一部分
A view of NVIDIA’s self driving car technology
毕业后,我把探索课堂上没有机会探索的话题作为自己的目标。我的目标是每天阅读两篇关于人工智能技术最新进展的文章(即机器学习、深度学习、人工智能在游戏中的应用,等等)。我一直在阅读关于 OpenCV 和自动驾驶汽车的文章,并在过去一个月的一些兼职项目中受到启发来实践 OpenCV。现在自动驾驶汽车很热门!大概还有至少 15 个其他帖子是关于爱好者是如何制作它们的。尽管如此,我很兴奋也很荣幸成为第 n 个分享我的尝试的人。在写了一个简短的车辆检测脚本后,我偶然看到了 Udacity 的无人驾驶汽车纳米学位项目,我意识到我可以做更多的工作来改进算法…
Basic vehicle detection code
**我没有参加这个项目,所以我在这里完全靠自己。**我仍然认为用我从自己的研究中学到的东西来实现我自己的解决方案会很有趣!
数据和算法
自动驾驶汽车的目标是创造能够在任何可能的道路条件下自动驾驶的车辆,特别是在被高速司机包围的情况下。研究人员得出结论,使用 SVM 分类器,以下算法会产生快速且最优的结果:
- 通过将图像分解成区域来执行定向梯度直方图特征提取,并使用光梯度或边缘检测用局部对象来训练分类器。
- 对所有分辨率和大小的图片执行色彩空间转换和空间宁滨,以实现最佳图像处理。
- 用训练好的分类器实现滑动窗口算法在图像中搜索车辆。
- 估计并绘制检测到的车辆的最终包围盒。
使用的车辆数据集来自 GTI 车辆图像数据库,路测视频和图像来自 KITTI vision 基准套件。Udacity 还发布了一个标签为的数据集,它可能会用于这个项目的后续组件。
数据准备
我从组织图像开始。我制作了列表,将所有标记的图像分组,然后为训练数据制作了额外的列表,以避免过拟合。这只是为了验证数据是否组织正确。
Side by side comparison between a vehicle and the road
Side by side comparison between a vehicle and an aerial image
特征抽出
梯度方向直方图(HOG)的思想是通过描述光强梯度或边缘分布方向来检测局部目标。通过将图像分解成更小的区域(单元),每个单元生成一个梯度方向直方图,或者可以表示这些组合的像素单元边缘方向直方图。为了提高准确性,可以在图像的较大区域(称为块)中评估局部直方图,比较光强作为标准化的度量,然后使用该值(measure)标准化块中的所有细胞。
HOG feature extraction example.
但是,对于这个特定的分类任务,什么样的特征是有用的呢?让我们用一个例子来讨论这一点。例如,假设我们想要构建一个对象检测器来检测衬衫和外套上的按钮。纽扣是圆形的,通常有几个用于缝纫的孔。你可以在一个按钮的图像上运行一个边缘检测器,仅仅通过观察边缘图像就可以很容易地判断出这是不是一个按钮。在这种情况下,边缘信息是“有用的”,而颜色信息不是。此外,特征还需要具有辨别能力。例如,从图像中提取的良好特征应该能够区分按钮和其他圆形物体,如硬币和汽车轮胎。这就是如上所述的光强度有用的地方。
在 HOG 特征描述符中,梯度方向(定向梯度)的分布(直方图)被用作特征。图像的梯度是有用的,因为边缘和拐角(突然强度变化的区域)周围的梯度幅度很大,并且我们知道边缘和拐角比平坦区域包含更多关于物体形状的信息。因此,HOG 描述符特别适合于人体检测。
注意在 HOG 图像中检测到的车辆和道路边缘。这些相同的特征在下面的附加图像中突出显示:
Road and Vehicle HOG
Road and Vehicle features
Road and Vehicle HOG with lower resolution pictures
Road and Vehicle features with lower resolution pictures
训练分类器
对于分类器,我使用了线性支持向量机 (SVM),这是一套用于分类、回归和离群点检测的监督学习方法。这是一个合适的分类器,因为我们已经标记了要处理的数据。
我存储了从车辆和非车辆图像中提取的特征,并将这些特征用于训练数据和测试数据。我使用了scikit-learn
中的帮助函数来分割数据进行训练。
分类器达到了 0.9817 的精度。现在我们可以开始测试了!
形象化
滑动窗口是一个应用在照片上的盒子。它有一个特定的高度和宽度,这个盒子从上到下滑过一幅图像。对于每个位置,我们训练的分类器应用于该区域,并寻找所需的对象。
Sliding window example looking for a face, courtesy of pyimagesearch.com
这是计算机视觉中的一种常见技术,因为我们将能够检测到**不同尺度和位置的物体,**特别是如果这在路上工作的话。
Bounding boxes drawn with a Sliding Window algorithm. It’s clear that there are some false positives
在上面的六幅测试图像中,分类器返回了肯定的检测结果,但是在道路的左侧有一些假阳性。一个建议的替代方法是尝试使用热图。热图背后的想法是,通过给值分配颜色,而不是简单地看图像,可以有效地可视化数据和模式。
热图
Heat map of detected vehicles
对于在边界框中发现的每个像素,添加热量并突出显示构成检测到的车辆的像素。映射和阈值算法计算汽车被检测到的次数。贴图中较亮的色调表示每个边界框中重复检测到的像素。因此我们增加了更多的热量。热图肯定更容易解读,尤其是在边界框更突出的情况下出现假阳性:
结果
Detection results
在应用检测算法之前,我使用了imageio
和moviepy
来平滑测试视频的帧。每个检测到的对象都存储在一个队列中。每次我们在剪辑的当前帧或后面的帧中检测到车辆时,我们都会检查是否在过去的帧中检测到类似的对象。如果我们这样做了,我们会添加检测到的对象,并在多个帧中增加对象的数量。下面的 gif 展示了一个成功的车辆检测程序示例:
Vehicle detection demo
结论
当我第一次尝试这个项目时,我只使用了预先训练的车辆级联。我从最近的尝试中学到了很多,并且能够制作出一个假阳性更少的演示。使用传统的机器学习技术很有趣,所以我很乐意使用深度学习来实现一个解决方案(PyTorch 是我的堡垒,但在阅读了这篇帖子后,我不得不尝试 Tensorflow 的对象检测 API)。我不会使用 Udacity 的确切课程,但我很高兴能继续构建这个项目。请继续关注未来组件的更多工作!
创业思维——数据和规模的革命
View from Potsdam Boat Ride
我们需要明白,非洲的革命不会被电视转播。这听起来可能像是陈词滥调,但这不是吉尔·斯科特-赫伦的歌词,现实更加不祥,因为革命几乎肯定会直播。事实上,它正发生在“ koro-koro ”之前,在我们的“非常的眼前。
席卷非洲的技术革命,在规模和范围上,以及最终在直接影响和间接影响上,将会更加混乱和/或更具破坏性(取决于你的估计)。发令枪已经开火了,尽管它被消音器扭曲了——这是非洲生活节奏的消音效果。但你可以感觉到它开始发挥出来,那些知情人士正在定位。与人工智能、机器学习和物联网的综合效应相比,这将使当前由移动驱动的技术相形见绌,因为这些技术是由我们的数据的离岸捕获驱动的。
我将数据中的“D”大写,以强调其重要性、相关性和影响。任何没有意识到这种中心性的组织或企业都已经奄奄一息或死亡;他们可能还不知道。面对这场革命,重要的是向现有的、新兴的和未来的创业人才发出响亮的号召,无论是盈利性的还是其他的。至少在短时间内,挑战带来的机遇为我们在当地的“霍布斯”环境中建立长期的企业提供了动力,促使我们现在就采取行动——特别是在创新的利基市场,或者永远保持和平。在这个新时代,数据积累的规模和范围是迄今为止单调乏味的模拟方法所无法比拟的。
**恰当的例子:**归根结底,互联网(这简直是人类历史上最指数化的数据增长工具)本质上是推动数据革命的真实平台的增值,是能源获取的嗡嗡声和鼓声。有能源丰富的国家和能源贫乏的国家;很明显,前者(数据殖民主义者)将永远智胜并超越后者(数据殖民地),除非我们现在就开始行动,至少强迫谈判解决。但是在我们开始谈判之前,为了确保取得一点点成功;在即将到来的对抗中,我们的 BATNA(谈判协议的最佳替代方案)是什么?很明显,快速失败、学习和调整的广泛和积极的游戏中的皮肤迭代必须超越任何存在的限制,以玩我们的进攻游戏和扩充我们的数据。
AE4H Innovation Lab 2017 Group Photo
我现在正在德国波茨坦的“人类可负担能源”(AE4H)创新实验室(https://ae4h.org/innovation_lab);这已经改变了我的想法。在评估其能源获取主题(以及潜在的实施考虑和可持续性动态)时,我的基本总结是,推动非洲在平等的基础上重新出现在全球舞台上所需的基础设施必须包含多元化利益相关者(角色)和价值(交换)网络的概念,交叉补贴提供基础设施所需的各种产品、服务、渠道和平台。对于许多非洲初创公司来说,理解快速和可持续地部署可用、可负担和可获得的技术支持产品和服务的需求(在我们缺乏支持基础设施的情况下)和即将到来的数据革命之间的联系需要更加清晰和明显。
事实上,维克多·阿塞莫塔在他最近的开创性文章(https://medium . com/@ as emota/the-age-of-zero-excuses-13fd 66265134)中概述了我们现在所承担的责任以及作为其特征的参数。根据他的前提,我试图强调这样一个事实,即这一责任不仅适用于软件或互联网支持的企业(在我们的地区相对更容易构思、开发和测试,基于物流的*),也适用于我们在这样做时必须克服的物理(和其他邻近)基础设施的缺乏。*
简而言之,数据稳定流动(尤其是来自金字塔底层用户)的一个关键障碍是持续缺乏可持续和可扩展的解决方案来解决普遍的能源获取难题。能源获取和数据之间存在共生关系;毕竟,在我们以移动为先的环境中,当用户因为相关运营成本而无法可靠地充电或使用智能手机时,使用智能手机的机会成本是多少?或者当提供商的服务或产品由于质量或服务水平差而经常无法获得时?由于网络拥塞、错误、故障或彻底崩溃,有多少价值被抹去?这应该被认为是驱动、塑造并时常限制用户行为(和参与)的核心考虑因素,是解锁迅速增长的有洞察力的数据的必要条件。
当我们站在另一场争夺非洲的风口浪尖时,尽管这是一场技术驱动的新殖民主义,但这种交付基础设施(及其支持的数据增长平台)的局限性必须作为战略要务(从一开始)纳入颠覆性的商业计划和模式。这种合并是必要的,既要对价值创造和交换网络进行证券化和交叉补贴,我们需要在成功规划我们的谈判僵局时采用这种网络。
换句话说,我们必须在相应的价值网络(参考框架)中准确描述相关(直接和间接)利益相关者,以便进行适当的交换,及时在市场上交付(和维持)我们的解决方案。这其中的一个关键部分围绕着(不太明显)直接和辅助的软硬件(read smart)基础设施。例如,转述一下我们的祖先,因为很明显电信公司头上顶着一头大象,我们不能指望他们用脚去寻找蚂蚁。创新必须来自当前“利益相关者”矩阵之外,这就是我们颠覆的机会。
从这个意义上说,借用我上一篇关于开源软件、商品化(嵌入式)计算硬件和日益减少的可再生能源三连胜所释放的创新的数量、速度和价值的文章,我们必须创造新的平台来帮助我们抵御随之而来的冲击。我们必须交付价值,在革命完全成熟之前,尽快将尽可能多的用户和客户带入我们的利基市场。因为如果我们成功地解放了我们 10 亿多美元的市场,那么当“成为的时候,我们就有机会比 Ojadili 用 10 头灵【1】更有把握地遇到巨人。这尤其是因为非洲当前数据驱动的殖民扩张的影响,这种扩张正被新兴新时代的技术巨头和互联网巨头无情地追求和维持。
出于我们的目的,数据策略的整合(及其释放或可能释放的价值)跨越 3 个主要领域【2】:
用于业务流程和决策优化的数据(提高生产力和运营效率)
用于产品/服务增强或创造的数据(提高满意度、保留率和终身价值)
销售或转售给新市场或客户的数据(对第三方,如广告商、顾问等的分析)。)
因此,当我们计划和发展我们的事业时,这个数据三位一体的圣杯必然会告知我们对我们所确定的利基中的价值(及其交换)的评估。这是因为至少,它们提供了新的方法和手段来提供基础的软件和硬件基础设施,以及增强我们当地环境所需的各种产品和服务。
顺便说一句,从 20 世纪 90 年代的互联网繁荣开始,席卷全球的互联网革命(部分)是以一种古老的商业模式为前提的,这种模式整合了数据的聚合、挖掘和分析,仍然在以谷歌、脸书、亚马逊等公司集体价值的货币化为基调。在此之前,报纸、广播和电视都是以相同的多面平台模式为前提的。事实上,像雅虎这样的前巨头已经消失了,这只是一个先行者未能认识到技术时代的流沙的作用;对自己的企业家也是一个警示。
在非洲,即使像我提到的那样降低了技术构建模块的成本,但现实是有限的人均购买力和其他大众市场规模扭曲抑制了向金字塔底层(BOP)用户提供大多数产品和服务,而这些用户正是随后的冲击的目标。尽管围绕互联网供电产品的接入、覆盖和服务进行了各种调整和创新,但仍有很大一部分眼球和思想份额在今天的非洲没有得到服务。赢得并保持这些大众所代表的数据矿脉的最终责任,是我们必须为自己设定的任务。
最终,非洲真正的购买力和价值的表面被锁定在未实现的潜在消费者身上,他们在我们关注的数字利基和领域中的直接和间接活动,可以在我们的形象和相似性中催生一个重新构建的新时代的曙光。我们可以直面数据驱动的革命,在公平价值交换的谈判僵局中。如果我们失败了,墙上那面镜子中最美丽的人将会以征服者的方式出现;我们都知道这个故事的结局。
所以,是的;这场革命不会被电视转播。因为它将从数以亿计像素有限的迷你屏幕上直播(我们希望如此),我们可以让这些屏幕点击它们的方式,从无能和服务不足的低迷状态中,到我们的数据 Eldorado。但话说回来,也许我错了。也许我的视力僵化了。然而,我们想打赌吗?如果——在我所有迷惑的近似中——如果我是对的呢?
乌切·奥努拉
联合创始人/首席宣传员——HITCH(由 Flexfinity 负责)
【网页:】【www.tryhitch.com】
推特:@HITCHStream
脸书:/HITCHStream
【2】http://Sloan review . MIT . edu/article/how-to-money-your-data/
Jupyter 笔记本的版本控制
Jonathan Whitmore 的 Jupyter 笔记本数据科学最佳实践非常有用,我一直强烈鼓励团队成员至少采用其中的一部分,特别是 post-save 挂钩和笔记本命名约定。
Jupyter 笔记本是一个基于网络的交互式计算平台。该笔记本结合了现场代码,方程式…
jupyter.org](http://jupyter.org/)
保存后挂钩
这样做的目的是在保存笔记本时自动保存一份 Python 脚本和 HTML 格式的副本。
我曾经在提交到版本控制之前清除笔记本中的所有输出,以使变更历史更加清晰,但是这产生了两个问题:
- 如果笔记本的数据处理部分需要 10 分钟以上的时间来运行,这将会产生一种强烈的激励,让审查者跳过实际运行笔记本,而只是通读代码,并假设它做了它看起来要做的事情。这是假设训练好的模型以某种方式被序列化以供审阅者加载,否则可能需要花费数小时在审阅者的系统上训练。预训练模型的分布带来了下一个问题:
- 没有简单的方法将数据和模型文件与笔记本一起分发。对于数据科学家来说,存储和传输千兆字节的数据不是那么容易的,而让数据工程师专门为此在内部构建一些东西可能不划算。对于“大数据”场景,您不希望将 Spark 访问凭据保存在笔记本电脑中(非常危险),因此您需要找到一些安全管理集群访问的方法。(有一个叫做数据版本控制的新框架,看起来很有前途。但你需要向谷歌或亚马逊支付云存储费用。)
总而言之,解决这些问题最直接的方法就是只需将笔记本的输出纳入版本控制。(尽管我建议在提交之前重启内核并重新运行整个笔记本。)
将笔记本转换为 Python 脚本和 HTML 文件。在评审过程中使用 Python 脚本进行代码差异。HTML 文件最适合作为跨团队沟通电子邮件的附件。(就我个人而言,只有当项目的积极参与者没有真正使用 Jupyter 时,我才会将 HTML 文件添加到版本控制中。)
以下要点基本上是从 Jupyter 笔记本数据科学最佳实践中直接复制的。它是根据最新的 Jupyter 测试的,放在这里供快速参考:
使用上述脚本有两种方式:
- 放在
~/.jupyter/jupyter_notebook_config.py
的顶部。(如果还没有,运行jupyter notebook --generate-config
创建它) - 如果你想要不同项目的不同配置,使用
export JUPYTER_CONFIG_DIR=~/.jupyter_profile2
来指定配置文件夹。 - 将其作为
jupyter_notebook_config.py
放在项目文件夹的根目录下(在那里运行jupyter notebook
命令)。
还有呢!
如果使用得当,Jupyter notebook 可以成为一个非常有效的工具,提高团队协作的效率。请查看 Jupyter 笔记本数据科学最佳实践了解更多信息。
[## Jupyter 笔记本电脑数据科学最佳实践-硅谷数据科学
Jupyter 笔记本是一个神奇的工具,可以用在许多不同的方面。因为它的灵活性,工作…
svds.com](https://svds.com/jupyter-notebook-best-practices-for-data-science/)
20190313 更新
Github 上有一个新工具可以直接区分 Jupyter 笔记本:
[## 点评 nb:GitHub 的 Jupyter 笔记本差异
Jupyter 笔记本的 HTML 渲染差异。告别凌乱的 JSON diff。通过审阅评论在笔记本上协作…
www.reviewnb.com](https://www.reviewnb.com/)
我还没有找到时间真正尝试它,但我听说过它的好处:
Jupyter 笔记本的 Git 版本控制
Don’t loose your version control history.
版本控制是数据科学工作流的重要组成部分。在多个实验之间,了解哪个团队成员做了哪些更改和哪些更新是非常重要的。不幸的是,默认的 jupyter 设置在这方面严重不足。
Jupyter 笔记本是以Json
格式存储的,因此很难看出笔记本上的差异,也很难在团队层面上进行代码审查。为了解决这个问题,我们将以.ipynb
和.Rmd
(r-markdown 格式)存储笔记本。这将使我们能够做差异以及合并,因为.Rmd
只是一个文本文件。
介绍 R-Markdown 及其优于普通 Markdown 的优势
R-Markdown 与 Markdown 格式相同,但有一个额外的优势,即您可以从它制作值得发布的 pdf/word-doc(和其他格式)。因此,如果你的笔记本存储为.Rmd
格式,你不仅可以控制它,还可以将其转换为纸质出版格式。
更多关于 R-Markdown 的信息可以在这里找到。此外,如果您打算使用 R-Markdown 编写一本书,请检查 R bookdown 包。它允许你用 markdown+code+outputs 写一本书。
以多种格式保存的方法
尽管第一种方法更容易设置,为什么我们选择 Jupytext?
第一种方法只是将它保存为代码,而 Jupytext 将其保存为 readme,因此它在 github 中可以很好地呈现,并保持文档完整。
安装和设置 Jupytext
您需要在将 git repo 用于笔记本的所有系统上执行此操作。这意味着你所有的队友都必须配置 jupytext。
我们使用 Jupytext 库(https://github.com/mwouts/jupytext)
pip install jupytext --upgrade
- 接下来用
jupyter notebook --generate-config
生成一个 Jupyter 配置,如果你还没有的话 - 编辑
.jupyter/jupyter_notebook_config.py
并添加以下内容:
c.NotebookApp.contents_manager_class="jupytext.TextFileContentsManager"
c.ContentsManager.default_jupytext_formats = ".ipynb,.Rmd"
- 并重启 Jupyter,即运行
jupyter notebook
注 : .jupyter
大多出现在你的主目录里。
- 打开现有笔记本或创建新笔记本。
- 禁用 Jupyter 的自动保存以进行往返编辑,只需在顶部单元格中添加以下内容并执行。
%autosave 0
- 您可以在 Jupyter 和文本编辑器中编辑
.Rmd
文件,这可以用于检查版本控制更改。
可能的 Git 工作流(2 种方式)
1.仅保存 Rmd 文件
我们将删除.ipynb
文件并对.Rmd
文件做一个小的修改。
ipynb
文件的所有输出都在它们的 json 源中,因此当这些输出存储在源代码管理中时,即使实际变化很小,也会在 diff 中增加巨大的变化。此外,他们有所有的图像/情节编码为字符串,所以它是沉重的源代码控制。因此,您只需要将 Rmd 文件签入源代码控制中。
要在你的.gitignore
文件中做到这一点,在新的一行中添加下面一行。
*.ipynb
*注意:*你的所有队友也需要这样做,这样他们才不会将ipynb
文件提交到 git 中。
如果您已经签入了ipynb
文件,那么在签入.Rmd
文件后,从源代码管理中删除它们。从 gitrepo 而不是本地目录中删除文件(请参阅此处的)
git rm --cached file1.ipynb
git commit -m "remove file1.ipynb"
接下来我们对.Rmd
文件做一个小的修改。
- 打开
vi
中的.Rmd
文件 - 在以
jupytext_formats: ...
开头的行,修改为:
jupytext_formats: ipynb,Rmd:rmarkdown
- 保存文件并退出
vi
*注意:*第一次创建.Rmd
文件并推送至 git remote 时,对该文件的修改只需要一次。
克隆回购并创建笔记本
一旦您删除了ipynb
笔记本,当您克隆回购时,您就要创建笔记本。让我们看看怎么做。
- 从文件浏览器打开 jupyter 中的
.Rmd
文件。 - 您可以直接使用
.Rmd
文件,但是它不会在会话之间保持输出,所以我们将创建一个 jupyter 笔记本。 - 点击
File->Save
(Cmd/Ctrl+S)。 - 关闭
.Rmd
文件(*File->Close and Halt*
) - 现在打开 Jupyter 的
ipynb
。 - 开始编辑和保存。您的
.Rmd
文件将不断更新。
2.保存 Rmd 和 Ipynb 文件
不要将.ipynb
添加到您的.gitignore
中。
对.Rmd
文件做一个小改动。
- 在
vi
中打开.Rmd
文件 - 在以
jupytext_formats: ...
开头的行上,将其改为:
jupytext_formats: ipynb,Rmd:rmarkdown
- 保存文件并退出
vi
*注意:*对.Rmd
文件的更改只需要在您创建它并第一次将其推送到 git remote 时进行一次。
在此工作流程中,由于您保存了这两个文件,因此在克隆时不需要做任何额外的工作,因此.ipynb
已经可用,因此只需在克隆回购后开始使用它。
记得将 %autosave 0
放入笔记本的第一个单元格,并一直运行它。因为你已经禁用了自动保存,所以记得经常保存你的笔记本。
更新
- 也可以只使用
.Rmd
格式。基本上不用.ipynb
用.Rmd
。将.Rmd
签入 git 进行版本控制。这样做的缺点是,当你登录 git 时,你的图/结果等将被删除,因为.Rmd
是纯文本格式。任何下载你的笔记本的人都必须运行代码才能看到图形/结果。
参考
Jupyter 笔记本作为 Markdown 文档,Julia,Python 或 R 脚本
github.com](https://github.com/mwouts/jupytext) [## Jupyter 笔记本的版本控制
Jonathan Whitmore 撰写的 Jupyter 笔记本数据科学最佳实践非常有用,我一直…
towardsdatascience.com](/version-control-for-jupyter-notebook-3e6cef13392d)
非常简单的 Python 脚本,用于从故事中提取最常见的单词
简单的 Python 脚本,不使用繁重的文本处理库,从语料库中提取最常见的单词。
莎士比亚戏剧中使用最多的词是什么?“king”比“Lord”用得多,还是反之亦然?
为了回答这类有趣的问题,人们通常需要快速检查和绘制文本文件中最常见的单词(通常从开源门户网站下载,如古腾堡项目)。然而,如果你在网上或 Stackoverflow 上搜索,你很可能会看到***【nltk】***和 计数矢量器 的使用的例子。虽然它们非常强大,使用起来也很有趣,但事实是,如果您只想提取单个文本语料库中出现的最常见的单词,就不需要它们。
下面,我将展示一个非常简单的 Python 3 代码片段来实现这一点——只使用了一个字典和简单的字符串操作方法。
请随意复制代码,并使用您自己的停用词来使它变得更好!
import collections
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline# Read input file, note the encoding is specified here
# It may be different in your text file
file = open('PrideandPrejudice.txt', encoding="utf8")
a= file.read()# Stopwords
stopwords = set(line.strip() for line in open('stopwords.txt'))
stopwords = stopwords.union(set(['mr','mrs','one','two','said']))# Instantiate a dictionary, and for every word in the file,
# Add to the dictionary if it doesn't exist. If it does, increase the count.
wordcount = {}# To eliminate duplicates, remember to split by punctuation, and use case demiliters.
for word in a.lower().split():
word = word.replace(".","")
word = word.replace(",","")
word = word.replace(":","")
word = word.replace("\"","")
word = word.replace("!","")
word = word.replace("“","")
word = word.replace("‘","")
word = word.replace("*","")
if word not in stopwords:
if word not in wordcount:
wordcount[word] = 1
else:
wordcount[word] += 1# Print most common word
n_print = int(input("How many most common words to print: "))
print("\nOK. The {} most common words are as follows\n".format(n_print))
word_counter = collections.Counter(wordcount)
for word, count in word_counter.most_common(n_print):
print(word, ": ", count)# Close the file
file.close()# Create a data frame of the most common words
# Draw a bar chart
lst = word_counter.most_common(n_print)
df = pd.DataFrame(lst, columns = ['Word', 'Count'])
df.plot.bar(x='Word',y='Count')
语料库中 10 个最常用单词的代码输出和绘图示例。正文是’ 《傲慢与偏见》 '而且可以看到大家熟悉的伊丽莎白和达西先生的名字!😃
喜欢这篇文章吗?成为 中等会员 继续 无限制学习 。如果您使用下面的链接, ,我将收取您的一部分会员费,而无需您支付额外费用 。
[## 通过我的推荐链接加入 Medium—Tirthajyoti Sarkar
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@tirthajyoti/membership)
Jupyter 笔记本中的视频流
ipywidgets 在 Jupyter 生态系统中起着至关重要的作用;它带来了用户和数据之间的交互性。
小部件是多事件的 Python 对象,通常在 Jupyter 记事本或 JupyterLab 中有一个可视化的表示:一个按钮、一个滑块、一个文本输入、一个复选框…
The user can get access and set the value of the slider writing Python code, and of course, interact with it using the mouse
表示小部件的 Python 对象在服务器端(后端)是活动的,在 Python 内核(负责执行 Jupyter 笔记本中的代码的部分)内部。Python 对象包含关于微件状态的所有信息。在 滑块 小部件的情况下,Python 对象包含滑块的最小值、最大值和当前值。这个 Python 对象(在后端,服务器端)与小部件的 Javascript 模型(在前端,客户端)同步,后者包含关于小部件的相同信息。每次用户在笔记本中显示小部件时,它都会创建一个与 Javascript 模型保持同步的视图。在 滑块 示例上,可以看到两个视图是同步的。
不仅仅是一个交互式小部件库,ipywidgets是一个强大的框架,基于它可以直接创建新的定制小部件。开发人员可以使用widget-cookiecutter项目,用代码结构和打包的最佳实践快速启动他们的 widget 库。
已经创建了许多不同的小部件库。您可以使用 mybinder 在线试用它们,无需安装任何东西!:
- **bq plot**:二维交互数据( 绑定链接 )
- ipyleaflet: 互动地图( 活页夹链接 )
- python reejs:交互式三维场景( 活页夹链接 )
- ipyvolume: 三维交互式数据可视化和多体绘制( binder link )
- nglview: 三维交互式分子可视化( binder link )
- **gmaps**:Google-maps 上的数据可视化
- itk-jupyter-widgets:交互式二维和三维数据可视化( 活页夹链接 )
- …
自从ipywidgets7.4 以来,我们有了两个新的小部件:音频和视频小部件,这使得在 Jupyter 笔记本和 Jupyterlab 中进行图像/音频处理变得很容易。****
像 图片 小部件一样,新的 音频 和 视频 小部件在后端和前端之间同步二进制数据。您可以使用自己喜欢的库(OpenCV、sci kit-image……)轻松操作这些数据,并动态更新小部件值。
Edge detection using OpenCV on a Video widget
这两个小部件是创建 ipywebrtc 库的很好的构件。 ipywebrtc 已由 马腾 创作(马腾是牛逼库 vaex 和 ipyvolume 的作者)。它使用 WebRTC 浏览器 API 的强大功能来允许 Jupyter 笔记本内部的视频流。
ipywebrtc的 API 非常简单:首先,用户会创建一个我们称之为 MediaStream 的小部件。一个 媒体流 小部件可以是:
- 一个 WidgetStream 小部件,给定任何输入小部件
- 一个 VideoStream 小部件,给定一个 Video 小部件作为输入
- 一个 ImageStream 小部件,给定一个 Image 小部件作为输入
- 一个 音频流 小部件,给定一个 音频 小部件作为输入
- 一个 CameraStream 小部件,它根据用户的网络摄像头创建视频/音频流
使用 MediaStream 小部件,您可以:
- 使用 录像机 小工具录制电影
- 使用image recorder小工具拍摄快照******
- 使用 录音机 小工具录制音频
- 使用简单的 聊天 功能将其传输给同伴
****至于其他的 widget 库,现在只要点击 这个链接 就可以现场试用了。你将能够尝试所有这些工作流程。
比方说,你想使用连接到电脑的摄像头动态执行图像处理,并运行人脸识别、边缘检测或任何其他复杂的算法。使用 ipywebrtc 真的很容易实现。您需要做的就是创建一个 CameraStream 小部件的实例,创建一个image recorder给定相机视频流作为输入,并实现处理图像的回调(例如使用 scikit-image)。******
Creation of an ImageRecorder taking snapshots of the CameraStream, and process images on the fly using scikit-image
ipywebrtc的另一个很好的特性是能够从任何小部件创建 MediaStream 小部件。这意味着您可以轻松地从您喜欢的小部件库中记录图像和视频,以进行二维或三维数据可视化(此处为 ipyvolume )。
Create a WidgetStream with an ipyvolume widget as input and record a video using the VideoRecorder
一旦你使用了库的这些好特性,你就可以下载你创建的视频/图片了。或者,您可以使用 聊天 功能直接分享。该功能将聊天室名称和您想要共享的流(默认为 CameraStream )作为输入,并允许您将您的 Jupyter 笔记本变成会议室!
Chatroom created live with ipywebrtc during a presentation at PyParis
你可以在 Github 上找到用来制作那些图片的例子:https://Github . com/quant stack/quant stack-talks/tree/master/2018-11-14-py Paris-widgets/notebooks
关于作者
我叫马丁·雷诺,我是 QuantStack 的科学软件工程师。在加入 QuantStack 之前,我就读于 SUPAERO 。我还在巴黎的 Logilab 和剑桥的 Enthought 工作过。作为 QuantStack 的开源开发人员,我参与了各种项目,从 C++的 xsimd 和 xtensor 到 Python 和 Javascript 的 ipyleaflet 和 ipywebrtc 。
VideoFi —简化视频注释和见解查找
看视频很好玩,但是尝试手动分析视频,就没那么好玩了!你可能会错过重要的细节,这是非常耗时的。如果这个过程可以自动化呢?它肯定能让少数人的生活更轻松。
能够在传媒公司工作,一切都围绕着视频。这就像宝藏一样,当我们试图涉足最新的流行词——人工智能时,分析视频是我和我的团队想到的最有用的用例之一。
先决条件
为了分析视频,我们必须采取的第一步是将视频转换成一系列图像。我们用 python 写了代码,用了一个叫做 ffmpeg 的工具。在为 python 安装了 ffmpeg 库之后,我们以每秒 10 帧的速度从视频中提取图像。图像的名称反映了图像帧出现在视频中的时间。有了这个,我们就知道图像在视频中的位置。
可以在 github 这里找到将视频转换为一系列图像的代码。
我们想找的东西
当时,我们一直在使用 AWS API 构建 ML 模型,并认为尝试他们最近的人工智能服务( Amazon Rekognition )—对象检测 API *(现在,对象和场景检测)*和名人识别 API 是一个好主意。
所以实际上,我们的目的是通过找到视频中的物品和名人的标签来发现视频中正在发生的事情。
拼接零件
这是我们用来完成使命的架构图:
VideoFi Architecture
我们将提取的图像上传到 AWS s3 存储桶中。我们通过 Rekognition APIs 发送对每个图像的请求,并收到对每个图像的响应。然后我们过滤数据并使用我们需要的参数。让我进一步解释一下。
名人识别一个图像的请求看起来像这样,其中每个图像被下载到本地机器上并被转换成字节:
client.recognize_celebrities(Image={'Bytes': imgBytes,})
对象检测 API 也有类似的请求。
API 以下列格式返回响应:
{
"CelebrityFaces": [
{
"Face": {
"BoundingBox": {
"Height": 0.6766666769981384,
"Left": 0.273333340883255,
"Top": 0.09833333641290665,
"Width": 0.4511111080646515
},
"Confidence": 99.9476089477539,
"Landmarks": [
],
"Pose": {
},
"Quality": {
"Brightness": 56.59690475463867,
"Sharpness": 99.9945297241211
}
},
"Id": "1SK7cR8M",
**"MatchConfidence": 100**,
**"Name": "Jeff Bezos"**,
"Urls": [
"[www.imdb.com/name/nm1757263](http://www.imdb.com/name/nm1757263)"
]
}
],
"UnrecognizedFaces": []
}
我们用来构建数据库的参数以粗体 (匹配置信度和名称)突出显示。另一个重要的参数是边框,它可以用来在名人的脸周围画框,但是我们没有画那么多。
来自标签检测 API 的响应更简单:
{
"Labels": [
{
"Confidence": 99.25341796875,
"Name": "Skateboard"
},
{
"Confidence": 99.25341796875,
"Name": "Sport"
},
{
"Confidence": 99.24723052978516,
"Name": "People"
},
],
}
我们在这里使用了两个参数(置信度和名称)。
For all you DiCaprio fans — AWS Celebrity Recognition found him!
构建数据库
得到响应后,我们构建了两个独立的表——一个用于名人,另一个用于物品。我们将每个图像的标签和置信度与图像名称、视频名称以及它们在视频中出现的时间戳粘贴在一起。随着我们收到更多的响应,我们不断地向表中添加行。为此,我们使用了 AWS 提供的 RDS DB。
上面讨论的过程的代码可以在这里找到。
我们使用 AWS batch 进行伸缩,以便可以同时运行多个流程。
带有完整管道的 github repo 可以在这里找到。
结果
事实证明,AWS 的对象检测和名人识别 API 的工作相当不错。它非常擅长探测物体,虽然它不能识别每个名人,但它能识别很多名人!
我们在这里学到的一点是,每秒的帧数很重要——每秒 2 或 3 帧无法捕捉到 10 帧所能捕捉到的信息。这是一个完美的数字——既不太高也不太低,给出了我们想要的结果。但是,作为一个起点,使用更少的帧数将是一件好事,因为调用 API 的次数会很少,并且可能会低于 AWS 提供的免费 API 调用限制。
此外,API 返回结果的可信度也起着重要作用——它检测到了许多对象和名人,但它对此并不十分有信心,因此我们以 80%的可信度过滤结果,在应用该过滤器后,结果非常准确。
这是我们项目最终结果的一个简短演示——名人的名字在左上角,物品和标签在视频的正下方。尽情享受吧!
VideoFi in Action
限制
没有什么是完美的,我们的项目和结果也是如此。虽然我们使用的 API 训练有素,但我们缺少的一项能力是——能够用我们想要预测的数据类型(例如 NBA 球员)来训练 API。希望 AWS 在听!😃
结论
这个原型的目的是展示人工智能和机器学习是如何变得如此容易,以至于任何想要解决其用例的人都可以用更少的复杂性和少量代码来完成。不仅仅是 AWS,还有其他云平台,比如 Google Cloud,Azure,IBM 等等。提供类似的服务。
我希望你喜欢这篇文章,并用它来解决至少一个你的 AI 用例。
最后但同样重要的是,我要感谢我的团队成员乔希·库尔茨和瓦伦·沃赫拉,他们是这个项目不可或缺的一部分。
如果您有任何问题或建议,请随时通过 LinkedIn 联系我们,地址是 Shivangi Shroff 和 Varun Vohra 。我们非常乐意与您联系并获得反馈。
“懒惰”人的虚拟环境,或自动环境魔术。
当您努力开发或部署大量不同的 python 项目时,您通常会使用一个 virtualenv 来分离和隔离 Python 环境。这绝对是一个好的实践,不仅对于开发人员,而且对于在生产环境中进行部署的人员也是如此。隔离环境使您的系统保持安全和清晰,也给了您很大的灵活性。
但是,当您更改目录时,经常会忘记激活所需的虚拟环境,或者当您离开时,又忘记禁用它。我发现自己经常这样做,所以我开始思考如何让这个例行程序自动化。嗯,我不是唯一一个有这种想法的人,善良的人们已经采取了必要的措施来解决这个问题。
我想向您介绍几个实用程序,它们可以让您更轻松地配置和自动更改每个目录的不同环境。这个实用程序像标准 bash cd 命令的包装器一样工作。每次当你“光盘”在一些目录,其中包含一些具体的。env 文件,它们为您激活先前配置的环境。还有,你出门的时候,他们会自动停用。还不错。
经过一番搜索,我停在了两个最有趣的项目上, Direnv 和 Autoenv 。你可以选择任何一个,但我更喜欢 Direnv,因为它是一个编译程序,所以我希望它能快一点。
Direnv 易于安装,因为它像一个包一样出现在最流行“apt”和“yum”发行版中,你也可以从源代码安装它几秒钟。
安装 direnv 后,您需要在~/中添加一个字符串。bashrc 文件:
eval "$(direnv hook bash)"
我们已经准备好了一些例子:
$ mkdir /home/projects && cd /home/projects
$ mkdir project1 project2
然后我们需要在两个目录中创建一个. envrc 文件,在 direnv 在目录中找到这个文件后,它将准备/启用新的环境并导出所有列出的本地变量。
出于检查的原因,我们将为每个项目目录声明不同的 python 版本。
$ echo "layout python" > project1/.envrc
$ echo "layout python3" > project2/.envrc
出于安全原因,您需要批准新的或更改的。envrc 文件首先,direnv 会要求您确认。
$ cd project1/
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.$ direnv allowdirenv: loading .envrc
Running virtualenv with interpreter /usr/bin/python
New python executable in /home/projects/project1/.direnv/python-2.7.13/bin/python
Installing setuptools, pkg_resources, pip, wheel...done.
direnv: export +VIRTUAL_ENV ~PATH
在您批准之后,direnv 将继续创建新的 python 2 环境。让我们对 project2 目录执行相同的步骤。
$ cd ..
direnv: unloading$ cd project2/
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.$ direnv allowdirenv: loading .envrc
Already using interpreter /usr/bin/python3
Using base prefix '/usr'
New python executable in /home/projects/project2/.direnv/python-3.5.3/bin/python3
Also creating executable in /home/projects/project2/.direnv/python-3.5.3/bin/python
Installing setuptools, pkg_resources, pip, wheel...direnv: ([direnv export bash]) is taking a while to execute. Use CTRL-C to give up.
done.
direnv: export +VIRTUAL_ENV ~PATH
正如你现在看到的,我们得到了 python 3,让我们“cd”到每个目录,并尝试安装不同的包或库。
$ cd project1/
direnv: loading .envrc
direnv: export +VIRTUAL_ENV ~PATH$ pip install ansible skip skip skip... :) Successfully installed MarkupSafe-1.0 PyYAML-3.13 ansible-2.7.1 asn1crypto-0.24.0 bcrypt-3.1.4 cffi-1.11.5 cryptography-2.3.1 enum34-1.1.6 idna-2.7 i
paddress-1.0.22 jinja2-2.10 paramiko-2.4.2 pyasn1-0.4.4 pycparser-2.19 pynacl-1.3.0 six-1.11.0$ ansible --version
ansible 2.7.1
config file = None
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /home/projects/project1/.direnv/python-2.7.13/local/lib/python2.7/site-packages/ansible
executable location = /home/projects/project1/.direnv/python-2.7.13/bin/ansible
python version = 2.7.13 (default, Sep 26 2018, 18:42:22) [GCC 6.3.0 20170516]$ which ansible
/home/projects/project1/.direnv/python-2.7.13/bin/ansible$ cd ..
direnv: unloading$ ansible
-bash: ansible: command not found$ cd project1
direnv: loading .envrc
direnv: export +VIRTUAL_ENV ~PATH$ ansible
Usage: ansible <host-pattern> [options]
bla bla bla...
正如你所看到的,我们刚刚在 project1 目录中安装了一个 Ansible,在我们离开这个目录之后,所有的环境都被卸载,所以在 project1 目录之外就没有 Ansible 了。同样,当我们返回时,我们将得到可工作的 Ansible 包。
这真的很方便,当您创建一个专用的 Ansible 部署服务器时,将使用这个 Ansible 安装的人可以直接“cd”到所需的目录来获得工作项目,以及所有导出的本地环境和变量。事实上,你可以在这个服务器上有几个不同的 Ansible 项目,有不同的参数和所有你需要的正确配置的环境,只需“cd”到所需的目录。有用,不是吗?
此外,我们可以在。例如,envrc 文件:
$ echo "export FOO=Hello" >> .envrc
direnv: error .envrc is blocked. Run `direnv allow` to approve its content. $ direnv allow
direnv: loading .envrc
direnv: export +FOO +VIRTUAL_ENV ~PATH $ echo $FOO
Hello
您可以在项目主页上找到关于安装和使用的所有附加信息。希望它对你也很方便有用。
祝你好运。
美德信号还是新闻阅读?参议员在推特上相互追随的原因探究
当你上唐纳德·特朗普的推特时,你首先注意到的一件事是他关注的账户很少。截至 2017 年 6 月 13 日,这一数字为 45。新闻 文章的一个号对他关注的账号进行了报道。
所以我就纳闷了,为什么会这样呢?为什么他只关注少数几个 Twitter 账户?但我很快意识到,我真的无法回答这个问题——我不认识唐纳德·特朗普,也不知道他脑子里在想什么。相反,我决定解决一个稍微简单一点的问题:为什么美国参议员在 Twitter 上互相关注?
在 Twitter 上关注某人是一个相对来说没有成本的行为。因此,有人可能会认为这里没有任何有趣的事情发生。然而,当一名参议员(比如说伯尼·桑德斯)追随另一名参议员(比如说苏珊·科林斯)时,两件事情发生了变化。首先,每个人现在都可以观察到一个参议员跟着另一个参议员的事实。也许这可以被认为是这两位参议员喜欢合作的信号。其次,桑德斯参议员的新闻订阅现在将包括柯林斯参议员的活动。这让桑德斯参议员获得了关于柯林斯参议员的有价值的信息
这篇文章探讨的问题是:平均而言,哪种效应占主导地位?参议员们互相跟踪是为了获取信息,还是为了表示合作?请注意,如果参议员相互关注以获取信息,twitter 关注作为合作信号的价值会大幅下降,因为接收的参议员希望他们收到关注,因为其他参议员希望监控他们的 Twitter 内容。
推特网
为了找到这个问题的答案,我需要构建一个数据集,描绘出参议员们在 Twitter 上是如何联系的。我使用 Python 和 Twitter API 来收集这些信息。我稍微清理了一下,然后用 Gephi 绘制出来。由此产生的网络可以在下面看到:
Senate Twitter network: Who follows who in US Senate
我用原力图谱算法创建了这个图像。直观上,彼此连接的节点被拉在一起,而彼此不连接的节点被推开。然后,我把每个参议员的政党作为每个节点的颜色:红色代表共和党,蓝色代表民主党,灰色代表无党派人士。一条蓝线意味着连接来自一个民主党节点。共和党人和无党派人士的红线和灰线相似。最后,节点大小表明他们关注多少参议院账户。
你可以看到民主党人和共和党人在 Twitter 关注方面的明显分歧——大多数人倾向于关注自己党内的人。没有一个参议员会过多地关注另一个政党的 twitter 账户,而不关注自己政党的账户。
此外,两位独立人士:安格斯·金和伯尼·桑德斯的行为相对不同。在这张图表中,桑德斯看起来更像民主党人,而金看起来像中间派。众所周知的两党参议员,如参议员柯林斯,也在中间位置有代表。
乍一看,这看起来很棒。Twitter 网络确实根据党派划分得很好,我们知道两党参议员也位于中心位置。
但是这普遍适用吗?为了检验这个问题,我们需要衡量参议员们是如何合作的。核心假设是这样的:如果平均而言,参议员们相互跟随以表示合作,那么 Twitter 中的网络结构将类似于合作的度量。如果参议员们相互追随以获取新闻,那么 twitter 中的网络结构就不像是合作的尺度。我们对因果关系不感兴趣。
共同赞助法案
合作的好尺度是什么?参议员可以给出的最廉价的合作信号之一是共同提案。法案联合提案只需要你在法案上签字,并没有明确承诺他们会投赞成票,甚至支持该法案。
我使用 python(和 scrapy)访问了国会的网站,收集到目前为止参议院已经审议的所有法案(超过 1200 个法案)的赞助数据。然后我用 Gephi 绘制了这个网络,使用了与 Twitter 网络相同的逻辑:
Senate Co-sponsorship network: Who co-sponsor with who in Senate
关于我是如何生成这个图的,还需要一个额外的说明。你可能会注意到有些箭头比其他的粗。这是因为共同赞助数据的结构方式。用专业术语来说,我们面对的是一个双向网络。两名参议员可能共同发起了多项立法,每个关联的权重就是这些参议员共同发起的立法的总和。
我们注意到一些我们之前看到的相同趋势:我们可以看到共和党和民主党之间的某种分离。伯尼·桑德斯表现得像一个民主党人,安格斯·金是一个中间派,苏珊·科林斯也似乎超越了党派界限(甚至看起来更像一个民主党人而不是共和党人)。)
你还会看到其他动态。麦卡斯基尔在推特上被定位在民主党的中间,但现在是共同赞助网络的中心。我们需要能够更普遍地量化这两种网络结构。
把它们放在一起
我提议的是比较每个网络中特定节点的中心性。图论中的中心性是衡量一个节点有多中心的指标——当你只使用现有的连接时,你可以多容易地到达任何其他节点。有许多中心性度量标准,但是今天,我将集中讨论两个度量标准:中间性和紧密性。
紧密中心性衡量一个节点与其他节点的紧密程度。直观地说,当您可以使用较短的路径到达其他节点时,您的亲密度中心性得分较高。
介数中心性衡量一个节点连接其他节点的位置。直观地说,当你位于大量连接其他节点的路径上时,中间中心性得分就高。
我计算两个网络的接近度和介数,并进行比较。如果它们彼此相关,这将支持我们的假设,即 twitter 关注更多地被用作合作的信号。否则,人们更有可能通过关注 twitter 来获取信息。
我在这里做了一个简单的回归。请注意,我并不特别关心内生性(在某种程度上被解释为“因果关系”,尽管这种解释有点问题),因为我真的只关心 twitter 是否有一些战略方面,我们也可以在参议员如何共同提案法案中看到。此回归的结果如下所示:
重点关注亲密度 _ 共同赞助线。“估计”一栏大致告诉了我 twitter 网络中的亲密度如何跟随共同赞助者网络中的亲密度。这并不重要。让我们来看看中间中心性的结果:
也差远了。从这两张表中我们可以看出,两个网络之间的中心性平均来说并不相似。一般来说,参议员倾向于使用 twitter 作为一种收集信息的方式,而不是信号合作。这是非常整洁的。
警告
不幸的是,这还不是故事的全部。需要讨论一些重要的假设和警告。
假设 1: 共同赞助是没有成本的。我们可以把 twitter 的关注和比尔的共同赞助放在一起的主要原因之一是,我们认为这两者都是免费的。例如,如果共同发起一项法案引入了一笔可观的成本,那么围绕你如何共同发起法案的决定可能与你使用 twitter 表示合作的方式不同。这意味着在 Twitter 上表示的合作可能并不总是转化为这种更昂贵的合作形式。
**假设二:**党派路线无关紧要。这里的另一个重要假设是,参议员不分党派,都以同样的方式对待彼此。这可能是本分析中使用的最不现实的假设。跟随和你在同一个政党的人的决定和跟随和你在不同政党的人的决定可能看起来不同。例如,两个民主党人之间的 twitter 关注的价值可能非常低,因为由于他们在同一个政党中,他们已经有了强烈的合作信号。另一方面,民主党决定追随共和党可能是一个更强烈的信号。在以后的帖子中,我希望探索这个想法。
假设 3: 议案协办“完成”。本届国会刚刚成立 6 个月。也许以共同提案法案为代表的合作还未能充分展现出来。这可以通过在将来使用一套更全面的立法再次查看这一分析来相对容易地解决。
需要远见
我成功地让一辆汽车自动跟踪了一条轨迹,但是我想不出一个更好的标题来写这篇文章。所以,这里引用一句话来代替!
“那些疯狂到认为自己可以改变世界的人,才是真正改变世界的人。”
―史蒂夫·乔布斯
“Think Different” Original Apple Ad Campaign
嗯,我做到了!我终于完成了 Udacity 自动驾驶汽车 Nanodegree 的第一学期。至少可以说,过去的三个月是一段坎坷的旅程,我已经成功地克服了这段时间所面临的障碍,无论是实际上还是象征性的!
在此期间,我花了很多个通宵,大口大口地喝着红牛和咖啡,试图摄入足够的咖啡因来坚持下去,并通过课程抛给你的各种障碍。我曾多次花数天时间研究一个想法,结果却对结果和进展如此失望,以至于完全放弃了它。后来才意识到我一直都是对的,只是在执行过程中犯了一个小小的错误!
事后看来(*剧透警告),这一切麻烦都是值得的!
以下是我对这门课程的想法…
*** 免责声明 :我希望这篇文章能帮助任何人辩论是否要参加这样的课程!我曾计划在完成每个项目后提供一个深入的回顾,但我的时间管理技能又一次让我失望了。因此,我不会对这些项目进行深入的回顾(我的同行已经广泛地讨论过了),而是描述我到目前为止的经历……
我为什么选择这门课程?
去年毕业后,我完全不知道自己下一步想做什么。我在大学的最后一个学期看着周围的每个人都在找工作或者已经申请了一个特定的硕士项目。我知道我想继续深造,但是我不知道该主修哪个领域,我也不想在一家专门招聘工程毕业生的 IT 公司工作。
所以,我决定休息一下,想清楚自己下一步想追求什么。我一直对数学很有兴趣,这也是我完成工程的原因。在大学期间,我还通过使用 Arduino、Raspberry Pi 和 Lego Mindstorms 等原型平台参与许多迷你项目,对机器人技术有所了解。
因此,我把我的重点放在了机器人技术和人工智能领域。在加入 SDCND 之前,我在 Coursera 上完成了 Magnus Egerstedt 博士的“移动机器人的控制”课程,在 Udacity 上完成了巴斯蒂安·特龙本人的“机器人的人工智能”课程。这两门课都很棒,我建议任何想进入机器人领域的人都去上。
我的本科和移动机器人课程让我对机器人的传统控制系统方法有了深入的了解,但我仍然需要获得人工智能方面的知识,以学习其认知应用。
因此,我报名参加 SDCND 并不是为了进入 ADAS( 高级驾驶辅助系统)行业本身,而是为了参加一个主要涉及人工智能和机器人领域的应用特定课程。
我过去在线学习的经历
我过去参加过在线课程,但从未真正完成过任何课程。起初,兴奋和兴趣总是显而易见的,但很快课程就变得像一个单调的例行公事,从而失去了它的魅力。一旦发生这种情况,这门课程被搁置只是时间问题,会被你的日常活动所掩盖。
这是****进行在线学习的最大弊端**。大学教育提供的同龄人和老师之间日常互动的缺乏仍然是激励学生完成手头任务的最大激励因素之一。与同龄人互动产生的恐惧因素是在线课程无法复制的。**
我发现 Udacity 最接近于复制这些特征而没有缺点。它肯定还不完美,但它肯定是下一个最好的选择。我将尽我所能在下面阐述我的观点…
无与伦比的学习方式
****“明天的工作从这里开始”,这是 Udacity 的使命宣言。他们的目标是通过为每个人提供一个在最受欢迎和要求最高的领域获取知识的机会来实现教育的民主化。
他们的工作直到现在都是不可否认的。在很短的时间内(成立于 2012 年),它们已经成为当今最好的 MOOC 之一,我想就我认为它们与竞争对手的区别提供一点见解。
第一学期概述:
特别是 SDCND,每学期花费 800 美元(卢比。53,000)和三个任期的跨度。术语划分如下:
- 学期一:计算机视觉和深度学习
- 术语 2:传感器融合、定位和控制
- 学期 3:路径规划、浓度和系统
每个学期预定为三个月,可以在更短的时间内完成。学期 1 跨越 5 个核心项目,唯一的重点是在计算机视觉、神经网络和深度学习领域建立一个强大的基础和基础。
以下是关于第一学期核心项目的细节,并附有我尝试的一个片段:
- ****车道线检测使用传统的计算机视觉技术(颜色渐变、canny 边缘检测和 hough 变换)
Pipeline Visual
P1 Output Video
2。基于卷积神经网络模型,使用 Tensorflow 构建一个交通标志分类器,该分类器可以基于使用德国交通标志检测基准(GTSRB)数据集设置的 43 个类别,最终预测交通标志。
P2- Traffic Sign Classifier
3。自动驾驶汽车(当然是在模拟器上!)使用行为克隆(在馈入我驾驶机器人绕赛道行驶的数据后学习驾驶赛道)和深度学习。
The Simulator
P3 Output Video
****4。高级车道寻找使用高级计算机视觉技术,如梯度和颜色阈值、透视变换和使用直方图的车道寻找。
Pipeline Visualization
P4 Output Video
5。使用 HOG 技术和监督分类算法(我使用支持向量机)在道路上检测车辆
Pipeline Visualization
P5 Output Video
你可以在这里查看所有这些项目的代码。
这些项目需要调整和进一步的修改,重新审视这些项目,没有一个期限悬在你的头上,将有望使世界变得不同。
优势
很明显,读完这些资料后,我非常喜欢 Udacity 和他们的纳米学位学习方式,尤其是他们的 SDCND 项目。因此,总结一下 Udacity 优于大多数竞争对手以及脱颖而出的主要原因:
- 课程材料: Udacity 投入了大量资源为他们的课程开发高质量的内容,并根据学生的反馈定期更新。为了进一步加强这一点,他们与业内最优秀的人合作,开发获得理想工作所必需的课程材料。提供的课程材料对于完成指定的项目是绰绰有余的。然后提供资源对其进行改进。这提供了一种自由,可以随意摆弄和深入学习刚刚学到的概念。
- ****导师项目:课程中的每个学生都有一名导师。导师的角色是帮助和指导学生克服他们在学习过程中遇到的任何障碍。导师是学生的直接联系点,每周提供有关他们的进展和面临的困难的最新情况。虽然,导师的表现无疑会因人而异,但与他人分享你的目标和进展的行为会让人感到更有责任感,从而推动他们完成这些目标。
- ****项目:课程设置中的核心项目确实令人惊叹。它们很实用,有助于简洁地形象化所学的概念,这使得学习困难的话题变得更容易。这些项目组合起来就像一个拼图游戏,每个项目都是为了教授一个特定的方面,所有在第一学期学到的概念在最终项目中完美地结合在一起。
- ****社区:除此之外,学习这门课程的学生最大的财富是有机会与世界各地志同道合的人交流。Udacity 开发了一个平台,让人们聚集在一起,讨论当今技术世界中最具智慧的话题。由于思维过程因人而异,看到别人对一个概念的理解和他们实现这个概念的想法是令人惊讶的。同样,看到你的同事的工作就像一种催化剂,激励你产生类似的结果,同时也教会你新的概念。
同样值得一提的是…
**# **Udacity 职业支持:除了课程材料,Udacity 还通过提供课程来帮助学生建立个人档案,从而帮助他们改善职业前景。我必须承认,我没有太注意这些,因为我参加课程的主要目的是进一步学习,而不是特别找工作。乍看之下,它看起来确实很棒,而且我有充分的理由相信它非常有帮助。无论如何,更多信息点击这里。
缺点
虽然到目前为止,我对这门课程给予了高度赞扬,但它也不是没有缺点。
- ****留学生招聘:这是很多学生心中的一大问号。Udacity 已经与世界上一些最好的公司合作,如 Mercedez、优步、福特、宝马、英伟达等等。很自然,任何想在自动驾驶汽车行业发展的人都不会介意与他们合作。但是作为一个来自次大陆的人,我知道很多在这里参加课程的人对如何进行这种雇佣缺乏透明度感到特别不安,因为涉及到各种麻烦,如签证审批等。
- 小组项目:我认为 Udacity 应该在他们的纳米学位课程中实施这个项目(至少作为选修项目)。将学生分成小组来完成一个项目将有助于进一步丰富学习体验。小组项目类似于现实生活中很少单独完成的项目。更重要的是,这将有助于培养团队合作、授权、沟通等重要技能。也有助于汇集他们的知识,从而帮助提高。
- 请停止填鸭式的喂养:在过去的几年里,自动驾驶汽车行业的受欢迎程度大幅上升。因此,像 SDCND 这样的课程有很大的需求,因为人们希望转向未来有前途的职业道路。这对于整个领域来说是很好的,但是对球场产生了负面影响。预备组的学生被提供了最低限度的必要资料,包括基本概念和完成项目所需的额外阅读材料。但是,随着时间的推移,为了帮助参加课程的学生清除项目,至少可以说这些项目并不简单,Udacity 提供了越来越多的补充材料来帮助学生清除他们面临的障碍。这严重阻碍了学习过程。在这些涉及大量研究的领域,学会学习是至关重要的,因为一切都还没有弄清楚,需要更多的创新和工作。
你认为呢?
在当今资源有限的世界,没有技术创新的全球化是不可持续的。人工智能是未来之路。一个人能叫进来一个妖孽的那一天(也就是如果它能枯萎当前的风暴!)无人驾驶汽车将到达你的住处,带你到达目的地,这并不遥远,希望不会太遥远。
当然,在这一切成为现实之前,有很多事情(至少可以说是轻描淡写)需要解决。但就我个人而言,我已经对这个领域产生了足够的热情,可以继续努力,展望未来。
以下是马丁·福特的畅销书《机器人的崛起:技术和失业未来的威胁》中关于人工智能现状的摘录:
*“特别是,像谷歌、脸书和亚马逊这样的公司的崛起推动了巨大的进步。从未有过如此财力雄厚的公司将人工智能视为其商业模式的绝对核心——也从未有过人工智能研究如此接近如此强大的实体之间的竞争关系。类似的竞争态势正在各国间展开。在威权国家,人工智能对军队、情报机构和监控机构来说正变得不可或缺。事实上,一场全面的人工智能军备竞赛很可能在不久的将来迫在眉睫。”
― 马丁·福特
硅谷所有领先的科技巨头都对人工智能进行了深入投资,希望实现突破,从而发挥主导作用,创造垄断。
特别看看自动驾驶汽车,深度学习的概念,如神经网络和 ConvNets,已经建立了一段时间,但在该领域没有取得重大进展。这些年来技术的进步,特别是 GPU 的引入,使得硬件最终能够赶上并处理如此大量的数据。
因此,SDC 所谓的领导人都拥有相同的硬件(在某些情况下,不像最近的指控那样同时发生),只是由于他们的软件实现而完全脱颖而出。
由于这一领域的急剧出现和炒作,与人工智能研究携手合作的自动驾驶汽车行业似乎即将取得重大突破!
对于无人驾驶汽车领域的任何人来说,希望未来是令人兴奋的时代,并最终改变好莱坞对该领域的看法……
Total Recall — Johnny Cab!
为什么选择这样的课程?
“数以千计的高技能信息技术岗位的消失,很可能是对知识型就业产生更广泛影响的前兆。”
― 马丁·福特,机器人的崛起:技术和失业未来的威胁
我只想说明一点,这不是一门容易的课程,也不适合所有人。它需要对学习的高度承诺以及灵活的时间安排。Udacity 表示,每周 10 小时左右足以完成课程,但这与我花在这上面的时间相差甚远。大多数概念虽然解释得很好,但本质上是非直观的,因此需要更多的研究。
也就是说,随着人工智能和机器学习的接受度越来越高,越来越多的工作岗位招聘不足,并有被自动化的风险。卡尔·纽波特(Cal Newport)在其畅销书《深度工作:分散世界中专注成功的规则》(Deep Work:Rules for Focused Success in a Distracted World)中创造的“新经济”即将出现。这是他的书的节选,内容大致相同…
“在新经济中繁荣有两个核心能力:
1.快速掌握硬东西的能力。
2.就质量和速度而言,有能力以精英水平进行生产。"
――卡尔·纽波特
像 SDCND 这样的课程为世界各地的学生提供了一个在这些领域工作的完美平台,专注于未来最苛刻领域的实践和应用学习。
虽然,它可能还没有一个标准学位的可信度,但在这样的课程上工作证明了个人有努力工作的毅力,更重要的是愿意学习。在这个时代,终身学习是成功的关键。
作为一个非计算机科学背景的人,这门课程是我迄今为止面临的最大的智力挑战。作为回报,它给人工智能领域注入了非常强烈的吸引力,我希望能在其中工作。我们这一代人面临着创造和想象新技术的艰巨挑战,以确保一个更加和平和繁荣的未来。
“教育是点燃火焰,而不是填满容器.”
― 苏格拉底
该表扬就表扬
我要感谢乌达城提供了一个机会,让我了解目前世界上最令人垂涎的领域之一。我特别感谢奥利弗·卡梅伦、瑞安·基南和大卫·西尔弗以及 Udacity 的其他工作人员,他们确保了课程的体验是一流的。
我还想感谢在课程中我有幸与之互动的许多人,我期待着见到更多的人。
现在我们来看几天后开始的第二学期。超级兴奋开始自动驾驶的机器人方面!
参考
神经网络揭秘:http://www . Welch Labs . com/blog/2015/1/16/Neural-Networks-demystalized-part-1-data-and-architecture(所有 Welch Labs 的视频都值得观看)
P2 深度评论 by 杰伦 (你的文章太神奇了 btw!):https://medium . com/@ jeremyeshannon/uda city-自驾-汽车-纳米度-项目-2-交通-标志-分类器-f52d33d4be9f
****卷积神经网络如何工作作者布兰登·罗尔:【https://www.youtube.com/watch?v=FmpDIaiMIeA】T2&t = 311s
****P3 深度回顾byVivek Yadav:https://chatbotslife . com/learning-human-driving-behavior-using-nvidias-neural-network-model-and-image-augmentation-80399360 efee
试图通过Param Aggarwal:https://medium . com/computer-car/试图实时可视化卷积神经网络-1edd1f3d6c13
克隆汽车模仿人类驾驶byMohan kart hik:https://medium . com/@ mohankarthik/Cloning-a-car-to-mimic-human-driving-5 C2 f 7 e 8d 8 aff
深度回顾由阿莱士:http://navoshta.com/detecting-road-features/****
P5 深度回顾作者 阿纳尔多·冈兹:https://chatbotslife . com/vehicle-detection-and-tracking-using-computer-vision-baea 4 df 65906
查看 聊天机器人生活 更多精彩文章!
麻省理工学院的 SDC 公开课:http://selfdrivingcars.mit.edu
Fast.ai,一个致力于教授深度学习和神经网络的令人惊叹的博客:http://www . fast . ai
你毕业后做什么比你在哪里上学重要得多
如果你喜欢这篇文章,请分享并推荐给任何想参加这类课程的人。谢谢!😃