基于神经网络的城市声音分类
使用深度学习进行声音分类
每天我们都会听到不同的声音,这是我们生活的一部分。人类可以很容易地区分不同的声音,但是如果计算机也能把声音分类,那该多好啊。
在这篇博文中,我们将学习使用带有神经网络的机器学习对城市声音进行分类的技术。该数据集取自一个名为城市声音的分析视频竞赛。该数据集包含 8732 个标记的城市声音摘录,来自 10 个类别:空调、汽车喇叭、儿童玩耍、狗叫、钻孔、发动机空转、枪击、手提钻、警笛和街头音乐。
我将使用 python librosa 库从音频剪辑中提取数字特征,并使用这些特征来训练神经网络模型。
首先,让我们得到所有需要的库,
**import** **IPython.display** **as** **ipd**
**import** **os**
**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**import** **matplotlib.pyplot** **as** **plt**
**import** **librosa**
**from** **tqdm** **import** tqdm
**from** **sklearn.preprocessing** **import** StandardScaler
**from** **keras.models** **import** Sequential
**from** **keras.layers** **import** Dense, Dropout, Activation
**from** **keras.optimizers** **import** Adam
数据集可以在 google drive 中找到,可以从这里下载。
数据集包含保存声音摘录的 train、test 文件夹,并且存在具有每个声音摘录的标签的 train.csv 和 test.csv。我将只使用训练文件夹进行训练、验证和测试,它包含 5435 个标记的声音。
现在让我们阅读 train.csv,它包含有关声音摘录的标签信息。
data=pd.read_csv('/content/drive/MyDrive/colab_notebook/train.csv')data.head()#To see the dataset
让我们听听数据集中的任何随机声音,
ipd.Audio(‘/content/drive/My Drive/colab_notebook/Train/123.wav’)
现在,主要步骤是从数据集中提取要素。为此,我将使用 librosa 库。这是一个很好的音频文件库。
使用 librosa 库,我将从音频文件中提取四个特征。这些特征是 mel 倒谱系数(MFCCs)、tonnetz、Mel 标度谱图和来自波形的色谱图。
mfc=[]
chr=[]
me=[]
ton=[]
lab=[]
**for** i **in** tqdm(range(len(data))):
f_name='/content/drive/My Drive/colab_notebook/Train/'+str(data.ID[i])+'.wav'
X, s_rate = librosa.load(f_name, res_type='kaiser_fast')
mf = np.mean(librosa.feature.mfcc(y=X, sr=s_rate).T,axis=0)
mfc.append(mf)
l=data.Class[i]
lab.append(l)
**try**:
t = np.mean(librosa.feature.tonnetz(
y=librosa.effects.harmonic(X),
sr=s_rate).T,axis=0)
ton.append(t)
**except**:
print(f_name)
m = np.mean(librosa.feature.melspectrogram(X, sr=s_rate).T,axis=0)
me.append(m)
s = np.abs(librosa.stft(X))
c = np.mean(librosa.feature.chroma_stft(S=s, sr=s_rate).T,axis=0)
chr.append(c)
我有 186 个功能,每个音频文件都有各自的标签。
从音频文件中提取特征后,保存特征,因为提取特征将花费大量时间。
mfcc = pd.DataFrame(mfc)
mfcc.to_csv('/content/drive/My Drive/colab_notebook/mfc.csv', index=**False**)
chrr = pd.DataFrame(chr)
chrr.to_csv('/content/drive/My Drive/colab_notebook/chr.csv', index=**False**)
mee = pd.DataFrame(me)
mee.to_csv('/content/drive/My Drive/colab_notebook/me.csv', index=**False**)
tonn = pd.DataFrame(ton)
tonn.to_csv('/content/drive/My Drive/colab_notebook/ton.csv', index=**False**)
la = pd.DataFrame(lab)
la.to_csv('/content/drive/My Drive/colab_notebook/labels.csv', index=**False**)
将特征连接成一个数组,以便传递给模型。
features = []
**for** i **in** range(len(ton)):
features.append(np.concatenate((me[i], mfc[i],
ton[i], chr[i]), axis=0))
对标签进行编码,以便模型能够理解。
la = pd.get_dummies(lab)label_columns=la.columns #To get the classestarget = la.to_numpy() #Convert labels to numpy array
现在归一化的特点,使梯度下降可以更快地收敛。
tran = StandardScaler()
features_train = tran.fit_transform(features)
现在,我将创建训练、验证和测试数据集。
feat_train=features_train[:4434]
target_train=target[:4434]
y_train=features_train[4434:5330]
y_val=target[4434:5330]
test_data=features_train[5330:]
test_label=lab['0'][5330:]print("Training",feat_train.shape)
print(target_train.shape)
print("Validation",y_train.shape)
print(y_val.shape)
print("Test",test_data.shape)
print(test_label.shape)
下一步是建立模型。
model = Sequential()
model.add(Dense(186, input_shape=(186,), activation = 'relu'))
model.add(Dense(256, activation = 'relu'))
model.add(Dropout(0.6))
model.add(Dense(128, activation = 'relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation = 'softmax'))
model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')
这是将用于培训的最终模型。
history = model.fit(feat_train, target_train, batch_size=64, epochs=30,
validation_data=(y_train, y_val))
该模型将针对 epoch =30 进行训练,并且批量大小为 64。
在训练模型之后,它给出了 92%的验证准确度。
现在让我们看看我们的模型将如何在测试数据集上执行。
predict = model.predict_classes(test_data) #*To predict labels*
这将获得现在的值,以获得作为类的预测。
prediction=[]
**for** i **in** predict:
j=label_columns[i]
prediction.append(j)
预测有 104 个测试标签,现在计算有多少是正确预测。
k=0
for i, j in zip(test_label,prediction):
if i==j:
k=k+1
在 104 个标签中,这个模型已经正确预测了 94 个标签,这是非常好的。
在这篇博客中,我们讨论了如何使用 librosa 库从音频文件中提取特征,然后建立一个模型来将音频文件分类到不同的类别中。
本文中的所有代码都驻留在这个 Github 链接上:
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/shubham7169/Projects/blob/master/Urban%20Sound%20Classification.ipynb)
基于 Librosa 的城市声音分类——复杂的交叉验证
使用 scikit-learn 展示“将一个群体排除在外”策略
作者图片[Marc Kelechava]
概述
这篇文章的目的有两个:
- 我将展示一个实现一篇有趣的研究论文的结果的例子,该论文基于音频片段的声音内容对它们进行分类。这将包括 librosa 库的应用,librosa 库是一个用于音乐和音频分析的 Python 包。剪辑是来自城市的短音频剪辑,并且分类任务是预测适当的类别标签。
- 我将展示有效的交叉验证方案的重要性。鉴于我将使用的音频源数据集的细微差别,很容易从录音中意外泄露信息,这会使您的模型过拟合,并阻止其泛化。这个解决方案有点微妙,所以看起来是一个写博客的好机会。
原始研究论文
http://www . justinsalamon . com/uploads/4/3/9/4/4394963/salamon _ urban sound _ acmmm 14 . pdf
论文作者的源数据集
【https://urbansounddataset.weebly.com/urbansound8k.html
他们的数据集摘要
“该数据集包含来自 10 个类别的城市声音的 8732 个标记的声音摘录(< =4s) ):空调、汽车喇叭、儿童玩耍、狗叫、钻孔、发动机空转、枪击、手提钻、警笛和街头音乐。这些类别来自城市声音分类法。
我将从这些声音摘录中提取特征,并安装一个分类器来预测 10 个类别中的一个。我们开始吧!
关于我的代码的注释
我创建了一个回购协议,允许您完整地重新创建我的示例:
- 脚本运行器:https://github . com/Marc muon/urban _ sound _ classification/blob/master/main . py
- 特征提取模块:https://github . com/Marc muon/urban _ sound _ classification/blob/master/audio . py
- 模型模块:https://github . com/Marc muon/urban _ sound _ class ification/blob/master/Model . py
脚本运行器处理从磁盘加载源音频,解析关于源音频的元数据,并将该信息传递给特征提取器和模型。
下载数据
您可以使用研究论文作者提供的表格下载数据,该数据可提取至 7.09 GB:https://urban sound dataset . weebly . com/download-urban sound 8k . html
目录结构[可选部分—如果您想自己运行它]
显然,您可以派生代码并将其重新映射到您想要的任何目录结构,但是如果您想要遵循我的:
- 在你的主目录中:创建一个名为数据集的文件夹,并将解压后的 UrbanSound8K 文件夹放在那里【从‘下载数据’中的链接获得】
- 同样在您的主目录中:创建一个项目文件夹,并将克隆的 repo 放在那里,以*~/projects/urban _ sound _ classification/…*结尾
在代码中,我使用一些方法将每个音频文件提取的特征向量自动写入*~/projects/urban _ sound _ classification/data*
我这样做是因为特征提取需要很长时间,而且你不想做两次。还有检查这些特征向量是否存在的代码。
TL;dr——如果你遵循我的目录结构,你可以简单地运行 main.py 脚本,一切都应该工作!
为什么这个问题需要仔细的交叉验证
请注意,源数据被分成 10 个子文件夹,标记为“文件夹 1”、“文件夹 2”等。
我们有 8732 个四秒钟的各种城市声音的音频剪辑。这些剪辑是由研究论文的作者手动创建的,他们将它们分为几组,如“汽车喇叭”、“手提钻”、“儿童玩耍”等。除了 10 折,还有 10 个类。
折叠数与类别标签没有任何关系;更确切地说,折叠指的是这些 4 秒钟的训练示例拼接而来的未剪切的音频文件。
我们不希望的是模型能够学习如何根据特定底层记录的各个方面对事物进行分类。
我们需要一个通用的分类器,它可以处理各种各样的录音类型,但仍能正确地对声音进行分类。
论文作者关于正确简历的指导
这就是为什么作者为我们预先构建了折叠,并提供了以下值得引用的指导:
不要洗牌数据! 使用预定义的 10 折,执行 10 折(不是 5 折)交叉验证…
… 如果您重组数据 (例如,组合所有折叠的数据并生成随机的训练/测试分割) 您将错误地将相关样本放入训练和测试集,从而导致分数膨胀,无法代表您的模型在看不见的数据上的表现。 简单地说,你的结果会是错误的。
正确方法的总结
- 在折叠 1-9 上训练,然后在折叠 10 上测试并记录分数。然后在第 2-10 层进行训练,在第 1 层进行测试并记录分数。
- 重复此操作,直到每个折叠都作为保持一次。
- 总得分将是来自 10 个不同维持集的 10 个准确性得分的平均值。
重新创建纸质结果
请注意,研究论文没有任何代码示例。我想做的是首先看看我能否用我自己的实现重新创建(或多或少)论文的结果。
然后,如果这看起来是一致的,我将在一些模型改进上工作,看看我是否能击败它。
这是他们的模型精度的快照,来自论文【他们的图像,不是我的】:
图片来自研究论文作者贾斯汀·萨拉蒙、克里斯托弗·雅各布和胡安·巴勃罗·贝洛
因此,我们希望在如图 3a 所示的褶皱上达到高 60%/低 70%的精确度。
音频特征提取
作者图片[Marc Kelechava]
Librosa 是一个优秀且易于使用的 Python 库,它实现了音乐信息检索技术。我最近在这里写了另一篇关于使用 librosa 库的模型的博文。这个练习的目标是训练一个音频类型分类器,这个分类器来自我的个人图书馆的带标签的音频文件(标签=音乐类型)。然后,我使用训练好的模型来预测我的音乐库中其他未标记文件的流派。
我将使用从该练习中学到的一些音乐信息检索技术,并将它们应用于城市声音分类问题的音频特征提取。具体来说,我将使用:
快速了解音频转换[可选]
[我的另一篇博文对这一部分进行了更详细的阐述,如果你对此有特别的兴趣的话]
请注意,从技术上讲,将原始音频源转换为数字矢量并直接对其进行训练是可行的。然而,一个(降采样)7 分钟的音频文件将产生一个长度接近~9,000,000 浮点数的时间序列向量!
即使对于我们的 4 秒剪辑,原始时间序列表示也是一个大约 7000 维的向量。考虑到我们只有 8732 个训练样本,这可能是不可行的。
各种音乐信息检索技术减少了原始音频向量表示的维度,并使其更易于建模。
我们将用来提取特征的技术试图捕捉音频随时间变化的不同特性。例如,MFCCs 描述了声音的频谱包络[振幅频谱]。使用 librosa,我们可以随着时间的推移获得这些信息——也就是说,我们获得了一个矩阵!
特定音频文件的 MFCC 矩阵在 y 轴上具有系数,在 x 轴上具有时间。因此,我们希望汇总这些系数随时间的变化情况(跨 x 轴,或 numpy land 中的轴=1)。假设我们在一段时间内取一个平均值,然后我们得到每个 MFCC 系数在一段时间内的平均值,即特定音频文件的数字特征向量!
我们能做的是对不同的音乐信息检索技术或不同的汇总统计重复这个过程。例如,频谱对比技术也将随着时间的推移产生不同频率范围的不同频谱特性的矩阵。同样,我们可以随时间重复聚合过程,并将其打包到我们的特征向量中。
作者使用了什么
论文作者明确指出了 MFCC。他们提到提取前 25 个 MFCC 系数
每个系数的每帧值使用下面的汇总统计数据在时间上汇总:最小值、最大值、中值、平均值、方差、偏斜度、峰度以及一阶和二阶导数的平均值和方差,得到每个切片 225 维的特征向量
因此,在他们的情况下,他们在不同的汇总统计上不断聚集 25 个 MFCCs,并将它们打包到一个特征向量中。
我将在这里实现一些稍微不同的东西,因为它在前面提到的流派分类器问题中对我很有效。
我认为(对于每个片段):
- 一段时间内 MFCC 矩阵的平均值
- Std。MFCC 矩阵随时间的发展
- 一段时间内光谱对比度矩阵的平均值
- Std。光谱对比度矩阵随时间的变化
- 一段时间内色谱图矩阵的平均值
- Std。色谱图矩阵随时间的变化
我的输出(每个音频片段)将只有 82 维,而不是 225 维,所以建模应该会快一点。
终于有代码了!行动中的音频特征提取。
[请注意,我将在博客文章和 GitHub Gist 链接中发布代码片段。有时 Medium 不能正确渲染 Github Gists,这就是我这样做的原因。同样,所有的文档内代码都可以复制并粘贴到 ipython 终端上,但是 GitHub gists 却不行]。
这里引用我的脚本运行程序:
[## Marc muon/urban _ sound _ 分类
使用 Urban Sound 8K 数据集-Marc muon/Urban _ Sound _ classification 的模型的一系列博客帖子的代码
github.com](https://github.com/marcmuon/urban_sound_classification/blob/master/main.py)
我解析元数据(与数据集一起提供)并获取每个音频文件的文件名、文件夹和类标签。然后这被发送到音频特征提取器类。
AudioFeature 类包装 librosa,并提取您输入的特征作为字符串,如上所示。然后,它还会将每个音频剪辑的 AudioFeature 对象保存到磁盘。这个过程需要一段时间,所以我将类别标签和折叠号与特征向量一起保存在 AudioFeature 对象中。通过这种方式,您可以返回并在以后对提取的特征使用模型。
这个类实现了我之前描述的内容,即随着时间的推移聚合各种音乐信息检索技术,然后将每个音频片段的所有内容打包到一个单一的特征向量中。
建模
作者图片[Marc Kelechava]
由于我们将所有的 AudioFeature 对象放在上面的列表中,我们可以做一些快速理解来获得建模所需的内容:
模型类将实现作者描述的交叉验证循环(记住相关的陷阱!).
提醒一下,这是作者的第二个警告:
"不要只在一个分裂上评价!使用 10 倍(非 5 倍)交叉验证并平均得分
我们已经看到仅提供单次训练/测试分割结果的报告,例如,在第 1-9 倍进行训练,在第 10 倍进行测试并报告单个准确度得分。我们强烈反对这样做。相反,使用提供的折叠进行 10 次交叉验证,并报告平均分数。为什么?
并不是所有的拆分都那么“容易”。也就是说,与(例如)在折叠 2-10 上训练和在折叠 1 上测试相比,模型在折叠 1-9 上训练和在折叠 10 上测试时往往获得更高的分数。因此,在 10 次分割中的每一次上评估您的模型并报告平均准确度是非常重要的。
同样,你的结果将无法与文献中以前的结果相比。"
关于他们的后一点——(这来自论文)值得注意的是,不同的录音/折叠对于片段何时出现在前景或背景中有不同的分布——这就是为什么一些折叠容易而一些折叠困难。
TL;简历博士
- 我们需要在第 1-9 圈进行训练,在第 10 圈进行预测和评分
- 然后在第 2-10 层进行训练,在第 1 层进行预测和评分
- …等等…
- 使用这一过程对测试折叠的分数进行平均将与现有的研究相匹配,并确保我们不会意外地将关于源记录的数据泄露给我们的维持组。
遗漏一组
最初,我根据给定的折叠,使用 numpy 手工编写了上述分割过程的代码。虽然还不算太糟,但我意识到 scikit-learn 以 LeaveOneGroupOut KFold 拆分的形式提供了一个完美的解决方案。
为了向自己证明这就是我们想要的,我运行了来自sk learn 文档的 splitter 测试代码的一个略微修改的版本:
请注意,在这个玩具示例中有 3 个组,“1”、“2”和“3”。
当我将每个训练样本的组成员列表输入到分离器时,它正确地确保了相同的组样本不会同时出现在训练和测试中。
模特班
多亏了 sklearn,这最终变得非常容易实现!
在这里,我添加了一些缩放,但本质上分裂会给我们想要的 CV。在拆分器的每次迭代之后,我在 9 个折叠上训练折叠,并在维持折叠上进行预测。这种情况发生 10 次,然后我们可以对维持折叠返回的 10 个分数列表进行平均。
结果
"""
In: fold_acc
Out:
[0.6632302405498282,
0.7083333333333334,
0.6518918918918919,
0.6404040404040404,
0.7585470085470085,
0.6573511543134872,
0.6778042959427207,
0.6910669975186104,
0.7230392156862745,
0.7825567502986858]
In: np.mean(fold_acc)
Out: 0.6954224928485881
"""
69.5%与作者在他们的论文中对顶级模特的预测基本一致!因此,我感觉很好,这是按照他们的设想实现的。另请注意,他们还显示 fold10 是最容易得分的(我们也有),所以我们也在那里排队。
为什么不为此任务运行超参数搜索?[非常可选]
这就是事情变得有点棘手的地方。
“正常”CV 流程:
如果我们可以任意地训练/测试/分割,我们可以做这样的事情:
- 分离维持测试集
- 从较大的训练部分中,分离出一个验证集。
- 在列车上运行某种类型的参数搜索算法(比如 GridSearchCV)(非 val,非测试)。
- GridSearch 将在训练测试上运行 k-fold 交叉验证,将其分成多个折叠。最后,使用 GridSearchCV 的内部 k-fold 交叉验证中找到的最佳参数在训练部分上重新装配估计器
- 然后,我们采用拟合的最佳估计值,并在验证集上评分
因为我们在第 5 部分中设置了验证,所以我们可以在不同的模型系列或不同的参数搜索范围上多次重复步骤 3 和 4。
然后,当我们完成时,我们将采用我们的最终模型,并使用维持测试集来查看它是否通用,我们还没有触及这一点。
但是这在我们基于 Fold 的 LeaveOneGroupOut 方法中是如何工作的呢?假设我们试图如下设置一个 GridSearchCV:
但是现在,当 GridSearchCV 运行内部拆分时,我们将会遇到使用 LeaveOneGroupOut 解决的相同问题!
也就是说,想象这个循环的第一次运行,其中测试集是折叠 1,训练集是折叠 2-10。如果我们随后将训练集(折叠 2-10)传递到内部 GridSearchCV 循环中,我们将以内部 KFold 案例结束,其中相同的折叠用于内部 GridSearchCV 训练和内部 GridSearchCV 测试。
因此,它将(很可能)在内部 GridSearchCV 循环中过度选择最佳参数。
因此,我不会在 LeaveOneGroupOut 循环中运行超参数搜索。
后续步骤
我很高兴这正确地实现了研究论文——至少在非常接近他们的结果方面。
- 我想尝试从每个例子中提取更大的特征向量,然后按照这里相同的 CV 过程通过几个不同的基于 Keras 的 NN 架构运行这些向量
- 在特征提取方面,我也想考虑类之间错误分类的细微差别,看看我是否能为困难的例子想出更好的特征。例如,它肯定是越来越混乱的空调发动机空转类。为了检查这一点,我在之前的音频博客文章中提供了一些代码,您可以使用这些代码来查看每个类的假阳性率和假阴性率:https://github . com/Marc muon/audio _ genre _ classification/blob/master/model . py # L84-L128
感谢您读到这里!我打算很快写这篇文章的第二部分,讨论接下来的步骤。其他一些可能感兴趣的工作可以在这里找到:
【https://github.com/marcmuon】T3
T5https://medium.com/@marckelechava
引文
J. Salamon、C. Jacoby 和 J. P. Bello,“ 城市声音研究的数据集和分类法 ”,第 22 届 ACM 多媒体国际会议,美国奥兰多,2014 年 11 月。[ACM][PDF][BibTeX
使用 Mask-RCNN/Keras/ArcGIS 从 EagleView 航空影像中分割城市入水口特征影像
一个很有前景的深度学习实践
在我上一篇 博客 中,我谈到了使用 Mask R-CNN 和 deepLabV3+模型,使用 EagleView 超高分辨率影像对建筑物足迹进行图像分割。尽管这两种深度学习模型的输出通常是有希望的,但它们仍然缺少一定的准确性阈值。这是为什么呢?因为地面实况标签的 GIS 数据没有被任何人验证,所以许多地面实况标签或者不准确或者错过了实际的真实对象描绘,这可能潜在地混淆模型分类器。我的好奇心:如果我验证每个地面真实标签并尽可能精确地描绘每个特征,结果会更好、更有希望吗?输出的统计数据是什么,比如训练模型预测的精度和召回率?该模型的预测能否应用于实际工作中,以节省人类数字化仪潜在的耗时工作?
这次我选择入水口作为使用 Mask R-CNN 的训练模型的目标。寻找进水口特征的训练图像提出了几个挑战。进水口遵循一般的椭圆形和三角形模式,但由于多年的环境风化,颜色方案变化很大,有时甚至很难在航空图像上用肉眼发现。模型必须学会不被道路和房屋特征所迷惑,这些特征可以描绘出表面上相似的模式和形状。
为了测试实验并更好地理解模型输出,我亲自在 1 x 1 mile EagleView (Pictometry ) 3 英寸分辨率航空影像(图 1 和图 2)的一个图块顶部确定了 178 个进水口要素(基于之前供应商数字化的要素),并使用 ESRI 的 ArcGIS 软件将每个要素数字化为多边形要素,以获得地面实况标签。在用掩模 R-CNN 训练深度神经网络以从瓦片图像中识别入水口特征之后,将 1×1 英里瓦片图像的另一不同位置馈送给训练的模型,以查看该模型是否能够发现数字化仪遗漏的图像中的入水口特征。该过程产生了更好的结果,因为模型发现了更多人类数字化仪没有注意到或错过的进水口特征。
图 1:用于训练数据的红色轮廓瓦片图像和用于推断的蓝色轮廓瓦片图像。
图 2:用于训练的 20,000×20,000×3 RGB 波段的放大图像。
用 Mask-RCNN 模型训练:
Mask R-CNN 是一种先进的深度神经网络,用于解决机器学习中的实例分割问题。Mask-RCNN 有效地检测图像中的对象,同时为每个实例生成高质量的分割掩模。该方法通过与用于边界框识别的现有分支并行地添加用于预测对象遮罩的分支来扩展更快的 R-CNN。可以阅读研究论文更好的理解模型(图 3)。
图 3:用于实例分割的掩模 R-CNN 框架。来源:https://arxiv.org/abs/1703.06870
ArcGIS Pro 中的【导出深度学习的训练数据】用于导出瓷砖图像和进水口多边形特征,例如分割数据集(图 4)。输出图像的尺寸为 512x512x3,旋转角度设置为 90 度,以生成更多的图像来防止过度拟合,并帮助模型更好地概化。您可以应用传统的图像增强方法来生成更多的模拟图像,您可以在这里参考ImgaugPython 库。对于这个实验,我跳过了增强技术,因为裁剪图像的旋转确实生成了一些增强训练数据集。
图 4:进水口多边形特征(红色)覆盖用于生成训练数据集的图像
生成的训练数据集包含超过 1800 个图像和标签。通过进一步的数据处理以去除没有标记的图像,最终数据集具有超过 1764 个训练图像和标记。我用 32 GB CPU 的戴尔笔记本来训练模型。这是一个相当小的数据集,用于训练深度神经网络从航空图像中提取城市特征。对于应用迁移学习,我从在 ImageNet 数据集上训练的权重文件开始。虽然 ImageNet 数据集不包括进水口类,但它包括许多其他类型的图像,因此经过训练的权重已经学习了许多自然图像中常见的特征,这有助于训练模型。
我使用了令人印象深刻的开源实现 Mask-RCNN 库,MatterPort 在 Github 上构建了这个库来训练这个模型。
需要在类(Utils.dataset)中修改三个主要函数,以将您自己的数据集加载到框架中。参见下面的数据加载实现(图 5)。锚的比率设置为(16,32,64,128,256)以预测进水口特征的较小尺寸。IMAGES_PER_GPU 设置为=1,因此 CPU 可用于训练模型。图像和遮罩的示例(图 6)。
图 5 将训练图像和标签加载到模型
图 6:用于训练的随机图像和标签掩模
迁移学习技术应用于主干网 ResNet-101 模型。我首先用 8 个历元训练最后完全连接的层,以适应进水口要素类,然后用 100 个历元训练整个网络(图 7)
图 7:训练头部层以适应进水口特征
对于 32gb 的 CPU,完成训练过程需要 5 天以上的时间(图 8)。图表显示在特定时期后验证数据集的丢失达到稳定状态。当您的训练数据集很小时,这通常会作为过度拟合而发生。
图 8:训练全网络层 5 天 18 小时
图 9:培训损失图表
这是一个不在训练集中的测试图像,在数字化多边形中有一个进水口特征未被识别(图 10)
图 10:具有人类数字化仪的遗漏检测的测试图像和标签
从上图推断的进水口特征进行比较。有趣的是,通过推理发现了一个缺失的进水口特征。(图 11)
图 11:根据上图推断,确定了缺失的进水口特征。
带有推论的测试图像的另一个例子(图 12 和图 13)。
图 12:测试图像
图 13:从上面的测试图像推断。
然后,我使用一个 20,000 x 20,000 x 3 尺寸的完整 2019 分块图像运行 python 推理脚本,该图像距离训练中使用的分块图像有 3 英里远(图 14)。脚本裁剪并处理 1600 张(512x512x3 dim)图像以进行推理。使用 32GB 内存的 CPU 笔记本电脑完成这个过程大约需要一个小时。缺少进水口轮廓主要是因为使用了非常小的训练数据集和进水口要素顶部的树木覆盖。从该县的不同位置选择几个有代表性的切片作为训练数据集可以提高结果的准确性。
图 14:等于 1600 (512x512x1)个裁剪栅格的完整切片图像推断
我想使用统计精度和召回来衡量输出性能。对于那些不熟悉这些术语的人,这里有一些基本的:
**精度:**由模型分类的所有正例中真正正例的比例
**召回:**分类模型实际检索到的正例总数的分数。
随着二进制交叉熵置信度的阈值设置为≥0.9,该模型在 1 平方英里的推理瓦片范围内选择了 271 个候选者。然后,我手动审查候选人,选择最有希望的一个,并在航空图像中确认了 194 个。精度为 71.58%。召回率为 70.78%。当置信度阈值设置为≥0.75 时,精度下降到 53.98%。但召回率高达 78.11%,这意味着更多的进水口被正确识别,也有许多错误检测的进水口特征。根据项目的不同,我们更有可能最大化召回以检索更多的进水口特征,然后快速处理以手动消除误报。下面是与航空影像叠加的推理进水口要素的放大图(图 15)。
图 15:推断:假阳性例子和阳性进水口特征(红色)
结论:
虽然它是一个相对非常小的数据集,但 Mask-RCNN 使用迁移学习技术为超高分辨率图像分割提供了有希望的结果。通过增加来自该县不同位置的高质量训练数据集和应用数据变化增强方法,可以进一步增强性能的结果。还可以在多年影像中使用该模型来推断用于比较的要素检测,甚至可以使用 ArcGIS 工具模型构建器或任何开源代码进行低成本的要素描绘,以实现业务任务的自动化。更重要的是,上述深度学习训练过程可以应用于其他类型的图像实例或分割案例。综上所述,我要提一个有趣的事实:当我将置信度≥0.75 的结果与 vendor 在推理瓦片上数字化的多边形特征进行比较时。该模型描绘的入水口特征比人类数字化仪描绘的多 67 个,但遗漏了 45 个人类数字化入水口特征。这让我相信,如果我们应用正确的深度学习模型,并且做得正确,ML 或深度学习可以在实际的现实世界项目中使用,并为用户节省大量时间,并创造全新的体验。
1。 【明凯】何,乔治亚·格基奥萨里,彼得·多拉尔,罗斯·吉尔希克 (2018)。Mask-RCNN ,https://arxiv.org/abs/1703.06870v3
*2。*面具 R-CNNhttps://github.com/matterport/Mask_RCNN
3。 U-Net:用于生物医学图像分割的卷积网络:https//lmb . informatik . uni-freiburg . de/people/Ron neber/U-Net/
美国 2020 年人口普查
可视化美国过去 230 年的人口普查数据!
2020 年对所有美国人来说都是特殊的一年——这是美国人口普查年。美国人口普查是世界上最大的人口调查之一,由美国宪法授权。它每十年举行一次,帮助政府决定在哪里建设和维护学校、医院、交通基础设施和警察部门等等。总之,各种人口普查决定了每年超过 4000 亿美元的联邦资金的分配。
为了庆祝这一时刻,我收集了 230 年的美国人口普查数据,并把它们变成了一场条形图竞赛。我记录了进入这个数据项目的所有步骤——这样,如果你想在未来处理类似的项目,你可以遵循它们。
美国人口普查 230 年
早在 1790 年,美国只有 16 个州,总人口略低于 400 万——比今天的洛杉矶市还少!整个纽约州只有不到 35 万人,而人口超过 70 万的弗吉尼亚州是迄今为止人口最多的州。
但这种优势并没有持续很久——随着 1792 年华尔街的建立和战略煤炭和木材港口的建立,纽约迅速成为美国的经济领袖。1810 年,纽约州的居民接近 100 万,成为美国人口最多的州——这一称号在接下来的 150 年里一直保持着!
那么谁拿了第一呢?你猜对了——加利福尼亚!从 1940 年开始,随着航空航天和电子等先进技术的兴起,加州成为美国新的经济强国。平均而言,加州人口每十年增长 400 多万人——这一趋势一直延续至今。
这些只是数据可以向我们展示的一些例子,但还有更多东西需要探索。例如,是什么导致了俄亥俄州人口在 1820 年和伊利诺斯州人口在 1960 年的突然增长?为什么弗吉尼亚的人口在 1860 年后下降了?是什么导致了 20 世纪中期佛罗里达人口的快速增长?
创建美国人口普查条形图竞赛
除了分享一些关于美国的有趣事实,这篇文章还将帮助你解决自己的数据项目,并教你如何使用一些数据科学家最流行的工具。对于所有步骤的深入描述,你可以查看我关于 github.com 的教程。为了展示这些数据,我选择了一个条形图竞赛,这是一个在 2019 年变得非常受欢迎的数据动画工具——在 Twitter、脸书和 LinkedIn 上都有趋势帖子。
数据采集
像几乎所有的数据科学项目一样,我从获取数据开始。我决定使用维基百科精心策划的关于美国人口普查的文章。尽管通常不建议解析来自网络的数据,但在这种情况下,维基百科的美国人口普查页面布局相对一致,因此易于解析。尽管如此,与几乎所有解析的数据一样,需要进行一些清理。为了获得原始数据,我使用了熊猫的读取 HTML 函数。
pd.read_html(
“https://en.wikipedia.org/wiki/1790_United_States_Census”)
数据清理
一旦我得到了原始数据,是时候清理不同的格式,并确保所有的数字看起来合理。一致性检查在数据科学项目中经常被忽视,并可能导致很多麻烦。在我的例子中,年份 1800 与其他年份不太合拍,使用了完全不同的牌桌布局。与其他年份不同的是,1800 年的人口普查数据被分解到不同的地区。
**State**
New York (excluding Duchess, Ulster, Orange co...
New York (Duchess, Ulster, Orange counties)
在这种情况下,我很幸运地在早期发现了这些不一致之处。但实际上,你可能并不总是那么幸运。但是不用担心——继续下去是完全没问题的。一旦您开始可视化您的数据,这些小问题应该会变得更加明显。例如,在我们的例子中,这个误差会导致 1800 年纽约人口突然明显下降。一旦您看到这样的异常,有两种可能的情况:要么发生了很酷的事情,要么您的数据是错误的。两者最好不要混用!
为了解决不同地区的问题,我将行名与当前 50+1 州的名称进行匹配,然后对共享相同行名的所有人口进行汇总。经过一些额外的清理后,数据可以使用了。
数据可视化
一旦数据格式正确,大部分工作就结束了。为了创建条形图动画,我使用了一个名为“繁荣工作室”的应用程序,它似乎为这项任务提供了一个友好的界面和布局。
结论
我希望这个简短的数据项目演练对那些刚刚开始接触数据科学的人有所帮助。要看完整的教程,请去 github.com/AntonMu/Census2020。
即使从这个小数据项目中,我们也可以学到两个重要的经验:
数据清理很重要!
数据清理和一致性检查通常是任何数据科学项目中最耗时的部分,也很少是最迷人的部分。然而,要成为一名成功的数据科学家,你需要投入时间来正确地做这些事情,否则即使是最花哨的模型也无法挽救局面。
使用强大的可视化!
一旦你完成了数据清理——尽情享受吧!我选择用条形图比赛来可视化数据,但是有许多不同的方式来可视化数据,在解决之前探索一些选项是值得的。有时一个简单的表格就足够了,但通常有更好、更吸引人的方法来展示数据并从中学习。强大的可视化的好处是双重的。它可以提高你对数据的理解,并引导你发现数据中需要进一步清理的潜在缺陷。它可以提高你的观众对数据的理解。一个好的视觉效果可以吸引你的观众,并保证你的信息被传达出去——无论是对你的老板,你的家人还是你最好的朋友。
使用 Python 的美国选举 Choropleth
如何创建美国选举结果的时间序列图表
这次美国大选带来了高度紧张,毫无根据的欺诈指控,最重要的是,一些伟大的形象化。至少对数据科学家来说很重要。看起来你在任何地方都看不到展示选举结果的新方法。那么,为什么不多加几个呢?在本教程中,你将学习如何使用 Python 创建一些你自己的可视化。
来源:作者
您将学习如何创建两个从 1976 年到 2016 年美国总统选举结果的互动合唱曲。第一张地图有一个时间滑块。当您移动滑块时,地图将会改变以显示给定年份每个州的结果。对于第二张地图,每个州都变成了一个按钮。您可以单击状态来查看一段时间内的投票趋势。我们会检查代码,你可以在 GitHub 上找到完整的项目。你也可以在这里下载的地图。您应该能够在浏览器中打开并浏览它们。
来源: flaticon
Python 包
我们将使用叶子来构建地图。这是一个非常有用的软件包,用于创建简单的地理空间数据可视化。除了 leav,我们还将使用一些其他的 Python 包。您可以使用下面的代码导入它们。确保你已经安装了所有的软件包。
数据源
美国形状文件
我们需要的第一个数据集是一个美国形状文件。shapefile 是一种用于存储地理空间矢量数据的文件格式。在我们的例子中,我们有一组定义美国各州边界的坐标。我们将数据作为地理数据框读入。数据框的 51 行中的每一行都给出了国家的名称和坐标(即几何图形)。
让我们使用这个 shapefile 来创建我们的第一个叶子地图。在下面的代码中,我们初始化了地图。通过设置 location=[50.77500,-100],地图打开时会聚焦美国。然后,我们使用 US shapefile 和 GeoJson 函数向地图添加一个 choropleth。在图 1 中,您可以看到这段代码创建的地图。shapefile 为我们提供了一个工作基础,但我们需要另一个数据集来获得选举结果。
图 1:美国形状文件 choropleth
选举结果数据集
对于选举结果,我们使用麻省理工学院选举数据和科学实验室提供的数据集。它包含了 1976 年至 2016 年的美国总统选举结果。该数据集包含每个州、年份和当年参选的候选人的一行。为了使事情变得简单一点,我们应该首先将这个数据集转换成不同的格式。
使用下面的代码,我们将数据集转换成一个嵌套字典。对于每一年,我们都有一个以州名为关键字的字典。对于每个州,都有一本字典给出民主党和共和党候选人的票数。该词典的格式如下:
{
<year>: {
<state> : {'dem':<#votes>, 'rep':<#votes>},
<state> : {'dem':<#votes>, 'rep':<#votes>},
...},
...
}
将数据可视化
在我们进入交互式地图之前,让我们使用这些数据集来创建一个简单的 choropleth。我们首先需要定义两个函数。 state_style 函数返回一个字典,用来定义一个州的颜色和边界。在某一年,如果一个州投了民主党的票,它就变成蓝色;如果它投了共和党的票,它就变成红色。根据是由 style_dictionary 还是 style_function 使用,该函数返回的词典略有不同。
对于这个 choropleth,我们将使用一个样式 _ 函数。GeoJson 包使用此函数将 GeoJson 要素映射到样式。在我们的示例中,GeoJson 要素将包含状态信息(即名称和几何)。这些特征由 GeoJson 包传递给 style_function 。通过设置 year=2016,我们使用 2016 年选举的结果来定义每个州的风格。
我们现在可以使用这些函数来创建我们的第一个 choropleth。该代码与我们用来创建第一张地图的代码非常相似。唯一的区别是我们现在将 style_function 传递给 GeoJson 函数。如前所述,这给每个州一种基于选举结果的颜色。生成的地图如图 2 所示。现在,让我们看看如何改进这张地图,使它更具互动性。
图 2: 2016 年选举结果
地图 1: Choropleth 滑块
我们首先创建一个带有时间滑块的 choropleth 地图。使用函数 TimeSliderChoropleth 完成。该函数假设所有日期都是 Unix 时间格式(即时间戳)。因此,我们使用 year_to_ts 函数将选举年份转换为时间戳。例如,2016 年将被转换为“1451606400”。
我们需要定义的第二个函数, style_dictionary ,返回一个样式字典。这与 style_function 类似,只是我们现在处理的是时间序列数据。所以,对于每一个州,我们需要定义从 1976 年到 2016 年每一年的风格。 style_dictionary 函数返回如下形式的嵌套字典:
{
<ID>: {
<timestamp> : {'opacity':1, 'color':<hex_color>},
<timestamp> : {'opacity':1, 'color':<hex_color>},
...},
...
}
上面提到的 ID 是给予一个国家的唯一 ID。由自动分配。to_json() 函数。TimeSliderChoropleth 使用这些 id 将状态映射到它们的样式。因此,为了确保我们有正确的映射,我们首先创建一个从 ID 到州名的映射。这是在下面的第 7 到 13 行中完成的。该函数的其余部分用上面看到的形式创建字典。
我们现在准备创建我们的地图。同样,代码与之前类似,只是我们使用了 TimeSliderChoropleth 函数并传入了一个样式字典。代码的结果如图 3 所示。你可以滑动地图上方的滚动条来查看不同时间的选举结果。例如,从 2012 年到 2016 年,我们可以看到几个州变红。这导致了共和党候选人的胜利。
图 3: Choropleth 滑块
我们应该提到上面第 6 行中保存地图的代码。这一行将地图保存为 HTML 文件。您可以在任何浏览器中打开并浏览它。如果您正在使用 jupyter 笔记本,地图也会显示在您的代码块下方。如果地图太复杂,笔记本可能会出现渲染问题。在这种情况下,您必须保存地图并在浏览器中打开它,然后才能看到它。
地图 2: Choropleth 按钮
对于下一个地图,我们将把每个州变成一个按钮。你可以点击状态来查看一段时间内的投票趋势。首先,为了创建这些趋势图表,我们使用下面的代码。函数为给定的状态创建一个标准的 matplotlib 图表。在最后几行中,我们将图表转换成 HTML,并将其添加到 IFrame 中。这是为了能够嵌入到我们的叶子地图中。您可以在图 5 中看到为加利福尼亚制作的图表示例。
图 5:加州投票趋势
在创建按钮 choropleth 之前,我们必须定义最后一个函数。highlight_style 函数用于定义当鼠标悬停在一个状态上时该状态的样式。当这种情况发生时,状态会变得稍微有点阴影。这让我们可以在点击鼠标之前看到它的状态。
最后,为了创建地图,我们首先使用 2016 年的结果创建一个 choropleth。我们使用与图 2 中的地图完全相同的代码来实现这一点。然后,使用每个状态的几何图形,我们创建一个状态标记,并为每个标记添加一个弹出窗口。每个弹出窗口都包含一个上面讨论过的嵌入式图表。单击时,标记将显示弹出窗口,我们将能够看到投票趋势。
您可以在图 4 中看到这段代码的结果。您可以看到悬停在一个状态上是如何突出显示它的。德克萨斯和加利福尼亚也被点击来揭示他们的趋势。在笔记本中查看这张地图可能会有一些困难。在这种情况下,将其保存为 HTML 文件并在浏览器中打开。
图 4: Choropleth 按钮
与本文不同的是,美国大选还没有完全结束。在我写这篇文章的时候,还有一些选票需要统计。当他们完成时,我们将能够用 2020 年的数据更新可视化。我们会看到一些州改变颜色,而其他州的投票趋势将保持不变。这些变化的原因很复杂。像这样的观想有助于我们理解它们。
图像来源
所有图片都是我自己的或从www.flaticon.com获得的。在后者的情况下,我拥有他们的高级计划中定义的“完全许可”。
历代美国总统的声音
使用自然语言处理和主题建模分析总统历史中词语的信息、情感和复杂性。
皮特·苏扎拍摄的白宫官方照片
“言语就是力量:言语是为了说服、转化和强迫。”—拉尔夫·瓦尔多·爱默生
自美利坚合众国诞生以来,美国总统的演讲既反映了国家的现状,也呼吁改变总统认为国家应该走的方向。
总统演讲提供了国家领导人的想法和对国家发展方向的希望,以及他们打算如何利用自己的力量来推动这个方向。他们传递的信息将影响公众对信息的接受和采取行动的能力。
我使用自然语言处理和无监督学习的数据科学技术和工具,通过检查 990 多份总统演讲的情绪、演讲的复杂性和内容的重点,来更好地理解总统对演讲力量的使用。然后,我会按时间和政党寻找趋势、模式和其他见解。
从乔治·华盛顿 1789 年的第一次就职演说到吉米·卡特 1977 年的全国能源演讲,再到唐纳德·特朗普的 2019 年国情咨文,迄今为止(2020 年)每一位总统的演讲都在该项目*中进行了分析。
至此,以下是我的发现…
美国总统的感悟
使用的工具:text blob的极性和主观性
语音情绪以两种方式测量:极性(即语气中更多的负面/悲伤到语气中更多的正面/快乐)和主观性(即更多的基于事实到更多的基于观点)。
以下是情绪分析结果,其中每个点代表不同的总统,每种颜色代表一个政党>
作者截图
正如你在图表中看到的,没有强烈的颜色聚类,这意味着总统的情绪似乎没有明显的党派区分——这似乎更像是个人的转变。
在这里你可以看到共和党总统的名字>
作者截图
这里你可以看到民主党总统的名字>
作者截图
从这些图表中,我们可以看到,例如,与其他美国总统相比,富兰克林·皮尔斯的语气平均更消极/悲伤,内容更真实,而唐纳德·川普的语气平均更积极/快乐,内容更固执己见。
请记住,极性和主观性并不能告诉我们总统在说什么;一位总统可能会说一些积极的话,但它可能会对人们产生负面影响。这种情绪分析只能告诉我们总统是如何传递这些内容的,以及他们是否在用事实或观点来支持他们的声明。
美国总统演讲的老练度
使用的工具:textstat的成绩等级分析
“演讲的复杂程度”是基于一个人需要达到什么样的等级水平才能阅读文本的衡量标准——这里指的是在听到演讲时完全理解它所需的等级水平。
下图显示了这些年来每篇演讲是如何按照理解它所需要的等级来评分的。颜色仍然代表政党>
作者截图
从图表中我们可以看到,在美国早期,总统们的演讲有更高的诡辩性,平均来说需要大学水平或更高的教育水平才能读懂。大约在 20 世纪 20 年代,演讲的复杂程度有下降的趋势,这种趋势一直持续到今天。一个潜在的原因可能是总统自己的词汇,也可能是一个更加精心策划的决定;20 世纪 20 年代是收音机在家庭中变得更加普及的时期——随着更多的人能够听到总统的演讲,总统们是否改变了他们的词汇,以更广泛地与听到他们的公众联系起来?这种分析不能明确地告诉我们,但这是一个有趣的探索领域。
还要注意的是,所有年级的政党都是混合的,这表明在政党言论的复杂性方面没有明显的差异。
美国总统演讲的话题
使用的工具:使用 gensim 的 LDA 模型 的无监督主题建模
现在让我们试着更好地理解总统演讲的内容。
使用潜在狄利克雷分配(LDA)主题建模,总统演讲的七个主题被确定为:
- 美国工作和家庭帮助与需求
- 法律、宪法和权利
- 法律、条约和行动
- 公共权力和职责
- 与美国自由的战争
- 工作与商业
- 世界和平与战争和武力
在这些主题之间需要注意的是词语的定位和平衡,例如看“美国自由战争”和“战争与武力世界和平”,其中一个目标与其他目标缓冲,例如战争…拥有美国的自由。或者寻找世界和平…但也会有战争和武力。
以下是这些年来总统演讲中七个主题的趋势>
作者截图
同样,我们看不到政党之间在演讲主题上有很大的区别,相反,随着时间的推移,我们看到了更多的区别。在美国发展的最初几年,我们看到“法律、条约和行动”和“公共权力和义务”更为常见。近年来,我们看到“美国的工作和家庭帮助和需求”、“战争和武力的世界和平”和“美国自由的战争”更受总统们的欢迎。
让我们换一种方式来审视这些话题,通过按照美国不同的历史时期来看一个话题在美国历史的什么地方出现过。颜色代表每个政治演讲主题>
作者截图
从这个图表中我们可以看出,某些历史时期似乎是总统演讲主题的结束或开始。例如,在新政时期,我们第一次看到“美国工作和家庭”成为总统演讲的主要话题,此后我们继续看到它出现在几乎每个时代。
调查结果摘要
总之,这个项目的分析告诉我们:
- 情绪似乎因总统而异,不一定因党派而异。
- 演讲中用词的“复杂性”多年来一直呈下降趋势。
- 演讲的主题随着时间的推移和政党的不同而变化。
- 演讲的主题似乎与国情和公众关注的问题有关。
- 历史时期可能是几代人演讲话题转变的催化剂。
最后,我想再次强调,这一分析显示了一些趋势和模式,但同样重要的是向我们表明,从表面上看,不同总统和政党的讲话语气和定位可能有相似之处。考虑到这一点,我们都需要关注总统演讲的深层实质,以做出明智的投票和明智的支持。这可能不是一个新发现,但却是一个重要的提醒。
感谢您的阅读,希望您对这篇分析和见解感兴趣。如果您有任何意见、问题或只是想联系,请通过 LinkedIn 联系我。
关于这项工作的几点说明:
- 请记住,派对会随着时间的推移而演变和改变——就像人一样。今天的民主党人并不一定拥有与 1850 年时相同的议程或价值观。因此,在进行政党层面的分析时,应该考虑到这一点。任何关于政党的见解都是一种概括,而不是一种硬性的结论。
- 我目前是 Metis 的一名数据科学学生,每天都在学习。这项工作是我最近在数据科学领域所受教育的应用,但我仍在该领域不断成长,因此随着技能的进步,我希望重新审视和更新我的发现。我欢迎任何关于未来迭代的建议。
- 我所有的图表都是在 Tableau 中制作的,并根据兴趣与过滤选项进行交互。本博客中显示的图表是那些 Tableau 图表的截图。
非常感谢 Joseph Lilleberg,他从弗吉尼亚大学米勒中心的 网站 收集了所有总统演讲的文字记录,并把它们放在【Kaggle.com】的一个易于使用的 csv 文件中供公众使用。也感谢米勒中心使原始抄本可供公众查阅。
美国事故数据分析
对 2016 年 2 月至 2019 年 3 月全国交通事故数据进行分析。
来源:https://unsplash.com/
介绍
近来交通事故变得非常普遍。T2 每年有近 125 万人死于交通事故,T4 平均每天有 3287 人死亡。此外,每年有 2000-5000 万人受伤或致残。道路交通事故是第九大死亡原因,占全球死亡总数的 2.2%。全球道路交通事故造成了 5180 亿美元的损失,单个国家的损失占其年度国内生产总值的 1-2%。
在美国,每年有超过 37,000 人死于车祸,235 万人受伤或致残。美国每年因交通事故损失 2306 亿美元,平均每人 820 美元。交通事故是出国旅行的健康美国公民每年死亡的最大原因。
(来源)
考虑到交通事故的严重性,我决定分析事故数据以发现一些有用的东西。我在这里,分享我的成果。
数据
数据集取自 Kaggle 。你可以在这里 找到。
这是一个全国范围的交通事故数据集**,涵盖了美国 49 个州。从 2016 年 2 月到 2019 年 3 月持续收集数据,使用几个数据提供商,包括两个提供流交通事件数据的 API。这些 API 广播由各种实体捕获的交通事件,例如美国和州交通部、执法机构、交通摄像机和道路网络中的交通传感器。**
数据集包含 **2,243,939(224 万)**行和 49 列(相当大的数据集)。需要注意的一点是,尽管数据集只包含三年的数据,但已经有 224 万起事故。
功能描述
如前所述,数据集包含 49 个要素,以下是对它们的描述。
数据集的要素描述
方法
在进入分析部分之前,让我们看看数据集中存在的空值。
下图仅显示了那些具有空值的要素。
具有空值的要素
探索性数据分析
我将首先从消除不必要的功能开始。
特性 Country 只包含一个条目——USA,这是显而易见的,因为我们处理的是美国的数据集。因此,我将删除此功能。
特征 Turning_Loop 也包含一个值——False。这意味着在任何事故附近都没有转弯环路。因为这个特性只包含一个值,所以我也将删除它。
让我们来看看源的特性。它代表报告事故的 API。
每个来源报告的事故数量
只有三个 API 来源报告了事故。可以看出,大多数事故(约 170 万起)是 MapQuest 报告的,其次是 Bing。
联邦法律正式规定美国有九个标准时区。整个 50 个州和哥伦比亚特区有六个主要时区。
在这六个重要时区中,我们看到(从下图中)数据集中只有四个时区。
大多数事故发生在时区上:东部标准时间,然后是太平洋标准时间。
数据集由一个令人兴奋的特性组成: TMC。 在谷歌上快速搜索会得到以下信息:
交通消息信道(TMC) 是一种向机动车驾驶员传递交通和出行信息的技术。它使用 ALERT C 或 TPEG 协议被数字编码成 RDS 类型 8A 组,通过传统的 FM 无线电广播传送。它也可以通过数字音频广播或卫星广播传输。TMC 允许在不中断音频广播服务的情况下,以用户语言无声地传递适合再现或显示的动态信息。
现在,让我们绘制出与 TMC 特征相关的事故数量。
相对于 TMC 的事故数量
该图显示大多数事故的 TMC 为 201。你可以参考 TMC 代码表来更好的理解。
最令人兴奋的特性是*的严重性。*代表事故的严重程度。
每种严重程度的事故数量
该图描述了大多数事故的严重程度等于 2(平均),然后是 3(高于平均),这是不幸的。几乎没有严重程度非常低(0 和 1)的事故。
让我们看看开始时间和结束时间的特性:
开始时间和结束时间特征
开始时间和结束时间特征描述了事故的开始和结束时间。为了更好地理解,我计算了每次事故的持续时间。
有趣的是,事故的持续时间从几分钟到几年不等。
前 10 个值的事故数量与持续时间
上面的图没有下面的图重要,但是,我想检查最常见的持续时间。大约 950,000 起(43%)事故持续时间为 29 分钟,然后是 6 小时。
需要注意的一点是,数据集描述告诉我们 Start_Time 和 End_Time 代表事故的起止时间。尽管一些事故的持续时间(通过取开始时间和结束时间之差计算)以小时计,甚至以月和年计,但一次事故持续几天或几年并不明显。也许这两个特征也包括修复时间,没有太多可以得出的结论。
查看每起事故持续时间的一个更重要的方法是查看持续时间单位。
每个持续时间单位的事故数量
该图描述了大约 77%的事故持续时间为分钟,而大约 22%的事故持续时间为小时。只有 52 起事故持续了几年,975 起事故持续了几天。这意味着持续时间更长的事故在美国很少发生。此外,持续时间短的事故更加频繁。
现在,让我们来看看每种严重程度的事故随时间变化的趋势。
每种严重程度的事故数量与时间
可以观察到,随着时间的推移,每种严重程度的事故数量都在增加。这令人担忧,需要采取严肃的行动。即使 2017 年事故数量有所减少,但在第 12 周左右,事故数量在那之后有所增加。严重度= 2 的事故更频繁,增加最多,其次是严重度= 3 的事故。
Start_Lat 和 Start_Lng 功能非常有趣,因为它们可以绘制在地图上,以获得事故的准确位置。首先,我将绘制两者之间的散点图。
散点图看起来不错,但同时,令人担忧的是,几乎美国的每个角落都被覆盖,这意味着在过去几年中,事故发生在大量的地点。
为了得到一个清晰的概念,我用美国地图上数据集给定的每个严重程度的坐标标绘了事故地点。
上面的情节看起来很乱!所以我们来分解一下。
严重性= 0 的事故
严重性= 1 的事故
严重程度= 2 的事故位置
严重程度= 3 的事故位置
严重程度= 4 的事故位置
我已经分别标出了每个严重程度的位置。
从上面的图表中,我们可以得出结论,大多数事故发生在美国的东部和西部,这说明了大多数事故发生在时区:东部标准时间和太平洋标准时间。
现在,让我们看看距离(mi) 特性。此功能显示受事故影响的道路长度(以英里为单位)。
上面的情节描述了大多数事故对道路的影响很小。
现在让我们看看美国最容易发生事故的城市。
事故数量最多的 10 个城市
我们看到大多数事故发生在休斯顿,其次是夏洛特和洛杉矶。
让我们看看美国最容易发生事故的州
事故数量最多的 10 个州
这里给出了美国各州及其代码的列表。
该图显示,加利福尼亚州的事故数量最多,其次是德克萨斯州和佛罗里达州。有趣的是,加利福尼亚州的事故数量几乎是德克萨斯州事故数量的两倍。
我们可以看到,美国最容易发生事故的城市是德克萨斯州的休斯顿,其次是北卡罗来纳州的夏洛特和加利福尼亚州的洛杉矶。
让我们更深入一点,绘制出与邮政编码相关的事故数量。
事故数量与邮政编码
可以看出,大多数事故发生在邮政编码为 91706 的地区,其次是 91765 和 91761。参考此链接了解更多关于邮政编码的信息。
现在让我们看看可见性(mi) 特性。它以英里表示能见度。
事故数量与能见度(mi)
该图显示,大多数事故发生在能见度高的时候,这意味着能见度不是发生事故时的一个重要问题。这是显而易见的,因为低能见度不是唯一的因素。
现在让我们看看事故发生时的天气情况。
事故数量与天气状况
该图描述了大多数事故的天气状况是晴朗的,随后是阴天,大部分是多云。与晴天不同,阴天和大部分时间多云是事故的合理因素,这意味着天气条件也不发挥重要作用。
让我们看看便利设施功能。该特征指示附近位置的便利设施的存在。
事故数量与舒适度
我们看到,几乎所有(98.84%)事故都没有无障碍设施,这很不幸。
现在我们来看看凹凸特征。该特征表明附近位置存在减速带或减速带。
事故数量与颠簸
我们看到 99.99%的事故都不是因为减速带。
这样,我们就结束了这个分析。
结论
对取自 Kaggle 的美国事故数据集进行了分析,并在上文讨论了结果。
我们发现了很多令人兴奋的事情,比如我们知道了美国哪个城市或州发生了最多的事故,我们甚至在地图上绘制了结果,还考虑了事故的严重程度。
希望你能了解一些东西,并喜欢这篇文章!!
对计数数据使用负二项式
提高你的统计游戏
负二项分布是一种离散概率分布,您的计数数据工具包中应该有这种分布。例如,您可能有关于某人在购买前访问的页面数量的数据,或者与每个客户服务代表相关的投诉或升级数量的数据。给定这些数据,您可能希望对过程进行建模,然后查看一些协变量是否会影响参数。在许多情况下,你可能会发现负二项分布非常适合。
在这篇文章中,我们将介绍分布,并计算其概率质量函数(PMF)。我们将通过使用二项式定理来涵盖它的基本属性(均值和方差)。这与通常的治疗方法形成对比,通常的治疗方法要么只是给你一个公式,要么使用更复杂的工具来得出结果。最后,我们将转而关注分布的解释。
负二项分布
假设你要掷一枚有偏向的硬币,硬币有正面朝上的概率 p ,我们称之为“成功”此外,你将继续抛硬币,直到在 r 成功。设 k 为沿途失败的次数(所以 k+r 抛硬币总共发生了多少次)。
在我们的例子中,我们可以想象:
- 用户可能会浏览您的网站。在每一页上,他们有 1%的概率看到他们想买的东西。我们想象当他们把物品放入购物篮时,他们准备结账。k 是他们会浏览但不会购买的页面数量。当然,我们将希望拟合模型以找到 r 和 p 的真实值,以及它们是否/如何在用户之间变化。
- 客户服务代表通常会收到投诉。接到投诉后,有概率 p 被训斥。然后,在被责骂几次之后,他们会因为行为的改变而停止抱怨。 k 是他们在改变行为之前没有被训斥的投诉次数。
你是否真的认为这是真的,一如既往,取决于你之前的信念和模型与数据的吻合程度。还要注意,失败的次数与事件的次数密切相关(k 对 k 加 r)。
使用一些组合学来写下概率质量函数是相对简单的。第 r 次成功发生在第(k+r)次抛硬币上的概率是:
- 第一次k+r–1翻转成功r–1的概率,次
- 第( k+r)- 次翻转成功的概率。
在第一次 k+r–1 次翻转中,有(k+r–1)次选择 k 次*(r–1)次成功和次 k* 次失败。(将 k A 和(r–1)B 排列成一行的方式的数量)。每一个都有相同的发生概率。这给了 PMF:
希望你记得一些关于组合和排列的基本事实。如果没有,这里有一个简单的事实回顾,你可以说服自己来帮助你。假设有 3 个 A 和 2 个 B,你想把它们排列成一个类似“AAABB”或“ABABA”的字符串。这样做的方法有 5 个选择 2(总共有 5 个东西和 2 个 B)这与 5 个选择 3(有 3 个 A)相同。为了看到这一点,假设每个字母实际上是一个不同的符号(所以这 5 个符号是 A1、A2、A3、B1、B2)。然后还有 5 个!=120 种排列不同符号的方式。但是有 3 个!=6 种在不改变 A 的位置的情况下重新排列 A1 A2 A3 的方法,以及 2!=2 种排列 B 的方法。所以总数是 5!/2!3!= 10.
诀窍是,二项式也适用于负数或者非整数。例如,如果我们扩展上面的内容,我们可以给分子中的每个 k 项添加一个减号:
负二项分布作为实际的负二项分布
因此得名“负二项式”
需要记住的另一个技巧是,我们可以用非整数来定义二项式。利用γ函数(γ函数)满足的事实,对于正整数 n ,
Gamma 函数扩展了阶乘
我们可以将二项式系数写成如下形式
n 不是整数的二项式系数
这使我们能够允许,在负二项分布中,参数 r 不必是整数。这将是有用的,因为当我们评估我们的模型时,我们通常没有办法将 r 约束为整数。因此, r 的非整数值不会有问题。(然而,我们将要求 r 为正数)。我们将回到如何解释非整数值的 r 。
负二项分布的性质
我们想计算期望和方差。作为热身,让我们检查负二项分布实际上是一个概率分布。为了方便起见,让q = 1–p。
负二项分布实际上是一种概率分布
关键点是第三行,这里我们使用了二项式定理(是的,它适用于负指数)。
现在让我们来计算期望值:
负二项分布的期望值
为了得到第三行,我们使用了恒等式
我们再次使用二项式定理得到倒数第三条线。
警告:这与你在维基百科上看到的相反。这是你将从Wolfram(Mathematica 的制造者)中找到的。这是因为维基百科考虑的是失败之前成功的次数,而我们计算的是成功之前的失败次数。一般来说,有各种类似的方法来参数化/解释分布,所以当在不同的地方查看公式时,要小心你的一切都是直的。
接下来,我们可以分两步计算方差。首先,我们重复上面的技巧,这次使用两次恒等式得到第三行。我们再次使用二项式定理来计算总和,并获得倒数第三行。
现在我们可以计算:
负二项分布的方差
同样,这与维基百科上的内容相反。
负二项分布的解释
我们已经介绍了负二项分布的“定义解释”:它是成功发生之前的失败次数,每一步成功的概率是 p。但是也有一些其他的方法来看这个分布,这可能是有启发性的,也有助于解释 r 不是整数的情况。
过分散泊松分布
泊松分布是一个非常简单的计数数据模型,它假设事件以一定的速率随机发生。然后,它对给定时间间隔内将发生多少事件的分布进行建模。在我们的例子中,它会说:
- 客户服务代表不断收到投诉。计数的变化只是由随机变化决定的。(比较他们的行为最终改变的模型)。同样,在对此进行建模时,我们可以基于外生协变量对代表之间的比率差异进行建模。
泊松分布的一个大问题是方差等于均值。这可能不符合我们的数据。假设我们用均值λ和停止参数 r 来参数化负二项分布。那么我们有
负二项分布的重新参数化
我们的概率质量函数变成了
均值λ参数化的负二项分布的概率质量函数
现在让我们考虑如果我们把极限取为 r →∞保持λ不变会发生什么。(这意味着成功的概率也趋向于 1,按照 p=r/[λ+r]定义的方式)。在这个极限中,二项式接近(–r)的 k 的幂除以 k!并且 r + λ接近 r。
均值λ固定的大 r 的负二项式的极限
在最后一行,r 的 k 次方相消,我们使用了指数的定义。结果是我们恢复了泊松分布。
因此,我们可以将负二项分布解释为泊松分布的推广。如果分布实际上是泊松分布,我们将会看到一个大的 r 和 p 接近 1。这是有意义的,因为当 p 接近 1 时,方差接近平均值。当 p 小于 1 时,方差高于同均值的泊松分布,所以我们可以看到负二项分布通过增加方差来推广泊松。
泊松分布的混合
负二项分布也是泊松随机变量的混合。例如,假设我们的客户服务代表每个人都以给定的比率收到投诉(他们从不改变他们的行为),但是这个比率在代表之间是不同的。如果这个比率是根据伽马分布随机分布的,我们得到一个负的二项分布。
这背后的直觉如下。我们最初说负二项分布是当我们掷硬币时,在成功之前失败的次数。相反,用两个泊松过程代替抛硬币。流程一(“成功”流程)的比率为 p ,流程二,“失败”流程的比率为(1-p)。这意味着,我们不是把负二项分布看作是数硬币,而是认为有独立的过程独立地产生“成功”和“失败”,我们只是在一定数量的成功之前数多少次失败。
伽玛分布是泊松过程等待时间的分布。设 T 为“成功”过程中成功的等待时间。t 是伽玛分布。那么失败次数的平均值为(1–p)T,并且服从泊松分布。
结论
最后几点值得指出。首先,没有一种解析方法可以将负二项分布拟合到数据中。相反,使用最大似然估计和数值估计。在 Python 中,您可以使用[statsmodels](https://www.statsmodels.org/devel/generated/statsmodels.discrete.discrete_model.NegativeBinomial.html)
包来完成这项工作。
此外,还可以进行负二项式回归,模拟协变量的影响。我们将在以后的文章中讨论这个问题。
在 Power BI 中对行使用聚合函数
在列上使用聚合函数是好的,但是在行上使用同样的方法是——太棒了!所有这一切只需要一行 DAX 代码!
约书亚·科尔曼在 Unsplash 上拍摄的照片
聚合函数是 Power BI 中的主要构件之一。无论是在测量中显式使用,还是由 Power BI 隐式定义,没有一个 Power BI 报告不使用某种聚合函数。
什么是聚合函数?
聚合意味着组合数据中的值,执行一些数学运算。可以是总和、平均值、最大值、最小值、计数、不同计数、平均值、标准偏差等。
但是,对聚合函数的深入观察不在本文的范围之内。在这里,我想演示如何以一种非常规的方式使用聚合函数,因为我相信它在一些特定的场景中是有用的。
聚合函数的默认行为
默认情况下,对列计算聚合。让我们看看下面的基本例子:
这是 SUM 聚合函数的一个典型例子。数字在年和月的级别上进行聚合,最后,我们可以在表中看到各个值的总和。
我们还可以执行 AVERAGE 来查找平均值,MIN 或 MAX 来查找最小值和最大值,等等。非常简单,可能大多数使用过 Power BI 或 Excel 的人都已经知道了。
行上的聚合—无需取消透视!
但是,如果我们想在行上而不是在列上执行聚合呢?有可能做到吗?如果是,如何实现?
让我们立即前往动力 BI 进行检查。我有一个 Excel 文件作为数据源,还有一个虚拟表,其中包含关于客户的数据以及他在一年内第一次购买的日期:
如您所见,有些客户每年都会购买一次产品,有些有缺口,有些是在以后几年购买的,等等。
现在,我想检索客户进行购买的最早日期,以便稍后可以基于该日期执行分析(例如,分析有多少客户在 2017 年 2 月进行了首次购买)。
我知道,你们大多数人可能会选择 Power Query 转换和 Unpivoting years 列,就像这样:
您会看到一个漂亮的新表格,所有日期都按客户分组:
但是,需要一个额外的工作负载来构建一个单独的列,该列将保存每个客户的最早日期(或最小日期)的数据,因此我们稍后可以使用该列进行过滤,甚至构建与[日期维度](http://However, an additional workload is necessary to build a separate column which will hold data about the earliest date (or MIN date) for every single customer, so we can later use this column for filtering purposes, or even for building a relationship to a date dimension. What if I tell you that you can do this with a single line of code and without any additional transformations? First, I will close Power Query editor and go straight to Power BI Data view:)的关系。
如果我告诉你,你只用一行代码就可以做到这一点,不需要任何额外的转换,那会怎么样?
首先,我将关闭电源查询编辑器,直接进入电源 BI 数据视图:
您会看到该表看起来与 Excel 中的一模一样。现在,我选择创建一个新列,当出现提示时,输入以下 DAX 代码:
First Purchase Date = MINX({Sheet2[2016],Sheet2[2017],Sheet2[2018],Sheet2[2019]},[Value])
让我们暂时停在这里,解释一下我们在做什么。因此,我们希望从每一行中提取最小日期。我们可以通过使用多个嵌套的 IF 语句和 MIN aggregate 函数来实现。因为 MIN function 只接受两个参数,所以我们会有多层嵌套的 IF 语句,这非常难看,几乎不可读。
这里的神奇之处就在花括号里! 通过使用它们,我们告诉 DAX 我们希望它从花括号内的列表中创建一个表,并使用 MINX 迭代器聚合函数,我们简单地遍历这个表并从中提取最小值。
那是多么的酷和优雅!它非常有效,下面是结果栏:
您可以很容易地发现 DAX 返回了预期值,因此现在我们可以将该列用作图表中的轴,在其上创建常规的日期层次结构,或者如果愿意,我们甚至可以在数据模型中创建首次购买日期和日期维度之间的关系。
结论
力量 BI 和 DAX 都是满满的隐藏宝石。老实说,我不得不承认,您可能不会每天都面临这样的场景,但是在某些特定的情况下,知道您可以以一种非常简单而强大的方式在行级别上执行聚合函数是很好的——使用一行代码!
订阅此处获取更多有见地的数据文章!
在你的 Mac 上使用 AMD GPU 来加速 Keras 中的深度学习
照片https://unsplash.com/photos/aVeKubCF-48
Mac + AMD 镭龙 RX5700 XT + Keras
如今,每个机器学习工程师都会希望使用 GPU 来加速他的深度学习计算。我碰巧从一个朋友那里得到了一个 AMD 镭龙 GPU。不幸的是,我看到 AMD 和 Nvidia GPUs 之间有很大的差异,而只有后者在深度学习库中得到了很大的支持,如 Tensorflow。我看到了一些文章,并让我的 mac+amd GPU 设置工作。🚀
这可以看作是对其他文章的理解(见“附加阅读”)和我这边在实现过程中的一些附加解决方案。
放弃
我与本文中使用的任何服务都没有关联。
我不认为自己是专家。如果你觉得我错过了重要的步骤或者忽略了什么,可以考虑在评论区指出来或者联系我。
我总是乐于听取建设性的意见以及如何改进。
本文写于 2020 年 3 月 10 日。
我无法监控我的所有文章。当你阅读这篇文章时,提示很可能已经过时,过程已经改变。
如果你需要更多关于某些部分的信息,请在评论中指出来。
目录
问题——答案
用于 Keras 计算的核心 Tensorflow 支持通过 CUDA 使用 Nvidia 显卡进行本地 GPU 加速。不幸的是,AMD 还没有这样的产品。
这个问题的答案是 PlaidML,这是一个 python 库和张量编译器,它允许我们加速矢量计算。
PlaidML 是一个先进的便携式张量编译器,用于在笔记本电脑、嵌入式设备或其他设备上实现深度学习,在这些设备上,可用的计算硬件没有得到很好的支持,或者可用的软件堆栈包含令人不快的许可证限制。
PlaidML 位于通用机器学习框架之下,使用户能够访问 PlaidML 支持的任何硬件。PlaidML 支持 Keras、ONNX 和 nGraph。
作为 nGraph 编译器堆栈中的一个组件,PlaidML 进一步扩展了专门的深度学习硬件(特别是 GPU)的功能,并使访问或利用子图级优化变得更加容易和快速,否则这些优化将受到设备计算限制的限制。
作为 Keras 下的组件,PlaidML 可以通过定制或自动生成的 Tile 代码来加速训练工作量。它在 GPU 上工作得特别好,并且它不需要在 Nvidia 硬件上使用 CUDA/cuDNN,同时实现可比的性能。
来源https://github.com/plaidml/plaidml
截至撰写本文时,以下硬件和网络已经过验证:
来源公文https://github.com/plaidml/plaidml/tree/plaidml-v1
由于 PlaidML 有助于 Keras 模型上的张量计算,它不会加速使用 Numpy 的独立张量计算。这可以通过使用 OpenCL 来完成,这将不在本文中讨论。查看“额外阅读”部分了解更多信息。
先决条件
如果你想继续下去,你应该
- 苹果操作系统
- 外部 AMD GPU
- Keras ,作为深度学习库
我的设置
马科斯·卡特琳娜
System Version: macOS 10.15.6 (19G2021)
Kernel Version: Darwin 19.6.0
Boot Volume: Macintosh HD
Boot Mode: Normal
Secure Virtual Memory: Enabled
System Integrity Protection: Enabled
外部 GPU
运行
system_profiler SPDisplaysDataType
会给你图形/显示输出。
它显示了我的外部 GPU:
Radeon RX 5700 XT: Chipset Model: Radeon RX 5700 XT
Type: External GPU
Bus: PCIe
PCIe Lane Width: x4
VRAM (Total): 8 GB
Vendor: AMD (0x1002)
Device ID: 0x731f
Revision ID: 0x00c1
ROM Revision: 113-D1990103-O09
Automatic Graphics Switching: Supported
gMux Version: 4.0.29 [3.2.8]
Metal: Supported, feature set macOS GPUFamily2 v1
GPU is Removable: Yes
库版本
keras=2.2.4=pypi_0
keras-applications=1.0.8=py_1
keras-preprocessing=1.1.0=py_0plaidbench=0.7.0=pypi_0
plaidml=0.7.0=pypi_0
plaidml-keras=0.7.0=pypi_0
将外部 GPU 连接到 Mac
安装软件包
pip install pyopencl plaidml-keras plaidbench
plaidml-设置
plaidml-setup
plaidml-setup 的设置步骤
plaidbench keras mobilenet
plaidbench keras mobilenet
运行 plaidbench 的结果
这表明 GPU 设置应该是可行的。现在让我们进入实际的实现。
实际实施
为了让它工作,你需要将它添加到笔记本/文件中:
import plaidml.keras
import os
plaidml.keras.install_backend()
os.environ["KERAS_BACKEND"] = "plaidml.keras.backend"
还有其他关于如何添加后端的建议。然而,它只在这个顺序下对我有效。首先安装后端,然后设置环境。(其他建议见“附加阅读”)
之后,做
from keras import backend as K
K
应该会给你这样的东西:
<module 'plaidml.keras.backend' from '/Users/XXXX/opt/anaconda3/envs/XXX/lib/python3.7/site-packages/plaidml/keras/backend.py'>
如果你不确定是否真的使用了 GPU,有几个命令可用,比如K._get_available_gpus()
。但它们对我不起作用。如果你得到的是类似上面的后端消息,它应该可以工作。你会在计算过程中看到无论如何,如果你的 GPU 正在运行或你的 Mac)
添加深度学习代码
为了测试它,你可以从他们的文档中使用基本的 Keras 示例代码:https://github.com/keras-team/keras/tree/master/examples
例如神经类型转移。
在我的标题中的基本图像上运行它(归功于 Nana Dua )并添加一些特殊的味道(归功于 Arno Senoner ,导致:
原创
风格转移
附加阅读和常见问题
- 在您的 Mac 上使用外部图形处理器
- AMD 上的 GPU 加速,使用 PlaidML 进行训练和使用 Keras 模型
- MAC OS 上 GPU 加速的机器学习
- 在深度学习中使用 GPU 可以带来哪些好处
- Stackoverflow 关于让 mac 与 GPU 一起工作
关于
丹尼尔是一名企业家、软件开发人员和律师。他曾在各种 IT 公司、税务咨询、管理咨询和奥地利法院工作。
他的知识和兴趣目前围绕着编程机器学习应用程序及其所有相关方面。从本质上说,他认为自己是复杂环境的问题解决者,这在他的各种项目中都有所体现。
如果您有想法、项目或问题,请不要犹豫与我们联系。
连接到:
你可以在https://www.buymeacoffee.com/createdd上支持我
使用 Apple 新的 ML 计算框架来加速 iOS 和 macOS 上的 ML 训练和推理
破解新的苹果 ML 计算框架,加速跨 CPU 和 GPU 的神经网络训练
随着最近新一波操作系统版本(BigSur,iOS 14 等。),苹果在最近的 WWDC 上宣布,它非常安静地引入了一个新的 ML 框架,以加速跨 CPU 或一个或多个可用 GPU 的神经网络训练。
ML Compute 并不完全是一个新的 ML 框架,而是一个新的 API,它利用了 CPU 的 Accelerate 框架提供的高性能 BNNS 原语和 GPU 的金属性能着色器。
在查看了文档并开始在 iOS/macOS 应用程序上使用它之后,我明白这并不是一个真正简单的高级框架,而是一些可能旨在加速现有第三方 ML 库的东西,如 ONNX 运行时或苹果平台上的 TensorFlow Lite 框架。
即使苹果的文档非常好,我也要说这些 API 对于在 iOS/macOS 上做通用 ML 来说并不是真正的开发者友好和快捷。例如,tensor API 非常粗糙,它需要处理 Swift 中的非托管指针。基本上,您自己负责管理传递给这些 API 的张量、节点和图形等对象的所有权和内存分配的生存期。
更一般地,ML Compute 根据定义并不为 TensorFlow 提供类似 Keras、PyTorch 或 Swift 的 ML APIs 来简化构建和训练 ML 模型,而是提供低级 API 来构建计算图和管理低级训练循环。
对于 iOS/macOS 上的通用 ML 编码,我建议继续使用 Core ML 和 CoreMLTools 这样的工具从其他框架(TensorFlow,PyTorch 等)导入模型。)或者,如果您想完全在设备上本地构建和/或训练模型,避免任何 Python 代码,最终可以尝试我开发的 SwiftCoreMLTools 库。
[## JacopoMangiavacchi/SwiftCoreMLTools
用于在 Swift 中创建 CoreML 模型的 Swift 库。这个库公开了一个(基于函数生成器)…
github.com](https://github.com/JacopoMangiavacchi/SwiftCoreMLTools)
无论如何,我个人的观点是,玩了这个之后,ML 计算可能会变得非常强大,甚至对于常规的 Swift ML 开发人员来说也是如此,例如,在此基础上增加一个 Swift Function Builder (DSL)高级 API,就像我为 SwiftCoreMLTools 开发的那个,以及一个高级 Tensor Swift API,有望与 Swift Numerics 多维数组集成。
为了快速测试这些 API 的能力,我决定开发并演示一个 PoC 应用程序,在 iOS 和 macOS 上使用 ML Compute 对 MNIST 数据集进行简单的浅层模型训练和推理。
演示 ML 计算游乐场
在进入这个 MNIST ML 计算应用的细节之前,请让我分享一个快速和肮脏的 Swift 操场,我最初用来熟悉 ML 计算张量和图形 API。
正如你在这里看到的,我还没有建立一个真正的 ML 模型,但我使用 ML 计算图来简单地运行一些基本的张量算术运算。
我认为先简单地熟悉一下这个会很有帮助。
准备 MNIST 数据集张量
现在,我们已经熟悉了用于构建张量和图形的 ML Compute API 的基础,让您开始了解如何构建第一个样本浅层模型来训练著名的 MNIST 数据集。
我们将首先高效地导入包含 MNIST 训练和测试数据集的 CSV 文件,然后看看如何在 ML Compute tensors 中进行转换。
如您所见,下面的代码并行读取,训练和数据集 CSV 文件,应用一些规范化,并转换 Swift Float 数组中的图像和标签。
这里有一个关于并发性和中央调度 API (GCD)的简短说明。为了快速并行处理一批数据,我在这里使用了方便的 dispatch queue . concurrent perform API 来轻松管理 Swift 中的并行 For-Loop。
效用函数
不幸的是,将 CSV 文件缓冲区读入 String 并使用 split()方法处理行实际上并不高效,因此我必须开发一种替代方法,使用更高效的 C 运行时 getline()函数逐行扫描 CSV 文件。
下面的其他函数将在稍后处理标签和损失函数成本时变得有用,以便使用损失函数所需的一种热编码技术来编码和解码标签(ML 计算不提供稀疏分类交叉熵)。
构建计算图
既然我们已经在 Swift Float 数组上加载了训练和测试图像和标签,我们终于可以开始构建 ML 计算图了,我们将分别使用它来训练和测试模型。
我们在此示例应用程序中特别使用的 ML 模型是一个非常简单的浅层神经网络,它有一个带有 relu 激活的密集层,后面是一个带有 softmax 激活的最终密集层,用于 MNIST 数据集的十位数类别。
正如你所看到的,ML 计算图是通过添加层节点和激活函数,向所有这些层和激活函数传递经典参数(如输入/输出张量的形状、权重/偏差初始矩阵等)而构建的。
这里需要注意的是,用于权重、偏差以及模型输入和输出的所有张量的形状。具体来说,你可以看到,当构建图形时,我们必须选择批量大小,我们稍后将用于训练和推理,根据批量大小创建所有这些张量形状。
构建训练图
现在我们有了一个 ML 计算图,我们可以构建一个 MLCTrainingGraph 来传递计算图和训练参数。
在这种情况下,我们将指定 softmax 交叉熵作为损失函数(ML Compute 不提供稀疏分类交叉熵), ADAM 作为具有标准默认参数的优化器。
训练图表
为了训练 MLCTrainingGraph,我们需要创建一个完整的训练循环,迭代所有批次的每个时期,只需将训练数据集中的样本总数除以上面用于创建张量和图形的批次大小。
具体来说,在批处理循环中,我们将从 Swift Float 数组获得图像切片和标签数据的 Swift 不安全缓冲区,我们将通过此数据切片的不安全指针构建 MLCTensorData,并最终将此张量数据传递给训练图执行方法,以最终使用批处理数据训练模型。
用验证数据测试图表
一旦该模型被训练了足够的时期,我们将验证该模型,建立一个类似的 MLCInferenceGraph 和饲料,一次一批,所有的测试数据。
在推理图执行闭包回调中,我们将通过简单地查看预测对应于测试标签的时间来计算模型的最终准确性。
完整的代码
和往常一样,这个故事的代码是完全开源的,可以在我的 GitHub 个人账户上获得:
通过在 GitHub 上创建帐户,为 JacopoMangiavacchi/MNIST-ComputeML 开发做出贡献。
github.com](https://github.com/JacopoMangiavacchi/MNIST-ComputeML)
特别感谢
最后,我想在此感谢 Apple ML Compute 团队,他们非常迅速、非常详细地为我提供了关于新 ML Compute 框架的建议和见解。
通过 SAP-C01 考试:用例层后,我在 AWS 上搭建了一个机器学习平台
“建筑是对真理的探索”——路易斯·康。问题是:什么真相?设计一个平台是一个不断寻求真理的过程。然而,如果“关于什么”没有很好地定义,这可能是一个无休止的过程。
约书亚·索蒂诺在 Unsplash 上拍摄的照片
这是我在 AWS 上构建机器学习平台之旅的第四章。这一章是基于我到目前为止在前面的部分中介绍的工作:ML 平台的高级概述 , 基础设施&软件层 ,以及 框架层 。
在这一部分,我将研究 AWS 上机器学习平台的第四层:用例层。
1 |那么,关于什么的真相?
当利益相关者选择一个新的用例时,最终目标是将这个用例放到机器学习平台上。实现这一目标受到解决三个谜题的限制:
- 用例背后的真相是什么?
- 用例所需的数据背后隐藏着哪些奥秘?
- 如何在机器学习平台上恰当地落地这个用例?
2 |用例背后的真相是什么?
即使机器学习是一个伟大的工具,它也不是大多数用例的正确答案。如果应用于错误的用例,它甚至可能是一种矫枉过正和预算浪费。这就是为什么,首先,业务分析师和数据科学家应该限定用例,并确保它有资格通过机器学习来解决。
“一个 大部分用例简答: 不使用机器学习。 保持简单!” 。
因此,如果用例可以通过传统算法和软件解决方案来解决,那么避免使用机器学习来解决它的复杂而危险的旅程是更明智的。
3|用例所需的数据背后隐藏着哪些奥秘?
现在假设我们的用例是一个真正的机器学习用例!还有两个重要步骤需要克服:
- 确定正确的数据源
- 将数据带到机器学习平台
3.1 |确定正确的数据源
传统上,具有深厚业务知识的人努力工作,以确定需要什么数据源,并试图编写一个清晰的用例规范,详细说明用例的棘手方面。
随着机器学习的出现,这个过程不再局限于拥有商业知识的人。数据科学家也应该融入这个过程,因为他们必须掌握那些棘手的方面,以努力产生一个强大的机器学习模型。
3.2 |将数据引入机器学习平台
提醒一下,从一开始,我就假设我试图构建的 ML 平台是数据的消费者,并使用另一个数据平台功能来带来想要的数据。
数据平台和机器学习平台的分离,作者作者
尽管如此,机器学习团队主要负责研究围绕数据的敏感话题。这些主题包括:
- 遵守一定的法规:数据是一座金矿,但它的使用要服从一定的条件。例如,欧盟的数据应遵循一般数据保护法规(GDPR)。“通用数据保护条例(EU) 2016/679 (GDPR)是欧盟法律中关于欧盟(EU)和欧洲经济区(EEA)数据保护和隐私的规定。它还解决了欧盟和欧洲经济区以外的个人数据传输问题。” *。*要研究的其他法规可能是健康保险便携性和责任法案(HIPPA) 和支付卡行业数据安全标准(PCI-DSS) ⁴ 。
- 数据敏感性:为了遵守内容分发政策,一些数据属性应该匿名。例如,这适用于个人身份信息(PII)。
- **数据收集属性:**在委派将数据带到数据平台的工作之前,必须回答几个问题:
-应该以流模式收集哪些数据?哪些数据是以批处理方式收集的?
-如何安排这些不同的数据收集流程?谁应该访问数据,谁不应该?
4 |如何在机器学习平台上恰当地落地这个用例?
几乎每个机器学习用例都可以通过七步通用工作流来解决:
- 数据准备
- 特征工程
- 模特培训
- 模型评估
- 模型打包和部署
- 模型服务
- 模型监控
到目前为止构建的 ML 平台就是为了简化这些步骤的执行。准确地说,上一篇文章中提到的抽象层,将是我们应用这些步骤的切入点。
提醒一下,这里是抽象层(框架层)的逻辑架构:
《机器学习框架的逻辑架构和实现》,作者作者
让我们讨论机器学习工作流的每一步,并看看在处理这些步骤时可能面临的一些挑战。
4.1 | 数据清理和准备
从 S3,使用由 Kubeflow 产生和管理的 Jupyter 笔记本,原始数据被加载和研究。
数据清理模式,作者作者
在此阶段,数据可能会发生很多变化。例如:
- 平衡数据:在某些情况下,数据是不平衡的。例如,当处理像将电子邮件分类为垃圾邮件和非垃圾邮件这样的用例时,与真实的电子邮件相比,我们可能有不显著数量的垃圾邮件。
存在多种技术来平衡数据,如过采样、欠采样和 SMOTE 。 - **标注更多数据:在监督学习中,有时标注样本的数量刚好不足以训练一个模型。在这种情况下,可以标记更多的数据。
亚马逊机械土耳其人可以用来完成这个任务。它是“一种网络服务,提供按需的、可扩展的人类劳动力来完成人类可以比计算机做得更好的工作,例如识别照片中的物体。” ⁵ 。 - 数据扩充:当我们没有足够的数据来正确训练机器学习模型时,数据扩充也可能是一种解决方案。这是一种用于从现有示例中生成更多标记数据的技术。例如,当用于图像时,可以通过翻转该图像,在该图像上应用一些滤镜,或者剪切该图像的一些部分以引入损失,从一个图像生成新图像。
结果数据存储在清理后的数据存储中。
4.2 | 特色工程
这是最具挑战性的步骤之一。识别特征需要大量的头脑风暴和想象力。优步特色的例子:“餐厅在过去一小时内的平均用餐准备时间。”, ’ 餐厅最近七天的平均备餐时间。 ⁶
特色工程模式,作者作者
如前一篇文章 **、**中所述,可以计算两种类型的特征:
- 在线功能:基于流数据计算,应该以非常低的延迟进行访问。这些特性存储在 DynamoDB 中。存储特征定义意味着存储其属性:特征名称、特征类型(数值、分类)、特征的最小值和最大值等。
为了计算在线特征,ML 平台使用数据平台的流处理能力。换句话说,就两个平台之间的集成协议而言,这将是在数据平台上运行的作业。 - 离线特性:基于历史数据计算,无低延迟访问限制。这些特征将被存储在 S3。与在线特征一样,离线特征通过数据平台的批处理功能进行计算。
离线功能商店必须定期与在线功能商店同步,以*“确保相同的数据和批处理管道用于培训和服务”**。*
4.3 | 模型训练
训练阶段的第一步包括将数据分成三组:训练组用于训练模型,验证组用于超参数优化,以及测试组用于评估模型的性能。
模特培训模式,作者作者
清理后的数据和特征一起被输入到数据和模型准备层的模型训练功能中。然后将几个模型应用于数据,旨在筛选出一个性能模型。
如基础架构层文章中所述,FSx for Luster 用作存储来托管从 S3 复制的培训数据。有了这种存储,训练阶段被加速,因为工作节点可以具有比直接从 S3 访问数据好得多的数据访问性能。
该模式的最后一步是将训练好的模型连同其版本化元数据一起存储在训练好的模型存储的版本化存储库中。模型的元数据可以是模型的名称和版本、用于构建模型的数据版本、模型使用的特性、模型的输出格式等等。
4.4 | 模型评估
使用 Katib 和验证集,在选定的 ML 模型上测试不同的超参数组合,以最终选择性能最佳的组合。
然后使用测试集来测试 ML 模型,以评估其性能。
最后,生成的模型与其元数据一起存储在训练好的模型库中。
模式评价模式,作者作者
4.5 | 模型打包和部署
两个步骤组成了这个模式:模型打包和模型部署。每一步都有自己的规范。
模型操作模式,由作者
首先,经过训练的模型应该与特征提取器和样本数据集打包在一起,这将有助于在部署后验证模型。
不过需要注意一件棘手的事情:如果 ML 模型是实时服务的,那么模型的代码必须高效以遵守 SLA。有时,应该用 C++或 Java 之类的编译语言而不是 python 来重新实现。
其次,生成的包是存储在弹性容器注册表(ECR)中的 docker 映像。
最后,模型被部署为 docker 容器。可以考虑不同的部署策略:
- 单一部署:已经部署的模型被新的模型简单替换。同一时间只部署一个型号。
这种策略是有风险的,因为:
-在现有型号的更换过程中会造成一定的停机时间。
-新的模型版本可能包含一些错误,回滚策略应该准备好执行。 - 蓝/绿部署:这种技术保持了模型的两个版本:一个新版本(绿色)和另一个已经运行的版本(蓝色)。然后,根据新型号的性能,流量逐渐转移到新版本。
通过这种策略,停机时间被最小化,并且可以进行一些 A/B 测试。 - 多臂土匪:通过这种“聪明”的方法,交通逐渐被引导到最佳模式。
4.6 |型号上菜
为模型服务的两种可能模式:
- 实时服务:当模型在线部署时,它以 REST API 的形式向最终用户公开。Seldon Core 与 Kubeflow 及其 Ambassador API 网关很好地集成在一起,以管理入口流量和 API 端点展示。
上菜模式如下:
**1。*如前所述,在线功能商店必须定期与离线功能商店同步,以确保“相同的数据用于训练和服务”***【⁶】2。 用户使用 API 端点将其上下文化的数据发送到模型:除了核心数据之外,请求中还可以包含一些重要的可追溯性信息,如发送时间、发送者的 IP 地址等*。
3。特征提取器处理接收到的数据,并使用模型的元数据来识别正确的特征。
**4。**然后构建特征向量并提供给模型。
**5。*在最后一步中,预测被发送回用户以及预测存储。这个预测存储对于监控模型的性能是必不可少的。
实时发球模式,作者作者
- 批量服务:如上一篇文章中所解释的,当 ML 模型应用于大输入量*时,如用户选择的歌曲的一周历史,这种服务模式用于推荐下一周的正确歌曲。
图案如下:
**1。就像实时上菜一样,离线和在线是同步的。
**2。**对于批量服务,从 S3 存储器中提取特征,因为对于快速访问没有限制。
*3。最后,该模型的预测并不直接发送给用户,而是转到另一个存储器以备将来使用。
批量上菜模式,由作者
4.7 |型号监控
由于人类行为是不可预测的,ML 模型的性能容易退化。这就是为什么在生产中部署 ML 模型时应该考虑监控模式。
数据变化不是性能下降的唯一原因,其他原因可能是一些工作节点或某项服务不可用,这可能导致不遵守 SLA。
模式监控模式,由作者
为了监控模型,应该连续计算一些指标,并将其注入到性能指标存储中。
常见的做法是:
- 从预测存储中获取数据,并将其视为未标记的数据
- 为这些数据构建正确的预测:例如,可以从用户那里恢复正确的标签,或者使用 Amazon Mechanical Turk
- 运行作业以将模型预测与这些标注进行比较。
Prometheus 和 Grafana 也可以分别用于收集和可视化这些指标。这两种解决方案都与 Seldon Core 很好地集成在一起。
结论
在这篇文章中,我试图解释如何在机器学习平台上实现一个用例。
我首先讨论了当涉众选择一个新的用例时所面临的挑战,比如研究用例的真实性质,以及识别解决用例所需的数据源。
然后,以 框架层 为基础,我研究了机器学习模型生命周期中使用的不同模式,并给出了一些已知的最佳实践。
我相信在 AWS 上构建机器学习平台的过程中遇到的很多话题应该会更加详细。一个例子是深入到 API 网关层来有效地服务于实时模型。这将是我即将发表的文章的主题。
如果您有任何问题,请通过 LinkedIn 联系我。
[1]https://freeandopenmachinehlearning . readthedocs . io/en/latest/ml-business-use . html
[2]https://en . Wikipedia . org/wiki/General _ Data _ Protection _ Regulation
【3】https://en . Wikipedia . org/wiki/Health _ Insurance _ Portability _ and _ account ability _ Act
[4]https://en . Wikipedia . org/wiki/Payment _ Card _ Industry _ Data _ Security _ Standard
https://docs.aws.amazon.com/mturk/index.html
[6]https://eng . Uber . com/米开朗基罗-机器学习-平台/
差异隐私的使用案例
新兴技术的创新应用笔记
查尔斯·德鲁维奥在 Unsplash 上拍摄的照片
在这篇博文中,我们将简要介绍差分隐私(DP)的几个用例,从生物医学数据集分析到地理定位。
如果你有兴趣在深入其他用例之前学习差分隐私的基础知识,请查看我的博客文章 差分隐私的高级介绍 。
本文中的注释是为 SG OpenMined Explorers 研究小组创建的—有关与本文相关的幻灯片,请参见 差分隐私和联合学习的用例 。
让我们从基因组学的差分隐私应用开始!
基因组学
机器学习对于基因组学应用具有重要的意义,例如对于精确医疗(即,针对患者的临床/遗传特征定制的治疗)和从不同人群收集的数据中检测细粒度的见解。
鉴于大量基因组数据集的快速创建为这些应用的统计分析和机器学习研究提供了燃料,这种应用的主要隐私风险之一是使用辅助信息的链接攻击。链接攻击涉及利用公共数据库中的信息与敏感数据集重叠的场景(通常是匿名/去标识的,以审查数据集)。我们稍后将讨论去标识化和 k 匿名化。
有许多说明链接攻击的例子,例如在去标识的医院记录和选民注册数据库上部署的链接攻击,其结果是成功地找到了马萨诸塞州州长的患者档案。
此外,考虑下面的引用:
“已经证明,即使是粗略水平的信息,如次要等位基因频率(MAF)也可以揭示给定个体是否是研究队列的一部分,从而潜在地揭示个体的敏感临床表型。”
从基因歧视的角度来看,这是令人担忧的,因为个人可能会因为基因突变而受到不同的对待。
这个问题的现有解决方案包括:
- 去标识化,包括从数据中删除唯一的标识符,如姓名、电话号码,甚至车辆标识符。这种方法的缺点是您可能会丢失对分析有用的有意义的信息。
- k-匿名化,涉及从发布的数据中删除信息,直到一个数据记录与至少(k1)个其他记录属于同一等价类。这种方法的缺点是它没有提供正式的隐私保证,容易受到链接攻击以及其他攻击。
与差异隐私相关的优势:
- 防范链接攻击
- 启用两种类型的设置:
- 交互式设置,您可以在其中查询非公共数据库——答案被注入噪音或仅发布汇总统计数据
2.非交互式设置,其中公共数据被注入了噪声
这种应用与差压相关的缺点:
- 平衡隐私与效用(即考虑结果的准确性)。
- DP 方法只允许预设查询,例如:“返回 p 值”、“返回前 K 个 SNP 的位置”
优步用户数据
在讨论用例之前,让我们快速定义不同类型的查询敏感度。
Sensitivity⁹:的定义
- *查询的敏感度:*当数据库发生变化时,金额查询的结果也会发生变化。
- *全局敏感度:*任意两个相邻数据库中查询结果的最大差异。
- *本地敏感度:*真实数据库和它的任何邻居的查询结果之间的最大差异。局部敏感度通常比全局敏感度低得多,因为它是单个真实数据库的属性,而不是所有可能数据库的集合。考虑局部敏感性时,平滑函数非常重要。
许多差分隐私机制基于全局敏感性,并不推广到连接(因为它们可以乘以输入记录)。
使用局部灵敏度的技术通常提供更大的效用,但是在计算上是不可行的。
用例
对于这个用例,让我们考虑 Uber 的一个示例应用程序——确定 users⁹.的平均行程距离较小的城市可能有较少的旅行,因此个人旅行可能会影响分析,这有助于解决差异隐私问题。
根据上一节的注释,考虑局部敏感性是有价值的,因为基于全局敏感性的 DP 机制不能推广到连接。下面的图片来自论文“面向 SQL Queries"⁹的实用差分隐私”显示了大量查询利用连接,这激发了对利用本地敏感性的方法的需求。
**旁注:**我强烈推荐阅读论文《SQL Queries"⁹的实用差分隐私》(参考资料中的链接),以获得类似的查询分析和弹性敏感度的详细定义。
图片来自“面向 SQL Queries"⁹的实用差分隐私”,第 2 页
作者提出弹性敏感度作为一种平衡局部敏感度的方法。这种方法的目的是“使用关于真实数据库中连接键频率的预计算指标,对查询中每个连接的影响进行建模”。请参见下表,了解弹性敏感度与其他 DP 机制之间的比较——我们看到弹性敏感度支持不同类型的等价联接,即“以两种关系中某一列的值相等为条件的联接”
图片来自“面向 SQL Queries"⁹的实用差分隐私”,第 4 页
作者展示了 FLEX,一个利用弹性敏感度的系统,如下图所示。以下是白皮书中描述的优势:
- 提供(ε,δ)-差分隐私,不需要与数据库交互。
- 只需要查询的静态分析和查询结果的后处理。
- 扩展到大数据,同时产生最小的性能开销。
图片来自“面向 SQL Queries"⁹的实用差分隐私”,第 9 页
医疗+物联网:心率监测
现在让我们转向一个涉及可穿戴技术和物联网的医疗保健应用。这里的用例是通过智能手表等设备收集固定间隔测量的健康数据流(例如,收集营业时间内每分钟测量的心率)。
在相应论文中描述的系统管道中,使用本地差分隐私来扰乱数据,其中数据贡献者添加了噪声。按照下面显示的管道,用户的智能手表识别数据流中的显著点,然后用噪声干扰它们,随后将有噪声的数据发送到服务器进行重建和存储。
照片摘自“保护隐私的个人健康数据流汇总”,第 5 页
生物医学数据集分析
对于下一个用例,我们将考虑使用不同的隐私保证来处理生物医学应用的大数据。DAMSEN⁴是一种系统,它支持针对众多数据分析任务的不同隐私保证,并利用有效的查询优化引擎来实现高准确性和低隐私成本。
如下图所示,DAMSEN⁴为数据分析任务(如直方图、长方体、机器学习算法(如线性和逻辑回归,可能推广到神经网络)和聚类任务)提供了不同的隐私保护。
注意:在与查询相关的数据分析任务的上下文中,直方图并不代表数据分布的传统可视化。直方图是一种特殊类型的查询,涉及将数据点分类到桶中。您可以将此类查询视为类似于 Pandas 的 groupby()函数,但功能更多。长方体是一项涉及多个汇总数据集和表格的分析任务——详细示例请参见 paper⁴大学。
照片摘自“Damson 演示:大 Data"⁴分析的不同隐私”,第 2–4 页
**潜在项目想法:**确保可视化的不同隐私保证。我找到的关于这个主题的两个资源是“个人数据的隐私感知可视化”和“可视化有差异的私人数据的挑战”。
有趣的是,DAMSEN 采用了压缩机制,这有助于将动力定位所需的噪音量降至最低:
CM 首先对数据进行编码,而不是在原始数据中添加噪声,就像在压缩感知中一样;然后,CM 将噪声添加到编码数据中,像在压缩感知中一样解码结果,并将其发布。因为转换后的数据是高度压缩的,它们需要更少的噪声来实现差分隐私。”⁵
减少噪音量很重要,因为我们希望确保被 DP 机制干扰的查询结果仍然尽可能准确。
分析电子健康记录
对于这个用例,我们考虑具有同态加密⁰.的 DP 扰动直方图论文《⁰》中提出的整个系统如下图所示:
照片摘自《通过混合方法传播保护隐私的生物医学数据》,⁰,第 3 页
我们可以看到,该系统涉及研究人员、可信第三方和云服务提供商等实体,每个实体在框架中都有自己特定的角色。
下图描述了提议框架的概念。我们可以看到用于密钥分发和安全直方图生成的同态加密组件所需的框架部分。根据该框架的 DP 部分,系统将加密的拉普拉斯噪声添加到直方图的每个箱的计数中,其中直方图计算的灵敏度为 1。
照片摘自《通过混合方法传播保护隐私的生物医学数据》,⁰,第 4 页
如前所述,直方图是一种查询,其结果可用于训练模型。
如下图所示,作者发现,虽然在原始数据集上训练的分类器实现了最高的性能,但作者在基于 DP 扰动 V 最优直方图采样的数据集上训练的分类器的性能类似于在基于无噪声 V 最优直方图采样的数据集上训练的分类器。当隐私预算减少到小于 0.1 时,这一发现出现例外,这导致大量噪声添加到数据中,AUC 下降,查询遗漏率增加。
照片摘自“通过混合方法保护隐私的生物医学数据传播”,⁰,第 7 页
因此,作者的一个结论是,隐私预算需要谨慎选择。他们还解释说,他们的安全模型可以防止所讨论的实体之间的信息交换出现各种泄漏——有关更多详细信息,请参见本文。
地理定位
微软的 PrivTree⁶系统利用不同的隐私来掩盖个人在地理位置数据库中的位置。该方法包括将地图分割成子区域,然后对每个子区域应用位置扰动,如下图所示。他们的系统,给定原始数据和一些其他参数(要使用的拉普拉斯噪声的尺度,用于决定是否应该发生节点分裂的阈值,等等)。),可以实现差分私有算法,并为几乎任何种类的位置数据输出噪声数据。
照片取自“隐私树项目:模糊你的“在哪里”privacy"⁶外景
美国人口调查局
一个有趣的用例是美国人口普查局决定将差分隐私作为隐私 strategy⁸.的一部分根据下图,他们打算在 2020 年通过“新隐私 system"⁷的全球首次大规模应用”来采用差别隐私。
照片片段摘自“Protections"⁷人口普查隐私史”
DP 研究挑战
让我们考虑一些我们在这篇博文中讨论的用例中常见的研究挑战(借用 DAMSEN⁵的话):
- “我们怎样才能最小化增加的噪音/最大化分析结果的效用?”
- “隐私预算是由数据所有者选择的参数,用于控制攻击者从发布的数据集中推断敏感信息的难度。每次分析都会消耗一些“隐私预算”。如何才能让预算尽可能长久?”
- **向读者提问:**还有其他研究挑战需要考虑吗?
差分隐私引用
- 机器学习和基因组学:精准医疗与患者隐私 ↩
- 旨在增强基因组数据共享隐私的新兴技术 ↩
- 隐私保护的个人健康数据流聚合 ↩
- damson 演示:用于大数据分析的差分隐私 ↩
- 压缩机制↩
- 项目隐私树:模糊你的位置隐私 ↩
- 人口普查隐私保护的历史 ↩
- 保护美国统计数据的机密性:在人口普查局采用现代的避免披露方法 ↩
- 面向 SQL 查询的实用差分隐私 ↩
- 通过混合方法进行隐私保护的生物医学数据传播 ↩
- 在 SQL ↩ 中制作直方图频率分布
- “个人数据的隐私感知可视化” ↩
- “可视化差异私有数据的挑战” ↩
其他资源:差分隐私:使用大数据的技术说明
差分隐私代码库
感谢您的阅读!敬请关注未来关于联合学习用例的博文!😃
原载于 2020 年 4 月 30 日 https://blog.openmined.org。
Python 找到了带有数据重复问题的 Kusto 表
Python 与 Kusto 一起寻找重复
约书亚·迈克尔斯在 Unsplash 上的照片
Azure Data Explorer ( Kusto )是市场上最专注的关系数据库之一。整个系统运行在固态硬盘和内存中,以提供快速响应的数据分析。作为热路径数据存储,这可能是一个不错的选择。
由于各种原因,如客户端功能不良、数据管道不完善等。数据可能会多次被输入到 Kusto。这导致了数据重复的问题。如果摄取的数据是汇总数据,比如一组商店的总收入等,这个问题可能会更加严重。
数据重复会搞乱所有后续的数据分析,人们可能会据此做出错误的决定。因此,数据清理/重复数据删除是必要的。在此之前,我们需要首先确认,当前的 Kusto 表是否存在重复问题。
确认步骤是本文的重点。
主要思想包含以下步骤:
- 连接到 Kusto 集群。
- 查询表架构。
- 创建每行的唯一标识
- 对具有相同标识的行进行计数
- 查找任何计数大于 1 的标识值,标记为重复。
连接到 Kusto 集群
Python 有连接 Kusto 的包:Azure Data Explorer Python SDK。在这里,我们使用包:azure-kusto-data。
下面的代码片段将允许我们创建 KustoClient。它用于查询 Kusto 集群。在连接到 Kusto 之前,我们需要创建 AppId,并将其注册到 Kusto 集群。
查询表模式
getschema 将返回表模式。KustoClient 将返回表模式作为我们熟悉的 Pandas DataFrame。我们很容易做进一步的加工。
每行的唯一标识
假设,该表是一个汇总表。没有可以唯一标识该行的列子集。因此,我们将使用模式中的所有列来创建标识。标识将是所有列值的串联。
因此,我们将使用 tostring()操作符将所有非字符串数据转换为字符串。这就是 schema.apply( axis = 1) 的目的,其中 axis = 1 将逐行遍历表。
最后,Kusto 的 strcat() 将根据 hashOp 定义的操作连接所有的列。
如果对于另一个表,我们知道列的子集可以唯一地标识行,例如 user_id 和 order_id 的组合。在这种情况下,我们可以使用第二个 hashKusto 案例。
相同标识值计数并查找重复项
注意,我们上面创建的 hashKusto 值在 Kusto 查询中用作扩展。这将在 KustoTable 中创建一个额外的列, hash 。我们稍后使用 summarize 来获得每个标识散列的计数。
最后,重复的记录是 recordsCount > 1 的记录。
带走:
通过使用 Python,我们建立了一种简单直接的方法来验证和识别 Kusto 表中的重复行。这将为后续的数据分析提供坚实的基础。
利用数据共情成为更好的数据科学家
数据共情如何帮助您获得有意义的见解,并让您从优秀的数据科学家转变为伟大的数据科学家。来源:茱莉亚·尼库尔斯基,图标来自弗里皮克、 itim2101 ,以及www.flaticon.com的桉树。
办公时间
数据的上下文关系到数据项目的成功
英斯顿·丘吉尔曾经说过:“我只相信我篡改过的统计数据”。虽然这可能是一个极端的说法,但总体思路是正确的。数据可以有意或无意地以某种方式呈现,以支持不反映现实或潜在数据的论点。
CRISP-DM 模型的第二步是数据理解。这一步需要收集、描述和探索数据,以及识别数据质量问题。这种理解数据的大致轮廓是有用的。但是它没有提到一个重要的维度:数据共情。
对数据科学家工作的描述通常集中在硬技能和技术领域。这符合数据科学的维恩图。数据科学家受其领域专业知识的指导。在统计和机器学习模型以及编程工具的帮助下,他们从数据中提取知识。但是经常被忽视的软技能——例如 沟通技能怀疑态度 ,尤其是 同理心——在实现成功的数据科学项目和成为更优秀的数据科学家中发挥着至关重要的作用。****
定义数据共情
术语移情 是指
“理解、意识到、敏感地感受和体验他人过去或现在的感情、思想和经验的行为,而没有以客观明确的方式充分交流这些感情、思想和经验。”
移情和数据科学之间的逻辑联系是最终用户或利益相关者。通过同理心了解他们的需求和愿望将指导您的数据分析。这将使您能够创建更好、更有用的数据科学产品。然而,数据共情重在理解数据。它考虑了人类在数据收集过程中引入的主观性,并确定了偏差。
乔希·卡拉布雷斯在 Unsplash 上的照片。
根据 Faghmous 和 Kumar (2014) ,数据移情意味着理解一个数据集的故事。数据是如何收集的,为什么要收集?根据数据的目的和收集过程,可以确定哪些偏差?元数据可以部分回答这些问题,元数据是与数据相关的结构化描述性信息。但是正如brnni Mann 和 Wintzer (2018) 指出的,数据共情走得更远。它描述了一个反思、解释和定性的过程:
- ****反思:我们应该思考任何可能影响数据收集过程的关于世界的无意识信念。这涉及到“人工智能中的偏见”——叙述。一个常见的例子是主要包含白人面孔的图像分类器数据集。该数据集不代表群体的多样性。任何使用这些数据构建的模型都将表现不佳。
- 解释性:我们需要考虑数据的背景。谁获取了数据,为什么,何时,如何获取的?以与疾病症状相关的数据为例。根据至少三种不同的情况,报告的症状可能会有所不同。(1)你说出你能想到的所有症状,而不需要医生提出任何引导性问题(潜在的回忆偏差)。(2)医生问你是否嗅觉丧失或喉咙痛(潜在的确认偏差)。(3)医生在没有问你任何问题的情况下对你进行检查并报告症状(潜在的观察偏差)。理解这些细微差别并揭示数据集中的这些偏差对于进一步的分析和见解的形成至关重要。
- ****定性:我们必须解决可能影响数据质量和收集流程的社会规范和价值观。尤其是自我报告的数据会受到社会规范的影响。社会期望偏差描述的是个体回答问题的方式符合社会规范和期望。
根据 Tanweer 等人(2016) 的说法,理解“……围绕数据的价值、意图和期望”是数据移情的关键。
数据共情的重要性
数据共情之所以重要,有几个原因。
- 首先,如果不应用数据移情,数据中的偏差可能仍然未被发现。这样会导致模型有偏差,结果无用。这在 Kaggle 比赛中可能无关紧要,因为你的主要目标是达到高精度。但是现实世界的项目有现实世界的含义。如果你在的招聘决策中使用有偏见的数据和模型,后果将是可怕的。
- ****第二,数据集的目的和背景可以指导你的数据分析过程。发现的偏差将决定您数据探索和准备步骤的重点。它会影响你对特性选择和工程的决定。甚至可以选择某些机器学习模型而不是其他模型来更好地控制偏差。
- ****第三,了解数据的背景可以带来新的数据收集流程和数据科学项目。一旦您确定了数据收集过程中的问题,请思考如何创建更好的数据集。你如何解释固有的偏见?假设你在你公司的历史招聘数据中发现了性别偏见。贵公司使用的其他数据是否存在类似的偏见或背景?你如何改善数据?利用这个机会来发现和描述这种偏见,以及如何在你的下一个项目中抵消它。
这对您的数据科学成功意味着什么
不要低估 CRISP-DM 模型第 2 步的重要性。如果你希望你的最终模型有用,数据理解,包括收集数据的步骤和理解周围的环境,是关键。虽然技术技能让你成为一名优秀的数据科学家,但考虑数据的社会维度会让你成为一名优秀的数据科学家。因此,要成为更好的数据科学家,请在您的项目中使用数据移情。不要只看数据集的数字,而要看上下文。
结论
数据共情是理解数据的背景、价值和意图的过程。在您的数据科学流程中使用数据移情可以让您识别偏见。它有助于指导您的数据分析过程,并为您指出可以在下一个项目中回答的新问题。虽然我们喜欢相信数据在客观上是对的或错的,或真的或假的,但现实却更加微妙。在数据收集、数据探索和数据解释步骤中引入了人的主观性。作为一名数据科学家,你的工作就是承认这一点,并在你的分析中说明这一点。只有这样,你的模型和结果才是重要的。只有这样,你才能成为更好的数据科学家。
你想在媒体上阅读更多高质量的故事吗?考虑注册一个支持我和其他媒体作者的会员。
** [## 通过我的推荐链接加入 Medium-Julia Nikulski
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@julia.nikulski/membership)**
如果你想马上应用数据移情,但你目前没有项目想法,请查看我的文章如何开发新的独特的数据科学项目想法**。**
帮助您识别值得一试的新颖独特的数据项目的指南
towardsdatascience.com](/5-steps-to-develop-unique-data-science-project-ideas-6c2b3a0014b)**
在下一个 Golang 项目中使用环境变量
golang 中有多种方法可以使用环境变量和文件。
照片由 Moja Msanii 在 Unsplash 上拍摄
当创建生产级应用程序时,在应用程序中使用环境变量是事实上的*。*
也可以看 youtube 视频。
我们为什么要使用环境变量?
假设您有一个具有许多特性的应用程序,每个特性都需要访问数据库。您在每个特性中配置了所有的数据库信息,如DBURL
、DBNAME
、USERNAME
和PASSWORD
。
这种方法有几个主要缺点,但也有很多。
安全问题:
- 你在输入密码中的所有信息。现在,所有未经授权的人也可以访问数据库。
- 如果你使用的是代码版本控制工具
git
,那么一旦你发布代码,你的数据库的细节就会公之于众。
代码管理:
- 如果你改变一个单一的变量,那么你必须改变所有的特征。很有可能你会错过一两个。😌去过那里
- 您可以对环境变量进行分类,如
PROD
、DEV
或TEST
。只需给变量加上环境前缀。
开始时,它可能看起来像一些额外的工作,但是这将在你的项目中奖励你很多。
⚠️只是不要忘记在
**.gitignore**
中包含你的环境文件。
是采取行动的时候了。🔨
在这个教程中我们要做什么?
在本教程中,我们将以 3 种不同的方式访问环境变量。
你可以根据你的需要来使用它。
os
包装godotenv
包装viper
包装
创建项目
在**$GOPATH**
之外创建一个项目**go-env-ways**
。
初始化模块
打开项目根目录下的终端,运行下面的命令。
***go mod init goenv***
这个模块将记录项目中使用的所有包及其版本。类似于nodejs
中的package.json
。
让我们从最简单的开始,使用os
包。
操作系统包
Golang 提供了os
包,这是一种配置和访问环境变量的简单方法。
要设置环境变量,
***os.Setenv(key, value)***
要获得环境变量,
***value := os.Getenv(key)***
在项目中创建一个新文件main.go
。
***package main**
import (
"fmt"
"os"
)
// use os package to get the env variable which is already set
**func envVariable(key string) string** {
// set env variable using os package
**os.Setenv(key, "gopher")**
// return the env variable using os package
**return os.Getenv(key)**
}
**func main() {**
// os package
** value := envVariable("name")**
**fmt.Printf("os package: name = %s \n", value)** **fmt.Printf("environment = %s \n", os.Getenv("APP_ENV"))**
}*
运行以下命令进行检查。
***APP_ENV=prod go run main.go**
// Output
**os package: name = gopher
environment = prod***
GoDotEnv 包
加载.env
文件最简单的方法是使用godotenv
包。
安装
在项目根目录下打开终端。
***go get github.com/joho/godotenv***
godotenv
提供了一个Load
方法来加载 env 文件。
*// Load the .env file in the current directory
**godotenv.Load()**
// or
**godotenv.Load(".env")***
Load 方法可以一次加载多个 env 文件。这也支持
*yaml*
。更多信息请查看 文档 。
在项目根目录下创建一个新的.env
文件。
***STRONGEST_AVENGER=Thor***
更新main.go
。
***package main**
import (
...
// Import godotenv
**"github.com/joho/godotenv"**
)
// use godot package to load/read the .env file and
// return the value of the key
**func goDotEnvVariable(key string) string {**
// load .env file
**err := godotenv.Load(".env")**
if err != nil {
log.Fatalf("Error loading .env file")
}
**return os.Getenv(key)**
}
**func main() {**
// os package
...
// godotenv package
**dotenv := goDotEnvVariable("STRONGEST_AVENGER")**
fmt.Printf("godotenv : %s = %s \n", "STRONGEST_AVENGER", dotenv)
}*
打开终端并运行main.go
。
***go run main.go**
// Output
**os package: name = gopher**
**godotenv : STRONGEST_AVENGER = Thor***
只需在主函数中添加 os 包末尾的代码即可。
毒蛇包装
Viper 是 golang 社区中最受欢迎的软件包之一。许多围棋项目都是使用 Viper 构建的,包括 Hugo、Docker 公证人、Mercury。
毒蛇🐍是 Go 应用的完整配置解决方案,包括 12 因素应用。它设计用于在应用程序中工作,可以处理所有类型的配置需求和格式。读取 JSON、TOML、YAML、HCL、envfile 和 Java 属性配置文件
更多信息请阅读蝰蛇的官方文档
安装
在项目根目录下打开终端。
***go get github.com/spf13/viper***
要设置配置文件和路径
***viper.SetConfigFile(".env")***
要读取配置文件
***viper.ReadInConfig()***
使用键从配置文件中获取值
***viper.Get(key)***
更新main.go
。
***import** (
"fmt"
"log"
"os"
"github.com/joho/godotenv"
**"github.com/spf13/viper"**
)
// use viper package to read .env file
// return the value of the key
**func viperEnvVariable(key string) string {**
// SetConfigFile explicitly defines the path, name and extension of the config file.
// Viper will use this and not check any of the config paths.
// .env - It will search for the .env file in the current directory
**viper.SetConfigFile(".env")**
// Find and read the config file
**err := viper.ReadInConfig()**
if err != nil {
log.Fatalf("Error while reading config file %s", err)
}
// viper.Get() returns an empty interface{}
// to get the underlying type of the key,
// we have to do the type assertion, we know the underlying value is string
// if we type assert to other type it will throw an error
**value, ok := viper.Get(key).(string)**
// If the type is a string then ok will be true
// ok will make sure the program not break
if !ok {
log.Fatalf("Invalid type assertion")
}
** return value**
}
**func main() {**
// os package
...
// godotenv package
...
// viper package read .env
** viperenv := viperEnvVariable("STRONGEST_AVENGER")**
fmt.Printf("viper : %s = %s \n", "STRONGEST_AVENGER", viperenv)
}*
打开终端并运行main.go
。
毒蛇不仅限于。环境文件。
它支持:
- 设置默认值
- 读取 JSON、TOML、YAML、HCL、envfile 和 Java 属性配置文件
- 实时观察和重读配置文件(可选)
- 从环境变量中读取
- 从远程配置系统(etcd 或 Consul)读取,并观察变化
- 从命令行标志中读取
- 从缓冲区读取
- 设置显式值
Viper 可以被看作是满足应用程序所有配置需求的注册表。
让我们实验一下:💣
在项目根目录下创建一个新的config.yaml
文件。
***I_AM_INEVITABLE: "I am Iron Man"***
要设置配置文件名
***viper.SetConfigName("config")***
要设置配置文件路径
*// Look in the current working directory
**viper.AddConfigPath(".")***
要读取配置文件
***viper.ReadInConfig()***
更新**main.go**
*// use viper package to load/read the config file or .env file and
// return the value of the key
**func viperConfigVariable(key string) string** {
// name of config file (without extension)
**viper.SetConfigName("config")**
// look for config in the working directory
** viper.AddConfigPath(".")**
// Find and read the config file
**err := viper.ReadInConfig()**
if err != nil {
log.Fatalf("Error while reading config file %s", err)
}
// viper.Get() returns an empty interface{}
// to get the underlying type of the key,
// we have to do the type assertion, we know the underlying value is string
// if we type assert to other type it will throw an error
**value, ok := viper.Get(key).(string)**
// If the type is a string then ok will be true
// ok will make sure the program not break
if !ok {
log.Fatalf("Invalid type assertion")
}
** return value**
}
**func main()** {
// os package
...
// godotenv package
...
// viper package read .env
...
// viper package read config file
**viperconfig := viperConfigVariable("I_AM_INEVITABLE")**
fmt.Printf("viper config : %s = %s \n", "I_AM_INEVITABLE", viperconfig)
}*
打开终端并运行main.go
***go run main.go**
// Output
**os package: name = gopher**
**godotenv : STRONGEST_AVENGER = Thor
viper : STRONGEST_AVENGER = Thor
viper config : I_AM_INEVITABLE = I am Iron Man***
结论
就这样,现在你可以探索他们更多的秘密了🔐。如果你发现一些值得分享的东西,不要犹豫😉。
完整的代码可以在 GitHub 上找到。