使用 tqdm 跟踪大型作业
TQDM 是 Python 的一个易于使用、可扩展的进度条包。这篇短文给了你一些有用的例子来帮助你开始。
Unsplash 上的 Volodymyr Hryshchenko
追踪你的进度
你真的无法击败一个伟大的,高质量的小包装,使你更有生产力。tqdm
就是这样一个包。这是一个易于使用、可扩展的进度条 Python 包,使得向 Python 进程添加简单的进度条变得极其容易。如果你是一名专业的数据科学家或机器学习(ML)工程师,你可能已经使用或开发了算法或数据转换,这可能需要相当长的时间——可能需要几个小时甚至几天——才能完成。
对于人们来说,选择简单地将状态消息打印到控制台并不罕见,或者在一些稍微复杂一些的情况下,使用(优秀的和推荐的)内置logging
模块。在很多情况下,这是好的。然而,如果您正在运行一个有数百个步骤的任务(例如,训练时期),或者运行一个有数百万个元素的数据结构,这些方法有时会有点不清楚和冗长,坦率地说有点难看。另外,在你的代码中加入一些“开发者体验”的东西(比如进度条!)也可以让你的代码更加用户友好。
给我看看代码!
这就是tqdm
的用武之地。它有一个漂亮干净的 API,可以让你快速地在代码中添加进度条。此外,它还有一个轻量级的“剩余时间”估计算法内置在进度条中。在一些 ML 包中使用了tqdm
包,其中最突出的可能是implicit
,一个 Python 隐式矩阵分解库。在这篇文章中,我们来看看下面这个使用tqdm
的模拟“训练循环”的例子:
import time
from tqdm import tqdm with tqdm(total=100) as progress:
for i in range(100):
time.sleep(0.25)
progress.update(1)
在这个简单的例子中,您设置了一个tqdm
进度条,该进度条预计包含 100 个步骤。然后,您可以运行循环(步骤之间有 0.25 秒的停顿),每次在步骤完成时更新进度条。如果你也跳出了循环,你也可以任意数量的更新进度条。这是两行代码(加上 import 语句),可以在代码中得到一个很酷的小进度条。以下是您得到的结果:
一个简单的 tqdm 进度条!Mark Douthwaite 截图
熊猫集成
除了给你的程序输出添加一些很酷的小东西之外,tqdm
还可以很好地与其他广泛使用的软件包集成。对于数据科学家来说,最有趣的集成可能是 Pandas,无处不在的 Python 数据分析库。看看下面的例子:
df = pd.read_csv("weather.csv")
tqdm.pandas(desc="Applying Transformation")
df.progress_apply(lambda x: x)
从技术上讲,tqdm.pandas
方法猴子将progress_apply
方法修补到熊猫的数据结构上,给它们一个常用的apply
方法的修改版本。实际上,当我们调用progress_apply
方法时,这个包用一个tqdm
进度条包装了标准的 Pandas apply
方法。当您处理大型数据帧时,这非常方便!
一个进度条的例子,由 Mark Douthwaite 截图的**tqdm**
与pandas.
的集成生成
平行过程
这里还有另一个值得一提的常见应用:tqdm
对于设置跟踪并行进程的进度条也很有用。下面是一个使用一些tqdm
内置支持更新平行贴图进度条的例子:
import time
from tqdm.contrib.concurrent import process_map def my_process(_):
time.sleep(0.25)
r = process_map(my_process, range(0, 100), max_workers=2, desc="MyProcess")
在这种情况下,在每个子流程中,每次my_process
调用完成时,都会有一个进度条更新。不过还有第二个用例:如果您有许多长时间运行的流程,并且希望单独跟踪它们,该怎么办?例如,如果您想避免在进程中序列化和反序列化大型对象,这可能更好。你也可以这样做:
import time
import multiprocessing as mp
from tqdm import tqdm def my_process(pos):
_process = mp.current_process()
with tqdm(desc=f"Process {pos}", total=100, position=pos) as progress:
for _ in range(100):
time.sleep(0.1)
progress.update(1) n_cpu = mp.cpu_count()with mp.Pool(processes=n_cpu, initializer=tqdm.set_lock, initargs=(tqdm.get_lock(),)) as pool:
pool.map(my_process, range(n_cpu))
这将为您提供类似以下内容的输出:
一个进度条同时跟踪 8 个任务的例子。Mark Douthwaite 截图
还有一个要点这个例子你也可以用:
一些示例代码,只给你!💛
还有一点
另外,tqdm
在 Jupyter 笔记本中运行时,提供了对进度条的支持,作为格式良好的小部件。例如,在笔记本中运行以下代码:
import time
from tqdm.notebook import tnrange, tqdmfor i in tnrange(10):
time.sleep(0.1)
会产生以下结果:
Jupyter 的进度条!Mark Douthwaite 截图
您可能会注意到您在这里重新导入了tqdm
。当您想要直接使用tqdm
对象时,您应该以这种方式导入tqdm
(如上例所示)。您应该能够直接放下上面的示例片段,并立即获得好看的进度条。哦,请确保从示例中删除time.sleep
行!
原载于https://mark . douthwaite . io。
在计算机视觉应用中跟踪 Raspberry Pi 内部温度
运行计算机视觉应用程序(或一般的人工智能应用程序)会给边缘设备带来压力,尤其是在组合模型时。使用散热器和风扇可能足以防止设备节流,但在您的设备变得这么热之前得到通知会很有帮助。收到潜在不安全温度的警报后,您可以在设备烧毁之前停止应用程序,并继续监控温度——当设备充分冷却后,您可以选择重新启动程序。
为此,我们创建了一个实用程序类,使您能够跟踪和记录温度读数,并提供所收集数据的摘要。
本教程使用一个 Raspberry Pi 4 和包“gpiozero”,它默认安装在 Raspbian 操作系统映像上。欲了解更多关于此包的信息,请参见以下链接。
要完成本教程,您必须具备:
- 一个 alwaysAI 账号(免费!)
- 在你的机器上设置 alwaysAI(也是免费的)
- 诸如 sublime 之类的文本编辑器或者诸如 PyCharm 之类的 IDE,或者任何你喜欢用来编码的东西
请参见 alwaysAI 博客了解更多关于计算机视觉、开发模型、如何改变模型等等。
本教程的所有代码都可以在 GitHub 上获得。
本教程有两个主要部分:
- 添加 GPIO 零要求
- 初始化 app.py 文件中的温度跟踪器
我们开始吧!
当你有了你的免费账户并建立了你的开发者环境后,你需要下载所有的入门应用;在继续本教程的其余部分之前,使用此链接完成操作。
为本教程修改的应用程序是“对象检测器”应用程序,因此 cd 进入 starter apps 文件夹,然后进入“realtime_object_detector”文件夹。
- 添加 GPIO 零要求:
- 首先,将 requirements.txt 文件添加到您的文件夹中。
- 将内容“gpiozero”添加到 requirements.txt。这将在您部署应用程序时安装。有关依赖关系的更多信息,请参见 alwaysAI 文档。
注意:如果您的 Pi 没有连接 wifi,将无法下载 requirements.txt 中的需求
2.更新 app.py 文件以使用温度跟踪器:
- 通过在“app.py”的顶部添加以下行来导入温度跟踪器代码:
from temperature_tracker import TemperatureTracker
- 在打印描述模型、引擎、加速器和标签的语句后,我们将创建 TemperatureTracker 实例。添加以下代码行:
temperature_tracker = TemperatureTracker()
- 现在,我们需要标记开始记录温度数据的时间。在 try/with 块内,但在“while”循环之前,在启动 FPS 实例后立即添加以下代码:
temperature_tracker.start()
- 要实际捕获温度数据,请调用“update”方法。将以下代码放入 while 循环中:
temperature_tracker.update()
注意:为了可读性,我在“预测中的预测”循环之后和温度语句之前添加了一个空行。这可以在任何时候使用’ text.append(" ")在流文本输出中获得更好的可读性。
- 要仅获取当前读数,而不修改存储的数据,可以使用“now”方法。这将返回温度和相应的时间戳。为此,请在上一步中添加的 update 调用之后添加以下代码行:
now = temperature_tracker.now()
- 我们可以将当前温度附加到发送给 streamer 的文本中,并检查返回的温度是否安全(至少对于 Raspberry Pi 4 是如此)。在前面两步中所做的更改下添加以下代码:
# log block showing current temperature
text.append(“{:1.2f}C/{:1.2f}F at time {}\n”.format(now[0], ((now[0]*(9 / 5)) + 32),time.strftime(‘%Y-%m-%d %H:%M:%S’, now[1])))# details whether the temperature is safe for a Raspberry Pi 4
if now[0] < temperature_tracker.MAX_TEMP_RASP4:
text.append(“Temperature is safe”)
else:
text.append(“TEMPERATURE IS NO LONGER SAFE”)
注意:如果您在应用程序停止之前没有在流媒体工具上看到警告消息,这意味着在应用程序停止之前浏览器提要没有刷新。一旦程序停止,您仍会在控制台上看到此警告消息。
- 在调用 fps.update()后,添加以下检查:
if now[0] >= temperature_tracker.MAX_TEMP_RASP4:
print(**“Maximum safe temperature reached, stopping program”**)
break
- 最后,在最后一个块中,在停止 FPS 实例后,通过添加以下内容来标记停止跟踪器的时间:
temperature_tracker.stop()
- 通过在“程序结束”打印语句前添加以下几行,捕获并打印温度汇总数据:
summary = temperature_tracker.summary()
print(summary)
就是这样!现在,您可以构建并启动您的应用程序来查看它的运行情况。您可能需要先配置应用程序,尤其是在您更改了边缘设备或从头开始创建新文件夹的情况下。您可以使用以下命令完成此操作,并在出现提示时输入所需的配置输入:
aai app configure
现在,要查看您的应用程序的运行情况,首先通过在命令行中键入以下内容来构建应用程序:
aai app deploy
构建完成后,使用以下命令启动应用程序:
aai app start
打开浏览器 localhost:5000,查看应用程序的运行情况,并在终止程序后观察控制台,查看您的温度数据摘要,如下所示。
一次追踪一颗子弹
如何在 Excel 中创建项目符号图表
假设您需要快速了解我们如何实现季度目标。好吧,让我们看看。
定性范围内的实际与目标
这给了你一个好主意吗?
几乎没有必要解释这个图表的元素。直观上很清楚。每项措施都有一个目标,成就栏嵌入在定性带中,告诉我们如何评估绩效。
这种可视化表示因其与众不同的外观而被称为“子弹图”。斯蒂芬·菲勒在他关于视觉数据交流的书中推广了这种方法。
在 Excel 中创建项目符号图
项目符号图可能是显示实际数据与目标数据的有效方法,但它并不作为一种现成的图表类型得到普遍支持。
让我们在普通 Excel 中创建一个项目符号图。
我将在 Mac 上使用 Excel 2016 进行截图。希望您的 Excel 版本(可能是未来的版本)足够相似,能够轻松地理解图表的结构。
在 Excel 术语中,基本思想是为定性带创建一个堆叠柱,并在次轴上为当前值创建一个标记线和细长柱。
我们的项目符号在 Excel 图表中的构建计划
我们将从一个单一的措施开始,一旦看起来没问题,我们将添加更多的“项目符号”。
我们走吧。
从数据开始
先看定性波段。我们将堆叠波段,因此每个波段都是根据其大小来定义的,而不是范围。
对于我们的第一张图表,让我们创建从差到**优秀的等级。**叠加它们的值给我们的总数是 125%。
我们还需要一个当前值和一个目标。我选择了 88%的现值和 100%的目标值。
我们第一个项目符号图的数据
创建堆积柱形图
我们需要一个堆积柱形图来形成我们的定性波段。我们将使用一些自定义格式从堆栈中取出当前值和目标值。
创建一个堆积柱形图并切换行/列,这样我们就有一个单一的柱形图。
第一步—创建堆积柱形图
创建目标标记
接下来,我们将分解目标值。
- 将目标值变为次轴上的标记线
- 删除图表中的次坐标轴,以便所有值使用相同的刻度
- 根据您的喜好格式化标记的外观
将目标分解为副轴上的标记线
格式化当前值
我们准备从堆栈中取出当前值。
- 将当前值移动到副轴。
- 增加其间隙宽度,使其看起来更薄。您可能需要修改图表区的宽度以获得正确的比例。
- 为条形使用合适的颜色。
将当前值分解为辅助轴中的一列
着色和润色
我们已经有了一个还过得去列表。根据您的喜好调整带子和记号笔的颜色。也许调整规模,以适应我们的范围 125%的最大成就。
完成后,您的图表应该如下所示:
单个度量的项目符号图
扩展到多个度量
我们现在想扩展图表以包含多个项目符号。每格一颗子弹。
首先在数据表中以列的形式提供附加度量的数据。一旦就位,您可以简单地拖动图表的数据区域来覆盖您的度量。
最后润色
添加一个图例,并对位置、比例和颜色进行一些最后的润色,应该会给你一个令人满意的最终结果。
我们已经做到了:用一个子弹图来跟踪定性区域中的多个目标
开始了。我们一次一颗子弹地追踪我们的目标…
追踪冠状病毒:你的国家、州或县的现状
在过去的一个月里,我一直在构建一个仪表板来帮助跟踪新冠肺炎的传播。它展示了世界各地确诊病例的最新数字,由纽约时报和 T2 提供,由约翰霍普金斯大学系统科学与工程中心(CSSE)的新冠肺炎数据仓库提供。
我的目标是尽可能快和清楚地提供这些信息,并且大规模地这样做,以便任何需要它的人都能得到它。
使用仪表板
可以通过以下链接找到仪表板:
- 【http://coronavirusmapsonline.com/
您可以使用此工具查找从 1 月下旬开始的案例的当前和历史信息。
无论你是想看看其他国家是如何渡过难关的,还是想查查自己家后院有多少病例,都在一个地方,很容易找到。页面包括
- 显示不同地区病例相对数量的地图
- 疫情期间每日新增病例和总病例图
- 按国家、州或县列出的总病例数和死亡数表
- 能够回放和查看过去任何一天的信息
要找什么
随着各州开始重新开放,我们都在警惕潜在的第二波病毒。像纽约这样的州处于第一条曲线的另一边。虽然新病例的数量一直在减少,但我们不能确定一旦解除居家禁令后会发生什么。
- http://coronavirusmapsonline.com/states/newyork:
随着各州重新开放经济,我们肯定会密切关注纽约和类似情况的地方,以确定潜在的新热点和回归热点。
例如,佛罗里达州迈阿密戴德县的病例数也有类似的情况。
另一方面,一些州可能仍然处于曲线的向上部分。
为什么它很重要
如果有一件事是清楚的,那就是冠状病毒会一直存在。然而,使用像这样的工具,我们可以确定病毒在世界不同地区传播的速度。
我们可以使用上面的曲线来确定在一段时间内具有相似病例分布的国家、州或县。通过这样做,我们从他们的经验中学习如何最好地前进。
虽然我们都在努力让曲线变平,但我的目标是提供一个清晰的画面,让我们能够做出明智的决定,帮助我们回到光明的未来。
我将很高兴收到以上任何反馈。让我知道你喜欢仪表盘什么,不喜欢什么!接下来我应该添加什么功能?欢迎在评论中告诉我,或者可以通过 Linkedin 或者 areevesman@gmail.com 的电子邮件联系到我。
穿越时空追踪冠状病毒
简介
全世界都在看着,新冠肺炎的影响与日俱增。当我们尽自己的一份力量来使曲线变平并战胜疫情时,病毒几乎已经传播到了世界的每个角落。
知识就是力量,有无数的资源可以帮助我们了解这种病毒。约翰·霍普金斯大学系统科学与工程中心的仪表盘,比如这个,给我们提供了当前世界范围内的病例和死亡人数。然而,我很难找到能让我回到过去的东西。
为了击败这种病毒,重要的是不仅要了解我们今天在哪里,而且要了解我们曾经在哪里。回顾过去的能力让我们知道疾病传播到了哪里,传播速度有多快。因此,我们对自己的现在和未来有更多的控制权。
仪表板
因为我一定不是唯一有这种感觉的人,所以我在这里创建了一个仪表板:
- 【https://coronavirusmapsonline.com
您可以使用这个仪表板为 1 月下旬以来的任何一天生成地图和表格。提供了(几乎)每个国家以及美国各州和县的病例和死亡人数。只需选择你想看的信息。
地图是交互式的,因此您可以放大并悬停以获取更多信息。
数据源
《纽约时报》和约翰·霍普金斯大学系统科学与工程中心正在 GitHub 上提供每日新冠肺炎病例计数文件。链接如下所示:
- 纽约时报
- 约翰·霍普金斯大学
Will has lett 的这个库收集了这些文件并实现了以下管道(更多细节可以在 README 中找到):
- 导入纽约时报和约翰霍普金斯大学的数据
- 在需要时执行类型转换
- 添加人口统计数据
- 将结果数据结构输出为一组长格式的时间序列。
有关数据收集过程中的任何注意事项或困难,请参见上面每个存储库中的自述文件。
我的存储库包括笔记本,这些笔记本从上面的存储库中提取并聚合数据以及应用程序源代码。该应用程序完全是使用 Plotly 和 Dash 在 Python 中创建的
我将很高兴收到以上任何反馈。我总是可以在 Linkedin 或 areevesman@gmail.com 的电子邮件上找到我。
使用地理空间分析追踪冠状病毒的传播
研究地理空间分析如何让我们预测冠状病毒如何传播
现场电晕病毒仪表板
我们的开源仪表板跟踪冠状病毒
重要的事情先来。
这个周末,我们在 Locale 的团队接手了一个小项目,来构建一个非启示录式的、更友好的、最小化的、易于使用的可视化 Covid19 仪表盘。该仪表板可帮助您在冠状病毒爆发时实时跟踪其爆发情况。在这里可以访问仪表盘。这个项目的数据源可以在这里找到,我们为这个项目使用的技术栈是 Vue.js , MapboxGL , DeckGL , Node.js 。
最好的部分是我们已经把代码开源了(所以请随意贡献)
科罗娜简史
冠状病毒(CoV)是一个大的病毒家族,可导致从普通感冒到更严重疾病的疾病,如中东呼吸综合征(MERS-CoV) 和严重急性呼吸综合征(SARS-CoV) 。世卫组织最近宣布一种新型冠状病毒为疫情,这种病毒已经传播到至少 114 个国家,并导致全球约 4600 人死亡。
下面是新型冠状病毒传播的简要时间表
2019 年 12 月
中国提醒世卫组织注意武汉出现的几例不寻常的肺炎病例。武汉是湖北中部的港口城市,人口 1100 万。病毒是未知的。
2020 年 1 月
中国开始出现冠状病毒阳性病例。中国首例死亡病例是一名与武汉海鲜市场有过接触的老人。截至 1 月底,中国报告了 7711 例阳性病例和 170 例死亡病例。这种新型冠状病毒还传播到了泰国、日本、俄罗斯、西班牙、瑞典和英国。
2020 年 2 月
致命的冠状病毒(新冠肺炎)蔓延到更多的国家。全球死亡人数超过 4600 人,阳性病例超过 126100 例。世卫组织宣布这种新型冠状病毒为疫情,影响除南极以外的所有大陆。世界各地的卫生专家正在夜以继日地寻找治疗这种不寻常的导致肺炎的冠状病毒的方法。
我们如何将地理空间分析用于疾病跟踪?
地图导致了流行病学的诞生。1854 年,当霍乱在伦敦爆发时,每个人都认为是空气中的微粒造成的。当时的医生琼恩·雪诺在伦敦地图上标出了所有的霍乱病例,并发现病因不是污浊的空气,而是来自街道水泵的污染水!
图片来源:维基百科
这一有史以来第一次进行的位置情报演习还催生了流行病学领域——研究疾病的发病率、分布和控制!
地理参照疾病案例为健康/环境联系提供了一个空间维度。这不仅有助于查明问题,还能描述原因或结果的强度或范围。我们可以通过识别可操作且具有生物学意义的数据模式、预测未来风险和流行轨迹以及描述一系列干预情景下的可能损失来实现这一目标。
地图有助于突出局部问题(如暴露于处置场所的疾病)和更广泛的问题(如暴露于大气臭氧减少的辐射)。它们可以作为预警工具。
隐藏在众目睽睽之下的交易模式
股票市场中有更长期的可交易模式,你不需要成为专业交易员或统计学博士也能搞清楚。
我在投资研究公司和资本市场数据供应商的销售和业务开发部门工作了 14 年。我现在正在将我的职业生涯从数据销售转向数据分析。我正在学习许多关于人工智能、机器学习以及如何使用 Python 代码来利用这些技术进行投资的很酷的东西。我发现学习新事物最快的方法是尝试去教它。所以我想分享一下我在学习过程中所学到的东西。
去年夏天,我去了一个零售“交易展”,发现了一个我认为值得研究的想法。这个想法是,有一些股票在一年中的特定时间可靠地上涨,年复一年,往往不是这样。在展会上谈论这一想法的演讲者当然是在推销一种订阅提醒服务,以便在发现这种交易“机会”时通知投资者。
但我想,“等一下。任何人都应该能够通过查看历史价格模式来验证这一想法,而我自己就有这样的技能和工具!”我是 Excel 高手,我最近学会了一些 Python 技巧,我知道如何从雅虎下载免费的历史价格数据。为什么不看看这个好玩的呢?
因此,我用 Python 编写了一个脚本来下载数据,运行一些统计数据,并将数据导出到一个潜在交易列表中,每个股票都有一个支持的 Excel 表格。我是这样做的。
第一步——从那些规模大、信誉好、盈利能力强的公司开始,这样我就有足够的历史数据可以利用,而且短期内我不必太担心基本面。我选择从标准普尔 500 指数中的上市公司开始。
接下来,我从哪里获取数据?幸运的是,雅虎财经免费提供大多数股票的完整历史收盘数据。雅虎的每个历史数据页面都包括一个免费的“下载数据”链接,只需几行 VBA 代码就可以轻松插入 Excel。此外,一个名叫的 Python 天才建立了一个免费的库 yFinance ,它用 Python 以最少的代码从雅虎下载数据。上帝保佑他!!
最后,现在我有了所有的数据,我应该计算什么样的指标才能让我找到表现出可靠的季节性表现模式的股票呢?我对“可靠”的定义是百分之八十的时间。那符合我的风险承受能力。我想找到在一年中可预测的时间上涨的股票,至少十年中有八年是这样。
我如何定义“可预测”?我决定查看 1 个月、2 个月和 3 个月的滚动时间段,每天递增,计算代表理论持有期结束的每个交易日的百分比回报。为了找到一个可靠的模式,我寻找稳定的时间段,跨越几天或几年,持有期回报持续为正。就百分比而言,这是大多数交易者的想法,我想找到这样的情况:一年中至少有 25 个交易日(10%),最好是连续几天,一只股票在过去十年或更长时间里至少有 8 个交易日表现稳定。
如果您要在 Excel 电子表格中直观显示这一点,每列代表一年,每行代表一年中的一个交易日,每个单元格包含一个持有期的百分比回报计算,以绿色显示正回报,您将会看到绿色的实心块遍布整个工作表。
体育用品制造商 VF 公司(纽约证券交易所代码:VFC)的情况如下。每一列都是一年,从 2001 年到 2019 年。每一行是一天,从三月到四月。这张表显示 VF 的股票价格在过去 20 年的 16 到 17 年中每年的 3 月和 4 月都在上涨。事实上,VF 的趋势周期从 2 月开始,3 个月的平均收益约为 6%。乘以四,你会得到大约 24%的年化收益率。
VFC 3 月至 4 月的 3 个月滚动回报
然而,我不想花几个小时查看 500 个电子表格。而是写了一个脚本,计算每只股票的一组统计数据,告诉我几分钟内想知道的事情。以下是我为每只股票计算的一些数据。
%就 VF Corp .而言,这一比例约为 18%。这意味着在 250 个交易日中的 45 个交易日,你有 80%的机会获得正回报,从而结束了 3 个月的持有期。这 45 天的大部分时间是在二月到四月。我更愿意看到这个数字在 10%或以上。
平均上涨回报率:回报率为正的每个滚动期的平均回报率。如上所述,VF 在我的计算中显示为 6%。这一开始听起来并不多,但是请记住,它只需要三个月就能实现。如果你将其乘以 12 个月,你会得到约 24%的年化回报率。
Avg StDev :所有滚动周期的收益标准差。这意味着预期回报应该在平均 67%的时间的+/-范围内。对于 VF,平均 StDev 为 11.4%。
%下跌:预期平均收益减去标准差。这意味着你至少应该在 67%的时间里超过这个回报。VF 公司的平均标准差为 11.4%。6.01%减去 11.37%等于-5.4%。这意味着你可能会在几年内损失 5.4%或更多。这是一个很好的止损阈值,它给了你一个风险与回报的指标。
最小痛点:最佳情况下,在最佳时机内下降 67%的时间间隔。这用于确定最低风险时间范围,即进入和退出交易的最佳日期。
最大连续 80%:10 年中至少有 8 年获得正回报的最长连续滚动周期数。你希望看到超过连续几年的上涨,以保证趋势是强劲的。对于 VF 来说,这个数字是 38 天,这已经很不错了。我通常喜欢看到 20 个或更多。
在过滤了超过 10%的上涨百分比和至少 10 年的历史后,我列出了大约 37 只股票,这些股票在 10 年中至少有 8 年显示出可靠的季节性上涨趋势。
我会建议立即执行这个清单上的交易吗?号码
首先,这种策略只有在整体市场上涨时才是可靠的。在查看了每只股票的回报细节后,我发现大多数股票在 2000 年至 2002 年、2008 年至 2009 年期间一直呈现负回报,许多股票在 2015 年和 2018 年底呈现负回报。然而,当我修改代码以生成一个卖空候选人列表时,没有一个符合连续年下跌期的 80%阈值。
因此,这种技术将简单地产生一个建议的多头交易列表,其中赔率肯定是对你有利的。但是在执行之前,您应该仔细看看每一个。在交易之前,你至少应该检查每只股票的技术和基本面。您可能还想在不同的回看时间范围内运行这个脚本。
时间框架很重要。我分析了 20 年的历史时间框架,但也许 5 年或 10 年更合适。例如,看看苹果公司(纽约证券交易所代码:AAPL)。回顾过去 20 年,交易 AAPL 的最佳 3 个月时间是每年的 2 月 1 日到 4 月 30 日。但是如果你看下面这张 AAPL 的表格,你会发现你只有 75%的时间有正回报。这对一些人来说可能没问题,但对我来说不是(白色太多,绿色不够)。
AAPL 3 月至 4 月的 3 个月滚动回报
然而,如果你向下滚动工作表,查看过去 10 年中从 9 月中旬到 10 月下旬结束的时间段,你会看到更多的纯绿色。这个时间框架给你 80%的机会获得持续的正回报。
AAPL 3 个月滚动回报 9 月至 10 月
这种模式背后的原因可能与苹果每年 9 月宣布新品发布的习惯有关。如果可以的话,深入了解每家公司并找出这些模式背后的基本驱动力会有所帮助。
对于 Python 代码,以下是基本步骤:
- 从 Yahoo 下载数据,并将其保存在 CSV 文件中:
for index, ticker in df_sp500_tickers.iterrows():
my_ticker = ticker['Symbol']
yf_ticker = yf.Ticker(my_ticker)
data = yf_ticker.history(period="max")
df = pd.DataFrame(data)
df.reset_index(level=0, inplace=True)
df['Symbol'] = my_ticker
df = df[['Symbol','Date','Close']]
#Yahoo has a tendency to duplicate the last row.
df.drop_duplicates(subset ="Date", keep = 'first', inplace = True)
df.to_csv(path_or_buf = my_path + "/data/" + my_ticker +".csv", index=False)
2.基于每月 20 个交易日,将价格转换为持有期回报。
def convert_prices_to_periods(): # dperiods is defined as 20, 40 or 60 days in a separate module
dfr = df.pct_change(periods = dperiods)
dfr.reset_index(level=0, inplace=True)
dfr.rename(columns={'Close':'Returns'}, inplace=True)
dfr = dfr.round(4)
3.将日期列分成月、年和日值,然后旋转数据框以创建一个顶部带有年份的表格。
def separate_date_column():
dfr['Month'] = pd.DatetimeIndex(dfr['Date']).month
dfr['Day'] = pd.DatetimeIndex(dfr['Date']).day
dfr['Year'] = pd.DatetimeIndex(dfr['Date']).year
dfr['M-D'] = dfr['Month'].astype(str)+'-'+dfr['Day'].astype(str)
pd.set_option('display.max_rows', len(dfr))def pivot_the_table():
dfr_pivot = dfr.pivot(index='M-D', columns='Year', values='Returns')
dfr_pivot.reset_index(level=0, inplace=True)
dfr_pivot = pd.DataFrame(dfr_pivot)
dfr_pivot.columns.name="Index"# Fill empty cells with EOD values from the previous trading day.
dfr_pivot.fillna(method='ffill', inplace=True)
# Drop the 2020 year column.
if 2020 in dfr_pivot.columns:
dfr_pivot.drop(2020, axis=1, inplace=True)
4.添加额外的计算列,以便于每种股票的统计计算。
def add_calculated_items():
# The lookback figure is the number (must be an integer) of years back from last year (2019) that you want to include in the analysis, i.e. the calculations below. It's probably a good idea to keep it at 20 years or less to reflect more recent market conditions. lookback = 20
start = 1
if lookback > len(dfr_pivot.columns) - 1:
start = 1
else:
start = len(dfr_pivot.columns) - lookback
dfr_pivot['YearCount'] = dfr_pivot.count(axis=1, numeric_only=True)
dfr_pivot['Lookback'] = lookback
dfr_pivot['UpCount'] = dfr_pivot[dfr_pivot.iloc[:,start:len(dfr_pivot.columns)-2] > 0].count(axis=1)
dfr_pivot['DownCount'] = dfr_pivot[dfr_pivot.iloc[:,start:len(dfr_pivot.columns)] < 0].count(axis=1)
dfr_pivot['PctUp'] = dfr_pivot['UpCount']/dfr_pivot['Lookback']
dfr_pivot['PctDown'] = dfr_pivot['DownCount']/dfr_pivot['Lookback']
dfr_pivot['AvgReturn'] = dfr_pivot.iloc[:,start:len(dfr_pivot.columns)-6].mean(axis=1)
dfr_pivot['StDevReturns'] = dfr_pivot.iloc[:,start:len(dfr_pivot.columns)-7].std(axis=1)
dfr_pivot['67PctDownside'] = dfr_pivot['AvgReturn']-dfr_pivot['StDevReturns']
dfr_pivot['MaxReturn'] = dfr_pivot.iloc[:,start:len(dfr_pivot.columns)-9].max(axis=1)
dfr_pivot['MinReturn'] = dfr_pivot.iloc[:,start:len(dfr_pivot.columns)-10].min(axis=1)
5.计算股票滚动持有期的交易统计数据。
def calc_trading_stats():
pct_uprows = (dfr_pivot.loc[dfr_pivot['PctUp'] > threshold, 'PctUp'].count() / dfr_pivot.loc[:, 'PctUp'].count()).astype(float).round(4)
max_up_return = dfr_pivot.loc[dfr_pivot['PctUp'] > threshold, 'MaxReturn'].max()
min_up_return = dfr_pivot.loc[dfr_pivot['PctUp'] > threshold, 'MinReturn'].min()
avg_up_return = dfr_pivot.loc[dfr_pivot['PctUp'] > 0.5, 'AvgReturn'].mean()
avg_up_return = np.float64(avg_up_return).round(4)
avg_down_return = dfr_pivot.loc[dfr_pivot['PctDown'] > 0.5, 'AvgReturn'].mean()
avg_down_return = np.float64(avg_down_return).round(4)
exp_return = dfr_pivot['AvgReturn'].mean().round(4)
stdev_returns = dfr_pivot['StDevReturns'].mean()
stdev_returns = np.float64(stdev_returns).round(4)
worst_return = dfr_pivot['MinReturn'].min()
pct_downside = exp_return - stdev_returns
pct_downside = np.float64(pct_downside).round(4)
least_pain_pt = dfr_pivot.loc[dfr_pivot['PctUp'] > threshold, '67PctDownside'].max()
total_years = dfr_pivot['YearCount'].max()
analyzed_years = lookback
n_consec = 0
max_n_consec = 0 for x in dfr_pivot['PctUp']:
if (x > threshold):
n_consec += 1
else: # check for new max, then start again from 1
max_n_consec = max(n_consec, max_n_consec)
n_consec = 1 max_consec_beat = max_n_consec try:
best_sell_date = dfr_pivot.loc[dfr_pivot['67PctDownside'] == least_pain_pt, 'M-D'].iloc[0]
except:
best_sell_date = "nan" try:
row = dfr_pivot.loc[dfr_pivot['M-D'] == best_sell_date, 'M-D'].index[0] - interval
col = dfr_pivot.columns.get_loc('M-D')
best_buy_date = dfr_pivot.iloc[row,col]
except:
best_buy_date = "nan"
6.如果满足% Up 行和历史条件,则创建 stat 值数组并将其附加到推荐交易列表中。
def filter_and_append_stats():
# Save the stats data separately to export to Excel for further research on each ticker if desired.
statsdata = np.array([my_ticker, hold_per, pct_uprows, max_up_return, min_up_return, avg_up_return, avg_down_return, exp_return, stdev_returns, pct_downside, worst_return, least_pain_pt, total_years, max_consec_beat, best_buy_date, best_sell_date, analyzed_years])
df_statsdata = pd.DataFrame(statsdata.reshape(-1, len(statsdata)), columns=['my_ticker', 'hold_per', 'pct_uprows', 'max_up_return', 'min_up_return', 'avg_up_return', 'avg_down_return', 'exp_return', 'stdev_returns', 'pct_downside', 'worst_return', 'least_pain_pt', 'total_years', 'max_consec_beat', 'best_buy_date', 'best_sell_date', 'analyzed_years'])
if pct_uprows > 0.1:
if total_years > 9:
df_tradelist = df_tradelist.append(dict(zip(df_tradelist.columns, statsdata)), ignore_index=True)
7.最后,将所有这些放在一个模块中,该模块提取每个 CSV 文件,计算统计数据,将它们加载到推荐交易表中,然后将数据保存在格式化的 Excel 文件中,用于每个报价器,如上所示。
def calc_3month_returns():
dperiods = 60
hold_per = "3 Mos"
interval = 90
convert_prices_to_periods()
separate_date_column() pivot_the_table() add_calculated_items() sortbydate_resetindex_export()
# Export the pivot table to CSV for further research if desired.
#dfr_pivot.to_csv(path_or_buf = my_path + "/data/" + my_ticker + "_dfr_pivot_3mo.csv", index=False)
# Save dfr_pivot to separate dataframe for exporting to Excel
dfr_3mo = pd.DataFrame(dfr_pivot) calc_trading_stats()
filter_and_append_stats()
# Save statsdata to separate dataframe for exporting to Excel
df_statsdata_3mo = df_statsdata.copy()for index, ticker in df_sp500_tickers.iterrows():
global df
global dfr
my_ticker = ticker['Symbol'] df = pd.read_csv (my_path + "/data/" + my_ticker + ".csv")
df.set_index('Date', inplace=True)
df = df['Close']
df = pd.DataFrame(df, columns=['Close'])
calc_1month_returns()
calc_2month_returns()
calc_3month_returns()
export_to_excel()
Excel 导出模块相当广泛。我使用了一个名为 XlsxWriter 的 Python 库来完成这项工作。下面是这段代码的样子:
def export_to_excel():
excel_file_path = my_path + "/data/" + my_ticker + ".xlsx"
# Create a Pandas Excel writer using XlsxWriter as the engine.
writer = pd.ExcelWriter(excel_file_path, engine='xlsxwriter')# Convert the dataframe to an XlsxWriter Excel object.
df_statsdata_1mo.to_excel(writer, sheet_name='Stats', index=False)
df_statsdata_2mo.to_excel(writer, sheet_name='Stats', startrow=2, header=False, index=False)
df_statsdata_3mo.to_excel(writer, sheet_name='Stats', startrow=3, header=False, index=False)
dfr_1mo.to_excel(writer, sheet_name='1 Mo Returns', index=False)
dfr_2mo.to_excel(writer, sheet_name='2 Mo Returns', index=False)
dfr_3mo.to_excel(writer, sheet_name='3 Mo Returns', index=False)# Get the xlsxwriter objects from the dataframe writer object.
workbook = writer.book
worksheet1 = writer.sheets['Stats']
worksheet2 = writer.sheets['1 Mo Returns']
worksheet3 = writer.sheets['2 Mo Returns']
worksheet4 = writer.sheets['3 Mo Returns']
# Add conditional formatting to highlight positive returns in green
end_column = dfr_1mo.columns.get_loc("YearCount")
grn_format = workbook.add_format({'bg_color': '#C6EFCE','font_color': '#006100'})
worksheet2.conditional_format(1, 2, 365, end_column - 1,{'type':'cell','criteria':'>','value':0,'format':grn_format})
worksheet3.conditional_format(1, 2, 365, end_column - 1,{'type':'cell','criteria':'>','value':0,'format':grn_format})
worksheet4.conditional_format(1, 2, 365, end_column - 1,{'type':'cell','criteria':'>','value':0,'format':grn_format})
# Freeze panes for scrolling
worksheet2.freeze_panes(1, 2)
worksheet3.freeze_panes(1, 2)
worksheet4.freeze_panes(1, 2)
# Save the file
writer.save()
交易列表输出如下所示,按最佳买入日期排序:
基于 3 个月滚动季节性回报的建议交易
我的主要观点是,你不需要成为一个数学博士或者是一个高速日内交易者来发现股市中的重复模式,你可以用它来增加对你有利的机会。你只需要知道去哪里找,并掌握一点编码技巧就能有效地完成。
在这种情况下,我使用 Python,但这也可以用 Excel 中的 VBA 代码轻松完成。你可以在 Github 上看到完整的 Python 脚本。请在 LinkedIn 上给我发消息,告诉我你想提供的任何反馈。
编码和交易快乐!!
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指南 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
情绪交易:(试图)从市场情绪中赚钱
来源:Shutterstock
很长一段时间以来,我读到投资者的情绪,通常被称为情绪,可以是一个很好的指标,通常是反向的,就近期市场价格行为而言。人们的想法是,在极端情况下,人们可能会做出不理性的行为,比如网络泡沫,甚至是 2009 年 3 月,当时美国股市触底,而空气中仍弥漫着大量恐惧。
我很好奇这是不是真的。我不否认直觉,但有时候直觉是假的。所以俗话说,“我们相信上帝……其他人都会带来数据”。
我是行为金融研究的粉丝,比如罗伯特·席勒、T2、理查德·塞勒、T4 和丹尼尔·卡内曼提出的见解,它们在理智和经验上与我联系在一起。我喜欢这个想法,我可以从那些不理性的不那么聪明的散户投资者身上获利。它打击了我的斯多葛派优越感。
但是如果很容易,别人大概已经想通了。
一个简单的情感系统
美国个人投资者协会(AAII)从 1987 年中期开始发布每周情绪指数,会员回答他们对未来 6 个月股市走向的看法。现在一个敏锐的观察者可能会说,“嘿,史蒂文,这是一个有偏见的样本,绝对不是一个简单的随机样本!”这是事实,但我们感兴趣的是市场参与者,而不是普通公民,这一数据比大多数其他情绪指标都要久远,如 VIX 或 CBOE 看跌/看涨期权比率。结果导致牛市,中性或熊市的结果。我选择使用简单的牛熊价差指标,即多头百分比减去空头百分比,因为这是一个简单的单一指标,包含了调查数据。
现在我们知道,从历史上看,至少在美国,存在一个统计上很强的股票风险溢价,这意味着投资者期望,并且通常会通过投资股票获得回报。根据 Kenneth French 数据库的数据,从 1927 年到 2020 年 5 月,投资者获得了 9.4%的年化回报率,其中 6.0%来自高于无风险利率的股票市场风险溢价。我会说,更令人印象深刻的是 4.24 的高 t-stat 和 1.078e-05 的 p 值,这表明实际的历史回报率不是运气。
因此,除非你有相反的有力证据,否则至少从历史上看,投资美国股票的结果是好的。但话说回来,提醒我一下,从 1927 年到 2020 年,谁 100%投资于股票?哦,是的,没有人!他们要么已经死了,要么已经在好几个场合认输了。在大萧条期间,谁会在 3 年半的时间里保持 84%的下降呢?因此,历史回报是不错的,但这并不意味着任何人实际上都实现了这些巨大的长期回报。
投资组合构建与分析
我们希望尽量保持大部分投资于股票,但也许不会走极端。我很好奇我们是否能在风险调整的基础上超越 if:
- 当牛熊价差处于历史区间的前十分之一时(即乐观情绪的前 10%),我们退出了市场,否则,继续投资。
我们必须从一开始就着眼于滚动的十分之一,而不是事后诸葛亮。
你可以通过 Github 这里访问 Python 代码进行下面的分析。
这里你可以看到实际的牛熊价差和 6 个月的滚动平均值,这有助于你看到信号和周噪声。
数据来源:AAII
以下是过去 6 个月股票市场的滚动配置。直觉上,市场情绪越乐观,我们的投资就越少。
数据来源:AAII
下面的图表显示了性能(y 轴对数刻度显示了相同距离变化时指数的相同百分比变化)
数据来源:AAII。性能是忽略税收和交易成本和纯粹的假设。
观察结果:
- 从 1987 年到 1995 年,市场和情绪投资组合之间的表现没有太大差异。
- 从 1995 年到 2004 年,有一个很大的分散,这是由于 AAII 战术投资组合只投资了 74%的时间,而通常 AAII 战术投资组合投资了 89%的时间。反向投资法确实不太奏效。
- 有趣的是,在 2003/2004 年,人们的乐观情绪超过了互联网泡沫的高峰期。
- 情绪指标每周都有很多噪音,如果你不小心,这样的噪音信号可能会导致高投资组合周转率和交易成本。
数据来源:AAII。性能是忽略税收和交易成本和纯粹的假设。
自 2009 年初大衰退结束至今,我们看到了与整体市场一致的表现,因为该指标通常不会超过 10%的上限。
开采愚人黄金
从最佳实践的角度来看,我们已经看到了所有的数据,但没有可行的策略。但是让我们探索一下,在交易成本之前,在实现更高的夏普比率(回报/风险)方面,技术上是否有可能超越市场。如果我们简单地使用年化回报率,我们就不会比较苹果和苹果,因为我们将在我们的数据挖掘策略中使用杠杆,波动性可能不相等。
我运行了一个 for 循环来探索以下策略的不同变体:
- 当牛熊价差超过某个百分点时(I)平仓(小心)
- 当牛熊价差低于某个百分点(j)时,做多 2x(激进)
直觉告诉我们,当其他人都非常积极的时候,我们要保守,当其他人都非常悲观的时候,我们要积极。
下面是一个热图,显示了情绪策略的夏普比率减去被动市场策略的夏普比率(越高越好)。阅读热图的方法:
- y 轴回答的问题是“在什么样的百分比我会退出市场(即持平)?”底部相当于 1.0 永远不出市,顶部相当于 0.0 永远不投资。
- x 轴回答的问题是“在多大的百分比上我才是积极进取的,对市场的敞口是两倍?”最右边相当于在 1.0 时从不使用杠杆,最左边相当于在 0.0 时一直使用两倍的杠杆。
数据来源:AAII
在这个数据挖掘练习之后,我们注意到以下情况:
- 与市场指数相比,所有使用 AAII 牛熊价差的市场时机策略的夏普比率都较低。
- 情绪时机策略的最高夏普比率出现在深红色阴影区域,主要是当你一直做多(左下)或一直杠杆操作(右下)时。请注意,由于 2 倍杠杆投资组合的波动性增加,由于复利效应,您不会获得 2 倍的几何年化回报(这是夏普比率的分子),因此 2 倍杠杆投资组合与 1 倍完全投资风险敞口的夏普比率不同。
因此,我们可以肯定地说,利用 AAII 牛熊价差的简单择时策略不起作用。然而,我们还没有探索,如果使用其他指标(如 VIX)对市场情绪进行综合衡量,是否会给我们带来不同的结果。
接下来,我将探索不同情绪指标的组合是否可以用于不同的机器学习算法,以实现卓越的风险调整性能。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
Python 交易工具箱:用 Matplotlib 介绍 OHLC 图表
交易工具箱
释放 OHLC 数据的力量
由 Aditya Vyas 在 Unsplash 上拍摄的照片
在其他帖子中,我们开始探索如何根据价格计算一些基本指标(简单移动平均线和其他移动平均线),以及如何将它们与价格一起绘制在图表上。在这些例子中,我们考虑了每日价格数据,并使用收盘价来表示每天的交易。很明显,金融工具全天交易产生不止一个价格。收盘价是最相关的价格之一,但不能说明交易日发生的全部情况。
OHLC 棒线和棒线图是捕捉金融工具全天交易中产生的价格范围的传统方式:对于每一天,记录四个价格:开盘价(开盘)、最高价(高)、最低价(低)和收盘价(收盘)。
条形图并不局限于每日价格:周线图和月线图可以使用每个时期的开盘价、最高价、最低价和收盘价来构建。它们也可以应用于日内图表,通过使用小时线,或者任意间隔的线(例如 30 分钟,10 分钟,直到 1 分钟)。
与条形图类似,蜡烛图基于每天的开盘价、最高价、最低价和收盘价,但使用不同的视觉表示。开盘价和收盘价之间的范围由一个“蜡烛体表示——它根据收盘价是否高于开盘价而采用不同的颜色(通常是白色和黑色)。高点和低点分别用放置在身体上方和下方的“蜡烛芯”(称为阴影)来表示。烛台图表的使用起源于日本,与一种基于模式的分析相关。
用 Python 创建 OHLC 条形图
有几个很好的可视化资源,使我们能够用 Python 创建条形图和蜡烛图。最好的两个是 Plot.ly 和 Bokeh 。两种解决方案都允许创建专业外观的交互式图表。另一方面, Matplotlib 专注于静态图表,能够产生漂亮的出版物质量的数字。当我需要制作静态图表时,这通常是我的第一个选择。
虽然 Matplotlib 库是使 Python 成为数据可视化的良好环境的元素之一,但就 OHLC 金融图表而言,它迄今为止的表现低于其真正的潜力。在 Matplotlib 中处理 OHLC 和烛台图表绘制的包被称为 mpl-finance ,这是一个模块,它曾经是主 Matplotlib 发行版的一部分,直到它被宣布过时,只能作为一个单独的包使用。我认为,这是有原因的: mpl-finance 没有与 pandas 很好地集成,也不像 Matplotlib 的其他绘图功能那样容易使用。最近,它找到了一个新的维护者, Daniel Goldfarb ,他正致力于为 mpl-finance 创建一个新的 API,以使其更加可用,并与 pandas dataframes 保持一致。新版本应该会在 2020 年的某个时候发布。
对不久的将来的一瞥
我们可以先看看即将到来的版本 mpl-finance 将如何工作以及看起来会是什么样子。要预览新版本(撰写本文时的预发布版本),您只需运行:
pip install mplfinance
注意即将到来的版本的拼写:名称中没有’-‘也没有’ _ ',而当前版本安装为mpl-finance
,导入(相当混乱)为mpl_finance
。新版本将结束这种名称混淆。
我们现在可以创建我们的第一个价格条形图,使用在系列文章的第一篇文章中使用的相同数据。你可以在这里下载 CSV 文件。
打字:
import pandas as pddatafile = 'SPY.csv'
data = pd.read_csv(datafile, index_col = 'Date')
data.index = pd.to_datetime(data.index) # Converting the dates from string to datetime formatdata
显示了我们的 OHLC 价格数据框架:
我们现在可以导入新安装的 mpl-finance 库:
import mplfinance as mpf
创建价格条形图(最近 50 天的数据)非常简单:
mpf.plot(data[-50:], no_xgaps = True)
如果您没有使用 Jupyter,请不要忘记添加下面一行来可视化这个图表和接下来的图表:
plt.show()
这是结果:
创建蜡烛图同样简单:
mpf.plot(data[-50:], type='candlestick', no_xgaps = True)
视觉效果看起来很吸引人。no_xgaps
选项是一个漂亮的功能,它消除了通常由没有交易数据的日子(如周末和公共假日)产生的缺口。
当前的 mpl-财务库
当前版本的 mpl-finance 可通过以下方式安装:
pip install mpl-finance
或者
conda install mpl-finance
如果你使用 Conda 作为包管理器。与即将发布的版本相比,当前的 mpl-finance 库需要一些数据操作来创建一个简单的 OHLC 或烛台图表。特别是:
- 我们需要将数据呈现为 OHLC 价格序列。
- 时间和日期需要明确地转换成 Matplotlib 能够理解的格式。
幸运的是,一旦新版本发布,所有这些操作都将过时,希望很快在 2020 年发布。目前,我只是给出了执行这些任务的代码,而没有过多地涉及细节。您可以直接使用它:
我们现在可以使用这些数据绘制一个条形图:
这表明:
默认情况下,收盘价高于开盘价的棒线是黑色的,而收盘价低于开盘价的棒线是红色的。图表中有一些可见的横向缺口:它们是由非交易日(周末和公共假日)产生的。移除它们需要一些额外的非平凡的过滤。
类似地,可以通过以下方式生成蜡烛图:
它产生:
释放 OHLC 数据的力量
使用 OHLC 价格而不仅仅是一个单一的系列作为收盘价开辟了一个新的可能性世界:我们可以评估每个交易日的价格范围,观察收盘价与开盘价的关系,检查价格是否高于先前的高点或低于先前的低点,等等。
这里我将展示一个相当简单的图表示例,它利用了最高价和最低价以及收盘价。这张图表来自一种交易技术,叫做“驼峰技术”。我对详细描述交易技术不感兴趣(大量信息可以在网站上找到):我们只是使用相关的图表作为发现现有趋势的有用工具。
我们在每日价格条形图上叠加了以下移动平均线:
- 40 天简单移动平均线的高点。
- 低点的 40 天简单移动平均线。
- 收盘价的 15 天指数移动平均线。
这可以编码如下:
这给出了:
两条简单的蓝色移动平均线创建了一个通道:与单一移动平均线相比,当价格既不在通道上方也不在通道下方时,我们现在有一个灰色区域。
例如,我们现在可以采用以下交易规则:
- 仅当价格棒完全位于更高的 40 天 SMA 上方时,输入多头头寸(买入)。
- 只有当价格棒完全位于下方 40 天均线下方时,才进入空头头寸(卖出)。
- 当价格在两个 40 天均线之间或者最后一根棒线穿过其中任何一个时,我们不进入任何头寸(我们在市场上保持持平)。****
另一个例子是:
- 仅当 15 日均线高于 40 日均线时,输入多头头寸。
- 仅当 15 日均线低于下方 40 日均线时,输入空头头寸。
- 在其他地方保持持平,即当 15 日均线在两个均线创建的通道内时。
在这个阶段,我们应该问这些规则(或者在关于均线的文章中提到的任何方法)是否可以用来建立一个有利可图的交易系统。换句话说,我们应该问这些想法是否会帮助我们产生利润而不是亏损,以及如何选择最佳的规则。我会在下一篇文章中尝试解决这个问题。我们将学习如何回测一个交易系统,根据历史数据计算盈利或亏损。
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
Python 交易工具箱:用指标支线剧情提升你的图表
交易工具箱
使用 matplotlib 向价格图表添加指标
在几个月的中断之后,我终于可以继续发布交易工具箱系列了。我们从学习如何在价格图表的顶部绘制指标(特别是:移动平均线)开始了这个系列。均线属于一组广泛的指标,叫做叠加指标,它们和价格有相同的尺度,因此可以在同一张图上绘制。然而,其他技术指标没有这种优势,我们需要将它们绘制在单独的区域,有时称为子图。
下面是一个取自 Yahoo!财务:
带有动量指示器的烛台图表
在这篇文章中,我们想探索如何使用 Matplotlib 创建类似的图表。我们还想探索如何利用 Matplotlib 的定制潜力,创建原创的、出版物质量的图表。首先,我们将学习如何使用 Matplotlib 获得那种子情节。然后,我们将应用它来绘制价格下方的第一个技术指标,即变化率(或 ROC )。然后,我们将看看如何在 OHLC 棒线或蜡烛图而不是折线图上做到这一点。
使用 matplotlib 的多个支线剧情
在这个阶段,我们需要深入研究 Matplotlib 如何工作的一些技术方面:这就是我们如何利用它的多图功能和工艺发布质量图表。提供的所有代码都假设您正在使用 Jupyter Notebook 。相反,如果您使用更传统的文本编辑器或命令行,您将需要添加:
plt.show()
每次创建图表时,为了使其可见。
在本系列的前两篇文章中,我们使用以下格式创建了第一个金融价格图:
plt.plot(dates, price, <additional parameters>)
你可以看第一篇关于移动平均线的文章或者第二篇关于加权和指数移动平均线的文章。
当调用该方法时, matplotlib 在后台做一些事情来创建图表:
- 首先,它创建了一个名为 figure 的对象:这是存储所有图表的容器。一个图形是自动地、安静地创建的,但是,我们可以显式地创建它,并在需要传递一些参数时访问它,例如使用指令:
fig = plt.figure(figsize=(12,6))
- 除此之外, matplotlib 创建了一个名为轴的对象(不要与轴混淆):这个对象对应于包含在图中的一个子情节。同样,这个动作通常发生在幕后。
在任何一个图形中,我们可以有多个子情节(轴)排列成一个矩阵:
有六个轴的图形
我们的第一个多重绘图图表
当涉及到有多个次要情节的图表时,有足够多的方式和方法可以让我们晕头转向。我们将只选择一个:.subplot()
方法将很好地服务于我们的目的。通过其他教程,你可能会遇到一个叫做.add_subplot()
的方法:.subplot()
方法是.add_subplots()
的包装器(这意味着它应该使它的使用更简单)。除了几个细节之外,它们的用法实际上非常相似。
每当我们向图形添加子图时,我们需要提供三个参数:
- 图表矩阵中的行数。
- 列数。
- 具体支线剧情的编号:你可以从上图中注意到,轴物体是从左到右,然后从上到下编号的。
让我们尝试构建一个通用 2x2 多曲线图的实际示例:
这给了我们下面的图表:
有四个次要情节的图表
向价格系列添加指示器子图
现在我们知道了如何创建具有多个图表的图表,我们可以应用我们的技能在价格图表的底部绘制一个指标。对于这个任务,我们将使用一个称为变化率 ( ROC )的指标。实际上,ROC 有几种不同的定义,我们在示例中使用的定义基于以下公式:
其中 lag 可以是任何大于零的整数,代表我们回头比较价格的周期数(在日线图上:天数)。例如,当我们计算滞后 9 天的每日价格的 ROC 时,我们只需查看与 9 天前相比,价格上涨(或下跌)了多少(百分比)。在本文中,我们不打算讨论如何解读 ROC 图并将其用于投资决策:这最好有一篇专门的文章,我们将在未来的帖子中进行讨论。
我们从准备环境开始:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt# Required by pandas: registering matplotlib date converters
pd.plotting.register_matplotlib_converters()# If you are using Jupyter, use this to show the output images within the Notebook:
%matplotlib inline
对于这个练习,我从 Yahoo!为跟踪纳斯达克 100 指数表现的 ETF景顺 QQQ 信托 的每日价格融资。你可以在这里找到我正在使用的 CSV 文件。我们可以加载数据并浏览一下:
datafile = 'QQQ.csv'
data = pd.read_csv(datafile, index_col = 'Date')# Converting the dates from string to datetime format:
data.index = pd.to_datetime(data.index)data
看起来像是:
然后,我们可以计算滞后 9 天的 ROC 序列,并将其作为一列添加到我们的数据框中:
lag = 9
data['ROC'] = ( data['Adj Close'] / data['Adj Close'].shift(lag) -1 ) * 100data[['Adj Close', 'ROC']]
哪些输出:
为了使我们的示例图表更容易阅读,我们只使用了我们的可用数据的选择。下面是我们如何选择最后 100 行,对应于最近的 100 个交易日:
data_sel = data[-100:]
dates = data_sel.index
price = data_sel['Adj Close']
roc = data_sel['ROC']
我们现在准备创建第一个多点图,价格在顶部,ROC 指标在底部。我们可以注意到,与带有子图的普通图表相比,我们的指标具有与价格图表相同的日期和时间(水平轴):
fig = plt.figure(figsize=(12,10))# The price subplot:
price_ax = plt.subplot(2,1,1)
price_ax.plot(dates, price)# The ROC subplot shares the date axis with the price plot:
roc_ax = plt.subplot(2,1,2, sharex=price_ax)
roc_ax.plot(roc)# We can add titles to each of the subplots:
price_ax.set_title("QQQ - Adjusted Closing Price")
roc_ax.set_title("9-Day ROC")
我们的第一个带指标的图表
我们刚刚绘制了我们的第一个图表,价格和 ROC 在不同的区域:这个图表完成了它的工作,它使价格和指标都可见。然而,它并没有以一种视觉上非常吸引人的方式做到这一点。首先,价格和 ROC 共享同一个时间轴:没有必要在两个图表上再次应用日期标签。我们可以使用以下方法将它们从顶部图表中删除:
price_ax.get_xaxis().set_visible(False)
我们也可以用下面的方法去掉两个支线剧情之间的间隙:
fig.subplots_adjust(hspace=0)
在 ROC 的零级别添加一条水平线也是一个好主意,这样可以使它更具可读性,同时在两个垂直轴上添加标签。
fig = plt.figure(figsize=(12,10))price_ax = plt.subplot(2,1,1)
price_ax.plot(dates, price, label="Adj Closing Price")
price_ax.legend(loc="upper left")roc_ax = plt.subplot(2,1,2, sharex=price_ax)
roc_ax.plot(roc, label="9-Day ROC", color="red")
roc_ax.legend(loc="upper left")price_ax.set_title("QQQ Daily Price")# Removing the date labels and ticks from the price subplot:
price_ax.get_xaxis().set_visible(False)# Removing the gap between the plots:
fig.subplots_adjust(hspace=0)# Adding a horizontal line at the zero level in the ROC subplot:
roc_ax.axhline(0, color = (.5, .5, .5), linestyle = '--', alpha = 0.5)# We can add labels to both vertical axis:
price_ax.set_ylabel("Price ($)")
roc_ax.set_ylabel("% ROC")
更好的带指示器的图表
这张图表看起来已经更好了。然而,在创建专业外观的图表时,Matplotlib 提供了更大的潜力。以下是我们可以做的一些例子:
- 为了增强 ROC 指标的可读性,我们可以填充图和水平线之间的区域。
.fill_between()
方法将服务于这个目的。 - 例如,我们可以设置日期标签的格式,只显示月份的缩写名称(例如, Jan , Feb ,…)。
- 我们可以对 ROC 纵轴上的标签使用百分比格式。
- 我们可以给两个支线剧情都添加一个网格,并设置一个背景色。
- 增加绘图和边框之间的边距(填充)。
- 为了最大化图表的 数据-墨迹比率 ,我们可以删除所有的竖线(子情节周围的边框)以及两个子情节的水平轴和垂直轴上的刻度线。
- 我们还可以将所有字体的默认大小设置为一个更大的数字,比如 14。
这是一个相当长的改进列表。不要在细节上迷失太多,下面的代码应该提供一个很好的例子:
这给出了:
带有指示器的更加定制化的图表
这个图表展示了我们通过操作默认的 Matplotlib 参数所能达到的效果。当然,我们总是可以通过应用现有的样式表来实现一些视觉上的改进,正如我们在本系列的第一篇文章中所做的,例如:
plt.style.use('fivethirtyeight')
当使用指标支线剧情时,大多数时候我们希望价格部分比图表中的指标部分占据更大的面积。为了实现这一点,我们需要操纵 Matplotlib 用来放置支线剧情的不可见网格。我们可以使用[GridSpec](https://matplotlib.org/3.1.1/tutorials/intermediate/gridspec.html)
函数来实现。这是 Matplotlib 的另一个非常强大的特性。我将提供一个简单的例子来说明如何使用它来控制两个支线剧情之间的高度比例:
哪些输出:
具有自定义高度比例的图表
顺便提一下,您可能会注意到这个图表是如何将前一个图表代码中的字体大小设置为 14 的。这是因为对rcParams
Matplotlib 参数的任何更改都是永久的(直到我们重新启动系统)。如果我们需要重置它们,我们可以使用:
plt.style.use('default')
如果我们用的是 Jupyter 笔记本,还要加上%matplotlib inline
。
OHLC 和蜡烛图指标
在前面的所有例子中,我们将价格绘制成了一个线形图。当我们每个交易周期只有一个数据点(在这个例子中是收盘价)时,折线图是可视化价格的好方法。通常,对于金融价格系列,我们希望使用 OHLC 条形图或蜡烛图:这些图表可以显示总结每天交易活动的所有价格(开盘价、盘高、盘低、收盘价),而不仅仅是收盘价。
为了在 Matplotlib 中绘制 OHLC 条形图和蜡烛图,我们需要使用 mplfinance 库。正如我在本系列的上一篇文章中提到的, mplfinance 的发展已经获得了新的动力,事情正在快速发展。因此,我们将只粗略地讨论如何使用它来创建我们的图表。
Mplfinance 提供了两种在图表中创建子图和添加指标的方法:
- 使用外部轴方法创建图表或多或少类似于我们目前所做的。Mplfinance 负责绘制 OHLC 或烛台图表。然后我们可以传递一个带有指示器的轴对象作为单独的子情节。
- 面板方法甚至比纯 Matplotlib 代码更容易使用: mplfinance 为我们控制所有的绘图和样式操作。为了处理图表的视觉方面,我们可以应用现有的样式或创建我们自己的样式。
在我写这篇文章的时候,外部轴方法发布还不到一周。我仍然期待着利用它来发现它所能提供的潜力。
作为使用 mplfinance 面板方法的尝试者,我们可以在单独的面板中绘制一个带有交易量的蜡烛图:
import mplfinance as mpfmpf.plot(data_sel, type='candle', style='yahoo', title="QQQ Daily Price", volume=True)
一个基本的 mplfinance 蜡烛图
我们也可以在单独的子图中添加 ROC 指示器:
# We create an additional plot placing it on the third panel
roc_plot = mpf.make_addplot(roc, panel=2, ylabel='ROC')#We pass the additional plot using the addplot parameter
mpf.plot(data_sel, type='candle', style='yahoo', addplot=roc_plot, title="QQQ Daily Price", volume=True)
我们的指标添加到图表中
结论
有几个软件包可以使用 Python 和 pandas 创建财务图表。特别是, plotly 因其创建好看的交互式图表的能力而脱颖而出。另一方面,Matplotlib 可能不会直接生成最好的图表(如果你需要的话,看看 seaborn )但是,它有巨大的定制潜力,可以创建在专业出版物中脱颖而出的静态图表。
这就是为什么我认为调整 matplotlib 的属性是非常值得的。mplfinance 的未来发展将使这些可能性变得更有吸引力。
风能交易:基于深度学习的风能预测模型
基于深度学习为能源交易者开发一个有利可图的风能需求预测模型。
Rabih Shasha 在 Unsplash 上的照片
动机
创造稳定的能源供应总是至关重要的,因为我们的现代社会真正依赖于此。这就是为什么化石燃料或核能等可预测的能源仍然是有利的。然而,能源短缺的风险将持续存在,促使我们使用金融来预测和避免未来可能导致停电的能源生产短缺。人们可以考虑利用可再生能源来应对这一挑战。
迄今为止,在这些可再生能源中,有些依赖于环境,例如风能。顾名思义,能量将由不同速度和方向的风产生。不幸的是,作为产生能量的唯一触发器,风是利用这种替代能源的明显障碍。
简而言之,我们有三方参与这一能源事务——电网运营商、能源生产商和能源交易商。电网运营商负责为社会提供稳定的电能供应。否则,如果停电,政府会对他们罚款。接下来,供应商将管理能源短缺的风险,风能生产商。通常情况下,能源交易员会帮助供应商提前预测出售给电网的能源产量。换句话说,能源交易商代表客户实现利润最大化。
目标
**我们将扮演能源交易员的角色。**目标是每小时获得一次 T+18 小时能量预测!使用我们的能源预测模型和给定的交易算法,我们将为我们的客户,即风能生产商,实现利润最大化。我们将使用深度学习(神经网络),特别是差分网络架构,基于时间序列数据集建立预测模型。
交易算法
来源:深度学习 Datathon 2020 (by ai4impact )
- 你需要对客户风电场的发电量进行 T+18 小时的预测。这个预测是你交易的核心
- 你的客户每向电网出售一千瓦时可获得 10 欧分。您只能向电网销售您预测的日期
- 如果实际发电量超过预测,超出部分将被电网吸收,但您的客户不会因此得到补偿。
- 如果实际发电量低于预测,您必须从现货市场购买能源(20 欧分/千瓦时)以供应电网。你有 10,000,000 欧分的现金储备,可以从现货市场购买能源。
方法学
- 检查随统计数据一起提供的数据。
- 标准化数据并设置基线风险(基于持久性)。
- 在风险函数上很好地拟合训练和测试集。测试损失应该超过基线风险。
- 提高模型性能(在减少滞后/保持零滞后的同时,不断降低风险)。
- 检查最佳模型的再现性。
检查数据
数据集
我们将使用如下两个不同的数据集:
1。风能生产 来源:法国能源传输管理局
该数据集名为 energy-ile-de-france,包含巴黎周围法兰西岛地区的统一近实时风能产量(单位为 kWh ),该数据已平均化并标准化为 1 小时的时基。数据提供时间为 2017 年 1 月 1 日至今。
数据不是真的有规律,但还是能看出一些趋势。例如,能量峰值在冬季和季节转换时最为常见。到目前为止,最大的发电量发生在 2019-2020 年冬季,高达 89000 千瓦时。数据的基本统计如下所示。
平均值= 17560.44 千瓦时
中值= 10500.0 千瓦时
最大值= 89000.0 千瓦时
最小值= 0.0 千瓦时
极差= 89000.0
标准差= 19146.63
2。风力预报 资料来源: Terra Weather
数据来自两种不同的风力预报模型(A 和 B),适用于法兰西岛地区的 8 个风电场。因此,有 16 个预报,每个预报有 2 个变量:风速(米/秒)和风向方位(北纬度-即。45 度表示风从东北方向吹来)。天气预报每天每 6 小时更新一次,并以 1 小时为时间基数进行插值。
风速图具有与能量图相似的趋势,表明这种预测数据可以作为输入特征用于我们的模型。关于这一点,最强的风出现在冬季,风速高达 12 米/秒。风数据的基本统计如下所示。
风速预测统计
与风速预测相比,风向模式很难解读。但是我们将会看到,即使这样的数据仍然可以给我们的预测模型带来好处。
最后,我们的原始数据排列如下:
原始数据集(31027 个示例)
标准化数据并设定基线风险
为了加快训练过程,我们将使用下面的公式对数据进行归一化处理,使平均值和方差都为零。
作者
标准化后的数据集
现在我们有了相同比例的每个特征。注意,我们只归一化能量和风速。风向值将在后面进行特殊处理。
接下来,我们将获得基于持久性风险的基线。我们使用均方误差(MSE)和平均绝对误差(MAE)提取基线风险。
- 持久性风险(MSE): 0.4448637
- 持久性风险(MAE): 0.6486683
开始实验!
使用差分网络结构,我们在风险函数(MSE 和 MAE)上很好地拟合训练和测试集。差异网络有助于我们更好地学习超越这个基线。提醒一下,我们的目标是获得提前 18 小时的能源预测。
作者设计的差分神经网络结构
以下是我们可以打开的几个超参数:
- 窗口输入特性(初始、差分、动量和力输入)
- 统计输入特征(平均值、标准差、最大值、最小值等)
- 优化器(Adam,SGD)
- 激活功能(Relu,Tanh)
- #隐藏层(2 至 5 层)
- 正规化(辍学,L2)
- NN 大小(8 到 256 个神经元,下一层减少 2/3)
- 子网(输入缩放、自动编码器)
- 感知器的类型(正常,平方感知器)
- 损失(MAE、MSE、动量损失、力损失)
事实上,这份名单太多了:)。但是请耐心等待,因为你会知道每个人对我们建立的模型有什么贡献。由于我们已经试验了很多次,我们将只向您展示提高我们目标的设置。
注意:每个实验使用 10000 次最大迭代和提前停止方法。
实验 1
输入缩放子网+ 4 个隐藏层(带辍学)
在第一个实验中,我们试图创建一个低 MAE(和 MSE ),它将超过基线。所以,我们希望自己的网络足够深,足够大,又不会过度拟合。因此,我们使用 Adam 来实现更好的学习,并添加一种称为 dropout layer 的正则化方法来防止过拟合。我们使用具有多重配置的 4 层网络,如下所示:
- 输入缩放子网络
- NN-尺寸:32/64/128/256
- 辍学概率:0.05/0.1/0.25
- 优化器:Adam
- 层数:4
实验一:特征选择
开窗是时间序列数据的基本操作。因此,对于输入特征,我们使用由过去 60 小时产生的能量(T-60)组成的窗口。然后,我们将窗口转换为不同动量力输入,提前时间为 18 小时。它将产生 72 个特征。这种调整有助于模型检测运动及其速率,以执行更好的聚类。
我们还添加了过去 60 小时的平均风速预测值和每个风模型在 T+18 小时的风速预测值。这又产生了 4 个特征。因此,我们总共有 76 个输入特征准备好提供给输入缩放子网。由于我们使用相对较大的输入,这个子网在将它提供给主网络之前减少了不需要的功能。
总之,这些是我们的输入功能列表:
- 差异+动量+T-60h 的力输入过去的能量产生于 18h 的提前期
- 预测的过去风速的 T-60h 平均值(模型 A)
- T+18 小时的风速预测(模型 A)
- 这同样适用于模型 B
实验一:最佳配置损耗
测试损失:0.554845(使用 MAE 作为损失函数)
实验一:评价
exp 的评估摘要。一
- 最佳测试损失/持续误差
MSE:0.280589/0.4448637
MAE:0.5544554865 - 最佳 NN 尺寸:128
- 最佳辍学概率:0.05
- 请注意,我们已经战胜了持久性,实现了零延迟。
- 训练和考输还是有很大差距的。可以考虑使用正则化,增加更多功能。
实验二
输入缩放子网+ 4 个隐藏层
(带辍学+ L2 正则化)
与之前的模型一样,我们在模型中加入了 L2 正则化。我们还运行多配置,同时考虑最佳超参数。
- 输入缩放子网络
- NN-尺寸:64/128/256
- 辍学概率:0.05/0.1
- 重量衰减:1.0E-4/1.0E-5/1.0E-6
- 优化器:Adam
- 层数:4
实验二:特征选择
我们添加了来自风向预测的新输入特征。虽然添加方向数据作为我们的输入有点无意义,但稳定的风向确实有所帮助。因此,我们不想天真地规范化方向,但我们将使用三角函数来“规范化”它。除了前一个,现在我们总共有 84 个输入功能个。
总之,这些是我们输入功能的补充:
- 过去风向预测的 T-18h(平均)sin 函数(模型 A)
- 过去风向预测的 T-18h(平均)cos 函数(模型 A)
- sin 函数中 T+18 小时的风向预报(模式 A)
- cos 函数中 T+18 小时的风向预报(模式 A)
- 这同样适用于模型 B
实验二:损失
测试损失:0.549824(使用 MAE 作为损失函数)
实验二:评价
exp 的评估摘要。2
- 最佳测试损失/持续误差
MSE:0.26769/0.4448637
MAE:0.54924/0.648864866 - 最佳 NN 尺寸:128
- 最佳辍学概率:0.1
- 最佳重量衰减:1.0E-4
- 请注意,我们已经产生了更好的测试损失,同时保持零滞后(也增加了滞后图的峰值)。
- 我们仍然可以通过向模型添加更多输入要素或图层来提高性能。
实验 3 —最终模型
输入缩放子网+ 4 个隐藏层
(带辍学+ L2 正则化)
通过设置固定的最佳超参数,以下是我们的网络配置:
- 输入缩放子网络
- NN-尺寸:128
- 辍学概率:0.1
- 重量衰减:1.0E-4
- 优化器:Adam
- 层数:4
实验三:特征选择
我们包括新的统计特征作为新的附加输入,取自能量和风速数据。最后,我们总共有88个输入特性。
- 过去产生能量的 T-60h 的平均值
- 过去产生的能量的 T-60h 的标准偏差
- 预测的 T-60h 过去风速的标准偏差(模型 A)
- 预测的 T-60h 过去风速的标准偏差(模型 B)
实验三:损失
测试损失:0.52758 (使用 MAE 作为损失函数)
实验三:评价
exp 的评估摘要。3
- 最佳测试损失/持续误差
MSE:0.258521/0.4448637
MAE:0.52758/0.6486683 - 以欧分计的净利润
MSE:1.392861351 e9
MAE:1.447243201 e9 - 我们使用最后一个模型实现了最佳测试损耗,同时没有延迟。因此,我们的利润是所有车型中最高的。
- 我们有更好的实际与训练/测试预测的散点图。虽然我们很适合训练集,但获得实际预测与测试预测的更好散点图仍然是一个挑战。
检查再现性
之前,上面的最终模型已经重复训练了 40 次,每次最多迭代 10000 次。请注意,我们使用 MAE 作为损失函数,因为它为客户提供了更高的利润。测试损失的统计如下所示。
均值= 0.540747
中值= 0.540757
最大值= 0.550977
最小值= 0.527580
范围= 0.023397
(均值-最小值)/标准差= 2.690480
最终模型预测
专门用语
- 增加更多的层减少了训练误差,但是增加了测试损失,降低了利润,尽管我们已经使用了正则化技术。因此,我们在最终模型中坚持使用 4 层。
- 自动编码器子网有助于减少输入特征的维数。然而,当添加到具有不超过 100 个特征的网络中时,它增加了我们模型的测试损失。
- 平方感知器被认为能提供比普通感知器更快更好的学习。然而,在实验过程中,它并没有在降低误差方面提高性能。
- 动量和力的损失被认为有助于减少滞后。然而,当我们将损耗加到网络上时,滞后图没有改变(仍然是零滞后),并且它使误差更高,因为网络需要将三个损耗(测试、动量和力损耗)一起最小化。
摘要
- 差分网络有效地利用时间序列数据建立预测模型,即使输入较少。
- 对于历史数据,DIFF 窗口与动量、力和统计特征相结合,可以帮助模型执行更好的预测。
- 更大更深的网络支持模型很好的记忆(小心过拟合)。
- 丢弃层(小丢弃概率)和 L2 正则化有助于网络处理过拟合问题,从而提高性能。
- 虽然 RMSE(或 MSE)作为时间序列数据中的损失函数也很受欢迎,但当使用 MAE 时,我们的模型会产生更高的利润。MSE 倾向于惩罚异常值,而 MAE 则更倾向于误差的线性。由于模型没有异常值,MAE 被证明最适合我们的模型。
本文是 ai4impact 组织的深度学习数据大会 2020 期间项目文档的一部分。
团队:Avektive
成员:Diardano Raihan,Mitchell Edbert,M. Taufiq Ismail Hatta
交通堵塞科学和可视化
曾经堵在路上,心想——如果别人开得更好,我就不会在这里了?德国物理学家 Kai Nagel 和 Michael Schreckenberg 在理解和模拟交通堵塞的出现方面取得了根本性的突破。事实证明,交通堵塞不是孤立的事件,事实上,它们是非常容易预测的。
模拟密度为 0.35 且 p =0.3 的 Nagel-Schrekenberg 交通模型。颜色指示车辆速度|塞犍陀·维维克
在 Nagel-Schrekenberg 模型中,汽车被模拟成网格单元上的离散物体。在每个时间步,车辆位置根据 4 个简单规则更新:
- **限速:**所有车辆行驶速度在 0 到限速之间。在最初的论文中,速度限制是“5”,所以车辆在 0 和 5 之间行驶。
- **加速至限速:**在每个时间步,只要车速低于限速,车速就会更新为当前速度+1。
- **如果太靠近前面的车辆,则减速:**如果一辆车辆以其当前速度将要撞上前面的车辆,则减速以避免碰撞。例如,在时间 t 时,一辆车距离它前面的车 3 个单元,并且它的当前速度是 4。车辆的速度减慢到 2,使得它从时间 t 到时间 t+1 仅移动 2 个单元的距离,以便不与前面的车辆重叠(不引起事故)。
- **随机减速:**每一个时间步长,车辆以一定概率减速 1, p 。如果 p=0.5,那么每辆车在每个时间步长都有 50%的机会减速。在这种情况下,如果速度是 3,它减少到 2,50%的时间。这代表了人类不完美的一面,导致了交通堵塞。
在视频中,你看到车辆向右移动,堵塞成核(红色车辆的补丁)与快速移动的车辆(绿色)的爆发相结合。这捕捉了走走停停的交通堵塞。密度为 0.35 表示 35%的单元被车辆占据。如果你有一个 100 格的网格,这意味着其中 35 格都是车辆。
可视化交通堵塞的时空图
密度为 0.35 且 p =0.3 的 Nagel-Schrekenberg 模型的时空图|塞犍陀·维韦克
可视化交通流的一种常用方法是时空图。深黑色区域表示车辆密度波。负斜率表示起始于时间 t=0 的最初上游交通堵塞在稍后时间向下游传播。例如,起始于位置 80 的阻塞在 t=100 时影响位置 30。
堵车的由来是什么?
p=0.3 |塞犍陀·维韦克的纳格尔-施勒肯伯格模型的速度与密度
随着车辆数量的增加,速度降低。在大约 0.2 的密度以上,速度急剧下降。这是因为在密度为 0.2 时,每辆车之间的平均间距为 1/0.2=5。为什么数字 5 很熟悉?因为 5 是可能的最大速度!因此,在这个密度以上,车辆开始感受到前面车辆的影响,并需要相应减速。
p=0.3 |塞犍陀·维韦克的内格尔-施勒肯伯格模型的通量与密度
通量密度图是理解交通堵塞出现点的另一个好方法。交通流量衡量单位时间内通过给定点的车辆数量(车辆通过量)。它基本上是一定距离内所有车辆的速度总和。在低密度下,每辆车基本上都以极限速度行驶,因此通量随着密度线性增加。然而,在较大的密度下,车辆不能以限速行驶,在某一点(这里密度= 0.2),较大数量车辆的影响被以较小速度行驶的每辆车辆抵消,导致流量减少。
有一个最佳车辆密度(单位距离的车辆数量),它使车辆吞吐量最大化。
现实世界中的交通堵塞
Nagel-Schrekenberg 模型很棒,因为它捕捉到了流量的关键特征。但是这些情节在现实世界中是什么样的呢?它们如何转化为真实的距离和速度?
2005 年 6 月 15 日,NGSIM 项目的研究人员在洛杉矶 101 号公路(也称为好莱坞高速公路)上收集了详细的车辆轨迹数据。
作为 NGSIM 项目一部分的车辆轨迹时空图|由塞犍陀·维维克绘制
时空图显示了与交通堵塞相关的独特波形。与 Nagel-Schrekenberg 模型相似,最初在上游 0.5 公里处成核的堵塞最终在大约 100 秒后到达下游 0.1 公里处。
作为 NGSIM 项目一部分的车辆轨迹数据|由塞犍陀·维维克绘制
来自飞行器轨迹数据的通量密度图看起来非常类似于 Nagel-Schrekenberg 图。然而,你看到的单位是不同的。在现实世界中,流量在大约 30 辆车/公里/车道的密度下开始下降。那一点为什么特别?包络计算的快速返回显示,30 辆车/km/车道对应于平均每辆车之间的 1000/30=33 m。一辆以 65 英里/小时(30 米/秒)速度行驶的汽车有 33/30 秒的时间——基本上是一秒钟到达前面的汽车。如果前面的人因为某种原因突然停下来,你有一秒钟的时间做出反应。
车辆以 30 辆/公里/车道的密度开始减速,因为这相当于 1 秒钟对前方车辆做出反应(以 65 英里/小时或 29 米/秒的速度行驶)。
总之,交通堵塞是人类驾驶不完善的结果。其中最重要的是开车时发出噪音的倾向——有时有人会无缘无故地停下来,或者没有以最佳状态开车。另一个原因是我们有一个有限的反应时间,这使我们远离前面的司机(通常是一秒钟)。一旦路上有太多的车辆,我们就会不舒服地靠近前面的车辆,而不会像在自由路段那样开车。下次你觉得如果人们更好地开车,城市的交通状况会有所改善,好好看看镜子里的人吧:)
如果你对自动驾驶汽车如何缓解交通堵塞感兴趣,请看看我的文章: 自动驾驶汽车能避免交通堵塞吗?
基于残差网络的交通标志分类
履行
用于交通标志分类的深度残差学习
汉斯·阿德里安·伯麦在 Unsplash 上的照片
深度卷积神经网络广泛应用于解决人工智能领域的各种计算机视觉任务。本文着重于开发一个深度学习模型,以便识别交通标志。🛑❌🚫🚷🚳
目录
- 数据分析
- 创建一个 ResNet 模型
- 模特培训
- 模型评估
- 预测
- 参考文献
首先,我们需要一个数据集来训练深度学习模型识别交通标志。 Kaggle Datasets 是为不同任务寻找数据集的最佳平台。比如机器学习(ML)、深度学习(DL)、数据科学。
这里有一个数据集,包含了 43 个类别的近 73139 个不同的交通标志图像。
大数据库的交通标志裁剪(+70%)
www.kaggle.com](https://www.kaggle.com/flo2607/traffic-signs-classification)
数据分析
在本节中,我们将使用一种简单的方法来分析数据集。
下面是一个简单的计数图,用于分析数据在类中的分布。以下代码用于绘制图表:
计数图 w.r.t 到类-作者图片
让我们来看看数据集中的一些样本。这将有助于我们理解数据。下面的代码通过绘制数据集中的 100 幅图像来实现这一目的。
来自数据集的图像-按作者分类的图像
创建一个 ResNet 模型
在这一部分,我们将创建一个深度学习模型来识别交通标志。
剩余网络
微软引入了深度剩余学习框架来克服“退化”问题,这是一项困难的优化任务。快捷连接,即跳过一层或多层。
这些快捷连接执行身份映射,并且输出被添加到堆叠层的输出中。这解决了许多问题,例如:
- 易于优化
- 它从大大增加的深度中获得准确性,产生比以前的网络架构更好的结果。
为了更好地理解深度剩余学习。使用 arxiv 上免费提供的题为“图像识别的深度残差学习”的研究论文。
[## 用于图像识别的深度残差学习
更深层次的神经网络更难训练。我们提出了一个剩余学习框架,以减轻训练…
arxiv.org](https://arxiv.org/abs/1512.03385)
我们将使用 TensorFlow 应用模块,该模块提供了不同的流行深度学习模型,并预先训练了可供使用的权重。
[## 模块:TF . keras . applications | tensor flow Core v 2 . 2 . 0
通过 TensorFlow 学习 ML 基础知识的教育资源
www.tensorflow.org](https://www.tensorflow.org/api_docs/python/tf/keras/applications/)
我们将使用没有预训练权重的 ResNet50 架构。我们在最后添加了 softmax 激活的密集层来预测类。下面是用来创建模型。
您可以看到使用 plot_model 方法创建的模型的可视化。
模特培训
这些是在训练过程中使用的参数。批量大小为 32,时期为 50,学习率为 0.001,损失度量为“分类交叉熵”,优化器为“Adam”。回调 ModelCheckpoint、EarlyStopping、ReduceLROnPlateau 和 CSVLogger 用于 ResNet50 模型的定型。你可以使用下面的链接来了解回调的具体细节。
回调是可以在训练的不同阶段执行动作的对象(例如,在一个时期的开始或结束…
keras.io](https://keras.io/api/callbacks/)
以下代码用于编译和拟合模型。
训练数据和验证数据在不同时期的准确性之间的图表。
准确性图表—作者提供的图片
训练和验证数据上的跨时期损失之间的图表。
损失图-按作者分类的图像
你可以看到损失和准确性在 20 个时期后收敛。
模型评估
分类报告
让我们看看分类报告,它有助于评估模型。
输出结果以精度、召回率、F1 分数的形式表示每个类。
混淆矩阵
混淆矩阵用于描述分类模型的性能。以下代码用于生成混淆矩阵:
合成的混淆矩阵如下所示:
混淆矩阵-作者图片
分类准确性
使用下面的代码可以获得类级精度:
预言
使用经过训练的 ResNet50 模型,来自未知数据的少量样本被用于预测类别标签。以下代码用于此目的:
未知数据的预测如下所示:
预测-作者图片
我为该任务编写的代码可以在 Kaggle Notebook 中找到。请随意使用。以下是链接:
使用 Kaggle 笔记本探索和运行机器学习代码|使用来自交通标志分类的数据
www.kaggle.com](https://www.kaggle.com/syamkakarla/traffic-sign-classification-using-resnet?scriptVersionId=35560377)
参考文献
用于图像识别的深度残差学习,何,,,任,;IEEE 关于…的会议
openaccess.thecvf.com](http://openaccess.thecvf.com/content_cvpr_2016/html/He_Deep_Residual_Learning_CVPR_2016_paper.html) [## 计算机视觉模型
“西蒙·普林斯(Simon Prince)的精彩著作提出了一种基于模型的计算机视觉方法,这种方法统一了不同的…
www.computervisionmodels.com](http://www.computervisionmodels.com/)
基于深度神经网络的交通标志识别
皮尤什·马尔霍特拉、普内特和塔尼什克·查莫拉
贾维尔·基罗加在 Unsplash 上拍摄的照片
在当今世界,随着车辆数量的增加,道路事故也在增加,据报道,印度是事故数量最多的国家之一。这是由许多原因造成的,如执法不力、粗心大意等。原因之一是人们不认识或不遵守交通标志板。因此,我们制作了一个交通标志识别器,它可以通知车辆驾驶员前方有交通标志,并跟随它。这可以减少交通事故。
卷积神经网络
卷积神经网络是深度学习的一部分,广泛用于图像识别。这些卷积神经网络由几层组成。首先,Conv2D 层用于在过滤器的帮助下进行特征提取。过滤器的数量通常是 2 的幂,如 32、64 或 128。在这一层中使用了激活功能。通常使用 ReLU(整流线性单位)激活功能。ReLU 函数被定义为最大值(0,x)。
接下来是最大池层,用于减少图像的尺寸。这样做是为了减少处理图像所需的计算能力。第三是辍学层。该脱落层用于防止过度拟合,并降低模型的复杂性。在这一层中,一些神经元被随机移除。
前三层的组合称为特征学习阶段。这三层被多次使用以改善训练。
第四个是 flatten 层,它将二维数据转换为一个完整连接层的长一维特征向量,该向量可以输入到神经网络中。
最后一层是密集层,用作输出层。最后一层的节点数量与类的数量相同。最后一个密集层使用 softmax 激活功能。Softmax 函数给出概率值(在 0 和 1 之间),以便模型可以预测哪个类的概率最高。
交通标志识别
1.资料组
我们采用了 2011 年国际神经网络联合会议(IJCNN)上举行的德国交通标志基准单幅图像分类挑战赛的数据集。链接—【kaggle.com/meowmeowmeowmeowmeow/gtsrb-german-traffic-sign
该数据集由 39,209 幅交通标志图像组成。
2.导入必要的库
我们将为此使用 Python 语言。首先,我们将导入必要的库,如用于构建主模型的 keras、用于分割训练和测试数据的 sklearn、用于将图像转换为数字数组的 PIL 以及其他库,如 pandas、numpy、matplotlib 和 tensorflow。
**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**import** **matplotlib.pyplot** **as** **plt**
**import** **cv2**
**import** **tensorflow** **as** **tf**
**from** **PIL** **import** Image *]*
**import** **os**
**from** **sklearn.model_selection** **import** train_test_split
**from** **keras.utils** **import** to_categorical
**from** **keras.models** **import** Sequential, load_model
**from** **keras.layers** **import** Conv2D, MaxPool2D, Dense, Flatten, Dropout
**import** **tqdm**
**import** **warnings**
3.检索图像
我们将检索图像及其标签。然后将图像大小调整为(30,30),因为所有图像都应该具有相同的大小以便识别。然后将图像转换成 numpy 数组。
data = []
labels = []
classes = 43
**for** i **in** range(classes):
path = os.path.join(os.getcwd(),'train',str(i))
images = os.listdir(path)
**for** j **in** images:
**try**:
image = Image.open(path + '**\\**'+ j)
image = image.resize((30,30))
image = np.array(image)
data.append(image)
labels.append(i)
**except**:
print("Error loading image")*#Converting lists into numpy arrays bcoz its faster and takes lesser #memory*data = np.array(data)
labels = np.array(labels)print(data.shape, labels.shape)
4.分割数据集
将数据集分为训练和测试。80%训练数据和 20%测试数据。
X_train, X_test, y_train, y_test = train_test_split(data, labels, test_size=0.2, random_state=68)
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
5.构建模型
为了构建,我们将使用 keras 库中的顺序模型。然后,我们将添加层,使卷积神经网络。在前 2 个 Conv2D 层中,我们使用了 32 个过滤器,内核大小为(5,5)。
在 MaxPool2D 层中,我们保留了池大小(2,2),这意味着它将选择图像的每个 2 x 2 区域的最大值。通过这样做,图像的尺寸将减少 2 倍。在脱落层,我们保持脱落率= 0.25,这意味着 25%的神经元被随机移除。
我们再次应用这 3 层,参数有一些变化。然后,我们应用扁平化层转换二维数据到一维向量。这一层之后是致密层、脱落层和再次致密层。最后一个密集层输出 43 个节点,因为交通标志在我们的数据集中被分为 43 个类别。该层使用 softmax 激活函数,该函数给出概率值并预测 43 个选项中哪一个具有最高概率。
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(5,5), activation='relu', input_shape=X_train.shape[1:]))
model.add(Conv2D(filters=32, kernel_size=(5,5), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(rate=0.25))
model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(rate=0.25))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(rate=0.5))
model.add(Dense(43, activation='softmax'))
6.应用该模型并绘制精确度和损耗的图表
我们将编译该模型,并使用拟合函数来应用它。批量大小将是 32。然后我们将绘制精确度和损耗的图表。我们得到了 97.6%的平均验证准确率和 93.3%的平均训练准确率。
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])history = model.fit(X_train, y_train, batch_size=32, epochs=2, validation_data=(X_test, y_test))model.save("Trafic_signs_model.h5")
*#plotting graphs for accuracy*
plt.figure(0)
plt.plot(history.history['accuracy'], label='training accuracy')
plt.plot(history.history['val_accuracy'], label='val accuracy')
plt.title('Accuracy')
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.legend()
plt.show()*#plotting graphs for loss*
plt.figure(1)
plt.plot(history.history['loss'], label='training loss')
plt.plot(history.history['val_loss'], label='val loss')
plt.title('Loss')
plt.xlabel('epochs')
plt.ylabel('loss')
plt.legend()
plt.show()
7.测试集的准确性
我们在测试集上获得了 94.7%的准确率。
**from** **sklearn.metrics** **import** accuracy_scorey_test = pd.read_csv('Test.csv')
labels = y_test["ClassId"].values
imgs = y_test["Path"].values
data=[]
**for** img **in** imgs:
image = Image.open(img)
image = image.resize((30,30))
data.append(np.array(image))
X_test=np.array(data)
pred = model.predict_classes(X_test)*#Accuracy with the test data*
print(accuracy_score(labels, pred))
图形用户界面
现在模型已经准备好了,所以我们可以在界面(GUI)上创建一个图形用户了。我们使用 tkinter 库来制作 GUI。图形用户界面代码:
输出
作者 GIF
结论
因此,我们开始了解卷积网络以及它们如何用于图像识别。我们利用卷积神经网络进行了交通标志识别,在验证集和测试集上的准确率分别达到了 97.6%和 94.7%。
完整的代码可以在下面的 github 库中找到:交通标志识别
谢谢你。
使用 TensorFlow 2.x 识别交通标志
从原始图像处理到模型评估的端到端示例
左:TensorFlow logo。图片来源:tensorflow.com 右:原始和灰度交通标志来自下面的数据
介绍
TensorFlow 是一个软件库,以其在神经网络中的灵活性和易用性而闻名。您可以在网上找到许多从图像分类到对象检测的示例,但其中许多都基于 TensorFlow 1.x。从 TensorFlow 1.0 到 2.0 有一个很大的变化,Keras 集成更紧密,重点是更高级别的 API。很多方法已经折旧了(也可以用tf.compat.v1
)。模型构建变得容易多了,每个模型中的默认参数已经可以很好地用于一般用途。尽管有这么多好处,但如果您需要更改参数,它仍然提供了灵活性。
在这篇文章中,我将使用 TensorFlow 2.0(更具体地说,TensorFlow 中的 Keras)对交通标志进行分类。网络上很多地方都有数据集,但我将使用 Kaggle 上的这个。
数据概述
数据包包括Train
、Test
和一个test.csv
的文件夹。有一个meta.csv
和一个Meta
文件夹来显示每个交通标志的标准图像。还有一个signname.csv
用于将标签映射到它的描述。Train
文件夹包含 43 个子文件夹,子文件夹的名称是其中图像的标签。例如,文件夹0
中的所有图像都有一个类别标签0
等等……这些图像的大小从 20x20 到 70x70 不等,并且都有 3 个通道:RGB。
所以我要做的第一件事是将所有图像的大小调整为 32x32x3,并将它们读入 numpy 数组作为训练特征。同时,我创建了另一个 numpy 数组,其中包含每个图像的标签,这些标签来自加载图像的文件夹名称。
我需要做同样的测试图像。然而,用于测试图像的标签与该图像的路径一起存储为test.csv
中的ClassId
。所以我使用 pandas 来读取csv
文件,从 path 加载图像并分配相应的ClassId
。
从训练集中,我随机抽取了 20%作为模型训练过程中使用的验证集。训练和验证的模型精度将为我们提供关于欠拟合或过拟合的信息。
接下来,我将图像转换成灰度,并对每个像素进行归一化处理。归一化使模型收敛更快。
这是 RGB 和灰度图像之间的比较。灰度图像仍然保留其特征,并且可以被识别,但是尺寸小得多。
原始图像和灰度图像的比较
模型构建
我将使用 Yann LeCun 等人在 1998 年发表的著名 LeNet,输入形状为 32x32x1。第一个卷积层的深度为 6,过滤器大小为(5,5),跨距为(1,1)。使用了有效的填充(即没有填充)。因此,该层的宽度(或高度)为 32–5+1 = 28,即形状为 28x28x6。该层的激活是 relu。
第一个卷积层之后是最大轮询层。它通过仅选择相邻像素的最大值像素来有效地缩减数据。LeNet 使用(2,2)内核大小。默认步幅与内核相同,这意味着从其中选择最大值的像素组之间没有重叠。现在输出的形状变成了 14x14x6。
下一个 LeNet 有第二个卷积层,深度为 16,过滤器大小为(5,5)和 relu 激活函数,后面是最大池层。输出的宽度(或高度)现在是(14–5+1)/2 = 5,即形状是 5x5x16。
然后,数据在完全连接的层之前被展平。输出的形状是 5x5x16 = 400。随后是 2 个完全连接的层,尺寸为 120 和 84,relu 作为两者的激活功能。增加一个脱落层以减少过度拟合。最后是大小为 43(类的数量)的全连接层。Softmax 用于返回每个类别的概率。
模型训练和评估
Keras 的培训非常简单。我们只需要指定优化器、损失函数和验证度量。在 10 个时期内,训练和验证的准确度都在 0.97 以上。对于脱层,没有明显的过度拟合。另一方面,增加训练只会产生最小的改善,所以我只在 10 个周期后就停止了。
我们还可以绘制每个时期训练和验证的模型性能。事实上,该模型似乎相当一般化,并且没有过度拟合训练数据。
每个历元的训练和验证的准确性和损失
最后,利用该模型对测试集的标签进行预测。精度在 0.925 左右。
结论
之前我写过一篇关于从零开始构建神经网络的文章,这需要核心的线性代数。通过使用 TensorFlow 这样的库,任务变得容易多了,模型也更强大了。
可以从 这里 获取完整代码。
使用 AWS Sagemaker | PyTorch 训练 GAN 并生成人脸
在 Unsplash 上拍摄的“我的镜头人生”
我想你已经听说过或研究过 GAN。如果你以前没有听说过,那么生成敌对网络(GAN)是一种神经网络架构,允许我们创建合成数据、图像或视频。它已经成为深度学习中一个有趣的子领域。不同类型的 GAN 包括 DCGAN、CycleGAN(CGAN)、GauGAN、StyleGAN、Pix2Pix 等。由于它是如此受欢迎,新类型的甘文件和建筑出现,因为我们说话!
虽然有许多不同的 GAN 架构,但它们都有一个共同点。为了训练一个 GAN,他们需要大量的计算能力,他们渴望 GPU。所以在本地环境中训练一个 GAN 真的很难,除非你有时间和金钱建立一个好的分布式 GPU。否则你可以利用云来训练甘。云环境可以用于各种神经网络训练,并且不限于 GAN 的。我在本地环境中运行时遇到了问题,所以我使用了云,并且能够轻松地进行培训并快速将其部署到生产环境中!
有不同的云提供商,我觉得 AWS 在许多领域领先于其他云提供商。特别是在机器学习领域,AWS 有不同的服务可以利用。所以在这篇博客中,我们将看看由 AWS 提供的 Sagemaker 服务。
Amazon SageMaker 是一个完全托管的服务,它为我们提供了快速构建、训练和部署机器学习(ML)模型的能力。SageMaker 的另一个巨大优势是,机器学习模型可以用更少的努力更快地部署到生产中。是的,一些云提供商比 AWS 便宜,但是 sagemaker 在部署方面有其他优势。在开发模型时,如果您有本地 GPU 环境,您也可以利用它。
在这个博客中,我们将生成新的面孔(再次!)通过训练名人数据集。为了生成新的图像,我将使用我的本地 GPU 环境(以节省一些钱)进行开发和健全性测试,并使用 Sagemaker 来训练一个成熟的模型。我还将展示如何为部署创建端点。
由于有大量关于 AWS 帐户设置和本地环境设置的文章,我将跳过这一部分。如果你有任何问题,请在评论区提问。Sagemaker 可以通过 AWS 服务控制台页面访问。
现在 Jupyter 笔记本有两种选择。
- 使用本地环境
- Sagemaker 环境
当地环境: 如果你有一个适合 Jupyter 笔记本的当地环境,那么恭喜你!通过使用本地环境进行开发和健全性测试,您可以节省一些钱。您安装 Sagemaker python 包并在本地使用 Sagemaker 函数。如果您的 GPU 启用了 Cuda,那么您可以使用它来测试整个代码并提交您的作业 sagemaker。下面是设置本地环境的步骤。全部代码都在我的 Github 页面中
步骤 1:安装包
在你的虚拟环境中安装 Sagemaker python 包https://pypi.org/project/sagemaker/
第二步:连接到你的 AWS 账户
,假设你已经创建了一个 AWS 账户,并且拥有 Sagemaker 和 S3 bucket 访问权限。您还可以在您。AWS/配置文件。
您还需要一个 IAM 角色来执行 sagemaker。它需要完全访问 Sagemaker。
import sagemaker
import boto3sagemaker_session = sagemaker.Session(boto3.session.Session(
aws_access_key_id='xxxxxxxxxxxxx',
aws_secret_access_key='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
region_name='update your AWS region'))bucket = sagemaker_session.default_bucket()prefix = 'sagemaker/dcgan'role = 'sagemaker_execution_role'
您可以通过在 S3 存储桶中上传测试数据来测试连接,并使用以下命令进行检查
input_data = sagemaker_session.upload_data(path=data_dir, bucket=bucket, key_prefix=prefix)
input_data
如果你没有得到任何错误和数据是在 S3 桶,那么你是好的开始。如果您遇到任何错误,请调试并纠正问题。或者,您可以在这里提供 S3 桶链接,并从 S3 下载数据进行本地测试。
Sagemaker 环境: 如果没有本地环境,可以启动 sagemaker Jupyter 笔记本。这将启动一个计算实例,并为 Jupyter 笔记本电脑部署所需的容器。
步骤 1:启动笔记本
转到笔记本实例部分 sagemaker 并创建一个笔记本实例
接下来,您可以设置 S3 bucket 和 IAM 角色。根据您的需求和规模选择云实例的大小和其他技术细节。
现在,我们可以开始“创建”了。AWS 需要一些时间来准备笔记本。我们可以在控制台上看到笔记本实例处于“挂起”状态。
准备好后,点击“打开 Jupyter”笔记本。你现在可以开始训练你的 GAN 了。
甘模型训练:
我用 PyTorch 来训练 GAN 模型。在训练之前,它需要一些预处理。如果您使用本地环境,您需要上传 S3 存储桶中的数据。下面是您需要执行的一些处理。
- 转换输入图像并使它们具有相同的大小。
def get_dataloader(batch_size, image_size, data_dir):
"""
Batch the neural network data using DataLoader
:param batch_size: The size of each batch; the number of images in a batch
:param img_size: The square size of the image data (x, y)
:param data_dir: Directory where image data is located
:return: DataLoader with batched data
"""
transform = transforms.Compose([transforms.Resize(image_size),
transforms.ToTensor()])
dataset = datasets.ImageFolder(data_dir,transform=transform)
#rand_sampler = torch.utils.data.RandomSampler(dataset, num_samples=32, replacement=True)
#dataloader = torch.utils.data.dataloader.DataLoader(dataset, batch_size=batch_size,shuffle=False, sampler=rand_sampler)
#dataloader = torch.utils.data.dataloader.DataLoader(dataset, batch_size=batch_size,shuffle=True)
return dataloader
测试时,您可以对输入数据集使用随机采样器,并在数据加载器中使用它。
2.缩放图像
缩放图像是神经网络中的一个重要步骤。在执行 GAN 时尤其如此。
def scale(x, feature_range=(-1, 1)):
''' Scale takes in an image x and returns that image, scaled
with a feature_range of pixel values from -1 to 1\.
This function assumes that the input x is already scaled from 0-1.'''
# assume x is scaled to (0, 1)
# scale to feature_range and return scaled x
min, max = feature_range
x = x * (max - min) + min
return x
3.创建模型
当执行 GAN 时,需要训练两种类型的网络。一个是生成器,另一个是鉴别器。发电机的输入来自潜在空间或噪声。一个生成器被训练来生成图像,一个鉴别器被训练来检测图像是真是假。在生成器和鉴别器之间玩这个游戏的最终输出是来自生成器的看起来像真实图像的真实输出。
如前所述,GAN 还有其他架构。然而,这是甘背后的想法。型号代码在 Github repo 的 model.py 中提供。我已经使用卷积测试编写了一个 DCGAN 模型
4.训练模型
这是我们要利用云的一步。在 sagemaker 中运行许多 epochs 之前,使用样本数据在本地环境中测试完整的工作流。
一些超参数需要调整,如学习率、β1 和β2。我从这篇论文中选出了它https://arxiv.org/pdf/1511.06434.pdf
一旦进行了健全性测试,就该将这项工作提交给 sagemaker 了。使用 sagemaker PyTorch API 创建一个估计器对象,并调用 fit 方法。
from sagemaker.pytorch import PyTorchestimator = PyTorch(entry_point="train.py",
source_dir="train",
role=role,
framework_version='0.4.0',
train_instance_count=4,
train_instance_type='ml.p2.xlarge',
hyperparameters={
'epochs': 15,
'conv_dim': 64,
})estimator.fit({'training': input_data})
上面的代码需要注意以下几点:
- 你可以改变 ML 框架。Sagemaker 支持 PyTorch、Tensorflow 等所有主流框架。
- 需要指定所有代码所在的源目录,如我的 GitHub 存储库中所示。
- 需要指定 Pytorch 框架版本。培训目录还应包含 requirement.txt 文件,其中包含数据处理和培训中使用的所有软件包。
- 实例类型取决于您需要多大的计算实例。如果你正在训练一个 GAN,我至少更喜欢 p2.xlarge,因为它包含 GPU。建议使用支持 GPU 的计算服务器。否则模型将永远训练下去。
一旦你调用了 fit 方法,它应该会创建一些日志,如下图所示。它正在启动一个计算实例并训练模型。
不同的颜色突出显示它使用不同的计算实例。我们还打印鉴频器和发电机损耗。现在你可以让它训练,直到它完成。
如果您的训练时间很长,您的内核会话可能会结束。不要担心,因为我们在云中训练,我们可以很容易地附加到我们通过下面的代码运行的会话。可以在 sagemaker 控制台中找到作业名称。
estimator = estimator.attach('sagemaker-job-name-2020-xxxxx')
一旦模型被训练,你就可以部署它了。
5.部署模型:
将模型部署到另一个计算能力较低的计算实例。但是,如果您需要 GPU 进行预测,请使用 p2.xlarge 或更高版本。该模型还可以通过实例计数参数以分布式方式提供服务。
predictor = estimator.deploy(initial_instance_count = 1, instance_type = ‘ml.m5.large’)
部署后,您可以获得端点名称
6.结果-生成面孔
部署模型后,是时候从我们训练好的模型生成人脸了。
#Generate random noise
fixed_z = np.random.uniform(-1, 1, size=(16, 100))
fixed_z = torch.from_numpy(fixed_z).float()sample_y = predictor.predict(fixed_z)
我已经在我的 Github repo 中添加了所有文件。
制作:
一旦我们部署了模型和端点,我们就可以创建一个可以通过 API 网关调用的 AWS Lambda 函数。API 可用于从任何应用程序生成图像。
所有的代码和包都在我的 Github 中找到,我希望你能利用这个故事中的回购。
有问题吗?评论?请在评论区留下您的反馈。
获取代码
要获得文章的完整工作代码和其他更新,请订阅我的 简讯 。
训练一个 GPT 2 变形金刚来写哈利波特!
用数据做酷事!
哈利波特图片,来源:【https://unsplash.com/photos/WE7YfTGpXlg
介绍
自然语言处理是近来越来越受欢迎的领域。世界各地的许多公司都在利用自然语言处理的能力和该领域的创新,从文本中提取有意义的见解并生成文本。在过去的几年里,随着谷歌大脑的注意力是你所需要的全部论文的发表,变形金刚架构已经进一步革新了这个领域。在几乎所有经典的 NLP 任务中,如机器翻译、问题回答、阅读理解、常识推理和总结,基于 Transformer 的架构击败了最先进的架构。从那时起,所有的科技巨头,如谷歌、脸书、OpenAI、微软,都在各种应用中试验 Transformer。
一个成为头条新闻的应用程序是语言生成任务,其中变形金刚能够根据提示生成有意义的文本。第一个头条新闻是 HuggingFace 的对话变形金刚网页,任何人都可以通过给出提示来生成他们自己的人工智能生成的文本。在这里,我们将探讨如何在语言生成中使用变形金刚。同样在博客的后面,我们将分享如何在你自己的语料库上训练 transformer 语言模型的代码。我们用哈利波特系列训练了一个 GPT-2 模型。当输入时,经过训练的模型能够生成像哈利波特书籍一样的文本。请参见下面的示例。我的 Github 上有完整的代码。
有趣的观察:1。模特得知海格有一双大脚!, 2.吉德罗·洛哈特写书,3。新书可以出现在霍格沃茨的书架上。
哈利波特 GPT2 模型输出
原文全文发表在我的网站这里。
什么是语言模型?
语言模型是学习预测单词序列概率的模型。简单地说,语言模型本质上是在给定一些文本的情况下预测下一个单词。通过在特定文本上训练语言模型,有可能使模型学习该文本的写作风格。虽然过去存在各种各样的语言模型,但在谷歌大脑团队推出变形金刚之后,它们变得更加强大(“注意力是你所需要的全部”)。
随着 transformers 的出现,多个小组能够为语言模型创建和训练定制的架构。一个这样的团体是开放人工智能社区,他们引入了 GPT(T2 的缩写,生成预训练转换器)。GPT 模型于 2018 年发布,但不幸的是,在发布后不久,它就被 BERT 从 GLUE 排行榜上除名了。但是,在 2019 年 2 月,OpenAI 通过对庞大的 15 亿个参数进行训练,扩大了他们的模型,这反过来又赋予了它类似人类的写作能力。它被命名为open ai 的 GPT-2”。
图 1: 出自https://blog.openai.com/better-language-models/。
变形金刚和 GPT 2
Transformers 是语言模型背后的基本架构。转换器主要由两个基本组件组成:编码器和解码器。
如上图所示,编码器和解码器都有可以堆叠在一起的模块,如 Nx 所示。主要地,编码器和解码器都具有前馈和多头注意力组件。
论文中的变压器架构—“关注是你所需要的”
在将输入和输出传递给组件之前,它们被嵌入到一个 n 维空间中。输入和输出组件中的一个重要步骤是位置编码,其中我们向转换器提供关于单词位置的信息。这些编码被添加到每个单词的嵌入中,生成的嵌入被传递给转换器。
编码器块具有多个编码器块,而解码器块具有相同数量的解码器块。块数是一个超参数,可以在训练时进行调整。
编码器-解码器架构
编码器-解码器堆栈的工作描述如下:
- 输入嵌入被传递到第一编码器。
- 嵌入在通过编码器的前馈和自关注层之后被转换。
- 转换后的输出被传递到下一个编码器。
- 最后一个编码器将输出传递给堆栈中的所有解码器。
编码器和解码器中的自我注意层在文字处理中起着非常重要的作用。它使模型能够查看输入序列中的其他单词,以更好地理解当前单词的上下文。
除了前馈和注意组件,解码器还有另一个注意层(掩蔽多头注意),帮助解码器关注输入序列的特定部分。
OpenAI 在两次迭代中扩展了语言生成任务的变形金刚概念:GPT 和 GPT-2。GPT 架构使用 12 层解码器,带掩蔽自关注头,训练 100 个纪元。使用 GPT-2 模型,词汇量扩大到 50,257 个单词。上下文大小也从 512 个令牌增加到了 1024 个令牌,并且使用了更大的批量 512。
潜入代码!
在这篇博客中,我们将利用令人敬畏的 HuggingFace 的变形金刚库来训练我们自己的 GPT-2 模型,使用哈利波特书中的文本。我们将向模型提供一个句子提示,模型将完成文本。为了训练模型,我们会喂饱所有哈利波特的书,让模型从中学习。
我们已经克隆了 huggingface repo,并更新了代码以正确执行语言模型训练和推理。请跟随我的 Github 回购。
下载哈利波特书籍并预处理文本
第一步是下载所有的哈利波特书籍并预处理文本。我们把前四本书的课文刮下来,合并在一起。然后我们写了一小段代码来删除合并文本中不必要的文本,比如页码。最后,GPT 新协议模型需要训练和验证文本。因此,我们将前 90%的数据作为训练样本,其余的数据作为验证样本。这里的预处理代码是。
训练一架 GPT-2 模型
为了训练模型,我们使用脚本 run_lm_finetuning.py。该脚本将模型类型及其大小以及预处理文本作为输入。该脚本还提供了一组可以调整的超参数,以便定制训练过程。培训的代码片段是:
cd examples ## Move to examples directory
python run_lm_finetuning.py \
--output_dir=output \
--model_type=gpt2 \
--model_name_or_path=gpt2-medium \
--do_train \
--train_data_file='input_data/train_harry.txt' \
--do_eval \
--eval_data_file='input_data/val_harry.txt'\
--overwrite_output_dir\
--block_size=200\
--per_gpu_train_batch_size=1\
--save_steps 5000\
--num_train_epochs=2
代码中使用的参数如下:
这里使用的参数解释如下:
- Output_dir 是存储模型权重的文件夹名称。
- Model_type 是模型的名称。在我们的例子中,我们在 gpt-2 架构上训练,我们使用“gpt-2”。
- 模型名称或路径是我们定义要使用的模型大小的地方。(“gpt2”代表小型,“gp T2-中型”代表中型型号,“gp T2-大型”代表大型型号)
- Do_train 本质上是一个标志,我们定义它来训练模型。
- train_data_file 用于指定训练文件名。
- Do_eval 是一个标志,我们定义是否评估模型,如果我们不定义它,就不会计算出困惑分数。
- Eval_data_file 用于指定测试文件名。
- gradient_accumulation_steps 是一个参数,用于定义在执行向后/更新传递之前要累积的更新步数。
- Overwrite_output_dir 是一个参数,当指定该参数时,将使用新的权重覆盖输出目录。
- block_size 是一个参数,根据该参数,训练数据集将被截断成这个大小的块用于训练。
- Per_gpu_train_batch_size 是用于训练的每个 GPU/CPU 的批处理大小。
- 保存步骤-允许您在最终设置权重之前定期保存权重
- num_epochs —确定运行多少个 epoch。
我们根据 4 本哈利波特的文本训练了一个中型的 GPT-2 模型。这款车型在一辆 GTX 1080 Ti 上训练只花了 10 分钟。训练模型的困惑分数是 12.71。阅读这个博客来了解更多关于困惑分数的信息。但是记住,分数越低,模型越好。
推理脚本
一旦模型被训练,我们就可以使用它进行推理。推理脚本是 run_generation.py
为了进行推理,输入文本首先通过标记器进行编码,然后结果通过一个生成函数进行传递,在该函数中,基于温度、top-p 和 k 值等参数生成文本。
进行推断的代码片段是:
cd examples
python run_generation.py --model_type gpt2 --model_name_or_path output --length 300 --prompt "Malfoy hadn’t noticed anything."
这些参数解释如下:
- 模型名称或路径:这是存储训练模型权重的文件夹路径。
- Prompt:这是输入提示,其余文本将基于该提示生成。
- Length:该参数控制输出中要生成的字符的长度。
一些可以调整的附加参数是:
- 温度:这个参数决定了模型在单词选择上的冒险程度。
来源:https://medium . com/hugging face/how-to-write-with-transformer-5ee 58d 6 f 51 fa
- p:这个参数控制延续的范围有多广。将其设置为高,以考虑所有延续。将其设置为低,以便仅考虑可能的延续。整体效果类似于温度,但更微妙。
- k:该参数控制概率序列中的波束或并行搜索的数量。值越高,精度越好,但速度越慢。
- 种子:该参数有助于设置种子。
- Repetition _ penalty:该参数惩罚重复所选单词的模型。
下面是模型输出的另一个例子。非常有趣的是看到这个模型创造的隐形人的故事。
经过训练的哈利波特模型的另一个输出
结论
变形金刚的出现真正革新了许多自然语言处理任务,语言生成就是其中之一。语言生成模型的潜力是巨大的,可以在许多应用程序中利用,如聊天机器人、长答案生成、编写自动报告等等。在这篇博客中,我们了解了 transformers 的工作原理,它们是如何用于语言生成的,以及一些例子说明了任何人如何利用这些架构来训练他们自己的语言模型并生成文本。
总的来说,我对 NLP、变形金刚和深度学习非常感兴趣。我有自己的深度学习咨询公司,喜欢研究有趣的问题。我已经帮助许多初创公司部署了基于人工智能的创新解决方案。请到 http://deeplearninganalytics.org/.的— 来看看我们吧
你也可以在 https://medium.com/@priya.dwivedi 的看到我的其他作品
如果你有一个我们可以合作的项目,请通过我的网站或 info@deeplearninganalytics.org 联系我
参考
- 变形金刚——注意力是你需要的全部。这是开始这一切的文件
- 伯特
- GPT-2 模型
- 抱脸回购
训练一个神经网络,在 10 分钟内对图像进行分类并优化 CPU 推理
最小化设置/转移学习/快速优化
英特尔 OpenVINO 工具包的可示教机器 2.0 图像项目
有大量关于简化训练和优化预训练推理模型的资源。然而,用最少的努力在现成的硬件上训练一些定制的东西来优化性能似乎仍然遥不可及!
在本文中,我们将利用迁移学习的概念,其中一个训练有素的图像分类模型用于在您的设备浏览器中使用可示教机器 (GUI)训练我们的定制用例(例如,您餐具室中的物品),并使用英特尔 OpenVINO 工具包优化 CPU 推理,而无需任何痛苦的软件安装(当然只需 10 分钟!).
优化有必要吗?跳到最后的性能比较。
实时演示
我事先需要做什么准备?
- 第六代至第十代英特尔酷睿或英特尔至强处理器
(即,如果您购买了 2016 年以后发布的英特尔设备) - Docker 安装在可以上网的 Linux 系统上hub.docker.com
- 使用摄像设备(如网络摄像头)
训练并将模型导出到您的本地机器
为培训捕获数据
- 在你带摄像头的笔记本电脑或桌面设备上,导航到https://teachablemachine.withgoogle.com/train/image
- 编辑 类别 标签(如麦片盒、曲奇)并根据需要添加
- 使用 Hold to Record 按钮从实时预览中捕捉几帧
- 对每个班级重复这一过程,最后点击训练模型按钮
注意:不要切换你的浏览器标签,让训练结束 - 在最右边的预览面板中测试,点击导出模型
- 在上导出你的模型…弹出点击第二个第二个第三个标签第三个张量流
- 选择 Keras 后,点击下载我的模型
这可能需要一些时间,但一个名为 converted_keras.zip 的文件最终会被下载。
导出 TF Keras 模型以进行局部推理和优化
将任何可示教的机器 2.0 图像项目 Keras 模型转换为 CPU 优化的 OpenVINO IR 格式
我已经创建了一个带有实用程序的 repo 来自动执行此操作,所以您不必这么做!确保系统上安装了 docker 、internet access、 *unzip、*和 git 。
克隆或下载/提取回购:
git clone [https://github.com/ojjsaw/teachable-machine-openvino.git](https://github.com/ojjsaw/teachable-machine-openvino.git)
替换 repo 目录中的自定义 converted_keras.zip 文件,并从 repo 根目录运行以下脚本。第一次下载 docker 图像可能需要几分钟时间。
./util_conv_teachable_to_openvino.sh
我的 repo 中的 Util 脚本,用于自动转换
在测试映像上运行英特尔 CPU 优化推理
确保捕获与您的定制训练模型相关的测试图像,并运行下面的代码。
仅在 TF Keras v1.15.0 模型到 OpenVINO IR 转换(包括移除训练节点)后,在 test.jpg 上使用 OpenVINO 推理 4ms 。
docker run --rm -it -v ${PWD}:/workdir openvino/ubuntu18_dev:latest /bin/bashcd /workdirpython3 teachable_img_openvino_classify.py frozen_model.xml frozen_model.bin labels.txt test.jpg
OpenVINO CPU 推断时间:4 ms**(test.jpg)**
性能比较
可教机器网站提供 TF Keras python 代码用于本地推理。
在我的例子中,使用默认示例代码和模型的预测函数花费了804 ms*(~ 1.2 fps),而在上一节的同一个test.jpg 图像上使用 OpenVINO python 代码仅仅花费了 4ms (~250fps) 。***
docker run --rm -it -v ${PWD}:/workdir tensorflow/tensorflow:1.15.0 bashcd /workdirpip install Pillowpython teachable_img_keras_orig_classify.py keras_model.h5 test.jpg
原 TM2.0 推断时间:804 ms(test.jpg)****
在一个实时摄像机上运行 OpenVINO 推理
第一个命令支持从 docker 呈现 OpenCV 预览窗口。
xhost + docker run --rm -it --privileged -v ${PWD}:/workdir -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -v /dev/video0:/dev/video0 openvino/ubuntu18_dev:latest /bin/bash cd /workdir python3 teachable_livecam_openvino_classify.py frozen_model.xml frozen_model.bin labels.txt
在 TM2.0 导出/转换模型上使用网络摄像头进行 OpenVINO 推理
结论
确实存在用日常硬件在本地快速训练定制图像分类模型的流程。
不需要修改代码,只需点击几下鼠标。
考虑到不需要任何额外的努力,在英特尔 CPU 上使用 OpenVINO 推理技术来减少(800 毫秒到 4 毫秒)的额外努力也是完全值得的!