让您的模型选择要学习的数据—主动学习的基础
没有足够的资源来为您的分类任务获取您自己的标记数据?尝试跳出思维定势,主动开始学习 主动学习 。让你的算法选择学习什么。
我们一直在谈论处理数据,以获得与我们的项目、我们的经历、利润最大化、增加收入和许多其他原因相关的具体见解。这是任何人一直在想的事情。但是…让我们退一步,从我们的“假设”数据中休息一下,从“实际”数据的角度来思考。
获取数据并不总是容易的。没有一家公司会免费给你。有很多交易发生。例如,你在金钱上帮助另一家公司,他们会帮助你得到你想要的数据。作为一名数据科学家,说服你的经理你想要的对公司有帮助的数据并不总是容易的,只是因为它的成本很高。你需要根据一家公司为其数据科学团队设定的预算来调整你的预期。
如果您正在处理大量带标签的数据,您以前一定面临过这个问题。主动学习可能是你的最佳解决方案。
定义—
主动学习是一种机器学习算法,其主要目标是 通过让算法选择它需要学习的数据 来减少训练数据量,以便通过表现更好或至少与更多训练数据相同来达到我们的评估指标的预期目标。
让我们更深入地探究——
主动学习的直观指南—最左边(图 1)、中间(图 2)、最右边(图 3)
在图 1 中,我们有一堆面孔,需要将他们分为男孩和女孩,但我们没有他们所有的标签。获得标签是昂贵的。在图 2 中,我们获得了其中一些人脸的标签,并通过随机选择数据子集对它们进行分类。正如我们可以看到的,如果我们使用这些人脸来分类实际人脸,分类误差会增加。在图 3 中,我们试图选择提高模型精度的面(通过选择最佳面,我们节省了资源)。这就是主动学习的意义所在。我们试图找到模型最有可能出错的实例(那些更接近决策边界的实例),以便在它们被标记并包含在训练集中之后,模型对于看不见的数据上的这些类型的错误变得更健壮。
它是如何工作的?
- 从整个数据集中,随机选择一个数据子集作为训练数据。
- 根据您的查询策略,在仔细检查之后,请求非常少的数据点的标签。
- 通过对上述数据进行训练来预测剩余数据点的标签。
- 将这些新标记的数据点添加到您的训练数据中,并反复重复相同的过程。
当我们谈论查询策略时,它主要是关于选择那些您最不确定其类别的数据点。有各种各样的场景来查询你的算法—
- 成员查询合成
- 基于流的选择性采样
- 基于池的采样
成员查询合成
顾名思义,它是一种基于某种隶属标准生成/ 综合 查询的策略。模型重新生成查询*(从头开始),即模型生成新的查询,而不是现有的查询。*
基于流的选择性采样
这是一种顺序策略,我们可以从抽样分布中随机抽取数据点,然后选择是否要对其进行标记。每个查询决策都是单独做出的。学习者决定是否要查询该实例。有一些“信息含量测量”可以帮助学习者决定查询策略。
基于池的采样
当在大的未标记数据池中存在小的已标记数据子集时,从该池中选择性地抽取查询。基于一些“信息含量测量”,所有的查询首先被排序,然后最好的一个被考虑。这是基于流的采样和基于池的采样(即个体查询和组查询)之间的主要区别。
你如何选择你的“信息含量测量”?
我们今天将讨论两种策略:
- 不确定性抽样—最小置信、熵、边际抽样
- 委员会质询
不确定抽样
在这种抽样策略中,学习者将查询那些标签最不确定的实例。这可以通过三种方式实现-
- 最不自信
查询预测可信度最低的数据点。这是通过计算数据点属于不同类别的概率并将它们从最不可能到最可能排序来完成的。最不可能是最不自信的。
- 边际抽样
通过使用最不自信策略,我们对其他标签的分布一无所知。因此,我们忽略了它们的信息量。因此,边缘采样通过考虑最可能标签和第二可能标签之间的差异来克服这一点。小的边距更加模糊,因此我们需要知道它们的真实标签。大幅度意味着我们几乎正确地预测了这些数据点的标签。
- 熵
熵描述了模型的不确定性。我们计算每个类的熵值。如果很高,很可能存在很多不确定性;一个数据点属于多个类别的概率是相等的,如果熵值较低,则这些点的分布具有相当大的确定性。对于我们的查询策略,我们将选择具有最高熵值的数据点。
委员会质询
有一个在带有不同训练实例的标记数据集上训练形成的模型委员会。每个委员会将为查询候选的标签投票。我们将选择所有委员会都无法达到固定多数的数据点。因此,信息最丰富的查询将是他们最不同意的查询。这是一个基于树的方法。
参考文献—
http://burrsettles.com/pub/settles.activelearning.pdf
让我们分析一下马德里的电动自行车共享站
BiciMAD 是西班牙首都的电动自行车共享服务,始于 2014 年,从 2016 年 5 月开始由马德里市政公司管理。
此分析的目的是了解网络中有多少站点,它们的容量有多大,以及网络的范围有多大。我还将尝试对马德里附近的每个电视台进行分类。
请注意,本文中讨论的数字、数据集、地图和 Python 笔记本可以在 GitHub 上找到(当然是免费的)。
资料组
马德里市政运输公司在马德里开放数据 EMT上以开放格式提供大量数据。该数据集仅限于 BiciMAD 服务,涉及 2018 年 7 月、8 月和 9 月的车站每小时情况以及 2017 年 4 月至 2018 年 9 月的个人租赁详情。由于这一分析涉及电台,最有趣的文件毫无疑问是第一批。
让我们下载situación estaciones bici mad por día y hora de September de 2018档案,了解我们有哪些数据。与自行车租赁相关的数据不同,没有指南解释这些字段以及数据在提取、保存和上传到网上之前是如何预处理的
该文件是包含单个 JSON 文件的 RAR 归档文件。文件的每一行都是一个单独的 JSON 文件实体,在第一层包含两个元素:日期-时间和一系列与该特定时间的站点状况相关的数据。
数据具有良好的详细程度(每小时一次),如果月份可用性涵盖的时间不仅仅是三个月,则可以进行更深入的分析。考虑到该市游客流量的季节性和马德里的大陆性气候,其特点是夏季高温,冬季低温,我认为这三个夏季月份对估计今年剩余时间没有意义。
在这方面,由于我们的目标是建立一个站的注册表,我考虑了可用的最新数据,即 2018 年 9 月文件的第一行,这是 2018–09–30t 23:42:38.647290”的情况
由于文件指的是 2018 年 9 月,所以总共算(30 * 24) -1 = 719 行。
乍一看,考虑到这项工作的目的和到目前为止所做的所有考虑,我们需要的数据(就列而言)明显少于 EMT 提供的数据。
按邻域分类
分析的第一步包括绘制每个 BiciMAD 站所属邻域的地图。这产生了一个副作用,即验证了所有站点的 GPS 坐标在地理上都在马德里大都市区域内。
实际上,有必要在经纬度坐标系中找到马德里街区及其边界的列表,使用可用数据构建多边形,并评估每个站点属于哪一个。
下载免费地理数据的顶级网站是什么?明明开街景图!
从这个表中,我可以找到用于标识西班牙城市中街区的标签,即 9,所以我从马德里数据生成了一个 GeoJSON 文件,其中 admin_level=9,boundary=administrative 。
至此,我已经定义了三个 Python 函数,它们可以生成多边形并验证每个站属于其中的一个。
数组([‘Centro ‘,’ Chamberí’,’ Moncloa-Aravaca ‘,’ Arganzuela ‘,’ Retiro ‘,’ Salamanca ‘,’ Tetuán ‘,’ Chamartín’],dtype=object)
这一阐述的结果被保存到这个 CSV 文件,它将对未来的应用有用。
碱基数量的评估
进行第二级分析时,考虑了每个站点的自行车底座数量,与我的预期相反,它们几乎由标准模块组成,事实上,数量总是在 18 到 30 之间。
由于很容易验证,在自行车流的特别重心点(例如靠近交通网络的其他节点)的情况下,管理 BiciMAD 自行车的公司已经设置了多个站点,而不是“在逻辑层”考虑具有更多基站的单个站点。
在这一点上,我还可以考虑网络可以支持的电动自行车的总数(这是考虑到每次用户应该有至少一个停放自行车的基地的总基地数),4095 个基地,并评估它们在各个社区的分布情况。
- 阿甘祖拉 342
- Centro 1380
- 沙玛丁 306
- 尚贝里 437
- 蒙克洛阿-阿拉瓦卡 243
- Retiro 550
- 萨拉曼卡 669
- 泰图安 168
不出所料,马德里中心附近包含了最多的座位。这是显而易见的,因为在这个地区,旅游流更加集中,此外,在这里,我们预计使用 BiciMAD 服务通勤上班的工人流。
制作比奇马德站的地图
作为一个“奖励”,我决定生成一个单独车站的地图,这有双重目的:提供一个简单的工具来查看车站未覆盖的马德里的任何区域,并为非马德里人提供他们位置的表示,以方便他们的生活,以防他们决定去西班牙首都并使用 BiciMAD 服务。
该地图是用 follow 模块生成的,可在这里获得。
让我们在 5 分钟内构建和部署 AutoML 解决方案
用于分类任务的全自动机器学习 API
实用的机器学习曾经很难——在一些专业领域仍然如此。普通的机器学习任务正变得越来越容易,并且在一定程度上实现了自动化。今天,我们将探索用 50 行代码创建和部署一个完全自动化的机器学习平台是多么容易。
在我们开始之前,让我先做一个大胆的免责声明。您将要看到的解决方案只适用于分类任务,尽管我们只需要对回归任务做一些小的改动。有些事情可以改进,比如日志记录,并且您可以自由地自己进一步处理代码。
此外,我们将把解决方案部署为 REST API。*为什么?*因为我们希望其他技术专家(非数据科学家)能够毫不费力地使用我们的 AutoML 工具。
下面是使用此解决方案的要求列表:
- 准备好的数据集 —数据集必须是机器学习就绪的格式,因此首先要做好适当的数据准备。我们的数据存储为 CSV 格式。
- 知道如何发出 POST 请求——要么通过像 Postman 这样的工具,要么通过任何一种编程语言(我们会谈到这一点)。
好了,事不宜迟,让我们开始吧!
数据集收集和准备
对于这个简单的例子,我们将使用虹膜数据集。数据集由各种花卉测量值和指示花卉种类的目标变量组成。
出于演示目的,这是一个完美的数据集,因为我们不想花太多时间清理数据。如果您正在跟进,请从提供的链接下载数据集,并将其存储在某个地方。我将它放在一个单独的文件夹中,Python 脚本最终将存储在这个文件夹中。
现在我们已经准备好了数据集,没有任何准备要求。现在让我们开始有趣的部分。
编写 AutoML 脚本
这就是乐趣的开始。在数据集所在的目录(希望是一个新的空目录)中,创建一个 Python 文件,并根据需要命名。我给我的取名为automl.py
。
在我们开始编码之前,我想提一下这个解决方案背后的逻辑是基于 PyCaret 库,特别是这篇文章。PyCaret 是一个了不起的机器学习库,你绝对应该了解更多。您可以从这里开始:
- PyCaret:用 Python 实现更好的机器学习
- 用 PyCaret 回归:一个更好的机器学习库
- 用 PyCaret 分类:一个更好的机器学习库
- PyCaret 2.0 已经发布,有什么新功能吗?
在automl.py
文件中,我们将导入熊猫库和 PyCaret 分类模块中的所有内容:
import pandas as pd
from pycaret.classification import *
接下来,我们将声明一个带有几个字段的AutoML
类:CSV 数据文件的路径、目标列名和我们想要优化的指标的名称(比如 accuracy、recall……)。我们还将声明一个自定义字段来存储关于最佳模型的信息:
class AutoML:
def __init__(*self*, *path_to_data*: str, *target_column*: str, *metric*):
*self*.df = pd.read_csv(path_to_data)
*self*.target_column = target_column
*self*.metric = metric
*self*.best_model = None
太好了!我们现在可以在__init__
下面声明一个处理所有机器学习逻辑的函数。我已经调用了我的fit()
,但如果你愿意,请随意更改它。该功能具有以下任务:
- 执行初始设置
- 找出最好的 5 种算法
- 调整这 5 个算法的超参数
- 进行装袋
- 执行混合
- 执行堆叠
- 为指定的指标找到最佳的整体模型
- 将模型保存到文件中
听起来要写很多逻辑,但它只有 10 行代码:
def fit(*self*):
clf = setup(*data*=*self*.df, *target*=*self*.target_column, *session_id*=42, *html*=False, *silent*=True, *verbose*=False) top5_models = compare_models(*n_select*=5) tuned_top5_models = [tune_model(model) for model in top5_models]
bagged_tuned_top5_models = [ensemble_model(model, *method*=’Bagging’) for model in tuned_top5_models] blended = blend_models(*estimator_list*=top5_models) stacked = stack_models(*estimator_list*=top5_models[1:], *meta_model*=top5_models[0]) best_model = automl(*optimize*=*self*.metric)
*self*.best_model = best_model save_model(best_model, ‘best_model’)
这就是这个文件。让我们继续进行 API 开发。
编写 REST API
我们已经讨论了机器学习部分,现在是时候让其他软件开发人员也能使用这个逻辑了。Python 让这一步变得非常简单,因为我们可以用像 Flask 这样的库轻松构建一个简单的 REST API。
在开始之前,创建一个名为app.py
的新 Python 文件。现在让我们将烧瓶连同automl.py
一起导入,并执行基本设置:
from flask import Flask, jsonify, request
from flask_restful import Api, Resource
from automl import AutoMLapp = Flask(__name__)
app.config[‘JSON_SORT_KEYS’] = False
api = Api(app)
太好了!我们现在准备好处理来自用户的请求。为此,我们将声明一个继承自flask_restful.Resource
的类。在内部,我们可以有各种方法,命名为 API 调用的类型。我们将我们的命名为post()
,因为我们将发出一个 POST 请求。
在这个方法中,我们需要捕获用户在调用时提供的 JSON 数据。metric
参数是可选的,如果没有指定,则设置为Accuracy
。记住,我们将把这些参数的值传递给AutoML
类的一个实例。
现在我们能够调用AutoML.fit()
方法并将结果返回给用户。下面是这个类的代码:
class Optimize(Resource):
@staticmethod
def post():
posted_data = request.get_json()
path_to_data = posted_data[‘path_to_data’]
target_column = posted_data[‘target_column’]
try: metric = posted_data[‘metric’]
except KeyError: metric = ‘Accuracy’ auto_ml = AutoML(*path_to_data*=path_to_data, *target_column*=target_column, *metric*=metric)
try:
auto_ml.fit()
return jsonify({ ‘Message’: ‘Success’, ‘BestModel’: str(auto_ml.best_model) })
except Exception as e:
return jsonify({ ‘Message’: str(e) })
最后,我们需要将我们的Optimize
类连接到某个实际的端点,并使app.py
可执行。方法如下:
api.add_resource(Optimize, ‘/optimize’)**if** __name__ **==** ‘__main__’:
app.run(*host***=**’0.0.0.0', *port***=**9000)
就是这样——这就是用于分类任务的全自动机器学习管道的全部代码!
以下是代码摘要,以防您在某处遇到困难:
正好 50 行代码
我们需要做的就是。让我们现在测试一下这个东西。
测试
我们可以使用像 Postman 这样的应用程序来测试我们的 API 是否工作正常。但是在此之前,我们需要运行app.py
文件。为此,打开终端/CMD 窗口并转到app.py
的位置。执行以下操作:
python app.py
您应该会看到弹出这样的内容:
我们现在可以打开 Postman ,将调用类型更改为 POST,输入 URL 和 JSON 参数及其各自的值:
即使对于这个简单的数据集,这个过程在我的机器上也需要大约 4 分钟,但这是训练和优化多个机器学习模型的代价。是的,一旦执行,你会得到最好的模型保存到你的电脑上,所以你可以马上做出新的预测。
差不多就是这样。让我们在下一部分总结一下。
在你走之前
如果你已经设法跟上了,就不要认为自己是机器学习专家。这篇文章不是为机器学习专家写的,而是为想要在项目中实现机器学习的普通软件开发人员写的。
我希望你看到完全自动化机器学习任务是多么容易。如果你需要更具体的东西,这可能对你来说还不够。对于大多数较简单的任务,这段代码将非常适合您。数据准备仍然是王道——所以这是你要花大部分时间的地方。机器学习很容易,至少对于大多数任务来说是如此。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
加入我的私人邮件列表,获取更多有用的见解。
让我们用简单的数字编码卷积神经网络
神经网络的奥秘
[## SkalskiP/ILearnDeepLearning.py
这个存储库包含与神经网络和深度学习相关的小项目。主题是紧密的…
github.com](https://github.com/SkalskiP/ILearnDeepLearning.py)
我们生活在一个迷人的时代,深度学习(DL)不断应用于我们生活的新领域,并经常给停滞不前的行业带来革命性的变化。与此同时,像 Keras 和 PyTorch 这样的开源框架让每个人都有机会使用最先进的工具和算法。这些库强大的社区和简单的 API 使尖端模型触手可及成为可能,即使没有使这一切成为可能的深入的数学知识。
然而,对神经网络[NN]内部发生的事情的理解对于架构选择、超参数调整或性能优化等任务非常有帮助。因为我相信没有什么比弄脏自己的手更能教会你的了,我将向你展示如何创建一个卷积神经网络[CNN],它能够对【MNIST】图像进行分类,准确率高达 90%,仅使用NumPy。
**注:**卷积神经网络是一种深度神经网络,最常用于分析图像。
本文主要面向对 DL 框架有一些经验的人。然而,如果你只是一个初学者——进入神经网络的世界——请不要害怕!这一次,我不打算分析任何数学方程式。老实说,我甚至不打算把它们写下来。而是尽量给大家一个直觉,在这些知名库的掩护下发生了什么。
**图一。**卷积神经网络架构
介绍
正如已经提到的,我们的主要目标是基于上图所示的架构构建一个 CNN,并在 MNIST 图像数据集上测试其功能。然而,这一次我们不会使用任何流行的 DL 框架。相反,我们将利用 NumPy——一个强大但低级的 Python 线性代数库。当然,这种方法将显著地使我们的工作复杂化,但是同时,它将允许我们理解在我们的模型的每个阶段正在发生什么。在此过程中,我们将创建一个包含所有必要层的简单库,因此您将能够继续尝试并解决其他分类问题。
**注意:**是一个手写数字的大型数据库,通常用作图像识别算法的基准。每张黑白照片都是 28x28 px。
数字图像、张量和形状
让我们停下来分析一下数字图像的结构,因为它会直接影响我们的设计决策。事实上,数码照片是巨大的数字矩阵。每个这样的数字代表单个像素的亮度。在 RGB 模型中,彩色图像由对应于三个颜色通道(红色、绿色和蓝色)的三个这样的矩阵组成。另一方面,要表现灰度图像——就像我们在 MNIST 数据集中看到的那样——我们只需要一个这样的矩阵。
****图二。数字图像背后的数据结构
在线性代数中,这些结构化的多维矩阵称为张量**。张量维度由它们的形状描述。例如,单个 MNIST 图像的形状是[28, 28, 1]
,其中连续的值表示高度、宽度和颜色通道的数量。**
顺序模型
顺序模型是一种连续层形成线性流的模型——第一层的结果用作第二层的输入,依此类推。模型在这个管弦乐队中充当指挥,负责控制各层之间的数据流。
****图 3。顺序模型数据流
有两种流量类型— 向前和向后。我们使用正向传播来基于已经积累的知识和作为输入X
提供的新数据进行预测**。另一方面,反向传播就是将我们的预测 **Y_hat**
与真实值 **Y**
进行比较,并得出结论。因此,我们网络的每一层都必须提供两个方法:forward_pass
和backward_pass
,这两个方法都可以被模型访问。一些层——密集层和卷积层——也将具有收集知识和学习的能力。它们保留自己的张量,称为权重,并在每个时期结束时更新它们。简单来说,模型训练的单个时期由三个元素组成:向前和向后传递以及权重更新。**
顺序模型—点击此处查看完整代码
盘旋
C onvolution 是一种操作,我们采用一个小的数字矩阵(称为内核或过滤器)并将其传递到我们的图像上,以根据过滤器值对其进行变换。将我们的内核放在一个选中的像素上后,我们从过滤器中取出每一个值,并与图像中相应的值成对相乘。最后,我们将所有内容相加,并将结果放在输出矩阵的正确位置。
****图 4。卷积层正向传递
很简单吧?对吗?嗯,通常情况下,事情会更复杂一点。为了加快计算速度,一个层通常一次处理多个图像。因此,我们传递一个形状为[n, h_in, w_in, c]
的四维张量作为输入。这里的n
对应于并行处理的图像数量,即所谓的批量**。其余的尺寸都很标准——宽度、高度和通道数量。**
****图 5。卷积超过体积
**此外,通常,输入张量可以有多个通道。上面,你可以看到一个对彩色图像执行卷积的层的例子。这个过程叫做体积卷积。**在这种情况下,最重要的规则是,滤镜和图像必须有相同数量的通道。我们的操作非常类似于标准卷积,但这次我们将三维张量中的数字对相乘。
**最后,为了使图层尽可能地通用,每个图层通常都包含多个滤镜。**我们分别对每个核进行卷积,将结果一个接一个地堆叠起来,然后将它们组合成一个整体。卷积层前向传递产生具有[n, h_out, w_out, n_f]
形状的四维张量,其中n_f
对应于在给定层中应用的滤波器的数量。让我们看看下面的图像,对这些维度有更多的直觉。
****图六。卷积张量形状
卷积层——点击此处查看完整代码
最大池化
**人们普遍认为,分辨率越高,照片质量越好。毕竟,图片中可见对象的平滑边缘会使整个场景对人眼更具吸引力。有趣的是,很多时候,更多的像素并不能转化为更详细的图像理解。看起来电脑根本不在乎。**存储这些冗余像素称为过表示。通常,即使张量体积的显著减少也不会影响实现的预测的质量。
****注:现在标准的智能手机摄像头能够产生 12Mpx 的图像。这样的图像由 3600 万个数字组成的共色张量来表示。
****池层的主要任务是减少我们张量的空间大小。我们这样做是为了限制需要训练的参数数量,从而缩短整个训练过程。这种效果是通过将张量分成几个部分,然后在每个部分分别应用我们选择的函数来实现的。该函数必须以这样一种方式定义,即对于每个部分,它都返回一个值。根据我们的选择,我们可以处理,例如,最大或平均池。
****图 7。最大池层
上面的可视化显示了一个简单的最大池操作。在正向传播过程中,我们迭代每个部分并找到它的最大值。我们复制这个数字并保存在输出中。同时,我们也记住了我们选择的数字的位置。因此,创建了两个张量,一个是输出,然后传递到下一层,另一个是掩膜,将在反向传播过程中使用。汇集层将张量从原始形状[n, h_in, w_in, c]
转换为[n, h_out, w_out, c]
。这里,h_in
和h_out
之间的比率由步幅和pool_size
超参数定义。
当通过池层反向传播时,我们从微分张量开始,并尝试扩展它的维度。首先,我们创建一个形状为[n, h_in, w_in, c]
的空张量并用零填充它。然后,使用缓存的掩膜张量将输入值重新定位到先前被最大数占据的位置。
最大池层—点击此处查看完整代码
拒绝传统社会的人
这是最流行的调整和防止神经网络过拟合的方法之一。这个想法很简单——辍学层的每个单元都被赋予了在训练中被暂时忽略的概率。然后,在每次迭代中,我们根据分配的概率随机选择我们丢弃的神经元。下面的可视化显示了一个遭受脱落的图层示例。我们可以看到,在每次迭代中,随机神经元是如何被去激活的。结果,权重矩阵中的值变得更加均匀分布。该模型平衡了风险,避免将所有筹码押在一个数字上。在推断过程中,dropout 层被关闭,因此我们可以访问所有参数。
****图 8。脱落层
****注意:当我们的模型过于接近有限的一组数据点时,就会发生过度拟合。给定一组新数据,像这样的模型将很难概括,而且很可能失败。
脱落层—点击此处查看完整代码
变平
这无疑是我们在旅途中实现的最简单的一层。然而,它在卷积层和密集连接层之间起着至关重要的连接作用。顾名思义,在正向传递过程中,它的任务是将输入扁平化,从多维张量变为向量。我们将在反向过程中反向执行此操作。
****图九。展平图层
展平图层——点击此处查看完整代码
激活
管理我们将使用的所有函数,有几个简单但强大的函数。激活函数可以用一行代码编写,但它们赋予了神经网络迫切需要的非线性和表达能力。如果没有激活,NN 将变成线性函数的组合,因此它本身就是一个线性函数。我们的模型表达能力有限,不超过逻辑回归。非线性元件允许学习过程中更大的灵活性和复杂函数的创建。
ReLU 层—点击此处查看完整代码
稠密的
与激活功能类似,密集层是深度学习的基础。您可以仅使用这两个组件创建全功能神经网络,就像您在下图中看到的那样。不幸的是,尽管有明显的通用性,但它们有一个相当大的缺点——计算量很大。每个致密层神经元都连接到前一层的每个单元。像这样的密集网络需要大量的可训练参数。这在处理图像时尤其成问题。
****图 10。密集连接的神经网络
幸运的是,这种层的实现非常容易。前向传递归结为将输入矩阵乘以权重并添加偏差——一行 NumPy 代码。权重矩阵的每个值代表图 10 中可见的网络神经元之间的一个箭头。反向传播稍微复杂一点,但仅仅是因为我们必须计算三个值:dA
—激活导数、dW
—权重导数和db
—偏差导数。正如所承诺的,我不打算在这篇文章中张贴数学公式。最重要的是,计算这些微分非常简单,不会给我们带来任何问题。如果你想挖得更深一点,并且不怕面对线性代数,我鼓励你阅读我的另一篇文章,在那里我详细解释了密集层向后传递的所有曲折。
****图 11。致密层
密集层——点击此处查看完整代码
结论
我希望我的文章拓宽了你的视野,增加了你对神经网络内部发生的数学运算的理解。我承认,通过准备这篇文章中使用的代码、注释和可视化,我学到了很多。如果你有任何问题,欢迎在文章下留言或通过社交媒体联系我。
这篇文章是“神经网络的奥秘”系列的另一部分,如果你还没有机会,请考虑阅读其他文章。此外,如果你喜欢我目前的工作,请在 Twitter 、 Medium 和 Kaggle 上关注我。看看我正在做的其他项目,比如make sense——小型计算机视觉项目的在线标记工具。最重要的是,保持好奇心!
让我们使用 React.js 创建一个新冠肺炎跟踪器
前端
照片由来自 Pexels 的 Markus Spiske 拍摄
因为封锁,现在世界上大多数人都呆在家里。你们大多数人都对长期呆在家里感到沮丧。因此,我们将制作一个新冠肺炎跟踪应用程序,并为我们创建一个跟踪应用程序而感到高兴。我们将从这个链接获取数据。
当我滚动 Youtube 视频时,我发现了一个关于如何制作 Corona 病毒跟踪应用程序的教程。我看了那个视频,开始创建一个新冠肺炎追踪器,最后,我使用 React.js 创建了一个追踪器。我添加了一些比视频中显示的更多的功能。这里我将描述如何从头开始使用 React 应用程序创建一个跟踪应用程序。这是 React 应用程序的演示。这是我在 Medium 的第 30 篇文章。
重要的事情,首先
像往常一样,我们需要使用 create-react-app 创建一个 React 应用程序。要创建 React 应用程序,请在您的 shell/终端中的特定文件夹(例如,桌面)中运行以下命令
npx create-react-app covid-tracker
将创建一个新文件夹,并将其命名为 google-map。从这一步开始,我们的应用程序用 Create React App 引导。有关更多信息,请单击链接。然后在 IDE 中打开该项目。我使用的是 VS 代码集成开发环境。
删除 src 文件夹中的所有文件,并在 src 文件夹中创建 app.js 文件和 index.js 文件。
现在,在我们的 src 文件夹目录中,我们用以下代码创建一个 index.js 文件:
然后在 src 文件夹中创建 api 文件夹、Components 文件夹和 images 文件夹。然后在组件文件夹中创建 Cards 文件夹、Chart 文件夹、CountryPicker 文件夹和 index.js 文件。现在我们项目的文件夹结构应该如下所示:
有了这个项目结构,每个文件夹(Cards、Chart、CountryPicker)都将有自己的风格和自己的组件。
现在,我们需要安装所有必要的依赖项,以便在与 VSCode 或 IDE 集成的 shell/终端中运行以下命令。
npm install --save axios react-chartjs-2 react-countup classnames @material-ui/core
如果您在安装依赖项时遇到问题,请尝试
npm cache clean — force
在 Axios 的帮助下,我们将向 API 发出 get 请求。react-chartjs-2 ‘是制作图表的较好的库之一。“反应-计数”将帮助我们在计数的同时制作动画。classnames’ 是一个在 React 中为我们提供条件类选择的库。“Material-UI”是世界上最流行的 React UI 框架,就像 bootstrap 一样。
照片由来自 Pexels 的安德里亚·皮亚卡迪奥拍摄
取数据
我们需要从 API 中获取数据。现在,在我们的 api 文件夹目录中,我们用以下代码创建一个 index.js 文件:
它加载负责 REST 调用的 Axios。如您所见,我们为 Chart、Cards 和 CountryPicker 打了 3 个不同的电话。
fetchData 函数用于根据全球或国家获取确认、恢复和死亡的详细信息,以及最后更新的时间。fetchData 函数帮助获取数据以在 Cards 组件中显示结果。
fetchDailyData 函数用于获取每日总死亡人数和总确认人数的详细信息以及相应的日期。不幸的是,我们现在无法获取全部恢复的详细信息(今天:2020 年 6 月 18 日)。fetchDailyData 函数帮助获取数据以在图表组件中显示结果。
fetchCountries 函数是将国家的简称与国家的名称进行映射。fetchCountries 函数帮助获取国家名称,以便在 CountryPicker 组件中显示结果。
卡片组件
这个组件加载 4 张卡片:感染,恢复,死亡,活跃在网站的顶部。现在,我们将使用以下代码在 Cards 文件夹中创建 Cards.jsx 文件:
Cards 组件是一个返回 JSX 的纯功能组件。我通过从确诊病例中减去痊愈病例和死亡病例来计算活跃病例。没有样式就没有创建 Cards 组件的意义,因此,我们将使用以下代码在 Cards 文件夹中创建 Cards.module.css 文件:
@media 标签负责响应视图。
是的,我们完成了卡片部分!!
由 Kaboompics 拍摄的照片。com 来自 Pexels
图表组件
这将加载条形图和折线图:折线图显示全球数据,而条形图代表单个国家。现在,我们将使用以下代码在 Chart 文件夹中创建 Chart.jsx 文件:
图表组件是一个返回 JSX 的纯函数组件。没有样式就没有创建图表组件的意义,因此,我们将使用以下代码在 Chart 文件夹中创建 Chart.module.css 文件:
CountryPicker 组件
下拉选择一个国家,基于所选国家显示一个条形图,并显示该特定国家的死亡、确认、活动和恢复详细信息的卡片。现在,我们将使用以下代码在 CountryPicker 文件夹中创建 CountryPicker.jsx 文件:
CountryPicker 组件是一个返回 JSX 的纯功能组件。没有样式就没有创建 CountryPicker 组件的意义,因此,我们将使用以下代码在 CountryPicker 文件夹中创建 CountryPicker.module.css 文件:
马丁·桑切斯在 Unsplash 上拍摄的照片
如果我们要在 App.js 中导入卡片、图表和 CountryPicker 组件,就像下面这样,只会使你的 App.js 变得混乱。
*import* Cards *from* "./Components/Cards/Cards";
*import* Chart *from* "./Components/Chart/Chart";
*import* CountryPicker *from* "./Components/CountryPicker/CountryPicker";
因此,我们需要使用一个简洁的小技巧。我们不需要像上面那样的进口。正如你所看到的,有很多重复的代码。我们花了很多时间来指定从哪里导入,从哪里导入。因此,我们可以有一个如下所示的导入文件。
*import* { Cards, Chart, CountryPicker } *from* “./Components”;
现在,我们将使用以下代码在 Components 文件夹中创建一个 index.js 文件:
应用程序组件
添加所有功能后,我们需要更新 App.js. App 组件负责将国家和数据一起发送到单个视图中,因此网站可以根据国家的选择动态改变是否显示条形图或折线图。现在,我们将以下代码添加到 src 文件夹中的 App.js 中。
在这里你可以下载日冕图像并将其添加到我们在 src 文件夹中创建的 images 文件夹中。App Component 是一个类组件,具有异步 React 生命周期方法 componentDidMount。我们需要给 App.js 组件添加一些样式。因此,我们需要使用以下代码将 App.module.css 文件添加到 src 文件夹中:
嘣!!!我们的新冠肺炎跟踪应用程序已经准备好了。通过运行以下命令启动应用程序
npm start
结论
上述网站的特点是易于使用,有吸引力的用户界面,图表比文本更有说服力,实时数据,最后但并非最不重要的是,它是一个桌面和移动视图的响应网站。新冠肺炎 API 将来自约翰·霍普斯金大学 CSSE 分校的数据作为 JSON API 提供。您可以从这个链接中克隆回购。最后,我要感谢 JavaScript Mastery 的 YouTube 视频。
今天尝试一些新的东西。自我感觉良好。
编码快乐!
让我们为交易创建一个技术指标。
如何开发自己的技术指标,如何回测。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
我刚刚出版了一本新书《Python 中的新技术指标》。它对复杂的交易策略进行了更完整的描述和补充,Github 页面致力于不断更新代码。如果你对此感兴趣,请随时访问下面的链接,或者如果你喜欢购买 PDF 版本,你可以在 Linkedin 上联系我。
亚马逊网站:交易策略之书(9798532885707): Kaabar,Sofien:书籍
www.amazon.com](https://www.amazon.com/gp/product/B09919GQ22/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=B09919GQ22&linkCode=as2&tag=sofien-20&linkId=bc5df3f6ab0f3af2df79641c56b949ba)*
技术指标就在我们身边。许多是著名的,如相对实力指数和 MACD,而其他人不太了解,如相对活力指数和凯尔特纳渠道。这些指标是为了帮助交易而开发的,有时它们在某些市场状态下很有用。例如,当市场波动时,RSI 运行良好。技术指标当然不是盈利交易策略的主角。
我们的目的是看看我们是否能想出一个技术指标的想法,如果可以,我们如何想出它的公式。斗争不会就此停止,我们还必须回溯测试它的有效性,毕竟,我们可以很容易地开发任何公式,并说我们有一个指标,然后将其作为圣杯进行销售。
我们将尝试将新指标的回溯测试结果与 RSI 的结果进行比较,从而给出我们工作的相对视图。如果你想在开始之前看到更多与 RSI 相关的交易策略,这里有一篇文章从一个不同的有趣的角度展示了它:
* [## 使用 RSI 和布林线创建交易策略。使用 Python 的新想法。
绝大多数交易者使用著名的相对强弱指数来帮助他们做决定,虽然它…
medium.com](https://medium.com/swlh/creating-a-trading-strategy-using-the-rsi-the-bollinger-bands-new-ideas-using-python-4115e1fdfbba)
头脑风暴&形成想法
创建指标的第一步是选择指标类型。是趋势跟踪指标吗?可能是逆势?它与时机或波动性有关吗?会是有界还是无限?
为了简化我们的信号生成过程,假设我们将选择一个反向指标。这意味着我们将尝试创建一个围绕循环值振荡的指标,该指标要么是稳定的,要么是几乎稳定的(尽管这个术语在统计学中不存在)。我最喜欢的方法之一是从取不同的值开始。这是向平稳性和了解随时间变化幅度的一个巨大飞跃。但是,为了使事情更有趣,我们不会从上一个值中减去当前值。由于我是斐波那契数列的粉丝,我们用当前值(即今天的收盘价或这个小时的收盘价)减去 8 个周期前的值怎么样?因此,该指标的第一步是一个简单的分布,可以用 delta(δ)作为分布的数学定义如下:
下一步可以结合权重调整或增加波动性指标,如平均真实范围或历史标准差。让我们坚持简单的方法,选择用我们的价差除以价格的滚动 8 期标准差。这给出了一个关于我们试图测量的动量力的波动调整。因此,我们将对收盘价进行滚动标准差计算;这将作为我们公式中的分母。记住,我们说过我们会用滚动标准差来除价差。让我们更新我们的数学公式。已知标准差的等式如下:
我们可以把 X 看作是我们目前得到的结果(正在构建的指标)。结果是价差除以标准差,如下所示:
现在要做的最后一件事是选择是否平滑我们的价值观。有时,我们可以从某些计算中得到波动和极端的值。幸运的是,我们可以使用移动平均来平滑这些值。因为我们想保持一致,我们做一个到目前为止的 8 期滚动平均值怎么样?这意味着我们将简单地计算 x 的移动平均值。
有关移动平均线的更多信息,请参考这篇展示如何对其进行编码的文章:
用 Python 编写不同类型的移动平均线。
towardsdatascience.com](/how-to-code-different-types-of-moving-averages-in-python-4f8ed6d2416f)
现在,我们可以说我们已经有了一个可以被可视化、解释和回溯测试的指标。在此之前,假设我们有一个 OHLC 数组,让我们看看如何用 python 编写这个指示器。
for i in range(len(Asset)): # Calculating the spread
Asset[i, 4] = Asset[i, 3] - Asset[i - 8, 3] # Calculating the Standard Deviation
Asset[i, 5] = Asset[i - 8:i + 1, 3].std() # Volatility Adjustment of the spread
Asset[i, 6] = Asset[i, 4] / Asset[i, 5] # Smoothing out and getting the indicator's values
Asset[i, 7] = Asset[i - 7:i + 1, 6].mean()
可视化指标
视觉解读是良好指标的首要关键要素之一。下面是我们的指标和一些外汇对的对比。
该指标相对于欧元兑美元、瑞士法郎、GBPUSD 和澳元兑美元。
看起来我们可能能够获得 2.5 和-2.5 附近的信号(可以与 RSI 上的 70 和 30 水平相比)。因此,交易条件将是:
- 当指标达到-2.5 时买入。
- 当指标触及 2.5 时,卖出(做空)。
- 尽管我们不会回测这个技术,但是看起来散度方法对这个指标也有效。
现在,在所有的透明度,**这篇文章不是关于提出一个创新的新的盈利指标。**这只是一种思考和创建指标的教育方式。
在我们进行回溯测试之前,还有最后一件事。我们把这个指标命名为?我总是想给它起一个很酷的名字,比如旋风或地狱犬、,但我相信如果我们根据它的功能来命名,它会看起来更专业。因此,在最终平滑结果之前,该指标采用除以滚动标准差的差值。因此,一个合理的名称可以是波动调整动量指标(VAMI)。
回溯测试和比较
是时候找出我们所创造的真相了。回溯测试确保我们在正确的轨道上。为了比较,我们还将回测 RSI 的标准策略(触及 30 或 70 水平是否可以提供反转点或修正点)。请注意,两种策略的持有期都是 6 个周期。
触发表。
以下是在执行回测后给出的一些信号图示例。注意,绿色箭头是买入信号,而红色箭头是做空(卖出)信号。
VAMI 战略信号图。左边是澳元,右边是欧元兑美元。
RSI 策略的信号图。左边是澳元,右边是欧元兑美元。
10 种主要货币对的 VAMI 策略权益曲线。
10 种主要货币对的 RSI 策略的权益曲线。
从视觉上看,VAMI 优于 RSI,虽然这是个好消息,但这并不意味着 VAMI 是一个很好的指标,它只是意味着 RSI 在单独使用时一直让我们失望,然而,VAMI 似乎在澳元和欧元对上做得很好。下面详细介绍了绩效指标以及 RSI 策略中的绩效指标(更多详细信息,请参见本文开头的链接)。
两种策略的性能比较。
如果你也对更多的技术指标和使用 Python 创建策略感兴趣,那么我关于技术指标的畅销书可能会让你感兴趣:
亚马逊网站:Python 中的新技术指标:9798711128861: Kaabar,Sofien 先生:书籍
www.amazon.com](https://www.amazon.com/gp/product/B08WZL1PNL/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=B08WZL1PNL&linkCode=as2&tag=sofien-20&linkId=e3cb9716bb6a07cf6c8b9fb585412b07)
另外,期望值是一个灵活的衡量标准,由平均赢/输和命中率组成。它提供了按命中率加权的美元数字的预期利润或损失。胜率就是我们在下面的公式中提到的命中率,通过它,损失率就是 1——命中率。
结论
为什么写这篇文章?如上所述,这不是为了找到一个有利可图的技术指标,也不是为了向公众展示一个新的技术指标。这是一个相当简单的方法,可以考虑在某一天创建一个可以为你的整体框架增值的指标。在我们的例子中,我们发现 VAMI 比 RSI 表现得更好,并且具有大约相同数量的信号。这个指标显然值得尝试优化。创造了 VAMI 之后,我相信我会在未来对如何提取更好的信号做更多的研究。
https://pix abay . com/photos/chart-trading-forex-analysis-840331/*
让我们部署一个机器学习模型
如何在生产中使用机器学习模型
数据科学太酷了,不能留在笔记本里。我们需要某种方法使模型对 web 应用程序有用,但是我们如何做到这一点呢?今天我们将训练一个简单的机器学习模型,并用 Flask 进行部署,然后用 Python 的请求库进行预测。
在 Unsplash 上paweczerwiński拍摄的照片
如果你更喜欢视频,或者只是想巩固你的知识,请随意观看我们关于这个主题的视频。源代码包含在内:
*我为什么要关心部署?*好问题。让我用另一个问题来回答它:如果你不打算使用它,你的模型的目的是什么?或者至少让别人用?想不出任何理由?很好,我也是。
什么是烧瓶? Flask 是一个开发 web 应用的微框架。我们不会为此使用它,但是我们将使用 Flask-RESTful 来公开我们模型的某些功能。
好吧,但是什么是请求呢?这只是另一个与 REST APIs 通信的简单库。
呃,什么是 REST API?REST 或表述性状态转移——无论哪个对您来说更自然——是一组用于创建 web 服务的样式和约束。一旦 Restful API 上线,我们就可以用特定的参数向特定的端点发出请求——这就是你现在应该知道的。这样做将执行一些后端逻辑——在我们的例子中是进行预测。
下面是目录结构(可以随意调整):
根目录叫做 mldeploy ,里面我们多了两个文件夹: modeler 和 models 。第一个包含 modeler.py 文件(Python 创建了另外两个),后者将包含一个保存的模型,一旦我们完成训练。
最后, app.py 将所有的东西绑在一起,并使用 Flask 和 Flask-RESTful 来暴露预测部分。
现在让我们做一个愚蠢的简单分类器。
制作分类器
我们将使用著名的虹膜数据集 ,因为对于这个例子,我们不能不关心任务的机器学习部分。我们只对模型如何部署感兴趣,而不是如何构建。
以下是进口货:
import os
import joblib
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
Joblib 可能是这里唯一的未知数。简而言之,我们可以用它来保存和加载机器学习模型。
接下来,我们编写了一个用于模型加载、训练、保存和预测的类。这里不涉及数据准备,所以一切都归结为几行代码:
class Modeler:
def __init__(self):
self.df = pd.read_csv(‘https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv')
try: self.model = joblib.load(‘models/iris.model’)
except: self.model = None def fit(self):
X = self.df.drop(‘species’, axis=1)
y = self.df[‘species’]
self.model = DecisionTreeClassifier().fit(X, y)
joblib.dump(self.model, ‘models/iris.model’) def predict(self, measurement):
if not os.path.isfile(‘models/iris.model’):
raise Exception(‘Model not trained yet. Call .fit() before making predictions.’)
if len(measurement) != 4:
raise Exception(f’Expected sepal_length, sepal_width, petal_length, petal_width, got {measurement}’) prediction = self.model.predict([measurement])
return prediction[0]
以上就是 modeler.py 的全部内容。我们将在下一节开发 API 本身。
REST API
我们现在可以开始部署部分了。让我们打开 app.py ,执行几个导入操作:
import os
import joblib
from flask import Flask, jsonify, request
from flask_restful import Api, Resource
from modeler.modeler import Modeler
我们还将在这里使用 Joblib ,但是这次是为了加载训练好的模型。在底部,我们正在导入之前编写的 Modeler 类。现在让我们做一些烧瓶内务处理:
app = Flask(__name__)
api = Api(app)
Flask-RESTful 的构造方式是每个端点都应该在自己的类中。在内部,我们声明了与最终用户发出的请求类型相对应的函数——最流行的是 GET 和 POST。
本例中使用了 POST,一旦发出请求,我们将获取用户提供的数据。需要 4 个值:萼片长度、萼片宽度、花瓣长度和花瓣宽度,对应于我们数据集的特征。
然后创建一个 Modeler 类的实例,用提到的输入数据调用 predict() 函数。最后,返回预测的 JSON 表示。
*听起来很简单吧?*因为是。代码如下:
class Predict(Resource):
@staticmethod
def post():
data = request.get_json()
sepal_length = data[‘sepal_length’]
sepal_width = data[‘sepal_width’]
petal_length = data[‘petal_length’]
petal_width = data[‘petal_width’] m = Modeler()
if not os.path.isfile(‘models/iris.model’):
m.fit() prediction = m.predict([sepal_length, sepal_width, petal_length, petal_width]) return jsonify({
‘Input’: {
‘SepalLength’: sepal_width,
‘SepalWidth’: sepal_width,
‘PetalLength’: petal_length,
‘PetalWidth’: petal_width
},
‘Class’: prediction
})
现在我们需要做更多的 Flask 内务处理,这实际上是将 Predict 类连接到一个端点——应该由 /predict 来完成:
api.add_resource(Predict, ‘/predict’)
代码方面的最后一件事是使 app.py 可执行:
if __name__ == ‘__main__’:
app.run(debug=True)
接下来,我们可以测试是否一切都像宣传的那样工作。
做预测
先运行 app.py 吧。在“终端”中打开根文件夹,然后键入:
python3 app.py
或者,如果您使用的是 Windows,则不带“3 ”:
API 现在运行在 http://127.0.0.1:5000/上。为了测试它是否正常工作,我们将使用笔记本——它们比代码编辑器更具交互性。
我们需要请求库:
import requests
从这里我们可以向 /predict 端点发出 POST 请求,请求值为萼片长度、萼片宽度、花瓣长度、和花瓣宽度。这很容易做到:
res = requests.post(
url=’[http://localhost:5000/predict'](http://localhost:5000/predict'),
json={
‘sepal_length’: 5.0,
‘sepal_width’: 3.2,
‘petal_length’: 1.5,
‘petal_width’: 0.3
}
)
酷毙了。我们可以检查 res 变量中的内容:
res**>>> <Response [200]>**
状态代码 200 表示一切正常,我们准备好提取预测了。对 res.json() 的调用完成了这个任务:
res.json()**>>> {‘Class’: ‘setosa’,
‘Input’: {‘PetalLength’: 1.5,
‘PetalWidth’: 0.3,
‘SepalLength’: 3.2,
‘SepalWidth’: 3.2}}**
就是这样!你必须承认——这比你想象的要容易。
最后的话
现在你知道如何采用任何机器学习模型并部署它。当然,我们在本地主机上做了所有的事情,但是在您的生产环境中,唯一会改变的主要部分是 URL。
所以它不会是http://127 . 0 . 0 . 1:5000/predict,而是类似于http://your _ URL:port/predict。
这个模型现在已经可以在某种应用程序中使用了,希望通过一个漂亮的 GUI。比留在笔记本里好多了。
感谢阅读。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
让我们用经典方法来预测你的时间序列
时间数列预测法
14 种经典预测技术及其在 Python 中的实现
背景
在我之前的文章中,我们学习了各种数据准备技术,还建立了一个健壮的 T2 评估框架。现在,我们准备探索不同的预测技术。
随着许多机器学习模型的出现,我们经常会忘记经典算法的强大功能。从经典方法开始是一个好主意。即使经典的方法集中在线性关系上,假设数据是适当准备的,它们在广泛的问题上表现良好。
下面是本文将要讨论的技术列表。我们还将讨论它们的 Python 实现。
1。单变量时间序列预测 1.1。自回归
1.2。移动平均线
1.3。自回归移动平均线
1.4。自回归综合移动平均线
1.5。季节性自回归综合移动平均线
2。多元时间序列预测 2.1。向量自动回归
2.2。向量移动平均线
2.3。向量自动回归移动平均
3。3.1 具有外生变量的时间序列预测 。萨里玛与外生变量
3.2。向量自回归移动平均与外生回归
4。用平滑技术进行时间序列预测 4.1。移动平均平滑
4.2。单一指数平滑
4.3。双指数平滑
4.4。三重指数平滑
单变量时间序列预测
这些数据集每次只观察到一个变量,例如每小时的温度。单变量时间序列被建模为其滞后的线性组合。也就是说,序列的过去值用于预测当前和未来。
自回归(AR)
自回归基于输入变量的线性组合(前一时间步的值)对输出(下一步的值)进行建模。例如,在线性回归中,y-hat 是预测值, β ₀和 β ₁是模型根据训练数据计算的系数,x 是输入值。
同样,在时间序列中,给定当前和先前时间步的观测值,我们可以预测下一个时间步的值。
p’是自回归趋势参数,p 的理想值可以从自相关图中确定。
该方法适用于没有趋势和季节成分的时间序列。
Python 实现— AR
# Import libraries
from statsmodels.tsa.ar_model import AutoReg
from random import random
# Generate a sample dataset
data = [x + random() for x in range(1, 100)]
# fit model
model = AutoReg(data, lags=1)
model_fit = model.fit()
# make prediction
yhat = model_fit.predict(len(data), len(data))
print(yhat)
移动平均线
观察值和预测值之间的差异称为残差。这些来自时间序列预测的误差提供了另一个我们可以建模的信息来源。其计算方法如下:
residual error = observed — predicted
因此,移动平均法也被称为残差模型,这种方法将序列中的下一步建模为残差的线性函数。您可以在下面的等式中观察到这种差异。
q '是移动平均趋势参数,q 的理想值可以从部分自相关图中确定。
该方法适用于没有趋势和季节成分的时间序列。
Python 实现—马
# Import libraries
from statsmodels.tsa.arima_model import ARMA
from random import random
# Generate a sample dataset
data = [x + random() for x in range(1, 100)]
# fit model
model = ARMA(data, order=(0, 1))
model_fit = model.fit(disp=False)
# make prediction
yhat = model_fit.predict(len(data), len(data))
print(yhat)
自回归移动平均(ARMA)
自回归移动平均(ARMA)方法使用上述信息(原始观测值和残差)进行预测,这是对单个 AR 和 MA 模型的改进。
因此,该方法将序列中的下一步建模为前一时间步的观测值和残差的线性函数。
建模者必须为模型的两个组件指定参数 p 和 q,即自回归(AR)和移动平均(MA)。
该方法适用于没有趋势和季节成分的时间序列。
Python 实现— ARMA
# Import libraries
from statsmodels.tsa.arima_model import ARMA
from random import random
# Generate a sample dataset
data = [random() for x in range(1, 100)]
# fit model
model = ARMA(data, order=(2, 1))
model_fit = model.fit(disp=False)
# make prediction
yhat = model_fit.predict(len(data), len(data))
print(yhat)
自回归综合移动平均(ARIMA)
到目前为止,我们讨论的统计模型假设时间序列是平稳的,但实际上,大多数时间序列都不是平稳的,即序列的统计特性(如均值、方差)会随时间而变化。
因此,我们可以增加一个步骤作为预处理步骤,即差分(‘d’)时间序列,使其平稳。
现在,我们有一种方法,它结合了自回归(AR)和移动平均(MA)模型以及序列的差分预处理步骤,使序列平稳,称为积分(I)。
因此,我们需要找出我们正在处理的时间序列是否是平稳的。我们可以通过观察时间序列图中的季节性和趋势,检查不同时期的均值和方差的差异,以及增强的 Dickey-Fuller (ADF)检验来诊断平稳性。你可以在我以前的文章“为时间序列预测建立基础”中找到这些技术的细节。
该方法适用于有趋势且无季节性成分的时间序列。
Python 实现— ARIMA
# Import libraries
from statsmodels.tsa.arima_model import ARIMA
from random import random
# Generate a sample dataset
data = [x + random() for x in range(1, 100)]
# fit model
model = ARIMA(data, order=(1, 1, 1))
model_fit = model.fit(disp=False)
# make prediction
yhat = model_fit.predict(len(data), len(data), typ='levels')
print(yhat)
季节性自回归综合移动平均线
该方法是 ARIMA 模型处理季节性数据的扩展。它分别对该系列的季节性和非季节性部分进行建模。
除了 ARIMA 方法中使用的三个趋势相关参数之外,还有四个其他季节性参数添加到该方法中。
非季节性参数与 ARIMA 相同
p:自回归阶
d:差分阶
q:移动平均阶
季节参数
p:季节自回归阶
D:季节差分阶
Q:季节移动平均阶
m:单个季节周期的时间步数
该方法适用于具有趋势和/或季节成分的时间序列。
Python 实现— SARIMA
# Import libraries
from statsmodels.tsa.statespace.sarimax import SARIMAX
from random import random
# Generate a sample dataset
data = [x + random() for x in range(1, 100)]
# fit model
model = SARIMAX(data, order=(1, 1, 1), seasonal_order=(1, 1, 1, 1))
model_fit = model.fit(disp=False)
# make prediction
yhat = model_fit.predict(len(data), len(data))
print(yhat)
多元时间序列预测
这些数据集每次观察两个或多个变量。在多元时间序列中,每个变量被建模为其自身的过去值和系统中其他变量的过去值的线性组合**。**
向量自回归
它是自回归模型的推广,用于预测多个平行平稳时间序列。它包括系统中每个变量的一个方程。每个方程的右边包括一个常数和系统中所有变量的滞后。
使用 VAR 进行预测时,我们需要做出两个决定,即系统中应该包含多少变量(K)和多少滞后§。
VAR 中待估计的系数数量等于 K+pK(或每个方程 1+pK)。例如,对于具有 K=5 个变量和 p=2 个滞后的 VAR,每个方程有 11 个系数,总共有 55 个系数要估计。需要估计的系数越多,估计误差越大。
因此,建议保持 K 值较小,并且只包含彼此相关的变量,因此在预测彼此时很有用。信息标准通常用于选择要包含的滞后数§。
Python 实现— VAR
# Import libraries
from statsmodels.tsa.vector_ar.var_model import VAR
from random import random
# Generate a sample dataset with correlated variables
data = list()
for i in range(100):
v1 = i + random()
v2 = v1 + random()
row = [v1, v2]
data.append(row)
# fit model
model = VAR(data)
model_fit = model.fit()
# make prediction
yhat = model_fit.forecast(model_fit.y, steps=1)
print(yhat)
VAR 也可以使用 Statsmodels 中的 VARMAX 函数实现,该函数允许通过 order 参数估计 VAR、VMA、VARMA 和 VARMAX 模型。
向量移动平均(VMA)
它是移动平均模型的推广,用于预测多个平行平稳时间序列。
Python 实现— VMA
# Import libraries
from statsmodels.tsa.statespace.varmax import VARMAX
from random import random
# Generate a sample dataset with correlated variables
data = list()
for i in range(100):
v1 = i+ random()
v2 = v1 + random()
row = [v1, v2]
data.append(row)
# fit VMA model by setting the ‘p’ parameter as 0.
model = VARMAX(data, order=(0, 1))
model_fit = model.fit(disp=False)
# make prediction
yhat = model_fit.forecast()
print(yhat)
向量自回归移动平均(VARMA)
它结合了 VAR 和 VMA 模型以及广义的 ARMA 模型来预测多个平行的平稳时间序列。
这种方法需要“p”和“q”参数,并且通过将“q”参数设置为 0 也能够像 VAR 模型一样工作,并且通过将“p”参数设置为 0 也能够像 VMA 模型一样工作。
Python 实现— VARMA
# Import libraries
from statsmodels.tsa.statespace.varmax import VARMAX
from random import random
# Generate a sample dataset with correlated variables
data = list()
for i in range(100):
v1 = random()
v2 = v1 + random()
row = [v1, v2]
data.append(row)
# fit model
model = VARMAX(data, order=(1, 1))
model_fit = model.fit(disp=False)
# make prediction
yhat = model_fit.forecast()
print(yhat)
具有外生变量的时间序列预测
具有外生变量的 SARIMA(SARIMAX)
带有外生变量的季节性自回归综合移动平均(SARIMAX)是 SARIMA 模型的扩展,它也包括外生变量的建模。
在继续之前,让我们了解内生和外生变量。
外生变量是其值在模型之外确定并强加于模型的变量。这里,X 是一个外生变量
一个内生变量是一个其值由模型决定的变量。这里,要预测的主要序列是一个内生变量。
在时间序列中,外生变量是一个平行的时间序列,不直接建模,但用作模型的加权输入。
该方法适用于具有趋势和/或季节成分以及外生变量的单变量时间序列。
Python 实现— SARIMAX
# Import libraries
from statsmodels.tsa.statespace.sarimax import SARIMAX
from random import random
# Generate a sample dataset with independent exogenous variable
data1 = [x + random() for x in range(1, 100)]
data2 = [x + random() for x in range(101, 200)]
# fit model
model = SARIMAX(data1, exog=data2, order=(1, 1, 1), seasonal_order=(0, 0, 0, 0))
model_fit = model.fit(disp=False)
# make prediction
exog2 = [200 + random()]
yhat = model_fit.predict(len(data1), len(data1), exog=[exog2])
print(yhat)
SARIMAX 方法也可用于通过包含外生变量对其他外生变量进行建模,如 ARX、最大值、ARMAX 和 ARIMAX。
带外生回归量的向量自回归移动平均(VARMAX)
这种方法是 VARMA 模型的扩展,也包括外生变量的建模。它是 ARMAX 方法的多元版本。
该方法适用于无趋势的多元时间序列和有外生变量的季节成分。
Python 实现— VARMAX
# Import libraries
from statsmodels.tsa.statespace.varmax import VARMAX
from random import random
# Generate a sample dataset with correlated multiple time series and an independent exogenous variable
data = list()
for i in range(100):
v1 = random()
v2 = v1 + random()
row = [v1, v2]
data.append(row)
data_exog = [x + random() for x in range(100)]
# fit model
model = VARMAX(data, exog=data_exog, order=(1, 1))
model_fit = model.fit(disp=False)
# make prediction
data_exog2 = [[100]]
yhat = model_fit.forecast(exog=data_exog2)
print(yhat)
滑动平均平滑的时间序列预测
移动平均平滑是时间序列预测中一种简单而有效的方法。与我们开始讨论的移动平均线模型同名,但有很大不同。早期版本的移动平均(MA)是一种残差模型,而这种平滑技术包括对连续时段窗口内的值进行平均。
一般来说,有两种类型的移动平均线被使用:
居中移动平均线
时间(t)时的值计算为时间(t)前后电流的平均值。例如,窗口宽度为 3:
centered_ma(t) = mean(obs(t+1), obs(t), obs(t-1))
中心移动平均线需要未来值的可用性,我们经常发现这种方法不适合用于预测。
移动平均线
时间(t)时的值计算为时间(t)前电流的平均值。例如,窗口宽度为 3:
trail_ma(t) = mean(obs(t), obs(t-1), obs(t-2))
跟踪移动平均线仅使用当前和历史观察值来预测未来。
这种方法主要用于特征工程,也可用于预测。我们可以使用新创建的“移动平均值”系列,通过一个简单的模型来预测下一步。在预测之前,我们假设时间序列的趋势和季节性成分已经被去除或调整。
这种方法没有可用的 python 函数,相反,我们可以创建一个自定义函数,您可以参考我以前的文章中的朴素模型实现。
指数平滑时间序列预测
指数平滑是一种单变量数据的时间序列预测方法。它是流行的博克斯-詹金斯 ARIMA 类方法的近似替代方法。
这两种方法都预测过去观测值的加权和,这里有一个重要的区别需要注意。
ARIMA 家族开发了一种模型,其中预测是最近的过去观察值或滞后值的加权线性和,而指数平滑明确地使用过去观察值的指数递减权重。
单指数平滑
这种方法也称为简单指数平滑法,适用于没有明确趋势或季节模式的预测数据。数学上,
其中,α是介于 0 和 1 之间的平滑参数。较大的值意味着模型重视最近的观察,而较小的值意味着最早的观察更重要。
Python 实现— SES
# Import libraries
from statsmodels.tsa.holtwinters import SimpleExpSmoothing
from random import random
# Generate a sample dataset
data = [x + random() for x in range(1, 100)]
# fit model
model = SimpleExpSmoothing(data)
model_fit = model.fit()
# make prediction
yhat = model_fit.predict(len(data), len(data))
print(yhat)
双指数平滑
双指数平滑法是上述方法(SES)的扩展,这种方法允许用趋势预测数据。数学上,
除了 alpha、 a 平滑因子之外,还添加了一个额外的平滑因子来控制趋势变化影响的衰减,称为 beta。
这些方法往往会过度预测,尤其是对于较长的预测范围。受这一观察结果的激励,Gardner & McKenzie (1985)引入了一个参数,该参数在未来某个时候将趋势“抑制”到一条平坦的线。
因此,结合平滑参数α和β(值在 0 和 1 之间),该方法还包括范围也在 0 和 1 之间的阻尼参数ϕ。
Python 实现—双指数平滑
# Import libraries
from statsmodels.tsa.holtwinters import ExponentialSmoothing
from random import random
# Generate a sample dataset
data = [x + random() for x in range(1, 100)]
# fit model
model = ExponentialSmoothing(data,trend='add', seasonal=None, damped=True)
model_fit = model.fit()
# make prediction
yhat = model_fit.predict(len(data), len(data))
print(yhat)
三重指数平滑
三重指数平滑是该系列中最高级的变化,这种方法也被称为霍尔特-温特斯指数平滑,以该方法的两位贡献者命名:查尔斯·霍尔特和彼得·温特斯。
除了 alpha 和 beta 平滑因子之外,还添加了一个名为 gamma ( g )的新参数,用于控制对季节性成分的影响。
加法和乘法霍尔特-温特斯方法都可以产生阻尼。一种经常为季节性数据提供准确可靠预测的方法。
Python 实现—霍尔特-温特斯指数平滑
# Import libraries
from statsmodels.tsa.holtwinters import ExponentialSmoothing
from random import random
# Generate a sample dataset
data = [x + random() for x in range(1, 100)]
# fit model
model = ExponentialSmoothing(data,trend="add", seasonal="add", seasonal_periods=12, damped=True)
model_fit = model.fit()
# make prediction
yhat = model_fit.predict(len(data), len(data))
print(yhat)
摘要
在本文中,您发现了所有重要的经典预测技术,这些技术可以帮助您开始解决预测问题。您可以深入研究合适的技术,并根据需要进一步调整。要构建一个健壮的预测模型,您必须从执行正确的数据转换开始,建立一个评估策略,并准备好一个持久性(基准)模型。
感谢阅读!请随时分享任何意见或反馈。
希望这篇文章对您有所帮助,在接下来的几篇文章中,我将详细讨论一些常用的技术。
参考
[1] Galit Shmueli 和 Kenneth Lichtendahl,实用时间序列预测与 R:实践指南,2016 年。
[2]杰森·布朗利,https://machinelearningmastery.com/
[4]https://www . stats models . org/stable/user-guide . html #时序分析
让我们开始艺术吧!用神经网络创建自定义 Snapchat 过滤器!
利昂·a·盖茨比神经风格迁移初探
普里西拉·杜·普里兹在 Unsplash 上的照片
和很多人一样,我可以强烈地说,拍照不是我的强项。我学会了变得更好,并养成了一种像《我是如何遇见你母亲》中的巴尼那样的半笑。最近,我想努力变得更上镜,所以我通过我的社交媒体搜索,看看别人是如何做到的。然后我突然想到,这些照片中的大多数都经过了某种过滤,主要来自 Snapchat。这让我困惑了一段时间,直到我亲自尝试。这些滤镜又古怪又愚蠢,而且确实让我在镜头前看起来更好看!
那时我就在想,“如果我们能自己制作过滤器会怎么样”?经过一些研究,我了解到 Snapchat 从许多计算机视觉技术中创建了这些增强现实过滤器。最后,经过几个小时的研究,我发现了一篇有趣的论文,名为“艺术风格的神经算法”,作者是里昂·A·盖茨比(Leon A. Gatsy)及其同事。他们使用神经网络从一张照片和一件艺术品中创建一个“风格化的图像”。然后,在突然意识到之后,我想探索一下我们是否可以使用这种技术来创建自定义过滤器,就像 Snap chat 上的过滤器一样。这是我用 Python 实现它的旅程!
附注:这种技术已经成为研究的热门话题好几年了,有许多很好的在线资源和视频很好地解释了这些概念。本文主要是尽我所能提供这种技术的高层次概述。好吧,让我们开始吧!
神经类型转移:算法
那么这个算法想要完成什么呢?本质上,我们希望产生一个图像,类似于我们的内容图像(我们希望风格化的图像),具有我们的风格图像的艺术风格。
图宾根斯纳卡前线梵高《星夜》风格转移的一个例子(图片来源
在最初的论文中,他首先使用 VGG19 模型来实现这个结果。VGG19 是一种流行的图像识别神经网络,但我们主要关注它如何从照片中提取特征。特征提取是通过可以检测小图案的多个连续层来完成的。它最初拾取的要素非常简单,但随着更多要素图层的添加而变得更加复杂。然后,我们可以使用这些功能,重新创建我们的原始图像!
内容损失
在这一步中,我们希望或多或少地重新创建我们内容图像的本质。为了实现这一点,我们将首先创建一个充满随机噪声的图像。然后,我们将使用从我们的网络中提取的特征作为指导,将这个图像塑造成看起来像我们的内容图像。随机图像特征和内容特征之间的距离被称为我们的“内容损失”。为了获得最佳的风格化图像,我们希望通过反向传播来最小化这个损失函数。我们将最终循环这整个事情,并优化每一步,以获得一个很好的重建我们的形象。
for i in range(1,epochs+1):target_features = model_activations(target,model)content_loss = torch.mean((content_features['conv4_2']-target_features['conv4_2'])**2)
风格丧失
格拉姆矩阵方程(图像来源
在这一步,我们要重新创建我们的风格形象的核心艺术方向。盖茨比用一种有趣的方式解决了这个问题!我们不是将我们的风格特征与另一个图像进行比较,而是将每个特征图与其自身进行比较。我们首先将样式特征转换成一个 gram 矩阵,它基本上是一个矩阵的内积。“风格损失”基本上是模型网络中所有特征地图损失的总和。我们将做一个类似的循环过程,并优化每一步。
style_loss = 0for layer in style_wt_meas:style_gram = style_grams[layer]target_gram = target_features[layer]_,d,w,h = target_gram.shapetarget_gram = gram_matrix(target_gram)style_loss += (style_wt_meas[layer]*torch.mean((target_gram-style_gram)**2))/d*w*h
我们在这个过程中的最后一步是计算我们的最终损失,作为我们的内容损失和风格损失的加权和。我们还将在训练循环的每一步优化这种损失。
total_loss = content_wt*content_loss + style_wt*style_loss
问题和未来工作
盖茨比风格转换法是此类方法中的首创,但也存在一些问题。主要的问题是它非常慢。这是因为由于优化是在训练循环中的每个周期进行的,所以算法需要一些时间来产生任何东西。其次,有时改变权重会大大破坏照片的稳定性。有一个修复方法是添加一个总损失变量,该变量与内容和样式图像的均值和方差对齐。根据我的研究,看起来神经风格转移仍然是一个热门话题,应用程序被应用于视频处理、模拟和设计。
我在 Youtube 上使用 Ayush Chaurasia: 艺术神经风格转移从零开始来创建代码。就像我在本文开头提到的,你可以在网上找到很多很好的资源。如果你想开始解决计算机视觉问题,我认为构建神经风格转换应用程序会非常有趣和令人兴奋!所以我希望这有所帮助,如果你想继续下去,我祝你好运!
感谢阅读!
这里有一些我拍摄的很酷的结果,我迫不及待地想看看你会创造出什么!
金门大桥上的红云
卡丁斯基论大海龟
米开朗基罗在你的真实(我)上的绘画(风格来源:照片由阿德里安娜·吉奥在 Unsplash 上拍摄)
完整的代码可以在我的 Google Colab 上找到:
Snapchat 应用
colab.research.google.com](https://colab.research.google.com/drive/1iUdLwtgV5cJZefR1j09PtpAYpcWxfZ1e)
您可以查看我的 GitHub 获取更多资源!
GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码、管理项目和构建…
github.com](https://github.com/MehrabiHasan/Snapchat-App)
参考
- 【https://www.youtube.com/watch?v=K_xBhp1YsrE
- https://www.youtube.com/watch?v=c3kL9yFGUOY
- https://towards data science . com/breaking-down-Leon-gatys-neural-style-transfer-in-py torch-fa F9 f 0 EB 79 db
- https://arxiv.org/abs/1703.06868
- https://arxiv.org/abs/1603.08155
- https://arxiv.org/abs/1508.06576
- https://github.com/reiinakano
让我们从 MongoDB 开始吧
如何设置 MongoDB Atlas,Compass 和 PyMongo
米卡·鲍梅斯特在 Unsplash 上的照片
介绍
MongoDB 是一个非常流行的非关系数据库应用程序。世界上许多主要的开发商和公司(EA,Google,威瑞森,Adobe 等。)使用 MongoDB 作为一种存储形式,因为它具有高可用性、可伸缩性、容错性、敏捷性和灵活性。
MongoDB 是一个文档数据库。这意味着它不是在数据框中存储传统的表和数据行,而是存储类似 JSON/dictionary 的对象。这使得它非常强大和灵活,因为您可以在文档中存储文档,并且您的文档不需要有固定/一致的格式。
从 MongoDB 获得的一个文档截图
MongoDB 为我们提供了非常强大的查询语言。在我看来,它和 MYSQL 一样简单,查询非常直观。更重要的是,MongoDB 为我们所有人提供了一个免费的云存储层。
本文的目的不是解释 MongoDB 提供的每一个方法。这是为了让您开始使用 MongoDB。因此,我强烈建议您访问文档。我将解释一些更重要的功能。
在本系列结束时,您应该:
- 设置您的云存储
- 将您的数据放在云端
- 能够处理所述数据
- 能够使用 MongoDB 的 GUICompass分析数据。
说够了,我们开始吧!
安装和设置
您需要设置 3 个主要区域。
MongoDB 地图集
MongoDB Atlas 是 MongoDB 完全托管的云数据库。您将需要设置它来将您的数据存储在云中。别担心,这是免费的。
- 参观https://www.mongodb.com/cloud/atlas
- 点击“免费开始”并创建一个帐户
- 创建一个空闲集群
创建一个集群
4.将所有内容保留为默认值,并将集群名称更改为任何名称。对于本文,我将把它命名为“mflix”
更改集群名称并创建集群
5.在左下角,注意它是免费的。这样,您可以单击“创建集群”
6.白名单 IP 地址。MongoDB 允许特定的网络和计算机访问您的数据库。
切换到网络访问
允许所有人访问
7.添加用户。MongoDB 使我们能够为特定用户提供访问权限。我们将需要设置一个用户,有数据库访问您的数据库。对于本文,我将用户名设置为“analytics”,密码设置为“analytics-pw”。你可以随意改变它,但你必须记住它。此外,将权限更改为“Atlas Admin”。
切换到数据库访问
键入您的凭证,更改权限并添加用户
您的云存储现在已经准备就绪!
MongoDB 服务器
我们将下载企业版。您可以将所有内容设置为默认值并完成安装。这也将为我们安装 Compass,一个 MongoDB GUI。
如果你想在命令提示符下使用mongo
命令,记得用设置你的环境变量。要设置的路径应该在这里:C:\ProgramFiles\MongoDB\Server\4.2\bin\
成功后,您应该能够实现以下目标:
确保 Mongo 正在命令提示符下工作
Jupyter 笔记本
我们将使用 Python 的库 PyMongo 与我们的数据库进行交互。
使用以下命令下载 PyMongo:
pip install pymongo dnspython
将数据导入云中
我们将使用的数据是 mflix,它包含关于电影的信息。
有一些术语你必须知道:
- 集合是数据表。
- 文档是数据行。
- 在 MongoDB 中,客户端由数据库组成。数据库由集合组成。集合由文档组成。
使用 mongoimport 手动导入数据
首先,在这里下载 movies_initial.zip ,由 Gratiaa 提供。提取 CSV 文件并将其放在您的桌面上。
接下来,我们需要一串标识符来标识我们的数据库。按照下面的截图获取您的字符串。
切换到命令行工具
获取您的网络字符串
现在,打开命令提示符,将目录切换到桌面(或数据所在的任何位置)。在替换字符串、用户名和密码时,键入以下命令。
mongoimport --type csv --headerline --db mflix --collection movies_initial --host "mflix-shard-0/mflix-shard-00-00-b23yi.mongodb.net:27017,mflix-shard-00-01-b23yi.mongodb.net:27017,mflix-shard-00-02-b23yi.mongodb.net:27017" --authenticationDatabase admin --ssl --username analytics --password analytics-pw --file movies_initial.csv
以下是其中一些的含义:
mongoimport
是将数据导入 Atlas 集群的命令--type csv
表示这是一个 CSV 文件--headerline
表示您的 CSV 文件行是文件头-- db mflix
表示我们正在写入的数据库是 mflix--collection
表示我们正在写入的集合是 movies_initial--host "<STRING>"
表示到我们数据库的路线。用上面复制的字符串替换它--username analytics --password analytics-pw
表示您的用户账户。替换为您的用户名和密码--file movies_initial.csv
表示数据的文件名。确保您的数据与您的命令提示符位于同一路径
数据上传!
使用 Compass 手动导入数据
或者,您也可以使用 Compass 导入数据。当你打开指南针时,你会看到这样一句话:
使用 Compass 连接到您的数据库
要查找连接字符串,请执行以下操作:
连接
连接应用程序
获取连接字符串
复制上面截图中的字符串。但是,您不需要整个字符串。您只需要:
mongodb+srv://<username>:<password>[@mflix](http://twitter.com/mflix)-b23yi.mongodb.net
穿过绳子进入你的指南针,你将能够像这样连接:
单击创建数据库,继续导入 CSV
只需按照图形用户界面导入您的数据!
导入样本数据
MongoDB 好心的给我们提供了样本数据。我们全部导入吧!
加载样本数据集
数据约为 350MB,需要几分钟时间才能导入集群。
体系结构
在上面的架构中,我们的数据存储在 MongoDB 集群中。在空闲层中,我们有 3 个节点。这意味着您的数据在 3 个不同的节点上复制了 3 次。每当主节点出现故障时,两个节点中的另一个将逐步成为主节点,为您提供数据。这也称为容错,即在一个节点出现故障的情况下,您的数据不会消失。
您可以使用 Compass 和 PyMongo 与数据进行交互。Compass 是一个 GUI,PyMongo 是一个库/框架,允许您使用 Python 语法在 MongoDB 上工作。
结论
恭喜你!现在,您已经成功地设置了 MongoDB 集群,导入了数据,并且现在能够使用 Compass 查看您的数据了。在本文的第二部分,我将深入研究 PyMongo 的 CRUD 操作的基础知识。本质上,您将学习如何插入、读取、操作和删除数据库中的数据。在那之前,注意安全!
参考
- https://www.coursera.org/learn/introduction-mongodb
- https://docs.mongodb.com/
让我们对摘要文本给予一些“关注”…
使用 LSTM 编解码器模型的文本摘要。
罗曼·维涅斯在 Unsplash 上的照片
文本摘要是自然语言处理领域中最具挑战性和最有趣的问题之一。这是一个从多种文本资源(如书籍、新闻文章、博客帖子、研究论文、电子邮件和推文)中生成简明而有意义的文本摘要的过程。现在,随着大量文本语料库的可用性,摘要是一项更加重要的任务。
那么有哪些不同的方法呢?
摘录摘要
这些方法依赖于从一段文本中提取几个部分,如短语和句子,并将它们堆叠在一起以创建摘要。因此,识别用于摘要的正确句子在抽取方法中是至关重要的。我们用一个例子来理解这个。
正文: 梅西和 c 罗的战绩都比他们的同行好。在所有比赛中表现出色。他们被认为是我们这一代中的佼佼者。
摘录总结: 梅西和 c 罗的战绩都比同行好。我们这一代最好的。
正如你在上面看到的,粗体字已经被提取出来并连接在一起形成了一个摘要——尽管有时候这个摘要在语法上很奇怪。
抽象概括
这些方法使用先进的 NLP 技术来生成全新的摘要。本摘要的某些部分甚至可能不会出现在原文中。我们用一个例子来理解这个。
正文: 梅西和 c 罗的战绩都比同行好。在所有比赛中表现出色。他们被认为是我们这一代中的佼佼者。
抽象总结: 梅西和 c 罗的战绩都比同行好,所以被认为是我们这一代的佼佼者。
抽象文本摘要算法创建新的短语和句子,从原始文本中传递最有用的信息——就像人类一样。
在本文中,我们将关注抽象概括技术,并且我们将使用编码器-解码器架构来解决这个问题。
什么是编码器-解码器架构?
常用的序列对序列模型(编码器-解码器)的总体结构如下所示
基本的编码器-解码器架构
该模型由三部分组成:En 编码器、中间向量和解码器。
En 编码器
- 编码器基本上由一系列 LSTM/GRU 单元组成(请阅读 LSTM / GRU 文档以更好地理解该架构)。
- 编码器接收输入序列,并将信息封装为内部状态向量。
- 解码器使用编码器的输出和内部状态。
- 在我们的文本摘要问题中,输入序列是来自文本的所有单词的集合,需要对其进行摘要。每个单词表示为 x_i ,其中 i 是该单词的顺序。
中间(编码器)向量
- 这是从模型的编码器部分产生的最终隐藏状态。它是用上面的公式计算的。
- 该向量旨在封装所有输入元素的信息,以帮助解码器做出准确的预测。
- 它充当模型解码器部分的初始隐藏状态。
解码器
- 几个循环单元的堆栈,每个循环单元在时间步长 t 预测一个输出 y_t 。
- 每个递归单元接受来自前一个单元的隐藏状态,并产生和输出它自己的隐藏状态。
- 在摘要问题中,输出序列是来自摘要文本的所有单词的集合。每个单词都表示为 y_i ,其中 i 是该单词的顺序。
- 任何隐藏状态 h_i 都是使用以下公式计算的:
如你所见,我们只是使用前一个隐藏状态来计算下一个。
- 使用以下公式计算时间步长 t 的输出 y_t :
我们使用当前时间步长的隐藏状态以及相应的权重 W(S)来计算输出。 Softmax 用于创建一个概率向量,该向量将帮助我们确定最终输出(如问答问题中的单词)。
请注意:
首先,我们需要明白什么是注意力。
在时间步长 t 生成一个单词,我们需要对输入序列中的每一个单词投入多大的注意力?这是注意力机制概念背后的关键直觉。
让我们用一个简单的例子来理解这一点:
问题:近十年来, 谁是最好的足球运动员 ?
回答 : 梅西 是最好的 球员 。
在上面的例子中,问题中的第五个字与谁相关莱昂内尔 梅西和第九个字足球运动员与第六个字球员相关。
因此,我们可以增加源序列中产生目标序列的特定部分的重要性,而不是查看源序列中的所有单词。这是注意力机制背后的基本思想。
根据所关注的上下文向量的导出方式,存在 2 种不同类别的注意机制:
全球关注
这里,注意力放在所有的源位置上。换句话说,编码器的所有隐藏状态都被考虑用于导出关注上下文向量。在这个总结任务中,我们将使用全球注意力。
当地的关注
这里,注意力仅放在几个源位置上。仅考虑编码器的几个隐藏状态来导出关注上下文向量。
现在让我们了解这种注意力到底是如何运作的:
- 编码器输出源序列中每个时间步长 j 的隐藏状态( hj
- 类似地,解码器输出目标序列中每个时间步长 i 的隐藏状态( si
- 我们计算一个称为对齐分数(eij )的分数,基于该分数,使用分数函数将源单词与目标单词对齐。使用 score 函数从源隐藏状态 hj 和目标隐藏状态 si 计算校准分数。这由下式给出:
eij=得分(si,hj )
其中 eij 表示目标时间步长 i 和源时间步长j的对齐分数
- 我们使用 softmax 函数归一化比对分数,以检索注意力权重( aij ):
- 我们计算关注权重 aij 和编码器隐藏状态 hj 的乘积的线性和,以产生关注上下文向量( Ci ):
- 关注的上下文向量和解码器在时间步 i 的目标隐藏状态被连接以产生关注的隐藏向量 **Si,**其中,Si=连接(【Si;Ci])
- 然后将关注的隐向量 Si 送入稠密层,产生 yi, yi=稠密(Si)。
让我们借助一个例子来理解以上的注意机制步骤。考虑源文本序列为[x1,x2,x3,x4],目标摘要序列为[y1,y2]。
- 编码器读取整个源序列,并输出每个时间步长的隐藏状态,比如说 h1、h2、h3、h4
- 解码器读取偏移了一个时间步长的整个目标序列,并输出每个时间步长的隐藏状态,例如 s1、s2、s3
目标时间步长 i=1
- 使用 score 函数从源隐藏状态 hi 和目标隐藏状态 s1 计算校准分数 e1j :
e11= score(s1, h1)
e12= score(s1, h2)
e13= score(s1, h3)
e14= score(s1, h4)
- 使用 softmax 标准化比对分数 e1j 产生注意力权重 a1j :
a11= exp(e11)/((exp(e11)+exp(e12)+exp(e13)+exp(e14))
a12= exp(e12)/(exp(e11)+exp(e12)+exp(e13)+exp(e14))
a13= exp(e13)/(exp(e11)+exp(e12)+exp(e13)+exp(e14))
a14= exp(e14)/(exp(e11)+exp(e12)+exp(e13)+exp(e14))
- 参与上下文向量 C1 由编码器隐藏状态 hj 和对齐分数 a1j 的乘积的线性和得到:
C1= h1 * a11 + h2 * a12 + h3 * a13 + h4 * a14
- 关联上下文向量 C1 和目标隐藏状态 s1 被连接以产生关联隐藏向量 S1
S1= concatenate([s1; C1])
- 注意力隐藏向量 S1 然后被送入密集层产生 y1
y1= dense(S1)
同样,我们可以计算 Y2。
Keras 没有提供注意力层,所以我们可以自己写或者使用别人提供的注意力层。这里我们使用这个实现关注层。
实施时间:
这个汇总任务的全部代码可以在这里找到。
显示数据:
我们将在本文中使用亚马逊食品评论数据集。让我们看一下数据的快照:
数据集的快照。
清理数据:
我们首先需要清理我们的数据,因此我们需要遵循的步骤是:
- 将所有内容转换为小写
- 删除 HTML 标签
- 收缩映射
- 移除(’ s)
- 删除括号( )内的任何文本
- 消除标点符号和特殊字符
- 删除停用词。
- 删除短词
数据的分布:
然后,我们将分析评论和摘要的长度,从而对文章 t 长度的分布有一个总体的了解。这将帮助我们确定序列的最大长度。
x 轴:字数,Y 轴:句子数量。
将数据标记化:
记号赋予器构建词汇表并将单词序列转换成整数序列。我们将使用 Keras 的分词器对句子进行分词。
模型构建:
我们终于进入了模型构建阶段。但在此之前,我们需要熟悉一些术语,这些术语是构建模型之前所必需的。
- Return Sequences = True: 当 Return Sequences 参数设置为 True 时,LSTM 为每个时间步长产生隐藏状态和单元格状态
- **返回状态=真:**当返回状态= 真时,LSTM 只产生最后一个时间步长的隐藏状态和单元格状态
- **初始状态:**用于初始化第一个时间步长的 LSTM 内部状态
- 堆叠的 LSTM: 堆叠的 LSTM 有多层 LSTM 堆叠在一起。这导致序列的更好的表示。我鼓励你尝试将 LSTM 的多层叠加在一起(这是学习的好方法)。
模型总结。
训练和提前停止:
这是在训练期间损失是如何减少的,我们可以推断在纪元 10 之后验证损失略有增加。因此,我们将在这个时代之后停止训练模型。
培训和测试损失
推论:
现在,我们将为编码器和解码器设置推理。这里编码器和解码器将一起工作,产生一个摘要。解码器将被堆叠在编码器之上,解码器的输出将再次被馈送到解码器以产生下一个字。
测试:
在这里,最后,我们可以用我们的定制输入来测试我们的模型。
**Review**: right quantity japanese green tea able either drink one sitting save later tastes great sweet
**Original summary:** great japanese product
**Predicted summary:** great tea**Review:** love body wash smells nice works great feels great skin add fact subscribe save deal great value sold
**Original summary:** great product and value
**Predicted summary:** great product**Review**: look like picture include items pictured buy gift recipient disappointed
**Original summary:** very disappointed
**Predicted summary:** not what expected
这是这篇文章的笔记本。
包装它
在本文中,我们已经看到了如何使用序列到序列模型来总结文本。我们可以通过增加数据集,使用双向 LSTM ,使用波束搜索策略等来进一步改进这个模型。
在我们的下一个故事中,我们将看到如何用迁移学习来实现它。我们将使用预训练的 GloVe 单词嵌入,并观察我们的模型如何表现,以及它是否能够通过预训练的嵌入更好地理解语义。在那里见。
参考
- https://www . analyticsvidhya . com/blog/2019/06/comprehensive-guide-text-summary-using-deep-learning-python/
- https://blog . keras . io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras . html
- 【https://www.kaggle.com/snap/amazon-fine-food-reviews
让我们用 SQL 估算缺失值
易于理解的自动化脚本来完成工作。
缺失值是机器学习中的一个巨大问题。在机器学习可以直接在数据库中完成的时代,人们想知道如何在没有其他编程语言(如 Python 和 r)的情况下使用 SQL 进行充分的数据准备。今天我们将看到它是多么简单。
出于本文的目的,我们将使用 Oracle Cloud ,因为它是免费的,无需在您的机器上进行任何下载和安装即可使用——通过 SQL Developer Web 。如果您决定跟随,创建一个免费的 OLTP 数据库,并转到服务控制台—开发— SQL Developer Web 。
关于数据集,我们将使用众所周知的 Titanic 数据集,原因有二:
- 这很简单,很容易理解
- 它包含了足够的缺失值供我们使用
一旦您下载了数据集,您就可以使用 SQL Developer Web 的上传数据功能来创建表并上传数据:
使用您的最佳判断更改数据类型,您已经准备好了!
准备和探索
我不想把源表搞乱,这个表叫做titanic
,所以我们复制一个:
CREATE TABLE cp_titanic AS
SELECT * FROM titanic;
让我们快速选择一下,确认一切正常:
SELECT * FROM cp_titanic;
厉害!如果您对这个数据集做过任何工作,您就会知道Age
列是最容易出现缺失值的列。让我们检查一下有多少:
SELECT COUNT(*) AS num_age_missing
FROM cp_titanic
WHERE age IS NULL;
如果我们考虑到数据集少于 1000 行,这就很多了。因此,我们需要找出如何填充这些缺失的值,并以一种简单和自动化的方式来完成。
插补时间
为了处理缺失数据插补,我们将创建一个PL/SQL
程序。如果你不知道那是什么,不要担心,因为跟随它会非常简单。在我们用代码做任何事情之前,让我们列出这个过程应该做的事情:
- 获得一个用于插补的值(平均值/中值/众数将在这个简单的例子中起作用)
- 对表进行更新-用计算值替换空值
太好了!这应该不难做到。我们还将接受用户的一些输入,更准确地说是 3 个参数:
- 表名 —缺失数据所在的表的文本表示
- 属性 —包含缺失值的列
- 估算方法——估算的一种方式——均值、中值或众数
这就是我们要开始学习的全部内容。让我们用目前已知的信息创建一个过程:
CREATE OR REPLACE PROCEDURE impute_missing(
in_table_name IN VARCHAR2,
in_attribute IN VARCHAR2,
in_impute_method IN VARCHAR2 DEFAULT ‘mean’
) IS
BEGIN
END;
/
厉害!在关键字IS
下面,我们将声明一些其他变量——用于保存将要使用的估算函数、获取平均值的语句、平均值本身以及更新语句。我们的过程现在看起来如下:
CREATE OR REPLACE PROCEDURE impute_missing(
in_table_name IN VARCHAR2,
in_attribute IN VARCHAR2,
in_impute_method IN VARCHAR2 DEFAULT ‘mean’
) IS
impute_func VARCHAR2(16);
get_avg_stmt VARCHAR2(128);
avg_value NUMBER;
update_stmt VARCHAR2(128);
BEGIN
END;
/
剩余的代码将位于关键字BEGIN
和END
之间。
估算方法
如前所述,我们的程序可以通过使用均值、中值或众数统计函数来处理缺失值插补。同样,这些是用户可以为in_impute_method
参数提供的值。
唯一的问题是——这些统计函数在 SQL 中的调用有点不同。我们可以使用CASE
操作符来处理这个问题,并将结果存储到impute_func
变量中。代码如下:
CASE in_impute_method
WHEN ‘mean’ THEN impute_func := ‘AVG’;
WHEN ‘median’ THEN impute_func := ‘MEDIAN’;
WHEN ‘mode’ THEN impute_func := ‘STATS_MODE’;
ELSE RAISE_APPLICATION_ERROR(-20001, ‘Invalid impute method!’);
END CASE;
那并不难,是吗?
我们差不多完成了一半,接下来的部分也很简单。
获取平均值
为了得到平均值,我们将不得不使用一个叫做动态 SQL 的东西。这意味着我们不会硬编码 SQL 语句,而是根据提供的用户输入来创建语句。
让我们看看如何创建一个动态查询来获取平均值,关于用户输入的参数(表名、属性和估算方法):
get_avg_stmt **:=** q’[SELECT ]’
**||** impute_func
**||** q’[(]’
**||** in_attribute
**||** q’[) FROM ]’
**||** in_table_name;DBMS_OUTPUT.PUT_LINE(‘get_avg_stmt = ‘ **||** get_avg_stmt);
它可能看起来和感觉起来有点奇怪,直到你习惯了这一点,但你以后会看到这一切归结为什么。这个DBMS_OUTPUT
行不是必需的,但是一旦我们运行这个过程,它会将get_avg_stmt
输出到控制台。
但是这还不够,因为我们仍然需要执行这条语句并将其结果存储在avg_value
变量中。这很容易做到:
BEGIN
EXECUTE IMMEDIATE get_avg_stmt INTO avg_value;
END;DBMS_OUTPUT.PUT_LINE(‘avg_value = ‘ || avg_value);
这一部分已经完成,现在我们应该以某种方式对表进行更新,以实际填充缺失的值。让我们看看怎么做。
归罪
如果你已经理解了前一部分,你就会理解这一部分。同样,我们需要动态创建一个 SQL 语句并执行它。唯一的区别是这次结果不会存储在变量中,因为这对一个UPDATE
语句没有意义。相反,该表被就地修改:
update_stmt :=
q’[UPDATE ]’
|| in_table_name
|| q’[ SET ]’
|| in_attribute
|| q’[ = ]’
|| avg_value
|| q’[ WHERE ]’
|| in_attribute
|| q’[ IS NULL]’;DBMS_OUTPUT.PUT_LINE(‘update_stmt = ‘ || update_stmt);BEGIN
EXECUTE IMMEDIATE update_stmt;
END;COMMIT;
这里唯一的新东西是COMMIT
关键字。它用于结束当前事务并使所有更改永久化。如果你不确定哪些语句必须提交,这里有一个解释。不客气
基本上就是这样,我们已经做了我们该做的一切。
概述
以下是整个过程,以防你遗漏了什么:
CREATE OR REPLACE PROCEDURE impute_missing(
in_table_name IN VARCHAR2,
in_attribute IN VARCHAR2,
in_impute_method IN VARCHAR2 DEFAULT ‘mean’
) IS
impute_func VARCHAR2(16);
get_avg_stmt VARCHAR2(128);
avg_value NUMBER;
update_stmt VARCHAR2(128);
BEGIN
CASE in_impute_method
WHEN ‘mean’ THEN impute_func := ‘AVG’;
WHEN ‘median’ THEN impute_func := ‘MEDIAN’;
WHEN ‘mode’ THEN impute_func := ‘STATS_MODE’;
ELSE RAISE_APPLICATION_ERROR(-20001, ‘Invalid impute method!’);
END CASE; get_avg_stmt **:=** q’[SELECT ]’
**||** impute_func
**||** q’[(]’
**||** in_attribute
**||** q’[) FROM ]’
**||** in_table_name;
DBMS_OUTPUT.PUT_LINE(‘get_avg_stmt = ‘ **||** get_avg_stmt); BEGIN EXECUTE IMMEDIATE get_avg_stmt INTO avg_value;
END;
DBMS_OUTPUT.PUT_LINE(‘avg_value = ‘ || avg_value); update_stmt :=
q’[UPDATE ]’
|| in_table_name
|| q’[ SET ]’
|| in_attribute
|| q’[ = ]’
|| avg_value
|| q’[ WHERE ]’
|| in_attribute
|| q’[ IS NULL]’;
DBMS_OUTPUT.PUT_LINE(‘update_stmt = ‘ || update_stmt); BEGIN EXECUTE IMMEDIATE update_stmt;
END;
COMMIT;END;
/
现在,让我们来测试一下!
测试
我们已经完成了所有的艰苦工作,现在我们可以测试是否一切都像宣传的那样工作。为此,我们将使用age
列的中值来估算其缺失值。方法如下:
BEGIN
impute_missing(‘cp_titanic’, ‘age’, ‘median’);
END;
/
就是这样!如果我们执行这段代码,我们将得到一些控制台输出,这是由于过程中的所有DBMS_OUTPUT
调用:
厉害!如果我们再次检查缺失值的数量,我们可以看到一切都按预期进行了:
SELECT COUNT(*) AS num_age_missing
FROM cp_titanic
WHERE age IS NULL;
有哪些可以改进的地方?
我们的程序完成了工作,但这并不意味着它不能进一步改进。这里有几个想法:
- 舍入结果——在几乎任何情况下调用
AVG
都会产生大量的小数点 - 用户可以选择输入插补值,而不是使用平均值/中值/众数
这不是一个明确的列表,所以你可以根据自己的需要随意修改程序。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
让我们从头开始制作一个 KNN 分类器
你只需要一点钱和一点时间。包括源代码。
从头开始编写整个机器的算法可能是一个乏味的过程。这就是为什么我们有图书馆。另一个原因是,如果我们没有投入足够的时间和精力,我们自己的实现很可能无法与来自 Scikit-Learn 的现成解决方案竞争。
然而,这并不意味着你不应该从头开始编写算法。以下是这样做的一些好处:
- 你已经完成了对代码的控制
- 你将把你对算法的理解提升到一个全新的水平
今天,我想向你展示用 NumPy 库编写一个简单的 K 最近邻算法是多么容易。当然,它不会是最先进的,会有很多东西需要优化,但这是一个好的开始。在这篇文章的结尾,我希望你能感觉到你已经发明了它。
如果你不想自己写代码,这里有 GitHub repo 。
事不宜迟,我们开始吧。你唯一需要的库是 Numpy (暂时是*)所以确保导入它。*
什么是 KNN?
KNN 代表 K-最近邻。这基本上是一种分类算法,它将根据定义的最近邻数量来预测目标变量的类别。它将计算从您要分类的实例到训练数据集的每个实例的距离,然后根据 k 个最近实例的大多数类别对您的实例进行分类。
如果你是第一次阅读这篇文章,这听起来可能会令人困惑,但它实际上是一个非常简单的算法。
由于有大量的理论解释,我决定不再深入研究,而是把时间集中在实现方面。然而,如果你缺乏理论背景,请随意参考这篇文章(或任何你在网上找到的其他文章):
大家好!今天我想谈谈 K-最近邻算法(或 KNN)。KNN 算法是一种…
blog.usejournal.com](https://blog.usejournal.com/a-quick-introduction-to-k-nearest-neighbors-algorithm-62214cea29c7)*
两个向量之间的距离
你可以把数据集中的行和 X 看作向量。有了这个想法,你可能知道有很多方法可以测量向量之间的距离。我脑海中闪现的一些想法是:
- 欧几里得距离
- 余弦距离
在本文中,我将把注意力集中在第一个方面,我们将从头开始编写代码。简单来说,欧氏距离就是欧氏空间中两个数据点之间的一个直线距离[1]。它可以计算如下:
这真的是一个简单的公式,你不必事先知道维数。让我们用 Python 来编码:
这就是全部了!
现在让我们做两个快速检查:
- 在相同的向量上(距离应为 0 )
- 在不同的向量上(距离不应为 0 )
算法实现
好了,前面的部分显然是工作的,现在是时候编码出算法的核心了。我将声明一个函数predict()
,它将接受 3 个参数:
k
:k 的值train_set
:带有目标变量的整个矩阵test_instance
:没有目标变量值的单个矢量
以下是所需的步骤:
- 计算
test_instance
和train_set
每行之间的欧氏距离 - 按距离值对距离进行排序,从最低到最高
- 保持
k
最小的距离 - 获取距离最小的
k
train_set
行的目标变量值 - 无论哪个目标变量类占多数,都将获胜
正如我所说的,这个算法非常简单,编码出来应该不成问题。为了方便起见,我对每一行代码都做了注释,这样你就不会迷路了:
我知道要写相当多的代码,但这是值得的。
现在,如果我们不能以某种方式评估这个算法,那么实现这个算法就毫无意义。这就是为什么我决定实现一个基本的准确性报告功能,它将报告算法在测试集上的表现如何:
让我们组成一个班级
如果你问我,我认为一切看起来比它应该的更乱。这主要是因为我们到处都有函数。因此,让我们通过将所有这些函数放在一个名为KNearestNeighbors
的类中来解决这个问题。你需要做一些小的修改,但是因为这些都是无关紧要的,所以我决定不对它们进行评论。
不管怎样,这是完整的课程:
我们来评价一下
是时候评估我们的算法了。为了简单起见,我决定使用著名的虹膜数据集,它可以从 Scikit-Learn 加载。
下面是让您开始工作的代码:
这是所有东西应该看起来的样子:
如果你想知道什么是 Bamboolib,请看这篇文章:
学习熊猫和数据分析从未如此容易
towardsdatascience.com](/introducing-bamboolib-a-gui-for-pandas-4f6c091089e3)
现在,我们需要以某种方式将数据集分成训练和测试部分。这很容易做到,代码如下:
现在让我们创建一个KNearestNeighbors
类的实例,并将k
设置为 3。然后,我们可以训练模型并轻松评估其性能:
K = 3 似乎是一个合理的选择。就这样,我们得到了 94.6%的准确率,这是惊人的。
但是我们怎么知道这是不是 K 的最优值呢?
我们不知道,我们需要手动验证。归结起来就是在一个循环中从上面包围代码:
如果你想知道为什么我决定只使用奇数**,那是因为这样在算法进行分类时不可能得到平局。**
K 的值 3 和 5 似乎产生相同的精度,我们可以设置 K = 13 来获得更好的模型。对于您来说,准确性分数可能会有所不同,这是因为训练集和测试集是随机采样的,但不应该有任何明显的差异。*
下一步是什么?
这是 K-最近邻算法的一个相当简单的实现。它工作得很好,但仍有一些事情你可以做,如:
- 尝试其他距离算法(如余弦距离)
- 数据标准化
后者实际上对 KNN 正常工作非常重要,因为您的输入可能不在同一个单元中。可以这样想——2.5 米和 250 厘米对你来说是一样的,但是算法会认为后者更重要,因为的尺度更大*。***
Iris dataset 没有这个问题,所以我决定跳过这一部分。在真实世界的数据集上,您可能不应该这样做。
感谢阅读,我希望你的机器一切正常。如果没有,就从我的 GitHub repo 下载代码。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
*** [## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)***
参考
[1]https://en.wikipedia.org/wiki/Euclidean_distance
让我们用深度学习制作一些动漫
文本生成方法比较:LSTM 与 GPT2
这个项目的动机是看看在 NLP 领域,尤其是在生成创造性内容方面,技术在短短几年内取得了多大的进步。我通过生成动画概要探索了两种文本生成技术,第一种是相对古老的 LSTM 单位技术,第二种是微调过的 GPT2 转换器。
在这篇文章中,你将会看到人工智能是如何从创造这些无意义的东西…
一个能干的年轻女人:一个被送回家的人类的神经劳力?打败一切成为他们的决心后,学校谁知道他们是否都使自己的能力。然而,那些叫她过去的学生焦油驳船在一起时,他们的神秘高艺术家是采取了计划,而吃饭打架!
敬这件艺术品。
一个名叫相户爱的女高中生暗恋一个名叫三木的神秘女孩。她是唯一一个能记住女孩名字的人,她决心要找出她到底是谁。
为了充分利用这篇文章,你必须了解:
- Python 编程
- Pytorch
- RNNs 的工作
- 变形金刚(电影名)
好吧,那么,让我们看看一些代码!
数据描述
这里使用的数据是从 myanimelist 上刮下来的,它最初包含了超过 16000 个数据点,是一个非常混乱的数据集。我已经采取了以下步骤来清理它:
- 删除了所有奇怪的动画类型(如果你是一个动漫迷,你会知道我在说什么)。
- 每个概要都在描述的最后包含了它的来源(例如:来源:myanimelist,来源:crunchyroll 等等。)所以我也把它去掉了。
- 基于视频游戏、衍生产品或一些改编的动画只有很少的摘要,所以我删除了所有单词少于 30 个的概要&我还删除了所有包含“衍生产品”、“基于”、“音乐视频”、“改编”等单词的概要。这背后的逻辑是,这些类型的动画不会真正使我们的模型有创意。
- 我也把剧情梗概词超过 300 的动漫给删了。这只是为了使培训更容易(查看 GPT2 部分了解更多详细信息)。
- 移除符号。
- 一些描述还包含日本字符,所以这些也被删除。
以下函数负责所有这些
LSTM 之路
传统的文本生成方法使用循环 LSTM 单位。LSTM(或长短期记忆)专门设计用于捕获正常 rnn 无法捕获的序列数据中的长期相关性,它通过使用多个门来实现这一点,这些门控制从一个时间步骤传递到另一个时间步骤的信息。
直观地说,在一个时间步中,到达 LSTM 单元的信息通过这些门,它们决定信息是否需要被*更新,*如果它们被更新,那么旧的信息被忘记,然后这个新的更新值被发送到下一个时间步。为了更详细地了解 LSTMs,我建议你浏览这个博客。
创建数据集
因此,在我们构建模型架构之前,我们必须将概要符号化,并以模型能够接受的方式对其进行处理。
在文本生成中,输入和输出是相同的,只是输出标记向右移动了一步。这基本上意味着模型接受输入的过去的单词并预测下一个单词。输入和输出令牌分批传递到模型中,每批都有固定的序列长度。我按照以下步骤创建了数据集:
- 创建一个配置类。
- 把所有的大纲连接在一起。
- 符号化概要。
- 定义批次数量。
- 创建词汇,索引词和索引词词典。
- 通过向右移动输入记号来创建输出记号。
- 创建一个生成器函数,批量输出输入和输出序列。
创建数据集
模型架构
我们的模型包括一个嵌入层,一堆 LSTM 层(我在这里用了 3 层),丢弃层,最后是一个线性层,输出每个词汇标记的分数。我们还没有使用 softmax 层,你很快就会明白为什么。
因为 LSTM 单元也输出隐藏状态,所以模型也返回这些隐藏状态,以便它们可以在下一个时间步骤(下一批单词序列)中传递到模型上。此外,在每个时期之后,我们需要将隐藏状态重置为 0,因为我们在当前时期的第一时间步中不需要来自前一时期的最后时间步的信息,所以我们也有“零状态”函数。
模型
培养
然后,我们只需定义训练函数,存储每个时期的损失,并保存具有最佳损失的模型。我们还在每个时期之前调用零状态函数来重置隐藏状态。
我们使用的损失函数是交叉熵损失,这就是我们不通过显式 softmax 层传递输出的原因,因为该损失函数是在内部计算的。
所有培训都是在 GPU 上完成的,以下是正在使用的参数(在配置类中提供):
- 批量= 32
- 最大序列长度= 30
- 嵌入维度= 100
- 隐藏维度= 512
- 纪元= 15
制作动漫
在文本生成步骤中,我们将一些输入文本输入到模型中,例如,“一个年轻的女人”,我们的函数将首先对此进行标记,然后将其传递到模型中。该函数还接受我们想要输出的概要的长度。
该模型将输出每个词汇标记的分数。然后,我们将 softmax 应用于这些分数,将其转换为概率分布。
然后,我们使用 top-k 采样,即我们从 n 个词汇标记中选择概率最高的前 k 个标记,然后随机采样一个标记,我们返回该标记作为输出。
然后,这个输出被连接到初始输入字符串中。这个输出令牌成为下一个时间步的输入。假设输出是“有能力”,那么我们的连接文本是“一个年轻女子有能力”。我们一直这样做,直到输出最后一个令牌,然后打印输出。
这里有一个很好的图表来理解这个模型在做什么
推理步骤。来源:机器对话
在上面的例子中,我把最大长度设为 100,输入文本设为“In ”,这就是我们得到的输出
在这几天的尝试中。虽然它已经,但是!他们认为人类的这些问题。看来,如果真的会做出什么事来。因为她必须永远不克服津贴与 jousuke s,为了她的家在他没有这一切在世界上:在医院里,她使他从自己的恶魔和屠杀。一个成员和一个偶像队的权力,以任何方式,但这两个来到它的世界,如果这仍然是等待和不去!在一个
这似乎在语法上是正确的,但毫无意义。虽然 LSTM 比基本 RNN 更擅长捕捉长期依存关系,但如果我们使用双向 RNNs 来捕捉文本的上下文,它们只能看到向后或向前的几步,因此当生成很长的句子时,我们会看到它们没有意义。
GPT2 方式
一点理论
变形金刚在捕捉所提供文本的上下文方面做得更好。他们只使用注意力层(没有 rnn ),这使他们能够更好地理解文本的上下文,因为他们可以看到尽可能多的时间后退(和前进,取决于注意力)。注意力有不同的类型,但是 GPT2、使用的注意力是语言建模的最佳模型之一,叫做掩蔽自我注意力。如果你不熟悉变形金刚,请在继续之前浏览这个博客。
GPT2 不使用转换器编码器和解码器堆栈,而是使用仅包含转换器解码器的高堆栈。根据堆叠的解码器数量,GPT2 变压器有 4 种变体。
变体。来源:贾勒马
每个解码器单元主要由两层组成:
- 隐蔽的自我注意
- 前馈神经网络
有一个图层规范化步骤,每个步骤之后还有一个残差连接。这就是我的意思…
单解码器单元
如果你之前读过这篇博文,你一定知道自我关注是如何计算的。直观地说,自我关注分数给予我们当前时间步中的单词应该给予其他单词的重要性或关注度(过去的时间步或未来取决于关注度)。
然而,在伪装的自我关注中,我们并不关心下一个或未来的单词。所以变压器解码器只允许参与到现在,过去的字和未来的字被屏蔽。
这是这个想法的一个美丽的代表…
伪装的自我关注。来源:贾勒马
在上面的例子中,当前单词是“it ”,正如你所看到的,单词“a”和“robot”有很高的注意力分数。这是因为“它”被用来指代“机器人”,所以“a”也是。
您一定注意到了上面输入文本开头的<s>
标记。<s>
只是用来标记一个输入字符串的开始。传统上是用 T2 来代替 s。
另一件事你一定注意到了,这类似于传统的语言建模,看到现在和过去的标记,下一个标记被预测。然后将这个预测的记号添加到输入中,然后再次预测下一个记号。
我已经对 GPT2 做了非常直观和高层次的了解。尽管这足以深入研究代码,但阅读更多关于这个概念的内容以获得更深入的理解将是一个好主意。我推荐杰伊·阿拉玛的博客。
代码
我已经使用 GPT2 和来自拥抱脸库的线性模型头来生成文本。在 4 个变体中,我使用了具有 117M 参数的 GPT2 small。
我已经在 Google Colab 上训练了该模型,训练中的主要问题是计算出批量大小和最大序列长度,以便我在 GPU 上训练时不会耗尽内存,批量大小为 10,最大序列长度为 300 最终为我工作。
出于这个原因,我也删除了超过 300 个单词的概要,这样当我们生成长度为 300 的概要时,它实际上是完整的。
创建数据集
对于微调,第一个任务是获得所需格式的数据,Pytorch 中的 dataloader 允许我们非常容易地做到这一点。
步骤:
- 使用上面定义的 clean_function 清除数据。
- 在每个剧情简介后添加
<|endoftext|>
标记。 - 使用 HuggingFace 的 GPT2Tokenizer 对每个大纲进行标记。
- 为标记化的单词创建一个掩码(注意:这个掩码与我们讨论过的掩蔽自我注意不同,这是为了掩蔽我们接下来将看到的填充标记)。
- 使用
<|pad|>
标记填充长度小于最大长度(此处为 300)的序列。 - 将令牌 id 和掩码转换为张量并返回它们。
资料组
模型架构
在这里,我们不需要明确地创建一个模型架构,因为拥抱面部库已经为我们做好了准备。我们只是简单地用语言模型头导入预先训练好的 GPT2 模型。
这个 LM 头实际上只是一个线性层,输出每个词汇标记的分数(在 softmax 之前)。
Hugging Face 提供的带有 LM head 的 GPT 2 模型的酷之处在于,我们可以在这里直接传递标签(我们的输入令牌),它们在内部向右移动一步,模型以及预测分数也返回损失。它实际上还会返回模型中每一层的隐藏状态以及注意力得分,但我们对此不感兴趣。
我们可以导入模型和标记器,并在一个配置类中定义所有的超参数,就像这样…
培训功能
步骤:
- 训练函数从数据加载器中获取 id 和掩码。
- 通过模型传递 id 和掩码。
该模型输出一个元组:- (loss,predicted scores, list of key&value pairs of every masked attention layer, list of hidden states of every layer,attention scores)
我们只对这个元组中的前两项感兴趣,所以我们访问它们。
- 执行反向传播并更新参数。
- 返回该时期的平均损失。
运行列车功能
步骤:
- 读取数据。
- 创建数据加载器对象。
- 定义优化器,我用的是 AdamW(权重衰减的 Adam)。学习率为 0.0001,重量衰减为 0.003。
- 定义调度程序。我用的是线性时间表,从拥抱脸部开始热身。热身步骤有 10 步(这基本上意味着前 10 个训练步骤的学习率将线性增加,然后线性减少)。
- 运行培训功能。我已经训练了 5 个时代。
- 保存损失最低的模型。
- 在每个时期后清空 GPU 缓存,以防止 OOM 错误。
制作动漫
在生成步骤中,我使用了 top-k 抽样(如 LSTM 方式)和 top-p 抽样。在 top-p 采样中,我们提供一个累积概率,比如 p,那么被选择的顶级词汇标记必须具有 p 的和概率。
我们可以组合 top-k 和 top-p 方法,首先选择具有最高概率得分的 top-k 个表征,然后为这些 k 个表征计算归一化得分。这使得 k 个表征的这些分数的总和是 1,我们也可以说概率质量只是在 k 个表征中重新分布。
接下来,对这 k 个分数进行 top-p 采样,然后从选定的标记中进行采样,最后我们使用概率进行采样,以获得最终的输出标记。
同样,我们不必编写所有这些代码,拥抱脸用它的生成方法来处理所有这些。
步骤:
- 获取输入文本并对其进行编码(tokenize + pad)以获得 id。
- 使用生成函数传递 id。在生成方法中传递编码后的
<|pad|>
标记非常重要,这样就可以区分它。 - 解码输出并返回。
- 将输出保存在文本文件中。
您一定注意到了 generate 方法有很多参数。可以对它们进行调整,以获得最佳输出。看看这篇详细解释这些参数的博客。
对于输入文本,“In the year”这是我们得到的输出…
2060 年,人类已经殖民了太阳系,现在正处于殖民其他星球的边缘。为了抵御这种新的威胁,地球联邦建立了一个特殊的单位,称为行星防御部队,简称 PDF。该单位由精英地球防御部队组成,他们的任务是保护地球免受任何可能威胁地球安全的外星生命形式的威胁。然而,当一艘神秘的外星飞船在巡逻途中坠毁时,他们被迫使用他们特殊的机动战士来抵御外星人的威胁。
你猜怎么着我真的会看这个。
LSTMs 和 GPT2 生成的大纲之间的差异是巨大的!该模型不仅能够很好地捕捉长期相关性,而且上下文也始终得到维护。
这里还有一个…
死神是传奇战士志贺美之父的后代,他被派往地球与被称为黑暗氏族的邪恶组织作战。然而,他的任务是去偷神圣的剑,光之剑,据说它可以授予使用它的人不死之身。
检查我的 github 库,在那里你可以浏览代码并看到一些更酷的人工智能生成的动画。
我希望你喜欢这篇文章,并且能够很容易地关注它。请在评论中提供宝贵的反馈。我很想知道你将如何完成这项任务,以及你是否有更好的方法来做这件事和改进模型。
参考
克里斯托弗·奥拉的《了解 LSTM
Martin Frolovs 的微调 GPT2 示例
杰伊·阿拉玛的《变形金刚》博客
杰伊·阿拉玛的 GPT2 博客