机器学习算法。这里是端到端。
通用分类算法的端到端运行;包括随机森林、多项式朴素贝叶斯、逻辑回归、kNN 和来自 sklearn 的支持向量机
约翰·汤纳在Unsplash【1】上的照片。
目录
- 介绍
- 随机森林
- 多项式朴素贝叶斯
- 逻辑回归
- 支持向量机
- k-最近邻
- 摘要
- 参考
介绍
本文的目标是:
1.学习常见的数据科学、分类算法。
2.执行这些算法的示例代码。
虽然有几篇关于机器学习算法的文档和文章,但我想总结一下作为一名专业数据科学家最常用的算法。此外,我将包含一些带有虚拟数据的示例代码,以便您可以开始执行各种模型!下面,我将从最受青睐的库 sklearn ( 也称为 scikit-learn)【2】中概述这些主要的分类算法:
- 随机森林(RandomForestClassifier)—可用于回归
- 多项式朴素贝叶斯(多项式
- 逻辑回归(逻辑回归
- 支持向量机( svm ) —可用于回归
- k-最近邻(KNeighborsClassifier)-可用于回归
什么是分类?
Assigning new data into a category or bucket.
而无监督学习,如常用的 K-means 算法,旨在将相似的数据组分组在一起,而无需标签、监督学习或分类——嗯,将数据分类为各种类别。下面描述了一个简单的分类示例。
标签:水果——香蕉、橘子和苹果
特征:形状、大小、颜色、种子数等。
分类模型从关于水果的特征中学习,以建议输入食物和水果标签。现在,想象一下,对于我将在下面描述的这些分类算法,来自数据的每个观察值,输入,都有关于它的各种特征,然后将基于预定的标签进行分类。类别的其他名称包括标签、类、组(通常在无监督聚类中引用,但仍然可以描述分类)和桶。
分类的重要性不仅仅在于教育,还在于它在商业世界中极其实用和有益。比方说你要给成千上万的文档分类,给衣服分类,或者检测图像;这些都使用了我将在下面描述的这些流行且强大的分类模型。
随机森林
Lukasz Szmigiel 在Unsplash【3】上拍摄的照片。
这种集成分类器通过在所用数据集的子样本上拟合几个决策树来工作。然后,它对这些决策树的准确性进行平均,并创建一个比仅使用决策树更好的预测准确性,以控制过度拟合。与大多数分类器一样,有大量的参数可以帮助您调整您的模型,使其更差或更好(希望更好)。下面描述了常见的参数,我将包括默认的参数值,以便您对从哪里开始调优有一个大致的了解:
**n_estimators**: number of trees in your forest (100)**max_depth**: maximum depth of your tree (None) - recommendation, change this parameter to be an actual number because this parameter could cause overfitting from learning your traning data too well**min_samples_split**: minimum samples required to split your node (2)**min_samples_leaf**: mimimum number of samples to be at your leaf node (1)**max_features**: number of features used for the best split ("auto")**boostrap**: if you want to use boostrapped samples (True)**n_jobs**: number of jobs in parallel run (None) - for using all processors, put -1**random_state**: for reproducibility in controlling randomness of samples (None)**verbose**: text output of model in process (None)**class_weight**: balancing weights of features, n_samples / (n_classes * np.bincount(y)) (None) - recommendation, use 'balanced' for labels that are unbalanced
我将在这里提供一个随机森林算法的例子。它将使用虚拟数据(所以准确性对我来说并不重要)。重点是代码、概念,而不是准确性,除非您的输入数据已经很好地建立。在代码示例中有五个单独的行,您可以注释掉所有的分类器, clf **,**除了一个——您正在测试的那个。下面是主代码示例[4]:
# import libraries
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.naive_bayes import MultinomialNB
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn import svm
from sklearn import metrics
import pandas as pd# text and numeric classes that use sklearn base libaries
class TextTransformer(BaseEstimator, TransformerMixin):
"""
Transform text features
"""
def __init__(self, key):
self.key = keydef fit(self, X, y=None, *parg, **kwarg):
return selfdef transform(self, X):
return X[self.key]
class NumberTransformer(BaseEstimator, TransformerMixin):
"""
Transform numeric features
"""
def __init__(self, key):
self.key = keydef fit(self, X, y=None):
return selfdef transform(self, X):
return X[[self.key]]# read in your dataframe
df = pd.read_csv('/Users/data.csv')# take a look at the first 5 observations
df.head()# use the term-frequency inverse document frequency vectorizer to transfrom count of text
# into a weighed matrix of term importance
vec_tdidf = TfidfVectorizer(ngram_range=(1,1), analyzer='word', norm='l2')# compile both the TextTransformer and TfidfVectorizer
# to the text 'Text_Feature'
color_text = Pipeline([
('transformer', TextTransformer(key='Text_Feature')),
('vectorizer', vec_tdidf)
])# compile the NumberTransformer to 'Confirmed_Test', 'Confirmed_Recovery',
# and 'Confirmed_New' numeric features
test_numeric = Pipeline([
('transformer', NumberTransformer(key='Confirmed_Test')),
])
recovery_numeric = Pipeline([
('transformer', NumberTransformer(key='Confirmed_Recovery')),
])
new_numeric = Pipeline([
('transformer', NumberTransformer(key='Confirmed_New')),
])# combine all of the features, text and numeric together
features = FeatureUnion([('Text_Feature', color_text),
('Confirmed_Test', test_numeric),
('Confirmed_Recovery', recovery_numeric),
('Confirmed_New', new_numeric)
])# create the classfier from list of algs - choose one only
clf = RandomForestClassifier()
clf = MultinomialNB()
clf = LogisticRegression()
clf = svm.SVC()
clf = KNeighborsClassifier()# unite the features and classfier together
pipe = Pipeline([('features', features),
('clf',clf)
])# transform the categorical predictor into numeric
predicted_dummies = pd.get_dummies(df['Text_Predictor'])# split the data into train and test
# isolate the features from the predicted field
text_numeric_features = ['Text_Feature', 'Confirmed_Test', 'Confirmed_Recovery', 'Confirmed_New']
predictor = 'Text_Predictor'X_train, X_test, y_train, y_test = train_test_split(df[text_numeric_features], df[predictor],
test_size=0.25, random_state=42)# fit the model
pipe.fit(X_train, y_train)# predict from the test set
preds = pipe.predict(X_test)# print out your accuracy!
print("Accuracy:",metrics.accuracy_score(y_test, preds))
如果你想看看. py 格式的 GitHub gist 在 python 中是什么样子的,这里有我的 GitHub gist 的代码【4】:
GitHub gist [4]上作者的整篇文章示例代码。
多项式朴素贝叶斯
帕特里克·托马索在Unsplash【5】上拍摄的照片。
这个分类器是一个朴素贝叶斯分类器,用于多项式模型,正如算法的名字所暗示的那样。它广泛应用于文本分类问题中,其中文本是来自字数统计的特征。使用该算法时,建议使用术语-频率逆文档频率 ( td-idf )管道,因为您想要一个分布良好的特性。因为这个分类器是基于贝叶斯定理的,所以假设特征之间存在独立性。下面是分类器的主要代码:
clf = MultinomialNB()
所用模型的参数和属性如下:
parameters - **alpha**: a paramter for smoothing (1.0)**class_prior**: looking at the previous class probability (None) attributes -**feature_count**: number of samples for each class or feature (number of classes, number of features)**n_features**: number of features for sample
逻辑回归
逻辑回归,或者更像逻辑分类,是一种使用 logit 函数的算法。估计值通常是二进制值,如真-假、是-否和 0-1。逻辑函数也使用 sigmoid 函数。关于这个模型的细节有很多文章(见下面有用的链接),但是我将强调如何执行 sklearn 库中的代码。下面是分类器的主要代码:
clf = LogisticRegression()
逻辑回归有许多重要的参数。以下是其中的几个例子:
**penalty**: l1 or l2 (lasso or ridge), the normality of penalization (l2)**multi_class**: binary versus multiclass label data ('auto')
支持向量机
一种监督技术,不仅包括分类,还包括回归。支持向量机(SVMs)的好处是,它比其他构成高维度的算法效果更好。支持向量机的目标是找到在两个分类类别之间划分数据的线(它们在那条线之间的距离)。支持向量机的代码与上面的算法略有不同:
clf = svm.SVC()
这种代码上的差异引用了增加的 SVC ,也就是 C-支持向量分类。对于多类情况,您可以使用参数:
parameter **-** **decision_function_shape**: 'ovr' or 'one-versus-rest' approach
k-最近邻
k 近邻法,或称 KNN 法,是通过多数投票来实现的。它根据周围的邻居对新类别进行分类;常用的距离测量函数是欧几里德函数。用于该算法的代码是:
clf = KNeighborsClassifier()
最重要的参数可能是:
parameter - **n_neighbors**: number of neighbors (5)
摘要
虽然有大量关于广泛使用的机器学习算法的文章;
我希望这篇文章对你有用,因为我已经提供了端到端的代码。
请查看下面有用的链接以及本文中描述的每种算法的官方文档。感谢您阅读我的文章,如果您有任何问题,请告诉我!
参考
[1]约翰·汤纳在 Unsplash 上拍摄的照片,(2016)
[2] sklearn, sklearn ,(2020)
[3]Lukasz Szmigiel 在 Unsplash 上拍摄的照片,(2015)
[4] M.Przybyla,分类-模型,(2020)
[5]帕特里克·托马索在 Unsplash 上拍摄的照片,(2016)
[6]照片由 Christian Stahl 在 Unsplash 上拍摄,(2017)
有用的 sklearn 链接:
机器学习——伦理评论
由 Unsplash 上的üMIT Bulut拍摄的照片
我正在熨斗学校完成我的数据科学项目,回顾我所做的五个项目,并考虑如果这些项目将投入生产并影响真实的人,我应该考虑哪些伦理问题。虽然机器学习伦理的介绍是 Flatron 项目的一部分,但将伦理分析整合到每个项目中超出了它的范围。
五项原则
我将使用弗洛里迪和考尔斯在 2019 年的论文中提出的五项原则,这是人工智能在社会中的五项原则的统一框架,对我的项目进行顶级审查。原则是有利、无害、自治、正义和可解释。慈善意味着“促进福祉,维护尊严,维持地球”。无罪意味着“隐私、安全和‘能力警告’”。自主指的是“我们为自己保留的决策权和我们委托给人为代理人的决策权之间的平衡”。正义意味着“促进繁荣、维护团结、避免不公平”。可解释性意味着“通过可理解性和可说明性实现其他原则”。
项目# 1——向新企业推荐电影类型
我的第一个项目是基于向一个虚构的新电影工作室推荐什么类型的电影。它实际上不涉及机器学习,它纯粹基于数据分析;然而,创建一个代替人类分析师做出建议的机器学习模型并不难想象,也不难实现。
对于电影工作室来说,要求机器学习模型告诉他们制作什么类型的电影,这对于五项原则来说意味着什么?在这个项目中,企业被认为是一个盈利性公司。它感兴趣的主要是经济利益,从分析来看,我推荐的类型是动画。我使用了来自电影数据库的数据,推荐什么类型的可能性是有限的。模型可以做出类似的建议,并随着数据集随时间的变化而更新其建议。随着娱乐和就业被视为商品,它可以被视为是有益的。侵犯隐私或安全的可能性似乎很小,通过自主测试将取决于实现。这个决定是由模型单独做出的,还是由一些人和模型共同做出的?如果只考虑模型,除了短期财务收益之外,可能永远不会考虑其他因素。当考虑正义时,这也将取决于实现,但是如果唯一的问题是类型,那么正义的方面将取决于模型建议的人类实现。关于可解释性,这将再次取决于模型的实现。然而,来自电影数据库的数据集是公开可用的这一事实将有助于模型的可理解性。
因为这个项目实际上没有进行机器学习,所以分析主要是推测性的,并且将取决于机器学习模型的实际实现。让我们继续下面四个使用机器学习模型的项目。
项目# 2——房价预测即服务
这个项目是基于一个虚构的服务,该服务将向搬到华盛顿州 King County 地区或希望搬到该地区新位置的人提供住房建议,并向企业提供类似的数据,以便他们可以做出明智的工资决定。
这个项目的机器学习方面是使用国王县房屋销售数据集的修改版本进行房价预测。
让我们开始伦理分析。我会把这个项目看作一个整体,而不仅仅是机器学习方面。出于慈善目的,可以向潜在购房者及其雇员提供的知识可以被视为通过向他们提供可能很难或很费时间来汇编的信息来促进购房者的福祉。该数据集不使用国王县尚未公开的个人信息,因此不会对人们的隐私造成损害。就自主性而言,该服务将几乎所有的自主性都给予了人类参与者。信息的消费者可以使用或不使用服务给出的建议,而不会产生任何影响。就公正而言,该服务最终可能会导致中产阶级化,并对该服务推荐的价格和便利性之间更好平衡的现有社区成员进行定价,而不考虑目前居住在那里的人。对于可解释性,我将同时考虑模型和数据集。首先,数据集是公开的。用于房价预测的模型是线性回归,其中内置了许多解释能力。它可以提供正在使用的参数列表及其对计算出的房价的重要性。
这项服务唯一潜在的道德问题是它对中产阶级化的潜在贡献。这项服务如何才能更加公正,使特定社区的住房成本不会迅速攀升?这是一个社区需要参与解决的复杂问题,但一个想法是增加服务的复杂性,以便考虑价格趋势,并阻止购房者在价格上涨过快的社区购买。
项目 3——坦桑尼亚水点分类
该项目旨在创建一个模型,用于预测供水点的分类,即功能性、功能性需要修复或非功能性,以便坦桑尼亚政府能够更好地利用其有限的资源,更好地为其人口提供清洁水。
这个项目看起来很有益处,它有助于为需要的人们提供干净的水。但是当把无罪和自主结合起来考虑时,就不那么明确了。不存在隐私或安全问题,但如果给予这种模式太多的自主权,可能会导致一些人永远无法获得当地供水点的服务。功能性水点的假阳性将导致那些水点被忽略。当考虑正义时,结果会是什么也不清楚。虽然拥有一个模型来确定需要访问哪些水点以获取服务可以消除人类决策过程中的偏差,但我们不知道在源数据集中存在什么偏差(如果有的话)。检查和记录结果以及每个水点信息的人做得好吗?他们是否同样注意或准确地检查了所有的水点?是否有任何水点被故意忽略,从而被排除在模型之外?如果不知道这些问题的答案,我们就无法知道通过源数据在模型中会产生什么样的偏差。现在让我们从可解释性的角度来看模型本身。表现最好并被选择用于实现的模型是随机森林分类器,它具有有限的互操作性。它可以告诉我们哪些特征对模型整体而言是重要的,但是考虑到随机森林模型中涉及大量树木,要解释特定水点的分类并不容易。
随机森林模型缺乏真正的互操作性,并且缺乏关于训练数据集中可能嵌入哪些偏差的信息,这使我认为,如果可以找到具有可比性能的模型,应该使用更具互操作性的模型。这样就可以审核一些已知的错误分类,以了解错误发生的原因,并对模型进行改进。
项目 4——推特情感分析
该项目旨在建立一个情感分析模型,以帮助一家虚构的公司监控公众对其新手机的反应,并对其竞争对手进行市场研究。
它使用机器学习模型对推文的情绪进行分类,但将解释和回应留给了人类分析师和决策者。该项目的好处是,根据 Twitter 用户的反馈,该公司将提供更好的手机。没有任何非恶意,模型中没有使用私人信息,但模型是在包含 twitter 句柄的公共数据集上训练的。虽然数据集不是为这个项目创建的,但数据集的创建者应该考虑是否包含这些 twitter 句柄,他们应该对数据进行某种匿名处理。虽然这些推文是公开发布的,但它们现在有了寿命,发布推文的人不再能够控制。这个系统通过只给人类参与者建议和观察,给予他们充分的自主权。公正的问题不适用于这个项目,因为它的范围有限。用于情感分析的模型是可解释的朴素贝叶斯分类器,并且数据集是公开可用的,使得项目是可解释的。
项目# 5——假新闻分类
这个项目是为一家虚构的社交媒体公司创建一个模型,将发布到其平台上的新闻故事分类为假或真,以帮助他们回应公众对允许假新闻在其网站上扩散的指控,然后监控假新闻的发展。
该项目的好处是有可能消除或限制这个平台上的假新闻,这将减少人们个人或其社区成员面临的 dis 和错误信息的数量。假新闻被理解为对其读者或公众造成伤害,因为其意图是为了创作者或创作者支持的人或团体的利益而误导读者。在处理无罪问题时,新闻自由和言论自由就发挥了作用。在这个项目中,不会因为分类而改变或删除任何帖子,这将由人类决策者决定,但如果模型被赋予基于其分类删除帖子的自主权,则需要提出审查和偏见的问题。是什么使得这个故事是假的?它实际上是错误或虚假信息,还是讽刺、耸人听闻或质疑主导故事线?如所实现的,充分的自主权被给予人类决策。在考虑公正时,必须考虑模型的准确性。该模型在两个类别之间实现了 89%的准确率平衡,但是有 11%的类别被错误地分类了呢?考虑到对具有真正公共价值的新闻报道的潜在错误分类,是仅仅基于这种模式采取行动,还是删除它们会超出潜在价值?训练模型的数据集是否包含对某些类型的假新闻的偏见?谁来决定假新闻的真正定义,他们如何决定?这个项目使用了一个随机森林分类器,就像上面解释的那样,只能部分解释。考虑到对言论自由的高度重视,以及解释特定新闻故事的分类而不仅仅是呈现整体特征重要性的需要,使用更具可解释性的模型会更好。
这个项目提出了许多关于无罪、公正和可解释性的伦理问题,如果它被实际执行或有一个执行计划,有些问题会有答案,但还有其他问题仍然存在,值得深思。
结论
虽然这些项目看起来大多是道德的,但它们都提出了许多问题,需要不同程度的深入调查或反思,才能完成真正的道德分析。也就是说,我认为这对我来说是一次值得的练习,我希望对你也是如此。
人力资源部门的机器学习和人工智能
生产力的新时代还是去除人力资源中的“人”?
资料来源:Pexels.com
介绍
深度学习和人工智能已经彻底改变了医疗保健、金融服务和零售等行业,许多公司都欢迎新技术。然而,人力资源(HR)部门在将智能系统集成到他们的工作流程中时遇到了更多的挑战。
人力资源部门的任务是管理组织的员工——雇用、解雇、解决纠纷、工资、福利等等。这些任务中的许多似乎已经成熟,可以通过机器学习实现自动化,然而,它们也往往是主观的,移交控制权带来了有趣的伦理挑战。
员工招聘
招聘过程既费力又昂贵。从审查简历、面试和培训新员工,雇用新员工会给组织带来新员工工资之外的巨大成本。然而,这种成本通常是值得的,因为如果必须解雇员工并重新开始这一过程,做出错误的决定会花费更多的钱。不仅需要再次产生雇佣成本,而且还会出现产量损失和新员工达到满负荷生产所需的时间。
正因为如此,许多公司已经将目光投向深度学习,以提供降低雇佣员工成本和提高雇佣员工质量的解决方案。然而,这些尝试并不总是按计划进行。
从 2014 年到 2018 年,亚马逊的一个团队建立了审查申请人简历的系统,以简化招聘顶级人才的流程。为了训练他们的算法,该团队利用过去十年提交给该组织的简历汇编了一个训练数据集。
亚马逊曾希望该系统能够自动识别前 x 名申请人,从而大幅减少从申请人中识别顶尖人才的时间。然而,他们后来发现,该系统对男性申请者比对女性申请者更有利。这是因为向亚马逊提交简历的男性求职者多于女性,这就产生了一个有偏见和扭曲的数据集。
创建公正的招聘系统可能是一项艰巨的任务。由于大多数公司很少有 50%的男性员工和 50%的女性员工,该模型通常可以识别出它认为最能说明一个好员工的因素,但实际上招聘经理并没有考虑这些因素。
为了创建准确的招聘决策和候选人排名系统,必须注意收集用于培训的数据集,以消除不必要的行为。此外,对模型进行硬编码以忽略某些特征(如姓名、性别和种族)也是可行的。
每小时调度
管理小时工的人力资源团队在创建时间表时有一项艰巨的任务。当你的员工不是全日工作且有一致的时间表时,经常会出现时间冲突。由于工作日程不可预测,人力资源经理(通常是总经理)的一个关键职能是管理休假和换班请求。
如果你问许多餐馆或零售店的经理,日程安排和与之相关的任务经常占据他们工作日的很大一部分。然而,深度学习系统开始承担这一负担。
自动化系统可以分析这些请求,并根据个人层面的预定义业务规则自动批准或拒绝它们。例如,许多雇用兼职倒班工人的组织不允许他们的员工在一周内工作 40 个小时或更多。如果换班请求使一名员工一周工作超过 40 小时,系统将拒绝该请求,无需任何人工干预。
当与预测需求信息相结合时,这些系统变得更加强大。准确预测何时需要额外的员工并相应地调整时间表和休假请求,可以在需求较低时节省劳动力成本,并在需求较高时确保有足够的员工工作,从而提高员工管理的效率。
虽然这些系统可以极大地改善员工管理并减少经理的工作量,但它可能会打击员工的士气。通常情况下,休假和换班请求可能是个人性质的。如果一个自动化系统拒绝了一个重要事件的休假请求,员工可能会对组织产生怨恨。
要使自动排班系统正常工作,重要的是要彻底定义业务规则,并确保员工有办法通过他们的经理获得对模型决策的否决。
劳动力分析
分析团队让组织能够以前所未有的方式利用他们的数据,让公司做出前所未有的明智决策。
当我们想到业务数据时,我们通常会想到他们收集客户数据以更好地了解他们。然而,许多组织也在收集其员工的数据。
跟踪组织员工的关键指标可以让人力资源部门更好地了解他们的员工。跟踪员工的情绪、生产力和与组织的联系使人力资源部门能够更好地分配资源并提高员工的效率。此外,它允许预测分析模型识别有离开组织风险或有可能晋升的员工。
虽然劳动力分析似乎是人力资源部门的一个显而易见的选择,但员工可能不会有相同的观点。将一名员工浓缩成一系列数字指标会使管理过程失去人性,让员工觉得自己只不过是一个数字。
结论
机器学习和人工智能在人力资源方面有着广阔的应用前景。然而,从人到机器驱动的管理的转换会导致组织内员工士气的重大问题。这些技术是开创了生产力的新时代,还是将“人”从人力资源中移除?我将把那件事留给你。
处理机器学习中的类不平衡
斯科特·凯利在 Unsplash 上拍摄的照片
处理高度不平衡数据的策略
介绍
将机器学习应用于现实世界的问题非常罕见,你可能会在教程或数据科学课程中找到一些简单明了的东西。很多时候你会遇到分类问题,你试图预测一些不经常发生的事情。这在试图预测诸如转换、流失、欺诈之类的事情时很常见。在这篇文章中,我将谈论机器学习中的阶级不平衡。特别是,我想回顾一下不平衡数据的一些含义,并强调和解释一些解决方法。我的希望是,在这篇文章结束时,你将拥有处理你可能遇到的任何预测问题所需的工具。
什么是不平衡数据,为什么这是一个问题?
就像我上面说的,当我们试图预测的类的比例有显著差异时,不平衡的数据就会出现。例如,在许多行业中,客户在一段时间内的流失是相对罕见的(希望如此)。如果我们尝试制定一个机器学习模型来预测客户是否会流失,我们可能只有 5%的客户会流失,而 95%的客户不会流失。对于像转换或欺诈这样的事情,这可能会更低。
好了,这个问题有希望变得更清楚一点,但是我们为什么要关心这个呢?我们来训练一下模型,做一些预测。让我们以上段中的流失为例,估计一个逻辑回归。在对模型进行估计后,我们得到了 95%的正确预测。那很容易。但是,如果我们更深入地研究结果,并查看混淆矩阵,我们可能会发现类似下面的图 1。我们的模型预测,基本上没有人搅动。这不是很有帮助,我们可以自己做这个预测,省去写代码的麻烦。显然,这种模式是非常无用的,并没有真正增加任何价值。这是怎么回事?为什么我们的模式这么差?训练集是如此不平衡,以至于模型很难在少数类中找到有用的模式。这在逻辑回归等算法中更为明显,因为它假设类分布是相等的。幸运的是,有几种方法可以解决这个问题,这就是我在这篇文章中将要经历的。
图 1:混乱矩阵:不平衡的数据
取样技术
我们可以尝试的第一个潜在解决方案是对数据进行重新采样,以平衡类别。我们可以尝试几种不同的采样方法,所有这些方法都可以在 imblearn python 库中轻松实现。
要提到的一个关键点是,这些重采样技术应该只在训练数据上执行。测试集应该保持不平衡。
为了开始我们的分析,让我们首先使用 sklearn 的一个方便的函数来创建一个数据集。make _ classification函数非常有用,允许我们创建一个数据集来演示这些技术和算法。请注意,我们已经将权重=[0.99,0.01]添加到参数中,以生成不平衡的数据集。这种不平衡程度非常类似于我最近参与的一个机器学习项目,在实践中看到这样的数据集并不罕见。
随机欠采样
首先,让我们看看欠采样。这种技术非常简单,包括从多数类中随机选择样本,并将这些样本与我们的少数类一起用于训练数据。结果是我们得到了相同数量的正面和反面的例子,可以避免上述问题。这种技术的优点是非常容易实现,而且非常有效。不利的一面是,你实际上是在丢弃数据。我可能不喜欢这种方法,除非我的训练数据非常大,并且我有能力扔掉这些数据。在下面的图 2 中,我们可以看到实现这一点的代码以及欠采样后的训练集。请注意我们删除了多少数据。
图 2:训练数据(左),欠采样(右)
随机过采样
过采样与欠采样相反。使用这种方法,我们从少数类中随机抽取数据,并复制它以创建更多的样本。我们这样做,直到类分布相等。尽管这对于解决失衡很有用,但也有一些缺点。最主要的一点是我们正在复制已经存在的数据。这意味着我们实际上并没有给分类问题添加任何额外的信息,这可能会导致过度拟合,这是我们绝对希望避免的。
图 3:训练数据(左),过采样数据(右)
合成少数过采样技术
顾名思义,SMOTE 是一种过采样方法,用于从我们已经拥有的数据中生成额外的数据。它类似于随机过采样,但我们不是复制现有数据,而是生成新的合成数据。最初的论文对该技术描述如下:
“通过获取每个少数类样本并沿着连接 k 个少数类的任何/所有最近邻居的线段引入合成样本,对少数类进行过采样”。
那么这意味着什么呢?嗯,该算法首先使用 k-最近邻来决定我们将使用哪些数据点来产生新数据。为简单起见,假设我们选择 k = 1。该算法将在我们最近邻的数据点之间创建一条线段,并沿着这条线在某处产生一个新的数据点。假设我们正在生成数据的特性是自用户上次访问我们的网站以来的天数。为了生成新的合成数据,该算法计算两个新变量。 间隙 是介于 0 和 1 之间的随机数,假设我们得到 0.8,以及 diff, 是用户最后一次访问我们的第一个数据点(20)和它的最近邻居(15)的天数之差。该特征的合成数据值为:24 = 20+(20–15)* . 8。
好的,让我们看看如何用 python 实现它,并可视化算法产生的结果。你可能会认为图表看起来有点奇怪,我可能会同意,但这只是算法的人工产物,并强调数据是“合成的”而不是全新的,因为它直接取决于其他数据点(或至少是最接近的数据点)。
图 4:训练数据(左),SMOTE(右)
这些技术各有利弊,但在实践中,我建议尝试所有这些技术,看看哪种效果最好,并让您的模型度量来指导您。
对于那些对细节更感兴趣的人,这里有一个全文链接:https://arxiv.org/pdf/1106.1813.pdf
类别加权
正如我上面提到的,许多机器学习算法假设类分布是相等的,所以它们可能不能很好地开箱即用。逻辑回归就是这种情况。为了避免这个问题,在 sklearn 中有一个很好的参数叫做class _ weights,它让我们告诉模型什么是类分布。这是一个简单而有效的解决方案,过去我发现它非常成功。更具体地说,它将更多地惩罚在少数群体中犯错误的模型。这些错误将使最小化成本函数变得更加困难,因此模型学习更加强调正确地得到少数类。
下面的代码展示了我们如何用 python 实现这一点。我们可以选择 class_weight = 'balanced ',或者传递一个具有特定类权重的字典,例如 weights = {0:0.01,1:1.0}
在向您介绍和解释了各种技术之后,我想我也将分享我与一位同事在讨论不平衡数据时的一段有趣对话。他指出:
使用逻辑回归等模型时,不平衡数据并不重要,只要它不影响系数估计值(仅截距)。
截距将根据不平衡进行调整,系数将保持不变。经过思考,我意识到他是对的。然而,这有一个问题。如果你画出预测概率的分布,你可能会看到一个非常偏斜的分布。例如,当我这样做的时候,我的分布范围是从 0 到 0.2。这对我来说是一个问题,特别是当模型的输出需要被解释并向你公司的业务团队解释的时候。仅仅因为这个原因,我认为重新平衡数据要好得多,尽管原则上逻辑回归可以处理不平衡。
算法和度量
正如我前面提到的,在处理不平衡数据时,算法的选择也会极大地影响您的结果。选择合适的指标来评估模型的性能也是非常重要的。同样,在这种情况下,准确性不是一个特别有用的衡量标准。使用 ROC AUC、Precision 和 Recall 以及混淆矩阵等指标,我们可以更好地了解模型的表现。
在这里,我不会深入探讨这些指标是如何工作的,但这里有一些资源可以详细介绍这些指标。
测试不同的方法
好了,这是足够的背景材料,让我们进入有趣的部分,看看这个例子的一些代码。我最近不得不在一个项目中应用这些技术,它们对我来说相当不错。不幸的是,由于数据是敏感的,我不能显示它,但我们可以通过生成一些数据来重新创建一个类似的场景。在任何情况下,我在这里展示的技术和代码应该可以很容易地转移到其他分类问题上。下面我们将评估几个不同的模型,看看它们在不平衡数据集上的表现。然后,我们将尝试上述技术,看看它们如何使用一些关键的分类性能指标来改善我们的结果。
生成建模数据
同样,我们可以使用 sklearn 中的 make_classification 函数来创建不平衡数据集。对于这个例子,我们将有 1%的正面例子和 99%的负面例子。
Imblearn 管道
为了使用不同的采样技术来估计这些模型,我们将使用 imblearn 管道。我相信你们中的一些人听说过 sklearn 管道,这些管道本质上是相同的,但专门用于采样技术。据我所知,目前还不能在 sklearn 管道上使用这些采样技术。这是我第一次使用管道,我不得不说,它们让你的代码更干净,更容易阅读。它们非常方便,所以我一定会将它们融入到我的工作流程中。
要使用这些管道,我们需要做的就是创建一个采样类和算法的实例,然后将它们作为元组传递给管道类。我最初试图看看我是否可以将多个算法传递到管道中,即逻辑回归和随机森林,但这不起作用。然而,如果你用一个合适的变换方法传递算法,比如 PCA,它应该工作得很好。从 imblearn 文档中:
管道的中间步骤必须是转换器或重采样器,也就是说,它们必须实现 fit、transform 和 sample 方法。
逻辑回归管道代码
随机森林管道代码
结果
逻辑回归
不平衡数据
图 5:逻辑回归:不平衡
我们可以看到,不平衡数据集的结果并没有那么好。阈值为 0.5 的模型表现非常差,几乎没有识别出我们的正面例子。我们可以尝试适当地改变阈值,但这将再次给我们非常倾斜的概率输出。我们还可以从我们的 PR 曲线中看到,该模型很难在不犯很多错误的情况下识别积极的标签。有趣的是,中华民国实际上看起来很好。这突出表明,在处理不平衡数据时,ROC 可能是一个误导性的指标。要了解这里发生了什么,想想 ROC 正在绘制的图,真阳性率(TPR)对假阳性率(FPR)。以下是 TPR 和 FPR 的定义。
- 召回/TPR = TP / (TP+FN)
- FPR = FP / (FP + TN)
因为我们的阶级不平衡,我们有更多的反面例子。本质上,我们的模型偏向于预测负面例子,所以我们有很多真正的负面(TN)。这使得我们的假阳性率(FPR)不会增加太多,因为我们的 TN 将在分母中增加。这就是为什么我们可以获得高 AUC,即使我们在对正面例子(我们最关心的例子)进行分类时做得不好。然而,如果我们使用精确和回忆,这个问题就被避免了,因为我们根本没有使用真正的否定(TN)。
- 精度= TP/(TP+FP)
- 召回/TPR = TP/(TP+FN)
在这种情况下,我倾向于使用混淆矩阵和 PR 曲线来衡量模型的性能。*注意,我使用了自己创建的几个助手函数来绘制这些指标。代码位于这篇文章的底部。*所有显示的数字都使用默认阈值 0.5。根据您的使用情况,这可以很容易地改变,以根据需要调整预测。
我们的抽样方法怎么样?
总的来说,不同取样方法的结果几乎完全相同。那么这种情况下我们应该怎么做呢?总的来说,这些结果不是很好,所以在这一点上,我建议尝试其他模型。但是,如果我们决定估计一个逻辑回归,我们有一个大的数据集,我们可以支持欠采样,因为它是三个选项中最不复杂的,并尝试优化我们的决策阈值,以提高我们的 TP 率。
欠采样
图 6:逻辑回归欠采样
过采样
图 7:逻辑回归过采样
重击
图 8:逻辑回归 SMOTE
随机森林
所以逻辑回归在这个问题上表现不太好,我们试试随机森林怎么样。这些模型往往在实践中表现良好,它们通常是我解决分类问题的首选模型。至于结果,该模型在识别 9% TP 的缺省阈值下对不平衡数据的表现略好于逻辑回归。显然,我们想要比这更好的东西,所以让我们再次尝试我们的采样技术。
比较这三种采样方法表明,欠采样对 65%的真阳性进行了最好的分类。它在识别真正的负面因素方面也比逻辑回归做得更好。然而,我们最好的结果来自于平衡类权重。因为这在 sk learn(class _ weights = ’ balanced ')中很容易做到,而且我们不必丢弃任何数据,所以这是我的首选。这样做给了我们 70%的 TP 率。
我们还能做些什么来提高模型得分?
这里我们还可以尝试一些其他的事情来提高我们的模型性能,并确保我们的预测是稳健的。
- KFold 交叉验证:我在这里没有执行交叉验证,但是我建议这样做。使用 sklearn 使用cross _ val _ score真的很简单。
- 其他车型:SVM、lightGBM、XGBoost 等等。
- 超参数优化 :这对于有许多超参数的模型特别有用。
欠采样
图 9:随机森林欠采样
过采样
图 10:随机森林过采样
重击
图 11:随机森林重击
类别权重
图 12:随机森林类权重
主要要点
那么我们能从这些例子中学到什么呢?
- 有许多方法可以解决不平衡数据的问题,每种方法的有效性很可能取决于您的问题和数据。
- 为特定问题选择合适的指标很重要:我建议多看一个。没有一个指标是完美的。
- 尝试多种算法可以给出更好的结果:每种算法都有自己的优点和缺点:例如,随机森林通常表现更好,但可能比逻辑回归更难解释,它们在计算上也更复杂。
- 不重新平衡数据会导致输出概率非常不准确,难以解释和说明。
- 改变阈值也是有效的:改变多少取决于你的模型犯错误的相对成本。
好了,伙计们,这篇文章到此为止,一如既往地感谢你的阅读,我希望你觉得这很有用。
帮助器函数的 Python 代码
下面是一些有用的函数来帮助我们评估我们的模型性能。
[## 丹尼尔·福利-数据科学家-产品疯狂| LinkedIn
在全球最大的职业社区 LinkedIn 上查看丹尼尔·福利的个人资料。丹尼尔列出了 5 份工作…
www.linkedin.com](https://www.linkedin.com/in/daniel-foley-1ab904a2/)
我的其他一些帖子你可能会感兴趣
用于实时数据管道的 Apache Beam 和数据流
towardsdatascience.com](/lets-build-a-streaming-data-pipeline-e873d671fc57) [## 高斯混合模型(GMM)
使用无监督学习理解文本数据
towardsdatascience.com](/gaussian-mixture-modelling-gmm-833c88587c7f) [## k 均值聚类
使用无监督学习理解文本数据
towardsdatascience.com](/k-means-clustering-8e1e64c1561c)
超越 CUDA: GPU 加速的 C++在跨厂商显卡上进行机器学习,使用 Kompute 变得简单
通过使用 Kompute 框架和 Vulkan SDK 的实际机器学习示例介绍 GPU 计算
C++中 Vulkan SDK 和 Kompute 的视频概述
机器学习,以及许多其他高级数据处理范例,非常适合 GPU 计算提供的并行处理架构。
图片作者作者
在本文中,您将学习如何用 GPU 优化代码从头开始编写自己的 ML 算法,该算法将能够在几乎任何硬件上运行,包括您的手机。我们将介绍核心的 GPU & ML 概念,并展示如何使用 Kompute 框架 只用几行代码就能实现它。
我们将首先构建一个简单的算法,将两个数组并行相乘,这将介绍 GPU 处理的基础知识。然后,我们将在 GPU 中从头开始编写一个逻辑回归算法。您可以在以下链接中找到回购协议的完整代码:
- Kompute 库
- GPU 阵列乘法库和 Kompute 代码
- GPU 逻辑回归库、 Kompute 代码和着色器代码
动机
近年来,GPU 计算的潜力和采用率一直呈爆炸式增长——从下图中的图表可以看出采用率的增长速度。在深度学习中,采用 GPU 进行处理的数量大幅增加,同时支持在越来越多的 GPU 节点上大规模并行分配计算任务的范例也大量增加。有许多令人兴奋的研究围绕着技术,这些技术提出了实现模型并行性和数据并行性的新方法——这两种方法都允许算法和数据分别细分为广泛的方法,以最大限度地提高处理效率。
本农、塔尔和托尔斯滕·霍夫勒。“揭开并行和分布式深度学习的神秘面纱:深度并发分析。”美国计算机学会计算调查(CSUR)52.4(2019):1–43。
在本文中,我们概述了理论,并实践了一些工具,这些工具将使初学者和经验丰富的 GPU 计算从业者能够利用这些迷人的高性能计算领域的当前开发和讨论,并为之做出贡献。
Vulkan 框架
在开始之前,有必要介绍一下核心框架,它使得构建超优化、跨平台和可扩展的 GPU 算法成为可能,这就是 Vulkan 框架。
与 Khronos 成员一起玩“瓦尔多在哪里”(图片由 Vincent Hindriksen 通过 StreamHPC 提供)
Vulkan 是由 Khronos Group 领导的一个开源项目,Khronos Group 是一个由大量技术公司组成的联盟,他们聚集在一起致力于定义和推进移动和桌面媒体(和计算)技术的开放标准。在左边,你可以看到范围广泛的 Khronos 成员。
您可能想知道,*为什么我们还需要另一个新的 GPU 框架,而这里已经有许多选项可用于编写可并行化的 GPU 代码?*主要原因是,与一些闭源的同类产品(如 NVIDIA 的 CUDA 或苹果的 Metal)不同,Vulkan 是完全开源的,并且与一些旧的选项(如 OpenGL)不同,Vulkan 是以现代 GPU 架构为基础构建的,提供了非常细粒度的 GPU 优化。最后,虽然一些替代产品为 GPU 提供了特定于供应商的支持,但 Vulkan 提供了跨平台和跨供应商支持,这意味着它打开了移动处理、边缘计算等领域的机会之门。
Vulkan SDK 提供对 GPU 的非常低级的访问,这允许非常专业的优化。这对 GPU 开发人员来说是一笔巨大的财富——主要缺点是冗长,需要 500–2000 多行代码才能获得编写应用程序逻辑所需的基本样板文件。这不仅会导致昂贵的开发周期,而且容易导致更大问题的小错误。
这实际上可以在许多新的和知名的机器学习和深度学习项目中看到,如 Pytorch、Tensorflow 和阿里巴巴 DNN 等,这些项目已经集成或正在寻求集成 Vulkan GPU SDK,以添加移动 GPU(和跨供应商 GPU)支持。所有这些框架都以非常相似和极其冗长的样板代码告终,这意味着它们会从使用统一的基线中受益(并且仍然会受益)。这是我们启动 Kompute 项目的主要动机之一。
输入 Kompute
Kompute 是一个构建在 Vulkan SDK 之上的框架,专门用于扩展其计算能力,作为一个简单易用、高度优化、移动友好的通用 GPU 计算框架。
Kompute 文档(图片由作者提供)
Kompute 不是为了隐藏任何核心的 Vulkan 概念而构建的 Vulkan API 设计得非常好——相反,它通过 BYOV(自带 Vulkan)设计增强了 Vulkan 的计算能力,通过减少所需的样板代码和自动化编写 Vulkan 应用程序中涉及的一些更常见的工作流来支持开发人员。
对于想了解更多信息的新开发人员来说,它为开始使用 GPU 计算提供了坚实的基础。对于更高级的 Vulkan 开发人员,Kompute 允许他们将其集成到现有的 Vulkan 应用程序中,并通过在需要时访问所有 Vulkan 内部来执行非常精细的优化。该项目是完全开源的,我们欢迎错误报告、文档扩展、新示例或建议——请随时在回购中提出问题。
编写你的第一个计算机
为了使用 Kompute 构建我们的第一个简单的数组乘法 GPU 计算应用程序,我们将创建以下内容:
- 两个康普顿张量存储输入数据
- 一个计算机张量存储输出数据
- 一个计算机操作创建并复制张量到 GPU
- 带有 Kompute 算法的 Kompute 操作,该算法将保存要在 GPU 中执行的代码(称为“着色器”)
- 将 GPU 数据同步回本地张量的 Kompute 操作
- 一个 Kompute 序列记录操作,批量发送到 GPU(我们将使用 Kompute 管理器来简化工作流程)
Kompute 建筑设计(图片由作者提供)
Kompute 的核心是用于 GPU 操作的“Kompute 操作”,以及处理 GPU 数据和内存的“Kompute 张量”操作。更具体地说,这个图显示了 Kompute 组件之间的关系(包括显式内存所有权)。
当与 GPU 交互时,您必须将指令发送给 GPU 来执行,并且您需要确保 GPU 在 GPU 内存中有所有可用的相关数据来开始处理。使用 Vulkan,您可以通过队列将这些指令发送到 GPU,因此为了直观地简化事情,您可以将您的 GPU 视为远程服务器,其中数据序列化、资源创建和内存分配是昂贵的,并且指令是通过队列提交的——仍然有 GPU-CPU 共享内存,但您倾向于仅将它用于向 GPU 传输数据。
让我们直接进入代码。通常,在 Kompute 应用程序中,我们将遵循以下步骤:
- 创建 Kompute 管理器来管理资源
- 创建 Kompute 张量来保存数据
- 使用 Kompute 操作初始化 GPU 中的 Kompute 张量
- 将在 GPU 上运行的代码定义为“计算着色器”
- 使用 Kompute 操作对 Kompute 张量运行着色器
- 使用 Kompute 操作将 GPU 输出数据映射到本地张量
- 打印您的结果
1.创建 Kompute 管理器来管理资源
首先,我们将创建 Kompute 管理器,它负责创建和管理所有底层 Vulkan 资源。
正如你所看到的,这里我们正在初始化我们的 Kompute 管理器,期望它在设备 0 上创建所有的基本 Vulkan 资源(在我的例子中,设备 0 是我的 NVIDIA 卡,设备 1 是我的集成显卡)。对于更高级的用例,也可以用自己的 Vulkan 资源(设备、队列等)初始化 Kompute 管理器,但这超出了本文的范围。
2.创建 Kompute 张量来保存数据
我们现在将创建用于输入和输出的 Kompute 张量。这些将保存所需的数据,这些数据将被映射到 GPU 来执行这个简单的乘法。
Kompute 设计使用std::shared_ptr
的原因是为了避免通过值传递对象,而是使用智能指针传递对象。
3.使用 Kompute 操作初始化 GPU 中的 Kompute 张量
现在我们已经用本地数据创建了张量,我们将把数据映射到 GPU 中。为此,我们将使用[kp::OpTensorCreate](https://axsaucedo.github.io/vulkan-kompute/overview/reference.html#optensorcreate)
Kompute 操作,该操作将初始化底层 Vulkan 缓冲区和 GPU 内存,并执行到 GPU 的相应映射。
同样值得一提的是,通过利用 Kompute 管理器buildTensor
助手功能,可以缩短张量创建的步骤。这将允许您跳过显式创建shared_ptr
以及下面概述的kp::OpTensorCreate
操作的需要(您也可以在这里找到这个变体的完整代码实现)。
4.将在 GPU 上运行的代码定义为“计算着色器”
现在我们已经初始化了必要的 Kompute 张量分量,并且它们被映射到 GPU 内存中,我们可以添加将在 GPU 中执行的 Kompute 算法。这被称为“着色器”代码,遵循类似 C 的语法。你可以在下面看到完整的着色器代码,我们将在下面分解每个部分。
#version 450
和layout(local_size_x = 1) in;
部分指定了版本和并行线程执行结构(我们将在文章的后面进一步研究)。然后,我们可以看到以以下格式定义的 GPU 数据输入和输出:
*layout(binding = <INDEX>) buffer <UNIQUENAME> {float <VARNAME>[]};*
- —将张量映射到 GPU 输入的索引
- —这必须是缓冲区的唯一名称
- —这是在着色器代码中使用的变量名
这些是可以在着色器代码中用于处理的参数。也就是说,在这种情况下,处理是在main
函数内部完成的。第一个变量uint index = gl_GlobalInvocationID.x;
是当前的并行执行指数,它将允许我们处理每个数据输入。
然后,我们进入该算法的核心,即乘法o[index] = a[index] * b[index].
,这一部分非常简单明了——我们将 GPU 数组a[]
和b[]
的元素相乘,然后将输出存储在数组o[]
中。
5.使用 Kompute 操作对 Kompute 张量运行着色器
为了运行上面的着色器,我们将创建 Kompute 操作[kp::OpAlgoBase](https://axsaucedo.github.io/vulkan-kompute/overview/reference.html#opalgobase)
。这个 Kompute 操作所需的参数包括绑定到 GPU 指令中的张量,以及着色器代码本身。
值得一提的是,Kompute 允许用户通过文件路径传递着色器,或者也有 Kompute 工具允许您将着色器二进制文件转换为 C++头文件。
6.使用 Kompute 操作将 GPU 输出数据映射到本地张量
一旦算法被触发,结果数据将保存在输出张量的 GPU 内存中。我们现在可以使用[kp::OpTensorSyncLocal](https://axsaucedo.github.io/vulkan-kompute/overview/reference.html#optensorsynclocal)
Kompute 操作按照下面的代码块同步 Tensor GPU 内存。
7.打印您的结果
最后,我们可以打印出张量的输出数据。
当你运行它时,你会看到输出张量的值被打印出来。就这样,你写了你的第一个 Kompute!
您也可以在 repo 中找到完整的示例,这样您就可以运行它并根据需要扩展它。你可以在这个库中找到完整的独立示例,其中包括如何构建它的说明以及 Kompute C++代码。
虽然看起来不明显,但上面介绍了 GPU 计算中核心概念和设计思维的一些直觉,同时还抽象了一些更深入的概念。在接下来的几节中,我们将提供更具体的术语,我们将触及一些更高级的概念,如线程、块、内存步长和共享内存(尽管很多内容将作为进一步的阅读材料提供)。
潜入机器学习直觉
让我们看一个更高级的 GPU 计算用例,具体实现机器学习的 hello world,逻辑回归。在我们介绍实现之前,我们将提供一些理论上的直觉,以及我们将贯穿始终使用的术语。
在机器学习中,我们总是有两个阶段,训练和推理。在下图中,您可以看到两个简化的流程。最上面是训练流程,在这里你识别一些训练数据,提取一些特征,训练一个模型,直到你对精度满意为止。一旦您有了一个经过训练的模型,您就可以持久化模型“权重”,并将模型部署到第二个工作流中,在第二个工作流中,模型将对看不见的数据执行推理。
数据科学流程(图片由作者提供)
在这种情况下,我们将有一个输入数据集X
,其中每个元素是一对xi
和xj
。我们的输入数据如下:
xi = { 0, 1, 1, 1, 1 }
xj = { 0, 0, 0, 1, 1 }
利用该输入数据,要预测的预期目标值Y
将如下:
Y = {0, 0, 0, 1, 1}
来自 DS Central 的逻辑回归示例
我们在机器学习中的主要目标是学习使用这些数据来找到函数(和参数),这将允许我们仅使用X
作为输入来预测值Y
。
值得注意的是,预测值被定义为ŷ
,它是用我们的推理函数计算出来的值,不同于我们上面定义的Y
的“真”或“实际”值。
我们将用于逻辑回归的函数如下:
让我们来分解这个函数:
z
——是我们的线性映射函数ŷ
—结果预测输出X
ᵀ——包含我们的输入 xi 和 xj 的矩阵的转置σ
—sigmoid 函数,将在下面详细介绍
我们希望通过机器学习算法学习的参数是:
W
—将应用于输入的权重b
—将要添加的偏差
还有环绕函数σ
也就是 sigmoid 函数。该函数迫使我们的输入更接近 0 或 1,这可以直观地视为我们预测为“真”的概率,定义如下:
这就是现在的推理功能,它将允许我们处理来自新数据点的预测。例如,如果我们说我们有一组新的看不见的输入X = { (0, 1) }
,并且我们假设在通过我们的训练数据运行我们的机器学习算法之后,学习到的参数是W = (1, 1), b = 0
(稍后我们将这样做),那么我们将能够通过我们的预测函数来运行它,方法是代入以下值:
在这种情况下,预测是0.73...
,这将是一个肯定的预测。这当然只是为了演示一旦我们学习了参数W
和b.
我们的推理函数会是什么样子
从 ML Academy 可视化的梯度下降
我们学习参数的方法是进行预测,计算误差,然后相应地重新调整权重。用于基于“预测误差”来“重新调整”权重的方法将通过利用梯度下降来完成。这将被重复多次以找到更精确的参数。
为此,我们将需要使用每个公式的导数。第一个是我们的线性映射函数z
的导数:
- ∂z = z(x) - y
其中变量定义如下:
∂z
—线性映射函数的导数z(x)
z(x)
—应用于输入x
的线性映射函数的结果y
—输入 x 的预期实际值标签
类似地,w 和 b 的导数分别如下:
- ∂w = (x - ∂z)/m
- ∂b = ∂z/m
在这种情况下,m
是输入元素的总数。
我们现在能够使用上述方法重新调整参数,如下所示:
- w = w - θ ∂w
- b = b - θ ∂b
在这种情况下,θ是学习率,顾名思义,它控制每次迭代中参数被修改的比率。直观地说,越小,算法收敛所需的迭代次数就越多,然而,如果学习量太大,它将会超调,导致永远无法收敛(从上面的图像中,你可以想象它将不断从一边跳到另一边,永远不会到达底部)。
为了计算损失,我们将使用对数损失函数,也称为交叉熵损失函数。该功能定义如下:
对数损失(交叉熵损失)函数
直观的图表,直观显示 ML Mastery 的成本函数
函数本身是这样设置的,预测类和期望类之间的差异越大,误差就越大(你可以看到如果预测类在完全不同的标签上,它会受到多大的惩罚)。
损失函数将为我们提供一个在迭代中改进算法的思路。
最后,这里最重要的一点将是我们如何利用 GPU 的并行架构来优化计算背后的直觉。在这种情况下,我们可以同时处理多个输入参数,称为微批处理,然后批量重新调整参数。这被称为数据并行化,是许多可用技术之一。在下一节中,我们将看到这是如何实现的,即传递一小批输入,存储权重,然后在下一次迭代之前重新调整它们。
注意:在这篇文章中,我们不会深入研究太多细节,也不会研究机器学习的最佳实践,但是在文章的最后,我们将列出一系列广泛的来源,供有兴趣将其机器学习(或 GPU 计算)知识提升到一个新水平的人使用。
机器学习 GPU 代码实现
现在我们已经讨论了一些核心概念,我们将能够了解着色器的实现,它是将在 GPU 中执行的代码。
首先,我们需要如下定义所有的输入和输出缓冲器:
如果您还记得,在上一节的结尾,我们提到了如何利用微批处理的概念来使用 GPU 处理的并行架构。这在实践中意味着,我们将把 X 的多个实例一次传递给 GPU 来处理,而不是期望 GPU 一个接一个地处理它。这就是为什么我们看到上面有一个分别用于xi, xj, y, wOuti, wOutj,
和bOut
的数组。
更详细地说:
- 作为数组 xi 和 xj 的输入
X
将保存小批量的输入 - 数组
y
将保存微批量输入的所有预期标签 - 两个输入权重参数
wini
和woutj
将用于计算预测 - 将用于计算预测的输入参数
b
- 输出权重
wouti
和woutj
包含权重,并将存储应被减去的所有微批次的 W 的导数 - 类似地,输出偏差数组包含所有应批量减去的微量批次的
b
的导数 - 最后
lout
包含了损失将被返回的输出数组
我们还收到常数M
,它将是元素的总数——如果你记得这个参数将用于导数的计算。我们还将看到这些参数是如何从 C++ Kompute 端传递到着色器的。
现在我们已经定义了所有的输入和输出参数,我们可以启动main
函数,它将包含我们的机器学习训练算法的实现。
我们将首先跟踪全局调用的当前索引。由于 GPU 并行执行,这些运行中的每一个都将直接并行运行,因此这允许当前执行一致地跟踪当前正在执行的迭代索引。
我们现在可以开始准备所有的变量,我们将在整个算法中使用。我们所有的输入都是缓冲数组,所以我们希望将它们存储在 vec2 和 float 变量中。
在这种情况下,我们基本上明确了当前“线程运行”所使用的变量。GPU 架构由稍微更细微的执行结构组成,涉及线程块、内存访问限制等,但我们不会在本例中涉及这些。
现在我们进入更有趣的部分——实现推理功能。下面我们将实现推理函数来计算ŷ,它既涉及线性映射函数,也涉及 sigmoid 函数。
现在我们有了yHat
,我们现在可以用它来计算导数(∂z、∂w 和∂b),在本例中是当前执行的索引输入元素的导数。
我们现在可以将导数作为输出传递,因此可以为下一次迭代重新调整参数。
最后,我们能够计算损耗并将其添加到输出lout
数组中。
就这样,我们现在已经完成了着色器,这将使我们能够在 GPU 中训练逻辑回归算法——你可以在 GPU 逻辑回归示例库中找到着色器的完整代码。
现在,我们将介绍 Kompute 代码,该代码需要针对数据集运行,以训练我们的第一个模型并找到参数。
Kompute 的机器学习编排
为了使用 Kompute 在 GPU 中运行我们上面创建的着色器,我们将遵循以下步骤:
- 导入 Kompute 并创建我们的主要功能
- 创建所有需要的 Kompute 张量
- 创建 Kompute 管理器并初始化 Kompute 序列
- 通过 Kompute 序列执行 Kompute 张量 GPU 初始化
- 记录 Kompute 序列中的批处理算法执行
- 迭代 100 次:运行微批处理执行并更新权重
- 打印结果参数,用于进一步推断
如你所见,这比我们上面使用的简单例子更复杂。在这种情况下,我们将使用 Kompute 序列,而不是直接使用 Kompute 管理器,因为我们希望对命令进行更深入的控制,这些命令可以被记录下来并批量发送到 GPU。我们将在讲述每个步骤时更详细地讨论这一点。让我们开始吧。
1.导入 Kompute 并创建我们的主要功能
我们将导入 Kompute 的单个头文件——如果需要,也可以使用更细粒度的基于类的头文件。我们还将创建一些基本配置变量;即ITERATIONS
和learningRate
,它们将在后面的码块中使用。
2.创建所有需要的 Kompute 张量
现在我们将创建所有需要的张量。在这一小节中,你会注意到我们将引用着色器中使用的所有缓冲区/数组。我们还将介绍参数传递的顺序如何与数据绑定到着色器的方式相关联,以便可以访问数据。
我们还将它们存储在一个参数向量中,以便于访问:
3.创建 Kompute 管理器并初始化 Kompute 序列
如果您还记得前面的例子,我们能够使用 Kompute 管理器直接执行命令。然而,如果我们想要更精细地记录可以在处理之前提交并加载到 GPU 中的命令批次,我们可以使用 Kompute 序列资源。为此,我们将创建一个 Kompute 管理器,然后通过它创建一个 Kompute 序列。
4.通过 Kompute 序列执行 Kompute 张量 GPU 初始化
我们现在可以从在 GPU 资源上运行指令开始——也就是说,我们将从初始化张量并将其映射到各自的 GPU 内存开始。在这里,您将看到 Kompute 序列如何在命令执行上为您提供进一步的粒度,但是直到 ML 推理部分,您才会看到 Kompute 序列的灵活性。
让我们从记录命令开始,即 OpTensorCreate 命令,然后评估上面所有张量的操作。此操作将创建各自的 Vulkan 内存/缓冲区资源。
5.记录 Kompute 序列中的批处理算法执行
在本节中,我们将清除 Kompute 序列的先前记录,并开始记录一组序列。您会注意到,与前一节不同,在这种情况下,我们不会立即运行eval()
,因为我们必须多次运行它,并使用额外的命令来重新调整参数。
您还会注意到,我们将记录三种类型的 Kompute 操作,即:
[kp::OpTensorSyncDevice](https://axsaucedo.github.io/vulkan-kompute/overview/reference.html#optensorsyncdevice)
—此操作通过将张量的本地数据映射到 GPU 数据,确保张量与其 GPU 内存同步。在这种情况下,这些张量使用设备专用内存来提高处理效率,因此在操作中使用分级张量来执行映射(为了提高效率,在整个操作中重复使用分级张量)。在这里,我们只想同步输入权重,因为这些权重将随各自的导数在本地更新。[kp::OpAlgoBase](https://axsaucedo.github.io/vulkan-kompute/overview/reference.html#opalgobase)
—这是一个 Kompute 操作,将我们上面写的着色器与所有本地 CPU/主机资源绑定在一起。这包括提供张量。值得一提的是,作为参数提供的张量的索引是它们通过各自的绑定在着色器中映射的顺序(正如您可以在着色器中看到的,每个向量都具有格式layout(binding = NUMBER)
)。[kp::OpTensorSyncLocal](https://axsaucedo.github.io/vulkan-kompute/overview/reference.html#optensorsynclocal)
—该 Kompute 操作执行与上述同步操作类似的一组指令,但它不是将数据复制到 GPU 存储器,而是相反。这个 Kompute 操作将 GPU 内存中的数据映射到本地张量向量,因此可以从 GPU/主机访问它。如你所见,我们只在输出张量中运行这个操作。
6.迭代 100 次:运行微批处理执行并更新权重
现在我们已经记录了命令,我们可以开始运行这些预加载命令的执行。在这种情况下,我们将运行一个微批处理迭代的执行,然后在本地更新参数,以便在接下来的迭代中使用它们。
7.打印结果参数,用于进一步推断
我们现在有了一个经过训练的逻辑回归模型,或者至少我们已经能够优化其各自的功能,以确定合适的参数。我们现在能够打印这些参数,并在看不见的数据集中使用这些参数进行推理。
我们完事了。
您可以在示例存储库中找到这个完整的示例,您将能够运行和扩展它。你会在 GPU 逻辑回归示例 repo 中找到所有完整的文件,包括 Kompute C++代码,以及着色器文件。
接下来呢?
恭喜你,你一路走到了最后!虽然这篇文章涵盖了广泛的主题,但是也有大量的概念被浏览过。其中包括底层 Vulkan 概念、GPU 计算基础、机器学习最佳实践和更高级的 Kompute 概念。幸运的是,网上有大量的资源可以扩展你在这些方面的知识。我推荐作为进一步阅读的一些链接包括:
- Kompute 文档了解更多细节和示例
- 机器学习工程师时事通讯如果你想了解关于机器学习的最新文章
- 令人敬畏的生产机器学习开源工具列表,用于部署、监控、版本化和扩展您的机器学习
- FastAI 的 ML for Coders 课程简介进一步学习机器学习概念
- Vulkan SDK 教程深入了解底层 Vulkan 组件
使用 Libra 的线性机器学习和深度学习
自动化机器学习和深度学习理解 Libra 的完全指南。
随着机器学习的兴起,我们看到了许多伟大的框架和库的兴起,如 sci-kit learn、Tensorflow、Pytorch。这些框架使得用户可以更容易地创建机器学习模型。但是仍然需要遵循整个过程,包括数据准备、建模和评估。数据准备包括数据清洗和预处理。建模接受预处理的数据,并使用算法来预测结果。评估为我们提供了一个衡量算法性能的方法。由于这些库和框架,我们写所有东西的时间减少了,但是我们仍然需要写少量的代码。
"机器智能是人类需要创造的最后一项发明."尼克·博斯特伦
在令人惊叹的开源社区的帮助下,这个领域的进步与日俱增,这些社区催生了现有的框架。想象一个在一行中完成上述所有过程的框架。是的,你没看错,现在你也可以这么做了。Libra 是一个框架,它在一行中为你做了这些工作。即使对于非技术人员来说,它也很容易使用。Libra 需要最少的平均行数来训练模型。
图片取自文档
在这篇博客中,我将给出如何使用天秤座的完整指导。我将针对不同的问题采用不同的数据集,并向您展示一步一步的方法。
使用 Libra 检测信用卡欺诈
我已经使用 Kaggle 数据集来预测信用卡欺诈。该数据已经经过主成分分析,因此与原始数据相比,它现在减少到更少的维度数据。解决这个问题需要遵循一个系统的方法。一般来说,你会按照第一段提到的顺序。但是和天秤座在一起,就不用担心这个了。
数据集的链接https:/[/www.kaggle.com/mlg-ulb/creditcardfraud](https://colab.research.google.com/drive/1khr-nqQVkP_XMUQ5y8GWrK5AUS41lyzC#)
该数据中的大多数交易在 99.83%的时间内是非欺诈性的,而欺诈性交易在数据集中的 0.17%的时间内发生。这意味着数据是高度不平衡的。让我们看看 Libra 对数据的预处理有多好,并给出结果。
安装 Libra
pip install -U libra
从 libra 导入客户端
from libra import client
利用天秤座
一切都是围绕客户机对象构建的。您可以对它调用不同的查询,所有内容都将存储在对象的 models 字段下。
我们在客户机对象中传递文件的位置,并将其命名为 newClient。现在要访问各种查询,请参考文档。我在这里使用决策树。英语中的指令是一个陈述,代表你想要完成的任务。比如预测房子价值中位数,或者请估计一下家庭人数。否则,该指令应该对应于数据集中的一列。Libra 自动检测目标列,但是为了确保它选择了正确的列,我传递了目标列名。
newClient = client('creditcard.csv')newClient.decision_tree_query('Class')
仅用两行代码,我们就获得了大约 0.99 的分数,这是我们能得到的最好分数。如果您查看其他内核,您会发现只有少数人获得了 0.99 的精度,并且他们需要花费数小时来预处理数据并为其编写代码。那样的话,天秤座为你节省了很多时间,给了你最好的结果。Libra 使用智能预处理,这样你就不需要自己预处理数据了。
你不需要担心分析结果。
newClient.analyze()为所有分类问题创建混淆矩阵和 ROC 曲线。它还计算召回率、精确度、f1 和 f2 分数。
newClient.analyze()
newClient.info()返回所有键,代表为数据集生成的每一类数据。
newClient.info()
newClient.model()返回该模型的字典。它包括从准确度、精确度、召回率、F1 分数到所有预处理技术的一切。对于已经了解这些概念并能编码的人更有帮助。非技术用户无需担心这一点。
newClient.model()
访问模型
返回一个字典,如果你想访问模型,你可以直接使用 newClient.model()[‘model’]
newClient.model()['model']
使用 Libra 的卷积神经网络
使用下面的代码在 colab 笔记本上下载 Laurence Moroney 的石头、纸、剪刀数据集。我可以直接向您展示使用 Libra 创建 CNN 的代码,但是我想创建一个示例,您可以在自己的 colab 笔记本中尝试,以便更好地理解。你不需要担心下面的代码。
!wget --no-check-certificate \https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps.zip \-O /tmp/rps.zip!wget --no-check-certificate \https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps-test-set.zip \-O /tmp/rps-test-set.zip
使用下面的代码提取下载的文件。
import osimport zipfilelocal_zip = '/tmp/rps.zip'zip_ref = zipfile.ZipFile(local_zip, 'r')zip_ref.extractall('/tmp/')zip_ref.close()local_zip = '/tmp/rps-test-set.zip'zip_ref = zipfile.ZipFile(local_zip, 'r')zip_ref.extractall('/tmp/')zip_ref.close()
使用下面的代码创建文件夹,并将提取的图像放入其中。
rock_dir = os.path.join('/tmp/rps/rock')paper_dir = os.path.join('/tmp/rps/paper')scissors_dir = os.path.join('/tmp/rps/scissors')print('total training rock images:', len(os.listdir(rock_dir)))print('total training paper images:', len(os.listdir(paper_dir)))print('total training scissors images:', len(os.listdir(scissors_dir)))rock_files = os.listdir(rock_dir)print(rock_files[:10])paper_files = os.listdir(paper_dir)print(paper_files[:10])scissors_files = os.listdir(scissors_dir)print(scissors_files[:10])
下图显示了数据集的相关信息。
使用下面的代码,你可以创建 CNN。数据将通过缩放、剪切、翻转和重缩放自动增加。然后将选择最佳的图像尺寸。您还会注意到每个类中图像的数量以及与之相关的类的数量。最后,你还会观察训练精度和测试精度。
还可以在 convolutional _ query 内部传递read _ modehyper-parameter,在其中可以指定读取模式。允许三种读取模式。我将一一描述它们。默认情况下**read _ mode = distinguisher()**自动检测数据的类型。允许的三种读取模式是:
1.Setwise
目录由“训练集”和“测试集”文件夹组成,这两个文件夹都包含分类文件夹,文件夹内有图像。[1]
图片取自文档
2.按类别
目录由分类文件夹组成,里面有图像。[1]
图片取自文档
3。CSV Wise
目录由图像文件夹和包含图像列的 CSV 文件组成。[1]
图片取自文档
newClient = client('/tmp/rps')newClient.convolutional_query("Please classify my images")
基于 Libra 的自然语言文本分类
对于这个问题,我使用了垃圾短信分类数据集。
链接:https://www . ka ggle . com/team-ai/spam-text-message-class ification
new_client = client('SPAM text message 20170820 - Data.csv')new_client.text_classification_query('sentiment')new_client.classify_text('new text to classify')
new_client.classify_text()将对输入其中的文本进行分类。在上面的输出中,你可以看到它已经把我的文本归类为‘火腿’。
k 表示使用 Libra 进行聚类
这个问题我用的是商城客户细分数据:https://www . ka ggle . com/vjchoudhary 7/Customer-Segmentation-tutorial-in-python
数据集的图像。
下面的代码将创建一个 K 均值聚类模型,并确定最佳质心计数和优化精度,以及最佳的聚类数。
使用 Libra 进行分类的神经网络
在本节中,我将使用神经网络查询进行分类。为此,我使用一个私人数据集,从大脑信号预测行为。让我们来看看它在数据集上的表现如何。
new_client = client('Mood_classification.csv')new_client.neural_network_query('Predict the behavior')
从上面的代码中,您可以注意到模型使用的初始层数是 3。然后,它还使用根据前一层的性能而变化的不同层数来测试精度。它预测找到的最佳层数及其训练和测试精度。看起来我需要为我的数据集收集更多的数据。
您可以使用 new_client.model()[‘model’]来访问模型,并可以使用 Keras 中的 summary()函数来获得神经网络模型的摘要。
new_client.model()['model'].summary()
结论
天秤座是一个非常有趣的框架,每天都在进步。该框架让我们大致了解了数据科学领域的发展速度,也让我们看到了该领域可能出现的变化类型。他们还为现有的数据科学家添加功能,以修改现有的神经网络,并在指定的索引处添加像 LSTM 这样的层。这个框架带来的概念让我兴奋不已。你也可以在 Github 上投稿。
参考资料:
[1] Libra,文献(2020),资料来源
机器学习与柏拉图的洞穴寓言
当前机器学习的方法如何符合柏拉图著名的寓言以及我们将从那里走向何方。
洞穴的寓言由希腊哲学家柏拉图在他的作品共和国中提出,最初是T5,用来比较“教育和缺乏教育对我们本性的影响”。奇怪的是,事实证明,最先进的机器学习领域仍然或多或少地符合这个超过 2000 年的模具。
洞穴的寓言
这个寓言是从苏格拉底和他的弟子格劳肯之间的对话中得到阐释的。
简而言之,苏格拉底告诉格劳肯想象人们生活在一个巨大的地下洞穴中,只通过一条艰难而陡峭的隧道与外界相通。人们被铁链锁着,面对着一堵高墙,无法转过脸去,也无法挣脱锁链。在囚犯的背后,有一个巨大的火在燃烧,从而将人们身后发生的事情投射到囚犯面对的墙上,形成各种形状的影子。
由于人们在一生中从未能够转过脸来一点,他们看着墙上的影子长大和死去,这些影子构成了他们所有已知的现实。
MatiasEnElMundo / Getty Images
从象征意义上来说,墙上的阴影代表了表面的真相——一个“虚拟”的现实,只通过我们的感官感知,而不是终极的“真实”现实,根据柏拉图主义,它是由我们凡人永远无法通过感官了解的形式(想法)组成的。
此外,墙上的二维投影构成了可怜的囚犯的整个世界。他们好奇的头脑会尝试为这些幻影开发故事或历史——它们倾向于如何相互作用,何时一些影子倾向于一起出现,是否一个特殊的影子导致另一个出现,等等。他们推测并想象出最复杂的理论来解释影子的行为;然而可悲的是,他们仍然不知道阴影的真正本质。
如果他们可以转身,他们会发现他们最喜欢的一些影子理论是基于他们身后的一些骗子的一些糟糕的笑话,他们可能会在任何时候停止游戏,从囚犯队中消灭一些最好的模特。即使我们假设一个仁慈的世界,没有人在那里捉弄可怜的囚犯,任何时候一个三维图形出现的角度的微小随机调整都会在墙上的投影上造成很大的差异,肯定会在囚犯理论家中引起相当大的混乱。
机器学习做什么
尽管围绕机器学习或人工智能有各种宣传和承诺,但本质上,机器学习算法会查看一系列关于现象及其附加标签/值的观察结果(取决于它是分类任务还是回归任务),尝试提出一个由形状似乎与数据形状匹配的已知函数组成的函数,然后在新观察结果出现时继续指定标签或值。
马库斯·斯皮斯克在 Unsplash 上的照片
经验法则是:( 1)任何机器学习输出的质量在很大程度上取决于输入的质量。简单来说,垃圾进,垃圾出;(2)机器学习算法永远无法“学习”或发现任何我们未知的新规则。
换句话说,我们最终可以通过机器学习模型实现的目标一方面受到数据质量的限制,另一方面也受到精心制作这些模型的研究人员的已知“现实”的限制。
相似之处
暂时回到洞穴的寓言。显然,正如现实生活中的三维图形被投影为墙上的二维阴影一样,在日常的机器学习实践中,对现实生活中的对象(变量)的描述,当作为数字或分类数据记录下来时,从来都不是原始对象的完整画面。
原因可能是由于各种逻辑约束,我们缺乏对某些属性的测量,但更有可能的是,作为一个从出生起就受到各种启动和集体学习经验约束的人,我们只是缺乏甚至是一个对象的某些关键属性的存在的知识。显然,如果我们甚至没有意识到一个东西的存在,我们怎么能首先要求它,然后对它提出问题,最后测量它呢?
投影从来都不是对原始对象的良好描述
在这种情况下,目前为所有机器学习问题引入替代数据的努力非常有意义,值得称赞,因为我们已经意识到传统的特征集不再满足我们的需求,而且既然我们正在处理“影子”的数据,为什么不借用其他“影子”的片段来帮助我们解决现实问题呢?难怪工厂的卫星图像或社交网络情绪数据越来越多地被纳入自动交易模型;事实是,它们一直是预测股票表现的良好因素,而受困于资产负债表的老学生们只是错过了机会。
不难想象,每天都有数百万个机器学习模型在“影子”数据的基础上接受训练,同时承担着计算出产生数据的现实生活对象之间的关系(相关性,甚至因果关系,如果一些过度成就的项目经理要求的话)的任务。在不进入散发主义的新柏拉图主义主题的情况下,我们也许能够通过转向另一个例子来描述这一困境,散发主义基本上认为一切都源于完美的第一现实,当进一步从第一现实中派生和异化时,变得不那么纯粹和不那么完美。
在 Lewis Carroll 的小说透过镜子中,当白骑士向爱丽丝解释歌曲阿道克斯的眼睛时,作者讨论了“这首歌,这首歌叫什么,这首歌的名字,以及这首歌的名字叫什么”之间的区别。歌曲本身,作为一种柏拉图式的形式,产生了派生的形式,如歌曲的名字,甚至是歌曲的名字(这可以无限地继续下去);然而,这些衍生词甚至可能与歌曲的主题没有密切关系。尽管如此,在大多数情况下,(低级)派生是真实对象所知道和分析的,而对象本身仍然是不可言喻的或未知的。
奥卡姆剃刀
因此,当我们对一个物体进行观察的时候,一个推导就产生了,我们在墙上创造了一个影子。如果我们意识到,在一天结束时,我们正在处理“影子”数据集,我们可能会更好地设定我们对磨床学习模型的期望。通过释放我们的好奇心和想象力,并假设一个现实的参数化模型,我们也许能够意外地、短暂地打破我们头脑中的锁链,但显然奥卡姆剃刀支配着这个洞穴,顿悟的洞察力终究并不常见。
机器学习和信号处理
机器学习性能与两种关键信号处理算法(快速傅立叶变换和最小均方预测)的有趣比较。
从信号处理的角度看机器学习和神经网络。
信号处理为我们提供了一套工具,在过去的五十年里,这些工具得到了完善并得到了很好的应用。举几个例子,有自相关、卷积、傅立叶和小波变换、通过最小均方(LMS)或递归最小二乘(RLS)的自适应滤波、线性估计器、压缩传感和梯度下降。不同的工具用于解决不同的问题,有时,我们结合使用这些工具来构建一个系统来处理信号。
机器学习或深度神经网络更容易适应,因为无论我们使用什么网络架构,底层数学都相当简单。神经网络的复杂性和神秘性在于它们处理的数据量,以获得我们目前拥有的迷人结果。
时间序列预测
本文旨在比较几种关键信号处理算法的神经网络性能。让我们看看时间序列预测作为第一个例子。我们将实现一个三层顺序深度神经网络来预测信号的下一个样本。我们也将以传统方式实现,使用抽头延迟滤波器,并根据均方误差调整权重,这就是 LMS 滤波,这是一种针对最优韦纳滤波器的迭代方法,用于从噪声测量中估计信号。然后我们将比较两种方法的预测误差。因此,让我们开始编写代码吧!
让我们首先导入我们需要的所有常用 python 库。由于我们将使用 TensorFlow 和 Keras 框架,我们也将导入它们。
用神经网络预测
让我们现在开始建立我们的 3 层神经网络。输入层获取 64 个样本并产生 32 个样本。隐藏层将第一层的这 32 个输出映射到 8 个样本。最后一层将这 8 个样本映射到 1 个预测输出。记住输入尺寸是由第一层的 input_shape 参数提供的。
我们将使用 Adam 优化器,而不考虑它是什么。这就是 TensorFlow 的好处,我们不需要知道神经网络使用这个惊人的框架构建一个网络所需的所有处理的每个细节。如果我们发现 Adam 优化器不能很好地工作,我们将简单地尝试另一个优化器 —例如 RMSprop。
现在让我们创建一个时间序列,一个简单的正弦波叠加。然后我们将添加噪声来模拟真实世界的信号。
现在我们有了数据,让我们考虑如何将这些数据输入神经网络进行训练。我们知道网络在输入端采集 64 个样本,产生一个输出样本。因为我们希望训练网络来预测下一个样本,所以我们希望使用第 65 个样本作为输出标签。
因此,第一个输入集是从样本 0 到样本 63(前 64 个样本),第一个标签是样本 64(第 65 个样本)。第二个输入集可以是一个单独的 64 个样本集(非重叠窗口),或者我们可以选择一个滑动窗口,从样本 1 到样本 64 取 64 个样本。让我们遵循滑动窗口方法,只是为了从我们拥有的时间序列中生成大量的训练数据。
还要注意,我们使用有噪声的样本作为输入,而使用无噪声的数据作为标签。我们希望神经网络即使在有噪声的情况下也能预测实际信号。
让我们看看时间序列数据和训练数据的大小。请注意,我们为时间序列数据生成了 5000 个样本,但我们为神经网络创建了 3935 x 64 = 251840 个输入数据样本。
train_data 的形状是输入集的数量 x 输入长度。这里,我们有 3935 批输入,每个输入有 64 个样本长。
print(y.shape, train_data.shape, train_labels.shape)(5000,) (3935, 64) (3935,)
我们现在准备训练神经网络。让我们首先实例化这个模型。模型摘要提供了关于有多少层、输出形状是什么以及我们需要为此神经网络训练的参数数量的信息。
对于第一层,我们有 64 个输入和 32 个输出。密集层实现等式 y = f(Wx + b) ,其中 f 是激活函数, W 是权重矩阵, b 是偏差。我们马上可以看到 W 是一个 64×32 的矩阵, b 是一个 32×1 的向量。这给了我们 32 x 64 + 32 = 2080 个参数来训练第一层。读者可以做类似的计算来验证第二层和第三层的参数,作为理解的练习。毕竟,除非你是机器学习的初学者并且渴望开始,否则你不会阅读这篇文章:)
model = dnn_keras_tspred_model()Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense (Dense) (None, 32) 2080
_________________________________________________________________
dense_1 (Dense) (None, 8) 264
_________________________________________________________________
dense_2 (Dense) (None, 1) 9
=================================================================
Total params: 2,353
Trainable params: 2,353
Non-trainable params: 0
_________________________________________________________________
好吧,继续训练吧。由于我们使用的是 Keras 框架,训练就像调用 fit()方法一样简单。对于 TensorFlow,我们需要做更多的工作,但那是另一篇文章。
让我们使用 100 个历元,这只是意味着我们将一次又一次地使用相同的训练数据来训练神经网络,并将这样做 100 次。在每个时期,网络使用输入和标签集的批次数量来训练参数。
让我们使用日期时间来描述这个训练需要多长时间,以及作为 Python 字典返回的历史值,以获得每个时期之后的验证损失。
DNN training done. Time elapsed: 10.177171 s
现在网络已经训练好了,我们看到验证损失随着时间的推移已经下降到趋于平缓的程度(表明进一步的训练不会产生任何显著的改进),让我们使用这个网络来看看它相对于测试数据的表现如何。
让我们以与创建训练数据集完全相同的方式创建测试数据集,但是只使用我们以前没有用于训练的那部分时间序列。我们想用以前从未见过的数据给神经网络一个惊喜,以了解它的表现有多好。
我们现在将调用 Keras 框架中的 predict() 方法来获得测试数据集的神经网络输出。如果我们使用 TensorFlow 框架,这一步会有所不同,但我们将在另一篇文章中讨论这一点。
正如我们所看到的,神经网络的预测非常接近实际的无噪声数据!
用 LMS 算法预测
我们将使用 L=64 抽头滤波器来预测下一个样本。我们不需要那么大的滤波器,但是让我们保持每个输出样本的输入数量与我们用于神经网络的数量相同。
通过计算预测样本和测量样本之间的误差,并基于均方误差和输入测量值之间的相关性调整权重,获得滤波器系数(或权重)。
如代码所示, yrlms[k] 是输入为 ypn[k-L:k] 时的滤波器输出,误差计算为噪声测量值 ypn[k] 与滤波器输出 yrlms[k] 之差。测量和误差之间的相关性由 ypn[k-L:k] 和 e 的乘积给出, mu 为 LMS 步长(或学习率)。
正如我们所看到的,尽管复杂性低得多,但 LMS 预测同样不错。
(64,) (1064,)
比较 LMS 和神经网络的预测结果
在我们结束本节之前,让我们比较一下 LMS 预测和神经网络预测之间的误差。公平地说,我忽略了 LMS 的初始部分,以便在测量均方误差和 SNR 时有时间收敛。尽管如此,我们看到神经网络性能比 LMS 性能好 5 dB!
Neural network SNR: **19.986311477279084**
LMS Prediction SNR: **14.93359076022336**
快速傅立叶变换
好吧,在信号预测方面,神经网络比 LMS 快 5 dB,但是让我们看看神经网络是否可以被训练来进行傅立叶变换。我们将它与 SciPy FFTPack 中的 FFT(快速傅立叶变换)进行比较。FFT 算法是信号处理的核心,可以训练神经网络来模仿它吗?让我们来找出…
我们将使用之前创建的相同信号,即正弦波叠加,来评估 FFT。让我们先看看 FFT 输出。
现在让我们创建一个神经网络模型来模拟 FFT。与我们之前创建的有 64 个输入但只有一个输出的模型相比,这个模型需要为每 64 个样本输入集生成 64 个输出。
由于 FFT 输入和输出都很复杂,我们需要输入端两倍的样本数,先用实数后用虚数排列。由于输出也是复数,我们再次 2 x NFFT 样本。
为了训练这个神经网络模型,让我们使用通过 numpy.random.normal 生成的随机数据,并基于我们正在比较的 SciPy FFTPack 中的 FFT 例程设置标签。
代码的其余部分与前面的神经网络训练非常相似。在这里,我一次运行 10,000 批,如果网络需要更多的训练,我有一个外部 for 循环来做多组 10,000 批。请注意,这需要在 for 循环之外创建模型,以便权重不会被重新初始化。
从模型摘要中可以看出,仅 64 点 FFT 就有近 50,000 个参数。我们可以减少一点,因为我们只评估实输入,而虚部保持为零,但这里的目标是快速比较神经网络是否可以被训练来进行傅立叶变换。
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_3 (Dense) (None, 128) 16512
_________________________________________________________________
dense_4 (Dense) (None, 128) 16512
_________________________________________________________________
dense_5 (Dense) (None, 128) 16512
=================================================================
Total params: 49,536
Trainable params: 49,536
Non-trainable params: 0
_________________________________________________________________
DNN training done. Time elapsed: 30.64511 s
训练结束了。现在让我们使用为 LMS 创建的相同输入样本来测试网络。我们将神经网络输出与 FFT 输出进行比较,它们是相同的!多神奇啊!
在结束本文之前,让我们做最后一次评估。对于一些随机输入数据,我们将比较神经网络输出和 FFT 输出,看看均方误差和 SNR 是什么样的。
运行下面的代码,我们得到一个体面的 23.64 dB 信噪比。虽然我们偶尔会看到一些误差较高的样本,但在大多数情况下,误差非常小。鉴于我们只训练了 10,000 批神经网络,这是一个相当不错的结果!
Neural Network SNR compared to SciPy FFT: **23.64254974707859**
总结
在新冠肺炎期间被困在里面,将机器学习性能与一些关键的信号处理算法进行比较是一个有趣的周末项目。我们看到,机器学习可以做信号处理可以做的事情,但天生具有更高的复杂性,其好处是可以推广到不同的问题。就复杂性而言,信号处理算法对工作来说是最佳的,但它们是针对它们所解决的特定问题的。我们不能用 FFT 代替 LMS,反之亦然,但我们可以使用相同的神经网络处理器,只需加载不同的权重集来解决不同的问题。这就是神经网络的多功能性。
有了这个提示,我将结束这篇文章。我希望你读这篇文章的时候和我整理这篇文章的时候一样开心。如果你觉得有帮助并且学到了一些东西,也请留下你的反馈!
https://www.linkedin.com/in/prasannasethuraman/
机器学习和供应链管理:动手系列#1
内部 AI
拥抱未来
由 Shaah Shahidh 在 Unsplash 上拍摄
机器学习、深度学习和人工智能正在从医学到音乐的所有领域实现转型变革。它正在帮助企业从采购到支付、计划生产、订购到兑现和记录到报告,发现优化机会并支持决策制定,这在以前使用传统商业分析和信息技术是不可能的。
机器学习和人工智能是一个复杂的领域,对我们这一代人来说有点令人畏惧,他们可能在本科教育之前没有接触过计算机。在这篇介绍性文章中,我将举例说明机器学习在采购和质量管理业务流程优化中的简化实现。在本文中,我将避免复杂和微妙的细节,在这一点上保持示例的简单性。我们将在本文的下一个系列中讨论复杂的场景。在本系列中,我将使用编程语言 Python 来实现机器学习算法,以解决供应链业务挑战,并且我假设您对 Python 语言有一些基本的了解。
商业案例
一个供应商供应不同的材料,其单价和采购订单总值相差很大。有时供应商的一些零件未能通过质量检查,但缺陷百分比似乎没有遵循一种趋势。在本系列的第一篇博客中,为了简单起见,我假设了独立特性和从属特性之间的线性关系。
目标
企业希望预测供应商交付的次品百分比。如果预测的次品百分比低于阈值水平,则不会执行质量检查。让我们考虑一下,如果交货中的次品率超过 0.4%,那么就需要明确的进货检验,以确保最终产品的质量。
这将有助于专注于特定采购订单交付的质量检查,以控制最终产品质量,并优化检验成本。它还能够发现有时影响少量材料有缺陷交付的变量/参数,并与供应商合作解决这个问题。
数据点和信息
ERP 中的采购订单信息和相应的进货检验结果为三年期间的所有订单提供了数据点。
对从 ERP 导出的历史数据进行采样,以训练机器学习算法
用于训练算法的样本数据
预计质量缺陷百分比的采购订单(PO)数据
用于预测值的测试数据
整装待发
为了简单起见,我假设过去的数据点是从 ERP 中导出的,并以 excel 格式保存在本地机器中。
我将解释每一行代码,然后将完整的代码放在文章的末尾以供参考。如前所述,为了让我们理解核心概念,我在这里简化了一些东西,在以后的系列文章中,我将在其上构建更真实的复杂示例。
第一步*——首先,我们将导入我们将在机器学习程序中使用的所有 python 模块。我不会在本文中详细介绍这些库和模块,您可以在网上找到关于这些模块的更多细节。*
*import pandas as pd
from sklearn.tree import DecisionTreeRegressor # Import Decision Tree Algorithm
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVR #import for support vector regressor*
Pandas 是一个用 Python 编写的软件库,用于数据操作和分析。使用 Pandas 可以非常轻松地读写 excel、CSV 和其他文件格式的数据,并处理时间序列数据。 Scikit-learn 是一个免费的 python 机器学习库。我们将使用决策树学习和支持向量机来预测未来供应商交付中的缺陷百分比。为此,我们将专门从 Scikit Learn 中导入这两个模块。
步骤 2 -我们将读取 excel 文件中过去的数据点,并将其保存到 pandas dataframe SourceData。类似地,我们将读取我们希望算法预测交付缺陷百分比的交付数据点。
*SourceData=pd.read_excel("Supplier Past Performance.xlsx") # Load the training data into Pandas DataFrameTestdata=pd.read_excel("Defect Predict.xlsx") # Load the test data*
注意 —我已经将 python 程序、过去数据点 excel 表、未来数据集保存在同一个文件夹中。因此,在代码中,只指定了文件名。如果文件位于不同的文件夹位置,则需要提供完整路径。
第三步 -现在过去的所有四个数据点,即采购订单金额、采购订单数量、交货前发送的采购订单和缺陷百分比将从 excel 读入 Pandas 数据框架。
我们将使用采购订单金额、采购订单数量、交货前发送的 PO(天数)来预测未来交货中的缺陷百分比。自变量是用于进行预测的参数,因变量是被预测的变量。由于我们将使用从 ERP 收集的过去的数据点来训练机器学习算法,因此我们将把它称为 SourceData_train_independent 和 SourceData_train_dependent 变量。
在下面的代码中,我们声明了除“缺陷百分比”之外的所有列数据为自变量,只有“缺陷百分比”为因变量。
*SourceData_train_independent= SourceData.drop(["Defect Percent"], axis=1) # Drop depedent variable from training datasetSourceData_train_dependent=SourceData["Defect Percent"].copy()
# New dataframe with only independent variable value for training dataset*
步骤 4 -采购订单价值从一千到一百万英镑不等,而订单数量从一百到一千个托盘不等。采购订单在交货日期前 15 到 45 天发出。由于独立变量的范围非常不同,因此我们需要对其进行调整,以避免一个变量(在本例中为采购订单价值)对其他因素的意外影响。
我们只需要缩放独立变量。
在下面的代码中,独立的训练和测试变量被缩放,并分别保存到 X-train 和 X_test。在 y_train 中,保存的从属训练变量不进行缩放。
*sc_X = StandardScaler()
X_train=sc_X.fit_transform(SourceData_train_independent.values)
# scale the independent training dataset variablesX_test=sc_X.transform(Testdata.values) # scale the independent test datasety_train=SourceData_train_dependent # scaling is not required for dependent variable*
步骤 5 -现在我们将分别输入独立和非独立的训练数据,即 X_train 和 y_train,来训练支持向量机模型。为了避免混淆,我不会在第一个系列中讨论复杂的细节,比如算法(超参数)的设置。
在下面的代码中,我们首先用一个拟合方法来拟合 X_train 和 y_train。在模型被训练后,我们通过测试独立变量值,即新订单的“PO 数量”、“PO 数量”和“交货前发送的 PO”以及 X_test 变量,并将预测的缺陷百分比存储在变量“预测”中。
*svm_reg = SVR(kernel="linear", C=1)
svm_reg.fit(X_train, y_train) # fit and train the modelpredictions = svm_reg.predict(X_test)
print("Defect percent prediction by Support Vector model for the order value of 95827 GBP with 851 pallets sent 55 days before delivery data is " ,round(predictions[0],2) , "%")*
最后,使用 print 语句打印预测的缺陷百分比。
步骤 6 —同样,我们将把训练数据集(自变量和因变量的值)送入决策树模型。
*tree_reg = DecisionTreeRegressor()
tree_reg.fit(X_train, y_train) # fit and train the modeldecision_predictions = tree_reg.predict(X_test) # Predict the value of dependent variableprint("Defect percent prediction by Decision Tree model for the order value of 95827 GBP with 851 pallets sent 55 days before delivery data is " ,round(decision_predictions[0],2) , "%")*
使用 print 语句打印预测的缺陷百分比。
我们已经了解了如何使用决策树学习和支持向量模型算法来预测未来交付中的缺陷百分比数量,并基于此为特定供应商的交付计划质量检查。请注意,为了建立最初的理解,我已经简化了一些实际用例之外的元素。
在此示例中,每次运行代码来预测新订单的结果时,我们都会对模型进行定型。对于大型数据集和复杂的示例,这可能不可行。在本文的下一个系列中,我将讨论保存训练好的模型,然后直接加载它来预测测试数据的结果。
完整代码
*""" Step 1 - Import the required modules"""
import pandas as pd
from sklearn.tree import DecisionTreeRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVR
""" Step 2 - Read the data source"""
SourceData=pd.read_excel("Supplier Past Performance.xlsx") # Load the training data into Pandas DataFrame
Testdata=pd.read_excel("Defect Predict.xlsx") # Load the test data
""" Step 3 - Declare the independent and dependent train data from the sample"""
SourceData_train_independent= SourceData.drop(["Defect Percent"], axis=1) # Drop depedent variable from training dataset
SourceData_train_dependent=SourceData["Defect Percent"].copy() # New dataframe with only independent variable value for training dataset
""" Step 4 - Scale the independent test and train data"""
sc_X = StandardScaler()
X_train=sc_X.fit_transform(SourceData_train_independent.values) # scale the independent variables
y_train=SourceData_train_dependent # scaling is not required for dependent variable
X_test=sc_X.transform(Testdata.values)
""" Step 5 - Fit the test data in maching learning model - Support Vector Regressor"""
svm_reg = SVR(kernel="linear", C=1)
svm_reg.fit(X_train, y_train) # fit and train the modelpredictions = svm_reg.predict(X_test)
print("Defect percent prediction by Support Vector model for the order value of 95827 GBP with 851 pallets sent 55 days before delivery data is " ,round(predictions[0],2) , "%")
""" Step 6 - Fit the test data in maching learning model - Decision Tree Model"""
tree_reg = DecisionTreeRegressor()
tree_reg.fit(X_train, y_train) # fit and train the modeldecision_predictions = tree_reg.predict(X_test) # Predict the value of dependent variableprint("Defect percent prediction by Decision Tree model for the order value of 95827 GBP with 851 pallets sent 55 days before delivery data is " ,round(decision_predictions[0],2) , "%")*
机器学习和供应链管理:动手系列#2
内部 AI
不准确的预测比不预测更糟糕。学习保存机器学习训练的模型以备将来使用,并测量模型的准确性。
照片由Shaah Shahidh&Alexandre debiève在 Unsplash
在本系列的第部分中,我已经讨论了机器学习算法的一个基本简化实现,它可以根据输入参数预测未来采购订单的缺陷百分比。
在这一部分中,我将谈到训练模型的准确性度量。我们有许多参数(称为估计量的超参数),这些参数在模型中作为变量传递以执行预测。在实践中,基于训练模型的准确性度量结果,在模型被实施用于生产中的预测之前,超参数被调整。算法可以搜索并推荐优化的超参数,而不是通过试错法手动调整超参数来获得优化的准确度分数。我将在本系列的后面部分讨论有效的参数搜索策略。
正如在本系列的前一部分中提到的,在预测之前每次都从头开始训练模型是不实际的。我还将讨论如何保存一个训练好的模型,并将其直接导入另一个程序进行预测。
注:我将详细解释新的领域和概念,并将避免详细重复我之前文章中解释的部分。我鼓励您参考前面的部分。
第一步
首先,我们将导入模型所需的包。需要使用 StratifiedShuffleSplit 导入来构建一个训练模型,其样本集很好地代表了不同的子集值范围。 Pickle 模块将帮助我们保存训练好的模型,然后直接在其他程序中导入模型进行预测。最后,sklearn.metrics 有一套方法来衡量任何模型的准确性。
import pandas as pdimport numpy as npfrom sklearn.model_selection import StratifiedShuffleSplit #import to have equal weigtage samples in training datasetfrom sklearn.tree import DecisionTreeRegressor # import for Decision Tree Algorithmimport picklefrom sklearn.preprocessing import StandardScalerfrom sklearn.svm import SVR #import for support vector regressorfrom sklearn.metrics import mean_squared_error # import to calculate root mean square
第二步
将从 ERP 和其他应用程序导出的样本数据集读入 pandas 数据框架。请参考早前的文章了解数据集的结构和其他细节。
SourceData=pd.read_excel("Supplier Past Performance.xlsx") # Load the data into Pandas DataFrame
第三步
粗略分析数据样本后,似乎“PO 数量”对“缺陷百分比”有着密切而强烈的影响,因此我们希望确保使用不同范围的“PO 数量”记录来训练模型。如果我们用由 30,000 到 60,000 英镑之间的“PO 数量”过度表示的数据集来训练我们的模型,那么我们的模型学习将不会准确到现实生活场景,并且可能不会准确预测。
在下面的代码中,引入了一个新的列“采购订单类别”,将 0 至 30,000 英镑的“采购订单金额”分类为采购订单类别 1,30,000 至 60,000 英镑的为采购订单类别 2。
SourceData["PO Category"]=pd.cut(SourceData["PO Amount"],
bins=[0., 30000, 60000, 90000,
np.inf],
labels=[1, 2, 3, 4])
第四步
StatifiedShuffleSplit 提供训练和测试索引,将过去的数据集分成训练集和测试集。在下面的代码中,我们保留了 30%的数据用于测试模型,60%用于训练模型
split = StratifiedShuffleSplit(n_splits=2, test_size=0.3)
第五步
使用前面步骤中的训练和测试索引,我们将初始源数据分成两部分,即。strat_train_set 作为训练数据集,strat_test_set 分别作为模型的测试和训练数据集。
在下面的代码中,我们使用“采购订单类别”来确保在每个分开的集合中,不同的采购订单类别都得到很好的表示。
for train_index, test_index in split.split(SourceData, SourceData["PO Category"]):
strat_train_set = SourceData.loc[train_index] # stratfied train dataset
strat_test_set = SourceData.loc[test_index] #stratified test dataset
第六步
我们引入了一个额外的列“PO Category ”,以确保在测试和训练数据集中充分表示来自所有 PO 金额范围的采购订单。由于已经完成,因此我们将从数据集中删除这个额外的 PO 类别。
for set_ in (strat_train_set, strat_test_set):
set_.drop("PO Category", axis=1, inplace=True)
第七步
现在,我们将为我们的模型定义、测试和训练数据独立变量和因变量。我们将使用独立和从属训练数据集来训练模型,因为它是一种受监督的机器学习。此外,我们将使用模型之前没有见过的测试数据集来测试模型性能。
SourceData_train_independent= strat_train_set.drop(["Defect Percent"], axis=1)
SourceData_train_dependent=strat_train_set["Defect Percent"].copy()SourceData_test_independent= strat_test_set.drop(["Defect Percent"], axis=1)
SourceData_test_dependent=strat_test_set["Defect Percent"].copy()
第八步
由于数据属性具有不同的范围,因此我们需要在使用它进行训练之前对其进行缩放。关于缩放数据的更多信息,请参考我之前的文章。
在下面的代码中,我们使用 pickle.dump()将 scale 保存为“Scaler.sav ”,以后我们可以在其他程序中导入以供使用。
sc_X = StandardScaler()
X_train=sc_X.fit_transform(SourceData_train_independent.values)
y_train=SourceData_train_dependentpickle.dump(sc_X, open("Scaler.sav", 'wb'))X_test=sc_X.fit_transform(SourceData_test_independent.values)
y_test=SourceData_test_dependent
第九步
我们将用训练数据集训练支持向量模型,并用 pickle 将训练好的模型保存为“SVR_TrainedModel.sav”。“SVR_TrainedModel.sav”和当前程序保存在同一个文件目录中,因为我们没有提供完整的路径和唯一的文件名作为保存参数。
svm_reg = SVR(kernel="linear", C=1)
svm_reg.fit(X_train, y_train)filename = 'SVR_TrainedModel.sav'
pickle.dump(svm_reg, open(filename, 'wb'),protocol=-1)
第十步
现在,我们将从经过训练的独立数据集预测因变量,即缺陷百分比值,并测量模型的误差/准确性。在下面的代码中,我们传递训练数据集,然后将模型的预测值与实际值进行比较。将独立训练变量数据集的预测与实际值进行比较,并通过评分方法返回回归估计量的 R 分数。
decision_predictions = svm_reg.predict(X_train)Score = (svm_reg.score(X_train, y_train)) # It provides the R-Squared Value
print ( "The score of the Support Vector model is", round(Score,2))lin_mse = mean_squared_error(y_train, decision_predictions)
print("MSE of Vector model is ", round(lin_mse,2))lin_rmse = mean_squared_error(y_train, decision_predictions, squared=False)
print("RMSE of Support Vector Learning model is ", round(lin_rmse,2))
在这篇文章中,我不会涉及 R-Square、均方差和均方根误差的统计细节,我强烈建议大家阅读维基百科中关于这些统计指标的页面。这将有助于解释模型是否被训练到可接受的极限,或者我们需要微调数据和超参数。
The score of the Support Vector model is 0.09
MSE of Vector model is 0.05
RMSE of Support Vector Learning model is 0.12
第十一步
对于决策树学习模型,我们遵循相同的步骤,并检查模型的准确性。
tree_reg = DecisionTreeRegressor()
tree_reg.fit(X_train, y_train)
filename = 'DecisionTree_TrainedModel.sav'
pickle.dump(tree_reg, open(filename, 'wb'),protocol=-1 predictions = tree_reg.predict(X_train) Score = (tree_reg.score(X_train, y_train)) # It provides the R-Squared Value
print ( "The score of model Decision Tree model is ", round(Score,2))lin_mse = mean_squared_error(y_train, predictions)
print("MSE of Decision Tree model is ", round(lin_mse,2))lin_rmse = mean_squared_error(y_train, decision_predictions, squared=False)
print("RMSE of Decision Tree model is ", round(lin_rmse,2))
第十二步
一旦模型预测的结果在可接受的误差范围内,我们就可以将模型以前没有见过的测试数据集输入到预测模型中。我们可以用与训练数据集相同的方式来比较测试数据集相关的数据准确性。
test_predictions = tree_reg.predict(X_test)
test_decision_predictions = svm_reg.predict(X_test)
导入训练好的模型和预测
要在另一个程序中使用训练好的模型,我们需要使用“pickle.load”导入自变量 scales 和学习模型,如下面的代码片段所示。
这里,我们从“Supply Chain Predict.xlsx”文件中读取新的独立值数据集,预测相应因变量的进一步步骤如上文针对测试数据所述。
import pickle
import pandas as pd testdata=pd.read_excel("Supply Chain Predict.xlsx") # Load the test datasc_X = pickle.load(open('Scaler.sav', 'rb')) # Load the pickleloaded_model = pickle.load(open('DecisionTree_TrainedModel.sav', 'rb')) # load the trained modelX_test=sc_X.transform(testdata.values) # scale the independent variables for test datadecision_predictions = loaded_model.predict(X_test) # Predict the value of dependent variableprint("The prediction by Decision Treemodel is " , decision_predictions )
完整的代码片段
# Importing the required modules
import pandas as pd
import numpy as np
from sklearn.model_selection import StratifiedShuffleSplit #import to have equal weigtage samples in training dataset
from sklearn.tree import DecisionTreeRegressor # import for Decision Tree Algorithm
import pickle
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVR #import for support vector regressor
from sklearn.metrics import mean_squared_error # import to calculate root mean squareSourceData=pd.read_excel("Supplier Past Performance.xlsx") # Load the data into Pandas DataFrame
SourceData_independent= SourceData.drop(["Defect Percent"], axis=1) # Drop depedent variable from training dataset
SourceData_dependent=SourceData["Defect Percent"].copy() # New dataframe with only independent variable value for training dataset
SourceData["PO Category"]=pd.cut(SourceData["PO Amount "],
bins=[0., 30000, 60000, 90000,
np.inf],
labels=[1, 2, 3, 4])
split = StratifiedShuffleSplit(n_splits=1, test_size=0.3)
for train_index, test_index in split.split(SourceData, SourceData["PO Category"]):
strat_train_set = SourceData.loc[train_index] # stratfied train dataset
strat_test_set = SourceData.loc[test_index] #stratified test datasetfor set_ in (strat_train_set, strat_test_set):
set_.drop("PO Category", axis=1, inplace=True) SourceData_train_independent= strat_train_set.drop(["Defect Percent"], axis=1)
SourceData_train_dependent=strat_train_set["Defect Percent"].copy()
SourceData_test_independent= strat_test_set.drop(["Defect Percent"], axis=1)
SourceData_test_dependent=strat_test_set["Defect Percent"].copy()
sc_X = StandardScaler()
X_train=sc_X.fit_transform(SourceData_train_independent.values)
y_train=SourceData_train_dependent
pickle.dump(sc_X, open("Scaler.sav", 'wb'))
X_test=sc_X.fit_transform(SourceData_test_independent.values)
y_test=SourceData_test_dependentsvm_reg = SVR(kernel="linear", C=1)
svm_reg.fit(X_train, y_train)
filename = 'SVR_TrainedModel.sav'
pickle.dump(svm_reg, open(filename, 'wb'),protocol=-1)
decision_predictions = svm_reg.predict(X_test)
Score = (svm_reg.score(X_test, y_test)) # It provides the R-Squared Value
print ( "The score of the Support Vector model is", round(Score,2))
lin_mse = mean_squared_error(y_test, decision_predictions)
print("MSE of Vector model is ", round(lin_mse,2))
lin_rmse = mean_squared_error(y_test, decision_predictions, squared=False)
print("RMSE of Support Vector Learning model is ", round(lin_rmse,2))tree_reg = DecisionTreeRegressor()
tree_reg.fit(X_train, y_train)
filename = 'DecisionTree_TrainedModel.sav'
pickle.dump(tree_reg, open(filename, 'wb'),protocol=-1)
predictions = tree_reg.predict(X_test)
Score = (tree_reg.score(X_test, y_test)) # It provides the R-Squared Value
print ( "The score of model Decision Tree model is ", round(Score,2))
lin_mse = mean_squared_error(y_test, predictions)
print("MSE of Decision Tree model is ", round(lin_mse,2))
lin_rmse = mean_squared_error(y_test, decision_predictions, squared=False)
print("RMSE of Decision Tree model is ", round(lin_rmse,2))
在本文的下一个系列中,我将讨论不同机器学习算法中的超参数,以及可用于为健壮的机器学习模型确定这些参数的最佳值的选项。
机器学习和第四次工业革命
科迪·诺丁汉在 Unsplash 上拍摄的照片
数据科学和机器学习
毫无疑问,机器学习算法正在通过为我们的日常生活添加一个新的维度来形成一个更加无缝的世界。该社区还推动了更全面、更协调地采用机器学习技术,包括在教育、政府服务和社区福利等重要领域利用机器学习来提高社会生活质量。
由于客户服务行业的这些举措,我们看到了机器学习的积极影响,客户服务行业正在逐步转向机器学习来管理其不断增长的需求。移动应用程序现在被开发来支持无缝的政府服务交付,可以看到聊天机器人在零售、银行、医疗保健和政府服务中的使用。
自动驾驶汽车、机器人、人工智能(AI)、物联网(IoT)和 3D 打印等众多转型技术,是第四次工业革命的新时代。人工智能是通过机器学习和深度学习推动第四次工业革命的最重要的技术之一。机器学习具有巨大的潜力,并在商业领域使用,包括零售、安全、医疗保健和运输。
深入学习机器学习的企业必须关注两件事——业务案例的好处和用例的好处。他们必须采取灵活的分阶段策略来开始建立势头。
研究公司 Venture Scanner 强调,与 2017 年相比,2018 年营销机构对机器学习技术的采用增加了 44%。客户服务团队对这种技术和算法的使用预计将在未来 18 个月内增长 143%。
然而,实现机器学习的最大挑战是感知到的冗余或失业威胁。实际上,应该开发机器学习来适应劳动力市场的不同目的,而不是让它变得多余。机器学习可能有助于提高劳动力的效率,因为机器可以完成劳动密集型和单调的任务,而人类则专注于更高层次的定性任务。
世界经济论坛(WEF)报告称,尽管机器学习和算法到 2022 年将取代 7500 万个工作岗位,但同期它们将创造另外 1.33 亿个新角色。
机器学习技术和算法正在以多种方式影响我们的日常生活。机器学习技术的最大受益者之一是安全性。例如,在中东,机器学习正被用于图像处理、面部识别和预测分析。这项技术正在推动其通过聊天机器人在零售领域提供更多个性化体验的可能性。
在医疗保健领域,机器学习正在通过说服使用全面的算法和软件来支持医生诊断患者和疾病,从而帮助该行业从传统方法转变。当谈到能源和 R&D 时,机器学习使精确钻井、油藏管理和驾驶安全和生产成为可能。机器学习也准备在全球范围内改变运输行业。在阿联酋,第一批自动驾驶出租车已经开始试验,一旦安全和交通可行性得到解决,预计很快就会在道路上推出。
总之,机器学习广泛代表了巨大的收入增长机会。例如,在阿联酋,政府披露了一项战略,通过在政府服务和私营部门利用机器学习技术,将该国定位为人工智能中心。它还旨在招聘和培训人们在不久将雇用机器学习工程师的行业中工作。对于希望在未来提高机器学习能力的企业来说,这是一个巨大的机会。
关于作者
Wie Kiang 是一名研究员,负责收集、组织和分析意见和数据,以解决问题、探索问题和预测趋势。
他几乎在机器学习和深度学习的每个领域工作。他正在一系列领域进行实验和调查,包括计算机视觉、自然语言处理和强化学习。
机器学习和情绪交易
建立一个分类算法的集合,以利用短期 SPDR 部门 ETF 价格行为
你将学到什么和学到什么技能
- 如何将多个分类机器学习模型构建成复合集成模型
- 使用时序分割和随机交叉验证进行超参数调整
- 探索评估模型质量的重要分类指标,如 F1 分数和准确度
- 可应用于多种策略的投资组合绩效和构建代码,将现实世界的交易成本考虑在内
- 如何使用一个热编码构建功能集
- 发现是否可以从基本机器学习模型中预测短期价格变动
在我之前的文章中,我探讨了是否有可能使用一个单一的情绪指标和一个简单的线性模型来系统地跑赢美国股市。不出所料,我发现一个简单的系统根本行不通。但也许结合不同情绪信号的机器学习模型可以创造一种有利可图的策略?
文献综述
随着社交媒体的出现,分析师已经使用社交媒体分析和自然语言处理来提取特定公司的情绪情绪,像 Ravenpack 这样的公司在长期高积极情绪公司和短期消极情绪公司中找到了阿尔法。他们发现,在 2-3 天的时间里,长/短的顶部 10%和底部 10%组合的回报率为 50-100 个基点。
Shlaefer 发现,有 1 到 12 个月的反应不足(股票价格在好消息后上涨,坏消息后下跌)表明投资者需要时间来处理新信息,但在 3 到 5 年的时间里,投资者反应过度,为一连串的正收益付出太多,并忽略了公司基本面的均值回复性质。
贝克和斯坦恩发现,一段时期的高流动性和较小的买卖差价会导致未来回报较低。由于非理性投资者往往使市场更具流动性,流动性的措施提供了一个指标,这些投资者的相对存在或不存在,因此价格水平相对于基本面。
贝克和沃格勒假设,对投资者情绪最敏感的股票将是那些更年轻、更小、更不稳定、不盈利、不支付股息、陷入困境或具有极大增长潜力或具有类似特征的公司。而“债券类”股票将较少受情绪驱动。他们发现,对于年轻、高度不稳定、接近财务困境且无利可图的小盘股和投机股,情绪可能是一个强有力的短期反向指标。具体来说,在这组公司中,当情绪低于历史平均水平一个标准差时,他们的月回报率平均为-34%,当情绪高于历史平均水平一个标准差时,他们的月回报率为 1.18%。
Borovoka 和 Dijkstra 在他们的深度神经网络模型中实现了 60%的准确性,根据围绕单个指数公司的高频新闻情绪预测欧洲斯托克 50 指数的价格走势。
泰特洛克发现,根据《华尔街日报》的“与市场同步”专栏的测量,媒体情绪是几天来整体股市回报的一个确认指标,尤其是对小型股而言。此外,他发现异常高或低的市场悲观情绪会导致高交易量。
数据和方法
没有一项研究调查了由整体投资者情绪驱动的特定行业效应,所以我很想探究一下。
我使用了 9 只 SPDR 行业交易所交易基金(XLU,XLK,XLB,XLI,XLV,XLF,XLE,XLP,XLY ),它们成立于 1998 年 12 月,提供了雅虎财经超过 21 年的每日 OHLC 和交易量数据。请注意,免费数据,如雅虎金融,并不总是最干净的价格数据,但我保留了它,这样你就可以用最小的成本利用代码,以防你想添加不同的 ETF 或股票报价机来测试模型。
我还利用了来自沙拉达、圣路易斯美联储、杜克大学、芝加哥期权交易所、密歇根大学、经济政策不确定性和
将 scikit-learn python 库中的多个分类机器学习模型组合成一个集成分类,我希望与任何单个模型相比,一个多样化的模型将在样本外表现良好。
将数据集转换为训练集、验证集和测试集:
- 训练/验证(样本内)—从数据开始到 2013 年底,训练占样本数据的 80%,验证占样本数据的剩余 20%
- 测试(样本外)—2014 年 1 月—2020 年 5 月
沉思和好奇
我将尝试回答的问题是:
- 基于市场情绪,在多长时间内行业回报最可预测?由于高 OHLC 和交易量数据,我只能在第二天开盘时买入,在 n 天后平仓。
- 在最终的集合模型中应该使用什么模型来组合?
- 什么超参数对于样本外数据的预测是最佳的?
- 在组合了最佳模型后,机器学习投资组合在扣除交易成本后是否会表现更好,因为这将是一种高流动战略?
- 该模型能胜过被动的买入并持有策略吗?
构建特征集
在整篇文章中,我将分享部分代码,但由于可读性,并非全部,但是您可以在 GitHub 上访问数据(由于许可限制,除了 Sharadar)和 python 文件供您个人使用。
以下内容构成了算法将从中预测期望值的特征集,即该证券在 n 天内是正回报还是负回报。
- 市场成交量(占一天交易的总流通股的百分比)
- 上涨/下跌比率(股票总数增加/股票总数减少)
- 简单移动平均线/价格在滚动的 2 到 22 个交易日内迭代
- 在滚动的 2 到 22 个交易日内迭代的年化标准差
- 维克斯
- Sahm 法则——在实时预测经济衰退方面非常有用
- 投资级——高收益公司债券利差
- 政治不确定指数
- 杜克首席财务官乐观指数
- 卖出/买入比率
- AAII 投资者情绪指数
- 密歇根大学消费者情绪指数
- 耶鲁/希勒投资者情绪指数
一热编码
我很好奇,在相同的功能集下,各个部门的 ETF 是否表现不同,因此我使用了一个热编码来为每个 ETF 创建列,如果使用,列为 1,否则为 0(见下图)。
最终的特性和值 pandas 数据帧如下所示,然后被转换为 NumPy 数组。
Credit Spread US Shiller Valuation Index Indiv (Lag) \
date
2003-10-17 3.95 66.24
2003-10-17 3.95 66.24
2003-10-17 3.95 66.24
2003-10-17 3.95 66.24
2003-10-17 3.95 66.24US Shiller Valuation Index Inst (Lag) ...
date ...
2003-10-17 76.64 ...
2003-10-17 76.64 ...
2003-10-17 76.64 ...
2003-10-17 76.64 ...
2003-10-17 76.64 ... XLK XLP XLU XLV XLY
date
2003-10-17 0.0 0.0 0.0 0.0 0.0
2003-10-17 0.0 1.0 0.0 0.0 0.0
2003-10-17 1.0 0.0 0.0 0.0 0.0
2003-10-17 0.0 0.0 0.0 0.0 1.0
2003-10-17 0.0 0.0 0.0 0.0 0.0
创建训练、验证和测试集
您可以很容易地创建一个训练和验证集,注意需要放置 shuffle=False 来防止数据中的混洗,因为财务数据不是独立的,这会使模型过拟合。我喜欢将样本数据(训练和验证)保存在一个 python 文件中,将样本外(测试)数据保存在一个单独的文件中,以防止任何欺骗和展望未来的诱惑。
############Creating Training/Validation Set################# Labels are the values we want to predict
labels = np.array(features['value'])# Remove the labels from the feature and the date
features_array = features.drop(['value','index'], axis=1)# Saving feature names for later use
feature_list = list(features_array.columns)# Convert to numpy array
features_array = np.array(features_array)# Using Skicit-learn to split data into training and testing sets, but in this case it is a validation set
test_ratio = .2 #variable for the percentage of train data to leave as validation# Split the data into training and testing sets, with simple split
train_features, validation_features, train_labels, validation_labels = train_test_split(features_array, labels, test_size=test_ratio, random_state=42, shuffle=False)number_features = train_features.shape[1]
组合模型和选择交易日期
准确度测试在 1-30 天的保持期内使用以下分类器进行:
- adaboost 算法
- 随机森林
- 梯度推进
- 高斯过程
- k 个最近邻居
- MLP 神经网络
- 支持向量机
当我在分类气泡中一步一步地浏览 scikit-learn 算法备忘单时,我特别选择了这些。
每个模型都基于 F1 分数、准确性分数(正确预测的百分比)以及两者的平均值进行测试。我选择排除 SVC 和 MLP 神经网络模型,因为它们分别具有最低的两个组合分数 0.516 和 0.521。接下来,我选择专注于 3 天的持有期,因为算法能够很好地预测时间范围,并且假设模型是好的,更多的交易机会将很好地服务于它,尽管受到交易成本的限制。下表使用条件格式直观地选择高分和低分,标准偏差有一个使用红色的单独公式。我希望看到的是所有模型之间的高平均分和低标准差,这向我表明在特征集中有一个信号要提取,并且算法能够可靠地访问它。
单元格用颜色编码,暗绿色表示较高的分数,底部行表示模型的标准偏差,以辨别跨模型的稳定性,暗红色表示较低的标准偏差。
超参数调整和交叉验证
我将使用 sci-kit 学习库中的时间序列分割和随机交叉验证搜索功能进行超参数调整。时间序列分割,也称为向前移动方法,是为时间序列数据设计的,因为它通常不是独立和同分布的。
然而,正如 De Prado 在机器学习进展中提出的挑战,交叉验证功能对所有分数进行同等加权,即使一些分数是在整体数据的一小部分上训练的。为了解决这个问题,我决定根据总使用折叠的分数来衡量交叉验证分数(即,对于 5 次交叉验证,最后一次测试的分数将为 5 / (5+4+3+2))。
De Prado 提出的另一个问题是,需要清除交叉验证方法中训练/验证分割边缘附近的数据,以尽量减少测试和训练集之间的数据泄漏。我试图利用他的 purgedKfoldCV 函数,但由于每个时间点都有多个数据点,我们同时在看 9 个行业 ETF,所以我做不到。
F1 得分是主要指标,由精确度和召回率的调和平均值组成,在交叉验证期间将通过它来测试模型的准确性。
使用随机 CV 搜索功能,我将给出一个参数列表,从中随机选择,然后分离出最佳评分组合,然后用于验证集。具有最高的,并且希望是不相关的,预测能力的算法将在一个多数表决系统中被组合,以创建最终的预测系统。
下面是一个随机森林算法的随机搜索参数的例子,我摘自威尔·科尔森的一篇文章,并根据我的目的进行了修改。
#### Create 5 K Fold Split Time Series ####number_of_splits = 5
tscv = TimeSeriesSplit(n_splits=number_of_splits)
#####Randomized CV for Random Forest using Timseries split #######
# Number of trees in random forest
n_estimators = [int(x) for x in np.linspace(start = 200, stop = 2000, num = 10)]# Number of features to consider at every split
max_features = ['auto', 'sqrt']# Maximum number of levels in tree
max_depth = [int(x) for x in np.linspace(10, 110, num = 11)]
max_depth.append(None)# Minimum number of samples required to split a node
min_samples_split = [2, 5, 10]# Minimum number of samples required at each leaf node
min_samples_leaf = [1, 2, 4]# Method of selecting samples for training each tree
bootstrap = [True, False]# Create the random grid
random_grid = {'n_estimators': n_estimators,
'max_features': max_features,
'max_depth': max_depth,
'min_samples_split': min_samples_split,
'min_samples_leaf': min_samples_leaf,
'bootstrap': bootstrap}
print(random_grid)# Use the random grid to search for best hyperparameters
# First create the base model to tune
rf = RandomForestClassifier(n_jobs=-1)# Random search of parameters, using time series split,
# search across 100 different combinations
rf_random = RandomizedSearchCV(estimator = rf, param_distributions = random_grid, n_iter = 100, cv = tscv, verbose=2, random_state=42, \
scoring='f1')
# Fit the random search model
search_rf = rf_random.fit(train_features, train_labels)search_rf.best_params_
search_rf.cv_results_
search_rf.best_score_
search_rf.best_estimator_
search_rf.scorer_
一些随机搜索需要一些时间,例如在我的 Mac 上随机森林需要 77 分钟,梯度提升需要 144 分钟(16GB 内存和 2.9 GHz 双核英特尔酷睿 i5)。你可以尝试使用基于直方图的梯度推进分类树,它被设计成在大型特征集上更快。
特征重要性和模型多样化
使用随机森林和梯度增强,您可以看到每个要素的相对重要性百分比。
一般观察:
- 在最右边,我们看到模型在 ETF 是否是特定部门的 ETF 方面几乎没有用处
- 毫无疑问,对 3 天回报率预测最高的波动特征是 2 天和 3 天的波动
- 整体市场动态,如上涨/下跌和市场成交量,对预测未来 3 天的回报最有用
从下面的相关矩阵可以看出,这五个模型的组合确实提供了多样性,这是有意义的,因为它们利用不同的数学算法基于特征集进行分类。
投资组合实施
在综合了所有 5 个模型的预测后,我创建了一个多数投票系统。接下来,我在训练和验证数据集上运行该策略,并与同等权重的投资策略进行比较。
设置实施投资组合所需的变量
######### Portfolio Construction ########
Predictions_DF = features.iloc[:,(-len(tickers)-1):]#Using the same in sample dates here and for equal weight benchmark
f_date = datetime.datetime.strptime(In_Sample_Start, '%Y-%m-%d')
l_date = datetime.datetime.strptime(In_Sample_End, '%Y-%m-%d')delta = l_date - f_date#Choose the number of periods (days in range / the forecasted return days)period_delta = np.floor(delta.days/(Number_days_to_hold))
period_delta = int(period_delta)
first_period = In_Sample_Start #using f_datereturns_df_portfolio = pd.DataFrame()
row_length = Predictions_DF.shape[0]
Portfolio_Turnover = pd.DataFrame()
创建遍历数据并执行交易的 for 循环(当我试图嵌入时,下面的代码看起来相当糟糕)。
注意:y 轴是对数刻度,红线表示验证集的开始
正如您所看到的,与验证集相比,in 样本高度超出预期,因此我解析出了图表来说明差异。
该策略有较高的风险调整回报率,表现为较高的夏普比率,但在其他方面并没有实质性的改善。
测试数据
下面是围绕模型分类的统计数据,最后一行显示了如果我假设市场将永远上涨,这类似于永远全额投资,结果会是什么。
每一栏中的最佳分数以红色突出显示
“市场总是上涨”的购买和持有取向是普遍的赢家。
正如在下面的混淆矩阵中看到的,集合模型在预测未来回报何时为正(右下)方面比预测何时会有负回报(左上)做得更好。
下面是使用测试数据(2014 年 1 月-2020 年 5 月)的策略实际性能图表。
该模型执行了 1074 笔单向交易,假设由于市场影响和滑点,交易佣金为 1 美元,成本为 15 个基点,那么现实世界的成本将从 10,000,000 美元的投资组合的总业绩中减去 17.9 %和 1,074 美元,导致年化回报率为 1.3%,远低于不切实际的 6.1%的年化回报率。
吸取的教训
- 集合模型在预测上涨天数方面做得很好,但在高交易成本之后,它并没有带来任何更好的风险调整表现
- 正如 53.4%的准确性所证明的那样,该模型确实比随机机会做得更好,但市场上涨的时间为 54.8%,因此,如果你有一个简单的命题“市场将上涨”,那么你会有更高的准确性分数。
- 机器学习模型能够从市场内部特征中提取一些信号,如市场成交量,但最终,并没有创造出一个优于天真的“总是被投资”模型的预测模型。
- 基于前面提到的其他相关研究,我希望机器学习模型能够从特定股票的社交媒体分析、小盘股和微盘股中提取出更有意义的信号,并通过深度神经网络提高整体准确性。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
机器学习和转化研究
从电脑到诊所
作者创造的形象
互联网网络服务的扩展和高通量技术的最新进展使得公众,特别是科学界,能够容易地访问重要的生物数据集。因此,处理、分析和推断知识的方式在最近几年发生了巨大的变化,无论是临床数据、测序数据、电子健康记录还是一般医学。正因为如此,像机器学习和人工智能这样的数据科学术语已经以这样或那样的方式成为我们日常使用词汇的一部分。他们已经彻底改变了转化研究的设计和执行方式,为改善人类健康带来了全球性的发现。
在这篇文章中,我们将介绍机器学习的基本概念及其在转化研究或医学方面的应用。
机器学习
机器学习无疑是当今世界谈论最多的技术之一。简单来说,机器学习就是把信息变成知识的工具。在当今世界,我们正在生成大量数据,除非我们分析这些数据并找到其中隐藏的模式,否则这些数据毫无用处。
机器学习专注于算法的分析和开发,使计算机能够根据之前观察到的数据做出决策和预测,而不依赖于基于规则的编程
机器学习主要分为三种类型:监督学习、非监督学习和强化学习。
作者创造的形象
监督学习
目标是生成一个模型或预测函数,它可以基于一个或多个输入值预测一个输出。
- 模型的输出通常被称为标签、目标值或响应变量。
- 模型的输入通常被称为特征或预测器。
该算法通过研究由几个观察值组成的数据训练集来“学习”最佳模型,每个数据都具有其特征和其标签的值。
进一步,监督学习又分为两类、分类 、 回归 。在分类中,输出变量被分类为“存在”或“不存在”或“疾病”或“无疾病”或分级(1 级、2 级等)。).在 回归中, 输出变量是一个真实值,如“浓度”或“重量”,例如,你根据标准曲线测量样品中的蛋白质浓度。
这种类型的机器学习可以广泛用于放射学、病理学或任何其他成像领域中的医学成像。这种研究是有用的,必须小心谨慎,因为它们需要大量的数据集才能足够准确,而且数据必须准确标注。
无监督学习
在无监督学习中,数据集有特征,但没有标签。无监督学习的目标是识别数据中我们不容易注意到的结构。因此,所设计的算法必须基于数据集中的相似性来创建其组和类别。与监督学习不同,无监督学习预测未知的结果,并发现隐藏的模式。同样,在无监督学习中,我们一般不会从可能的标签会是什么这个先入为主的概念开始。聚类是非监督学习的一个例子。下一代测序等技术帮助科学家建立模型,从一组不同的独立变量中预测结果。无监督学习方法一般称为降维技术(如 PCA、tSNE 等。).单细胞测序分析过程中细胞在不同组中的聚类就是其中一个例子。另一个例子是基于基因表达值的组织样本聚类。
强化学习
强化学习是指计算机程序从它的错误和成功中学习,并最终根据它的经验建立一个算法。所以,这种学习是基于试错法。强化学习任务的示例包括训练算法(I)下棋或玩视频游戏,(ii)驾驶自动驾驶汽车,(iii) 了解医疗注册数据上的治疗方案, (iv) 找到治疗化疗患者的最佳策略。
在麻省理工学院研究人员发表的研究中,作者报告了一个作为强化学习问题的临床试验剂量的成功公式,其中算法教会了适当的剂量方案,以减少接受化疗和放疗临床试验的患者的平均肿瘤直径。
机器学习算法正在帮助揭示数据矿下隐藏的宝石。但有一点应该永远记住,“更复杂的算法不一定会产生最好的结果”。
机器学习和转化研究——“友谊”
机器学习的应用包括但不限于简化行政工作、医院记录管理、医疗和传染病等。下面只是几个例子,讨论了在医学研究和医疗保健中具有重大潜力的机器学习任务。
作者创造的形象
医学成像(磁共振成像(MRI)、X 射线、计算机断层扫描、乳房 X 线摄影、组织切片等)分析可以通过使用机器学习算法而受益匪浅。例如,目前,病理学家手动检查载玻片并决定患者是否患有转移性癌症。因为人的判断是不一致的,并且诊断可能因人而异,甚至由同一个人每天都不同。在这种情况下,机器学习算法可以自动完成这一过程,并且最好能够提供无偏见的结果。这些算法通过从以前的样本中学习来提高诊断的准确性,因此可以提供治疗选择。有前景的应用包括检测肿瘤、动脉狭窄、、乳腺癌、淋巴结、器官描绘等。
如今,高通量技术的出现产生了海量数据,这些数据被收集起来,可供研究界使用。此外,像癌症基因组图谱研究网络等社区资源项目提供了对基因组数据的访问。每个人都有许多已知或未知的基因变异。即使有先进的测序技术,预测突变的发生及其后果仍然具有挑战性。完整的基因组序列的可用性允许更好地观察和理解个体的遗传图谱,这最终与健康直接相关。在多组学(基因组、转录组、蛋白质组、表观基因组、代谢组和微生物组)时代,医疗保健的前景看起来很有希望。二十多年来,各种不同的机器学习算法被广泛应用于**疾病的预后和预测。**机器学习有助于预测易感性、复发率和存活率。
药物发现和开发过程漫长而艰难,取决于众多因素和学科。一种新药从实验室走向药店货架平均需要 12 年时间,耗资超过 3 . 5 亿美元。机器学习算法可以通过帮助决策来改进药物发现,因为它可以生成高质量和高维度的数据。它适用于药物发现的所有阶段,无论是**靶标验证、预后生物标志物的识别,还是临床试验。**然而,方法和算法仍处于开发阶段,但有助于加快过程并降低失败率,最终将节省时间和金钱。此外,遗传学数据与药物-蛋白质结合数据库的结合允许针对细胞类型、突变等的每种可能组合来测试不同的化学物质。这种分析使研究人员能够建立模型,从各种独立变量的组合中预测结果。
个性化医疗,这是一种根据患者个体特征(临床、分子或行为)而非总体平均水平做出医疗决策的医疗方法。个性化医疗的概念与数据科学,特别是机器学习有着密切的联系。预计到 2023 年,市场规模将达到870 亿美元,机器学习将成为设计个性化药物的发电站,这将有助于打破一刀切的方法。
在诊所中使用机器学习有可能改变现有的医疗保健提供模式。然而,人们应该牢记道德和监管问题,以避免不必要的风险和陷阱,阻碍“计算机到诊所”的流动。
结论
为了提高生活质量,需要多学科的努力,包括数据科学家、研究科学家、临床医生、监管事务机构和医疗保险组织。
感谢阅读😄。
机器学习在岩石物理行业的应用:声波测井综合预测故事
扎卡里·西奥多在 Unsplash 上的照片
岩石物理学是什么意思?
岩石物理学是对岩石性质的研究,也是对液体相互作用的简要描述。它主要用于石油和天然气行业,以研究不同类型的油藏的动态。它还解释了地下孔隙的化学性质以及它们之间的联系。它有助于控制油气的运移和聚集,同时解释化学和物理性质,岩石物理学还解释许多其他相关术语,如岩性、含水饱和度、密度、渗透率和孔隙度。
岩石物理学家的职责是什么?
岩石物理学强调与孔隙系统及其流体分布和流动特征相关的性质。这些属性及其关系用于识别和评估:
- 油气藏
- 碳氢化合物来源
- 密封
- 含水层
岩石物理学家或岩石物理工程师作为油藏管理团队的一员实践岩石物理学。这位岩石物理学家提供了团队成员需要和使用的产品的答案,以及其他队友需要的物理和化学见解。要确定的储层和流体特性有:
- 厚度(地层边界)
- 岩性(岩石类型)
- 多孔性
- 流体饱和度和压力
- 流体识别和表征
- 渗透率(绝对)
- 分流(油、气、水)
来自 斯伦贝谢 媒体公司
很容易定义这些特征并理解它们在储量评估中的作用。困难的部分在于确定它们的实际价值,这种确定性是作出导致开发和生产的经济决策所必需的。列出的七个特征是相互依赖的(即,为了正确确定电缆测井的孔隙度,必须知道岩性、流体饱和度和流体类型)。然后,岩石物理学被用来解读从地表以下到超过四英里深的储层中岩石和流体性质的隐藏世界。然后,这位岩石物理学家利用虚构侦探夏洛克·福尔摩斯的许多特征,从最贫乏的线索中推断出地下储油层的真实情况,用顽强的决心从现有数据中获取所有可能的信息,同时享受狩猎的刺激。
岩石物理学家是如何解决这个难题的?
阿奇的一般方法是将问题细分成更小的片段,使用所有数据迭代,直到所有数据一致。一个起点是确定岩石类型(岩相),其中我们确定:
- 孔隙类型
- 气孔分布
- 孔喉型
- 孔喉分布
当与流体类型相结合时,可以建立一个毛细管压力模型,这将导致对原位流体饱和度和流体流动的理解。然而,可供岩石物理学家使用的工具有:
案例研究:声波测井综合预测
由于财政或操作的限制,并不是在一个油田中钻探的所有井都获得压缩旅行时(DTC)和剪切旅行时(DTS)测井。在这种情况下,可以使用机器学习技术来预测 DTC 和 DTS 测井,以改善地下表征。本岩石物理数据驱动分析项目的目标是通过处理 casr 研究“1 井”中“易于获取”的常规测井数据开发数据驱动模型,并使用数据驱动模型生成案例研究“2 井”中的合成 DTC 和 DTS 测井数据。用于期望的声波测井合成的稳健的数据驱动模型将导致低的预测误差,这可以通过比较合成的和原始的 DTC 和 DTS 测井,以均方根误差(RME)来量化。
提供了井数据集(由井 1 和井 2 组成),目标是使用井 1 数据集建立可概括的数据驱动模型。接下来,您将在 Well 2 数据集上部署新开发的数据驱动模型,以合成 DTS 和 DTC 日志。数据驱动模型使用从以下七种测井中导出的特征集:井径、中子、伽马射线、深层电阻率、介质电阻率、光电系数和密度。数据驱动模型应该合成两个目标日志:DTC 和 DTS 日志。
数据源
数据的位置是一个 Github 存储库,该存储库来源于由位于 Petrophysical 数据驱动分析的 amazing 团队维护的 GitHub 存储库
来自 SPWLA
用哪种机器学习算法?
照片由 Charles Deluvio 在 Unsplash 上拍摄
对于给定的问题,找到最佳算法的唯一方法是尝试和测试所有算法
为这个项目尝试所有可能的机器学习算法非常耗时,因此在本文的上下文中,我们将使用 eXtremeGradientBoosting(XGBoost)算法。从问题陈述中,我们预测两个特征,使其成为一个多目标回归问题。将应用 XGBoost 回归器和 SKlearn 的 MultiOutputRegressor 。
XGBoost 是什么?
来自 Github 库的 XGBoost 徽标
这是一个由陈天琦创建的梯度推进机器的实现,现在有许多开发者参与其中。它属于分布式机器学习社区或 DMLC 旗下更广泛的工具集合,他们也是流行的 mxnet 深度学习库的创造者。这是一个免费的开源软件,可以在 Apache-2 许可下使用,它支持以下主要接口:
- 命令行界面(CLI)。
- Python 接口以及 scikit-learn 中的一个模型。
- C++(编写库的语言)。
- r 接口以及 caret 包中的一个模型。
- 朱莉娅。
- 像 Scala 这样的 Java 和 JVM 语言以及 Hadoop 这样的平台。
为什么选择 XGBoost?
图书馆被激光聚焦
- **计算速度:**一般情况下, XGBoost 快。与梯度增强的其他实现相比,速度非常快。
- 模型性能: XGBoost 在分类和回归预测建模问题上主导结构化或表格化数据集。证据是,它是竞争数据科学平台 Kaggle 上竞争获胜者的首选算法。
XGBoost 安装
对于稳定版本,可以使用 python 包索引(PyPI)将 XGBoost 包安装到 Python 环境中。
pip install xgboost
导入包
这里,我们从导入这个项目需要的所有 python 库开始。
warning
:用于抑制 python 包中不推荐使用的函数的警告控件。numpy
:用于科学计算。pandas
:为了数据争论和分析matplotlib
:用于图形和图表的可视化。xgboost
:用于预测的机器学习算法。MultiOutputRegressor
:提供多目标回归环境。StandardScaler
:缩放数据train_test_split
:拆分数据RandomizedSearchCV
:随机参数调谐mean_square_error
:用于评估预测的性能指标。
读取数据
首先,在数据输入过程中,大多数情况下缺失值被替换为-999
,因此将其识别为系统的缺失值指示器是理想的。这里,空白以及Nan
和NaN
也被识别为数据集中的缺失值指示符。
获取数据概览
各个特征的数据描述如下:
- CAL:井径测井(单位为英寸)
- CNC:神经元日志(单位为十二月)
- GR:伽马射线测井(单位为 API)
- HRD:深电阻率测井(单位为欧姆每米)
- HRM:中电阻率测井(单位为欧姆每米)
- PE:光电系数(单位为谷仓)
- ZDEN:密度测井(单位为克每立方公尺)
- DTC:压缩传播时间 lo(单位为纳秒每英尺)
- DTS:剪切传播时间测井(单位为纳秒每英尺)
DTC 和 DTS 称为**声波测井,**可以从接收器记录的波形中计算出来。还计算了描述性统计。
检查缺失值
可以观察到,在训练数据中存在大量的缺失值。让我们来看看数据的分布情况。
填充缺失的值
大多数要素的直方图是单摩尔直方图,而其他直方图是倾斜的,用数据框中的前一个值填充前者,用中值填充后者将非常合理。pandas fillna backfill
方法和 medianmedian.()
方法将支持使用先前值方法进行填充。
特征工程
本出版物中的特征工程主要关注伽马射线测井(GR)特征。从直方图中可以观察到异常值,因为 GR 值通常在 0-200 之间。我们将从 GR 中创建两个新特性,同时将其限制在上限和下限。要创建的两个新功能是:
- 伽马射线指数(IGR)
- 自然伽马辐射(NGR)
在使用伽马射线测井(GR)功能创建其他功能以减少数据冗余后,应将其删除。
拆分数据
训练数据以 70:30 的比例分割
数据的标准化
当各种变量放在相同的刻度上时,大多数机器模型工作得最好。
模型建立和拟合
XGBoost 回归是用已经调优的超参数实例化的。超参数调整是一个非常耗时的过程,本文中跳过了这一步,但是可以在 github 上的笔记本中查阅。该模型适合于训练数据,以帮助学习过程。
模型预测和评估
模型的最终输出—预测。****的值越低,表明拟合度越好,模型看起来越好!最后,模型被应用于它没有见过的数据——“测试”数据。
我希望本文能拓宽机器学习在岩石物理行业的应用领域。感谢阅读和保持安全。
作为创造性工具的机器学习,以及对人工智能的探索
苹果 | 谷歌 | SPOTIFY | 其他 | 剪辑
史云光·斯廷布鲁奇在 TDS 播客上
📸由 sergio souza 在 Unsplash 上拍摄的照片
编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris 主持。Jeremie 帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客:
大多数机器学习模型的使用方式大致相同:它们接受复杂的高维输入(如数据表、图像或文本正文),并返回非常简单的内容(分类或回归输出,或一组聚类质心)。这使得机器学习成为自动化重复任务的理想选择,这些任务在历史上可能只能由人类来完成。
但这种策略可能不是未来机器学习最令人兴奋的应用:越来越多的研究人员甚至行业参与者正在试验生成模型,从零开始产生更复杂的输出,如图像和文本。这些模型有效地执行了一个创造性的过程——掌握这个过程极大地拓宽了机器可以完成的范围。
我今天的嘉宾是史云光·斯廷布鲁格,他的重点是机器学习的创造性方面。除了为大公司提供咨询,帮助他们将最先进的机器学习模型投入生产,他还将大量工作集中在更多哲学和跨学科问题上,包括艺术和机器学习之间的互动。出于这个原因,我们的谈话朝着一个不同寻常的哲学方向发展,涵盖了从语言结构到什么使自然语言理解比计算机视觉更具挑战性,到人工通用智能的出现,以及所有这些东西如何与机器学习的当前艺术状态相联系。
以下是我最大的收获:
- 公司内部开发的大量机器学习模型最终都没有被部署。从他的咨询经验来看,史云光表示,出现这种情况的原因是,公司往往对部署“酷”的最先进模型的前景感到兴奋,而不是专注于解决真正的业务问题。然而,这个问题并不是公司独有的:伟大的数据科学家的标志是,他们在考虑花哨的模型之前,先考虑创造商业价值。
- 语言数据本质上比图像数据对变化更敏感。你可以通过改变一两个单词来完全改变一个句子或段落的意思,但改变一小撮像素的颜色不会对图像所传达的意思产生太大影响。这是语言建模尚未赶上计算机视觉的很大一部分原因,尽管最近取得了重大进展。
- 目前,语言模型仅参考其他单词来定义单词的含义。这可能感觉就像我们做的一样——毕竟,如果我让你定义苹果是什么,你回答的唯一方式是引用其他词,比如“水果”、“甜”或“树”。你可能会想象——哲学家雅克·德里达也是这样想的——因为这些单词中的每一个都是相对于其他单词来定义的,所以所有的语言基本上只是一种任意的、自我指涉的混乱,与任何具体事物都没有联系。
- 然而,这可能不是故事的结尾,因为人类不仅仅是通过阅读数百万篇维基百科文章和将一个词与另一个词连接起来建立一个相互依赖的网络来学习单词的含义。相反,我们用其他来源的数据来补充这个策略,比如视觉、声音、嗅觉和触觉。因此,要创造一个真正的人工智能,可能还需要多种输入类型。
- 在关于构建人工智能需要什么的辩论中,有两个阵营:一个阵营认为,我们主要通过提高计算能力和增加内存来解决问题,另一个阵营认为,需要更复杂的模型。史云光认为有可能两者都需要,而且以新的方式结合模型也可能导致 AGI 式的性能显著提升。
夹子
我们正在寻找能与我们的观众分享有价值的东西的客人。如果你碰巧知道谁是合适的人选,请在这里告诉我们:publication@towardsdatascience.com。
保险公司的机器学习
洞察保险公司对先进模型的缓慢采用
谁是德尼罗? on Unsplash
这些年来,我阅读了很多关于保险公司以及由商业和技术创新驱动的即将到来的变革的论文,通常被称为保险技术。与传统的保险业务模式相比,这些保险技术公司利用技术开发基于分析的方法来改进现有流程,从而获得竞争优势。保险公司被警告要么跟上,要么灭亡…
鉴于竞争格局和不断蒸发的利润率,传统保险公司被建议发展成为由机器学习(ML)和人工智能(AI)驱动的数据驱动型企业。保险公司的这些高级模型有几个用例。大数据分析(BDA)为保险公司带来的优势如下:
资料来源:ei opa——欧洲保险和职业养老金管理局,https://www.eiopa.europa.eu/,专题评论
保险公司在采用 ML 和 AI 方面取得了一些进展。一些公司已经建立了数据科学卓越中心来定义和实现他们业务中的用例。此外,一些保险公司正在投资,通过向员工提供数据科学和大数据课程,有机地构建他们的内部知识。
为了进一步加速数字创新,一些保险公司正在通过内部孵化器、加速器和创新实验室与初创公司合作。这对双方都有利,因为初创公司受益于成熟的技术支持、指导和与行业专家的联系,而保险公司则获得了新技术。
另一方面,一些保险公司通过组建企业风险投资公司来投资 T2 的保险技术公司。向多家初创公司投入相对较少的资金,可以让保险公司在他们感兴趣的众多领域获得潜在突破。
尽管围绕高级模型的嗡嗡声令人麻木,这些创新的解决方案还没有获得显著的牵引力。保险公司没有像预期的那样迅速瓦解,而是慢慢适应了这些变化。因此,我想解释一下保险公司采用先进模型的缓慢过程。
下图总结了保险公司面临的大数据分析(BDA)挑战。
资料来源:ei opa——欧洲保险和职业养老金管理局,https://www.eiopa.europa.eu/,专题评论
保险公司在负责任地实施 ML 和 AI 方面面临着相当多的挑战。我想考虑其中的一些挑战,并提供额外的背景。首先,保险公司认为主要风险在于与消费者打交道,这需要保持消费者的信任,合乎道德地使用人工智能,并识别危及保险公司和保险行业声誉的潜在风险。
创新是保险公司的一个议程项目,然而,预测机器学习项目的投资回报几乎是不可能的。规划或预算这样的项目并不容易,因为根据调查结果,项目期间的资金可能会有所不同。因此,这一项被忽视了,尤其是与更紧迫的项目相比,如符合新的和即将出台的(监管)标准或保险公司的盈利能力考虑到当前的低利率环境。
每个数据科学家都知道 GIGO " 垃圾输入,垃圾输出"。这是 ML 在保险公司中没有获得牵引力的另一个原因,即数据质量。高质量和各种输入数据的可用性是应用高级模型的先决条件。目前,保险公司的数据质量很差,因此最大限度地降低了 ML 和 AI 的附加值。
保险公司 AI 和 ML 的一个有利发展是新法规和即将出台的法规对数据的要求增加。具体来说,新的报告标准(IFRS 17)要求更多的数据粒度,因为保险公司正在彻底检查其 IT 系统和架构,以应对数据量和质量的增加。
最后,保险公司也意识到他们需要“保持控制”,尤其是在定价和保留领域。ML 和 AI 模型通常与术语黑盒模型联系在一起。因此,保险公司不清楚如何在不超出法律和监管要求的情况下使用人工智能。因此,保险公司面临的挑战是在监管空间内构建一个合规且可解释的垫款模型框架。
结论
颠覆通常与创新发展结合使用。然而,要真正颠覆一个行业,仅仅创新是不够的。颠覆需要大规模采用。
保险业已经注意到了这些技术的发展,保险公司也相应地动员了他们的努力和资金。考虑到保险公司在 ML 和 AI 方面面临的一系列挑战,他们正在慢慢适应不断变化的环境。因此,它们越来越受数据和技术的驱动。
边缘的机器学习!
使用 OpenCL 在运行嵌入式 Linux 的小型处理器的 GPU 上实现机器学习/图像处理,以获得实时性能
(图片由维基百科提供)
内容:
- 概观
- 旅行寻找可行的解决方案
- 构建您自己的工作解决方案
- 吸取的教训。
概述
所以,我有一个工作机器学习(ML)模型,我想把它移到边缘。
顺便说一下,我的 ML 模型处理图像以进行深度估计,从而为自主机器人提供感知能力。使用的机器学习模型是基于麻省理工学院的快速深度。这是一个专注于速度的 U-Net 架构。它使用一个 MobileNet 编码器和一个匹配的带跳跃连接的解码器。
(图片由作者提供)
它是在 Python 上使用 Keras(起初是 PyTorch)开发的,带有 CUDA 后端。
通过移动到边缘,我的意思是我需要在运行嵌入式 Linux 的小型 CPU/GPU(高通 820)上运行,其中 GPU (Adreno 530)只能通过 OpenCL(即,不是 CUDA)访问。)
警告——如果你在 iOS 或 Android 上,你已经相对自由了。这篇文章是为了在嵌入式 Linux 的 GPU 上使用 OpenCL 进行机器学习。
四处寻找可行的解决方案
这很容易。哈!原来一旦你离开 CUDA,你就在荒野中…
实际上,有两种广泛的方法可以在边缘部署模型。
- 尝试在边缘复制您的开发环境,并让它在那里运行。如果这是可能的,这总是一个好的第一步,如果只是为了说服自己它的表现有多慢。我尽可能地探索了这个世界,尽管在我的设备上甚至没有完整的 Linux,所以我甚至不能支持 Python。
- 找到一个推理框架,它可以在一个更高性能、更少资源的环境中运行你的代码。这需要你做更多的工作,特别是当你要把你的 C++编码技能拿出来的时候。这就是我们要探索的地方。
通过谷歌搜索和参考资料,我发现了一系列可能的方法。
同样,我有一个 Keras 模型,我想在嵌入式 Linux 上的高通 820 GPU(实际上 Adreno 530 是 GPU)上尽可能快地运行。没有量化的方法进行评估。
这是我探索的世界:(即,很多很多的“死胡同”)
GPU“边界”的地图
解释:
- Keras —该模型是在 Keras 开发的。
- ONNX —一些选项提供了 ONNX 导入,例如 OpenCV。原来 ONNX,至少在那个时候——2019 并不支持我在用的所有 Keras 算子。
- Tensorflow-这是一个重要的层,因为大多数(如果不是全部)引擎都是从 tensor flow 导入/转换的,而不是从 Keras 导入/转换的。最终的解决方案——MACE 需要相对较旧版本的 tensor flow——他们要求 1.08 版——尽管 1.14 版也能工作……请参见下面的 SYKL 了解如何使用 Tensorflow runtime。
- Tensorflow Lite/TF-Lite。然而,为这种情况设计的,没有办法(我能找到)通过 OpenCL 把它连接到 GPU。
- SYKL——据说是一种将 Tensorflow 连接到 OpenCL 的方法。没什么进展就只好放弃了。
- Arm 计算机库。这是可行的,但是缺点是(我无法找到)导入模型。使用这些或用他们的语言编码。
- ARM 神经网络。来自制造商的一种“官方”方式——ARM。应该很容易。见鬼,我被卡在巨大的安装区域的某个地方,永远也不能让它工作。这是一个可以从提供 Docker 环境中真正受益的群体。
- 移动 AI 计算引擎——MACE。至少部分是为这个用例设计的!来自小米。这个居然管用!而且效率很高!他们的支持很好——这些人很棒!更多见下文。
- 移动神经网络-MNN。只是玩玩这个,因为我最近刚刚“发现”这个,但这个看起来很棒,可能会更容易从 Keras 过渡到平台,也可能会进行更多的优化。来自阿里巴巴。
- tvm.ai .专为在 GPU 上执行而设计,尤其是为了效率。然而,它需要的比我的迷你 Linux 所能提供的更多,而且他们并不真正喜欢 OpenCL。我想让这个工作,特别是发挥了 MNN 的效率。
- OpenCV。DNN 软件包是为运行 ONNX 模型而设计的,事实也的确如此。如果 verrryyyy 慢。非常失望。此外,结果是我不能在我的运行时使用 OpenCV,所以这是一个不成功的例子。
- 骁龙神经处理引擎。从高通,见鬼,这应该很容易。首先,来自高通的支持让康卡斯特看起来像明星。见鬼,就此打住——这个工具在我的环境中是行不通的。
- open vino——看起来很有前景,但似乎只面向英特尔。
在 MACE 上构建自己的工作解决方案
下面是让你的模型在 GPU 上运行的大致步骤(在使用 OpenCL 的嵌入式 Linux 系统上!)这很像是他们文档的画外音,其中有一些关键的提示。
- 克隆权杖。【https://github.com/XiaoMi/mace
- 让 Docker 环境工作起来。我用的是全环境。
- 为您的目标配置。有多种架构选项以及 Linux/Android 选择。在我的例子中,我的架构选择是 armeabi-v7a。(这是一个更长的故事,为什么不是 64 位架构。)不幸的是,为该架构配置的操作系统是 Android。所以我不得不稍微混合搭配一下来得到 Linux。
- 为目标制造狼牙棒。
所有这些都是一次性的启动事件(一旦成功)。
现在,要获得你的 Keras 模型的梅斯转换…
输入张量流
哦,等等。原来 MACE 只支持 Tensorflow 到大约 1.14 版,根本不支持 Keras。因此,我必须将我的 Keras 模型转换为正确年份的 Tensorflow。这是一些工作,基本上是在 Tensorflow 中制作完全相同的模型,然后复制权重。和迭代,因为没有什么是那么容易的。Netron 是一个很好的工具,可以深入了解和比较你的模型的本质。
一个优化是,您还可以轻松地添加图像预处理以提高性能。例如,这些线不在 Keras 模型中,只在 Tensorflow 模型的前面。这允许我们将预处理从 CPU 转移到 GPU 上,特别是图像大小调整和数据规范化。
Rs224 = tf.image.resize_bilinear(input,(224,224), name='resize224')
# normalize data, identical to how we trained
Norm224 = tf.scalar_mul(1./255., Rs224)
Norm224 = tf.scalar_mul(2., Norm224)
Norm224 = tf.math.add(-1., Norm224)
继续转化为狼牙棒
回到转换:
- 创建您的 YAML 文件。请注意,您需要为模型的每个新版本创建一个 sha256sum 代码。
- 做你的转换。
python tools/python/convert.py — config ../mace-models/yourmodel.yml
3.测试你的转换。好吧,梅斯倒在这里。事实证明,如果不加入一些东西来移动,Linux 版本并不能真正工作。应该起作用的是…
python tools/python/run_model.py \
--config ../../mace-models/yourmodel/yourmodel.yml \
--validate \
--target_abi arm-linux-gnueabihf \
--target_socs root@192.168.8.1 \
--device_conf ../../mace-models/820.yml
但事实并非如此。结果他们的剧本失败了。(修复—您需要手动将“/tmp/mace _ run/your model/validate _ in/XXX”上移一级,然后执行。他们脚本中的/mace_run 命令。)
运行时的 c++
最后,编写在目标环境中运行的 C++代码。我在一个 ROS 节点内运行,该节点监听新的摄像机图像事件。这个节点将处理它们,并创建深度云输出,以供下游处理,比如说八分图。
调用 MACE 推理引擎的关键部分包括:
**// define input node (output nodes not shown)**
const std::vector<std::string> mace_input_nodes{"input"};
const std::vector<int64_t> mace_input_shape{{1, 480, 640, 3},};
...
**// initialize the 'engine' (though of course more surrounds this)**
create_engine_status = CreateMaceEngineFromProto(reinterpret_cast<const unsigned char *>(
model_graph_data->data()),
model_graph_data->length(),
reinterpret_cast<const unsigned char *>(
model_weights_data->data()),
model_weights_data->length(),
mace_input_nodes,
mace_output_nodes,
config,
&engine);
...
**// execute model**
run_status = engine->Run(inputs, &outputs, nullptr);
真正的好消息。我希望每秒 10 帧。即使在添加了之前显示的图像预处理(通常在 C++代码中)后,我最终达到了 25 fps。太棒了。以至于整个系统的其他部分成了门控因素。实际上,我必须降低 ML 推理的执行速度,以免系统的其他部分过载!
吸取的经验教训
- 对于所有这些推理方法,请确保您的操作受到支持。例如,OpenCV 不支持上采样。
- 你必须尝试一下,看看是否行得通。
- 如果工具供应商提供了一个 Docker 环境,那么它工作的可能性会大得多。
- 如果他们对论坛上的问题做出回应,这是一个好迹象。如果没有,那就跑吧,不要走开。
- 尝试多种方法,因为许多方法都会以某种方式失败,通常是你不怀疑的方法。
祝你好运!