TowardsDataScience 博客中文翻译 2019(一百二十三)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

预测体育结果的自动化框架

原文:https://towardsdatascience.com/creating-an-automated-framework-for-predicting-sports-results-5fe01623d74b?source=collection_archive---------11-----------------------

我如何建立一个自动化的机器学习框架来预测橄榄球比赛的结果,并在没有任何监督的情况下发布输出

我最近决定开始一个兼职项目,将我对橄榄球的热爱与我对数据科学的热爱结合起来——于是梅尔橄榄球诞生了。Mel 是我用 R 编程语言创建的一个框架,它首先从网上的各种来源收集橄榄球比赛的数据,然后通过一组预先训练的机器学习模型运行这些数据,以产生最终比分的预测,最后将预测的输出和准确性发布到@mel_rugby twitter 帐户。

在这篇文章中,我将讨论一些我必须考虑的要点,我是如何开发这个框架的(作为一个非机器学习专家),最后,我学到了一些经验。

动机

我从 4 岁开始玩橄榄球,所以当我大约一个月前想到一个潜在的项目时,这是我首先想到的话题之一。鉴于橄榄球世界杯(RWC)将于几周后开幕,这似乎是一个完美的时机。所以我着手做了一些关于如何最好地预测体育比赛结果的研究——大部分集中在足球或 NFL 上。根据以前的经验,我知道接下来要做的最好的事情就是开始,看看我能走多远,所以我就这么做了!

工具

在这个项目中,我使用了 R,因为它是我最精通的语言。使用 Python 可以获得相同的结果(也许更有效),但就我个人而言,这会花费我更多的时间。我用的主要包有: rvestXML 2&RSelenium用于抓取数据; dplyrtidyrstringr&lubridate进行数据角力;脱字符号 & 神经网络用于训练模型;以及在推特上公布结果的 T21。在这一点上还值得注意的是,我着手使整个框架尽可能自动化。因此,整个项目本质上是一组嵌套的函数,它们依次相互调用。下面是当前流程的示意图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Flowchart outlining the current process of the Mel Rugby framework

目前,所需要的是每隔几天运行一次“master()”——这可以被安排或在线托管以实现完全自动化。

获取数据

首先要克服的问题是获得一些我可以用来模拟橄榄球比赛的数据。我很早就决定,调查每一场橄榄球比赛将会大大增加所需的时间和精力,不仅因为它将包括用不同的结构收集数据,而且影响国际比赛和国内/俱乐部比赛的因素也不太可能相同,因此考虑两者可能需要不同的模型。随着世界杯的临近,国际比赛数据是最容易获得的,我决定只考虑国际比赛,如果可能的话,以后再把框架扩展到国内比赛。在网上搜索后,我找到了一个网站,里面包含了从 20 世纪早期开始的所有国际比赛的基本数据。

变量的选择

在考虑变量时,我可以使用两种通用方法——关注团队层面的变量或个人变量。在这里,我受到可用数据的限制:每场比赛的个人球员数据更难获得,也更不可靠(至少我使用的数据源是这样)。澄清一下,我这里指的是诸如身高、体重、近期表现等信息。在玩家层面。我能够获得每个球员之前为国家出场次数的信息,并将其整合到我的模型中。

一旦我决定专注于球队层面的变量,我就争论各种数据来源,以获得一支球队可能影响比赛结果的明显特征,包括:他们的总上限数(我最终分成前锋的总上限和后卫的总上限);他们最近的表现(过去 5 场比赛);他们目前的排名(为此我使用了我自己的——与 IRB 官方排名非常相似,但略有不同——以及他们是在主场、客场还是在中立场地比赛(大多数 RWC 奥运会都是如此),等等。

型号选择

过程的这一部分出乎意料的简单和快速。我目前正在改进现有的模型,并希望有“第二阶段”模型很快实施。我绝不是机器学习方面的专家,所以一旦我粗略地研究了以前是如何处理这个问题的,我就开始尝试不同的模型和模型组合,直到我找到一个相对更好的组合。对于那些感兴趣的人,我开始使用主成分神经网络(PCANNet)和线性支持向量机(LSVM),两者都将两个团队的特征作为输入,然后输出每个团队的预测分数。然后我取了两个分数预测的简单平均值,因为这被证明是最准确的。

在第一阶段的模型被训练并在即将到来的几场比赛中测试后不久,很明显模型失败的一个方面是在一个球队“逃脱”的比赛中。在这些比赛中,一支球队获得了动力,并最终轻松获胜(超过 20 分),这些比赛我称之为“大胜利”。我决定开发一些模型来解决这个问题,这导致了:

  • 一个用于预测比分的套索回归模型,假设其中一个队将以特别大的优势获胜
  • 一种随机森林分类器,试图确定一个团队是否可能在给定的游戏中以特殊的优势获胜。

这意味着对于每场比赛,每支球队都会产生一个预测得分和一个预测的“大胜”得分。如果随机森林暗示比赛中的一个队会彻底消灭他们的对手,我用“大胜”分数作为预测。这产生了积极的影响——例如,在撰写本文时,新西兰最近以 63 比 0 击败了加拿大。最初的模型预测新西兰以 43–5 获胜,但是“大胜”随机森林模型将比赛分类为可能以大胜结束,因此选择了“大胜”得分预测,预测结果为 66–0,这大大提高了模型的性能。

交流输出

从这个项目一开始,我就想确保这个框架所做的预测有一个公开的记录,为了透明,也为了增加对这个项目的参与。我决定使用 Twitter 有几个原因,最重要的是因为 rtweet 软件包让自动化一个 Twitter 账户变得非常容易。因此,我建立了@mel_rugby twitter 账户,并编写了一些功能来获取预测并发布它们,包括根据预测的情况添加表情符号,以便让 mel 看起来更有感觉和更有吸引力。

经验教训

我现在每三天手动打开一次项目并运行主功能。我仍然这样做,以防意外出现错误(这种情况已经好几次没有发生了,所以祈祷继续发生吧!),但实际上我可以设置我的笔记本电脑在预定的时间运行该框架,甚至付费让它在线托管,这样我就可以忘记它,它就可以运行了。我在这个项目中学到的一个关键教训是我从数据科学专家那里一次又一次听到的,但只是刚刚开始意识到:数据来源和清理比实际训练机器学习模型花费更多的时间和精力。

当前性能和未来添加

梅尔目前在预测方面是一个非常混杂的包,许多已经被 bang on 和其他人没有那么多。我对第二阶段模型投入生产感到兴奋,因为我相信这将大大改善预测。有关梅尔如何预测结果/分数的更多信息,请查看梅尔橄榄球推特账户!

就该项目的未来补充而言,我已经开始开发一个 web 应用程序,它将允许人们与 Mel 进行交互,并查看比分预测如何变化,例如:比赛日阵容中挑选的确切球员;从现在到正在讨论的游戏之间将要进行的游戏的结果;当天的天气;和其他变量。如上所述,我还在研究模型的第二阶段,我希望 a)提高用作输入的数据的质量和数量,b)提高对“冷门”的预测,即低排名球队击败高排名球队,以及 c)研究球员水平的表现模型,以及如何使用这种模型来增强得分预测。我还计划增加 Twitter 机器人 Mel 的复杂性,以便它可以与查询进行交互和响应。这可能最终会被托管在某个地方,所以我可以让它无限期地运行下去!

结论

感谢阅读,我希望你觉得这很有趣!如果你想让我再写一篇文章详细阐述以上任何一点,请在下面留下评论。我正在考虑一个更详细的帖子,要么是关于建立一个 Twitter 机器人,要么是关于数据转换过程的更多细节。如果你觉得这有用或有趣,请鼓掌,并与其他可能喜欢它的人分享!

页(page 的缩写)如果你想知道这个项目的名字,我最初把它叫做 rugbyML(机器学习),但是为了让它更有个性,我想给它取一个人类的名字,所以叫“ML”->“Mel ”!

为数据科学创建一个简单的网站抓取器

原文:https://towardsdatascience.com/creating-an-easy-website-scraper-for-data-science-sports-prediction-pt-1-f024abd53861?source=collection_archive---------23-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

收集数据是任何机器学习项目的重要部分,但许多教程倾向于使用已经以方便的格式存在的数据。这对于案例来说是很好的,但是对于学习整个过程来说不是很好。在现实世界中,并不是所有的数据都可以在谷歌上找到…至少现在还不行。这是教程的一部分,我们收集所有必要的统计数据来训练我们的神经网络进行 NHL 预测,但更重要的是,我将向您展示如何应用这些概念并从万维网上收集您想要的任何数据。

突出

  • 构建刮擦环境
  • 使用 selenium 删除 HTML
  • 美颜组处理
  • 写入 CSV 文件

先决条件

  • 必须能够理解 Python

1-概述

对于这个例子,我们将采用整个赛季的 NHL 每日游戏统计数据。输出将由两行数据组成,每行是一个队对比赛的看法。这些数据将以 CSV (逗号分隔值)格式保存到一个文本文件中,这本质上只是一个 excel 工作表,但它没有用线来分隔单元格,而是用逗号和换行符。作为参考,我们将从 NHL.com 每日统计页面的开始,以包含 2.1k 行的输出文件结束:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A single day worth of data, in CSV format

这项工作所需的工具

from bs4 import BeautifulSoup as soup
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from numpy import array
import pandas as pdimport csv
from datetime import date

Selenium 本质上是一个库,它可以打开一个 web 浏览器实例并自动与之交互,而 BeautifuSoup 是从页面中提取 HTML 以供我们使用的。 NumpyPandas 都用于数据处理和格式化,如果你只是想制作一个 web scraper,这是不需要的,但是因为我们稍后将在 Tensorflow 中使用这些数据,所以立即使用 Numpy 数组是最容易的,特别是考虑到我对这些数据的计划(更不用说它比常规 Python 逻辑更有效)。

2-网页到 HTML

进入实际的抓取,我们首先需要一个可以访问网页的功能,并把它变成更加用户友好的东西。实现这一点的计划是简单地创建一个简短的方法,该方法将在 selenium 中打开页面,获取 HTML(每个网页都有的基于文本的框架),将其转换成可以使用的,然后将其返回给用户。

这个简短的方法完成了实际“刮擦”的所有步骤。如果你给它一个 URL,页面的 HTML 将会以一种功能性的格式返回,你可以从中找到你所需要的内容。让我们深入了解它的工作原理。

def url_to_soup(url):
    # selenium driver setup
    driver = webdriver.Firefox() # get url
    driver.get(url) # create sauce (raw HTML) using driver
    source = driver.page_source
    driver.close() 

第一步是定义一个 web 驱动程序,它本质上就是 selenium 将要使用的浏览器。我喜欢 Selenium 的一点是,它可以实时自动打开网页,这样你就可以看到程序的每个动作。我决定用火狐。你可以使用任何浏览器,selenium 将完成访问该浏览器的所有工作,这非常简单,只需定义你想使用的浏览器。现在你所要做的就是给驱动一个 URL,它会自动打开页面,但是不要忘记一旦你完成了从页面中拉出,就关闭驱动

变量包含从页面中提取的原始 HTML。我用“原始”这个词是因为它就是这样,原始而杂乱。我们必须首先把这种文本风暴变成我们可以轻松享用的汤。因此,我们简单地通过接受两个输入的“soup”函数来运行它;源页面和解析器

解析器函数不是您可能知道的解析器。您可以查看 B.S .文档来找到不同种类的解析器,但是它们都做相同的事情,即清理 HTML 以便我们可以用自己的代码解析它。有些可能行得通,有些则不行,但在这种情况下,‘lxml’恰好做到了。不过有一个技巧。在指定解析器之前,必须打开命令行并下载解析器。既然我选择了 lxml,我必须首先做:

$ pip install lxml

在这之后,您就可以运行接下来的两行代码了…

# soup(input, parser)
url_soup = soup(sauce, 'lxml')# return the parsed soup
return url_soup

3-收集有效数据

在我们能消化汤之前,我们需要先收集它。到目前为止,我们所做的只是定义了一个从单个网页中删除数据的方法,但是我们需要整个赛季的每日游戏数据,所以我们将多次调用这个方法。因此,首先我们需要找出一种方法来快速收集所有这些信息,并将其保存在一起进行处理。

理解这个 web scraper 的一个重要概念是 URL 的操作。NHL 网站碰巧对表中的每个统计数据实例都使用相同的 URL 结构。下面是一个 NHL.com 每日统计页面的链接。如你所见,这个 URL 中嵌入了一个日期,在两个不同的地方。如果您将这些更改为不同的日期,您会发现该链接仍然有效,您将被重定向到包含该特定日期统计数据的页面。

[http://www.nhl.com/stats/team?reportType=game&dateFrom=2018-10-08&dateTo=2018-10-08&gameType=2&filter=gamesPlayed,gte,1&sort=points,wins](http://www.nhl.com/stats/team?reportType=game&dateFrom=2018-10-08&dateTo=2018-10-08&gameType=2&filter=gamesPlayed,gte,1&sort=points,wins)

我们可以利用这一点,只需自动修改嵌入 URL 的日期。为了让我们将这个概念付诸实施,我们需要一个函数,它将为任何特定日期生成到 NHL.com 页面的链接,这正是下面五行代码所做的。

def nhl_daily_data(year, month, day):
    nhl_daily = f"[http://www.nhl.com/stats/team?reportType=game&dateFrom={year}-{month}-{day}&dateTo={year}-{month}-{day}&gameType=2&filter=gamesPlayed,gte,1&sort=points,wins](http://www.nhl.com/stats/team?reportType=game&dateFrom={year}-{month}-{day}&dateTo={year}-{month}-{day}&gameType=2&filter=gamesPlayed,gte,1&sort=points,wins)"
    nhl_soup = url_to_soup(nhl_daily)

该函数通过使用 f 字符串来实现这一点。您可能不熟悉这个工具,但它是 Python 3.6 的默认版本。实际上,无论您在函数的参数中输入什么日期,f 字符串都会填充 NHL.com URL 中的年、月和日位置。然后,它利用前面的 url_to_soup() 函数来返回该页面的 soup。所以不用分别调用这两个函数,这个函数会替你做。

例如,如果您想要查找 2018 年 10 月 8 日玩的游戏的统计数据,您可以使用这些参数调用函数: nhl_daily_data(2018,10,08) ,然后它会从这个特定的 NHL.com 网页中提取调味汁,通过解析器运行它,并以汤的形式返回它。

您可能会问自己,为什么在您的项目中需要这个函数?事实是,也许你不知道。找到网络数据的第一步是想出一个攻击计划。也许你想要的所有信息都存储在同一个页面上,在这种情况下,你可以跳过这一步,只需一次扫描就可以得到你需要的所有数据。如果你不能使用这个 URL 技巧,selenium 提供了“手动”点击的功能,你可以使用它来浏览网站,你可以在 Selenium 的文档中找到这些功能。

接下来,我将亲自讲解如何阅读 HTML,这样你就可以告诉你的程序要寻找什么。

3.1-阅读 HTML

为了完成下一部分,你需要知道如何阅读 HTML。第一步是导航到你需要数据的页面,我去了一个随机的每日 NHL 统计页面。看看你的数据在页面上的位置。你可以看到游戏的统计数据都被嵌入到某种表格中,所以很可能这个表格是它自己的类。您的数据可能不像我的数据一样在一个独特的 JavaScript 元素中,但是过程仍然是一样的。

接下来,右键单击要使用的文本信息,然后按“检查元素”。这将在您的 web 浏览器中打开检查窗格,您可以在其中找到该页面的所有类和子类。浏览这些,找到你想要的对象、图表或信息所在的类的“路线”。你需要这个来告诉你的铲运机去哪里找。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

When selecting the “rt-table” class, the table on the web page is highlighted.

find() 函数是在代码中寻找你所需要的东西。我们不需要让程序遍历 HTML 中的每个文件夹来找到表格,你只需要指定要查找哪个类,然后 BeautifulSoup 就会找到它。

# finding table data
table_body = nhl_soup.find(attrs="rt-table").find(attrs='rt-tbody')

这个一行程序在 python 中定位保存表数据的类,并将其转换为对象“table _ body**”**,然后我们可以解析该对象来记录我们需要的数据。

该表实际上是二维数组的格式;每个游戏有两个数组。每个数组都是一个队对那场比赛的看法的统计数据。

3.2-收集信息

下面的大块代码可能看起来很难,但实际上我们已经到了最后阶段。

# loading the game data
game_data = []# finding the chart and looping through rows
for rows in table_body.find_all(attrs="rt-tr-group"):
    row_data = []

通过阅读 HTML,我们可以简单地使用 find() 函数,并在它前面放置一个 for 循环,它将自动提取类中的所有内容,一次一行。但是我们不能就此止步,因为 table 元素中包含的不仅仅是我们想要的数据,还有一些我们不想要的数据,比如标题和分部。如果我们查看表的数据部分的特定 HTML,可以看到它有一个不同的标签: td (表数据)。这意味着我们需要做一个嵌套的 for 循环,以便将搜索范围缩小到这个表数据。

 # looping through row data
    for td in rows.find_all():
         row_data.append(td.text)
         game_date = f"{year}-{month}-{day}" enemy_team = row_data[4][14:].lstrip()
         win = row_data[8]
         loss = row_data[9]
         over_time = row_data[11]
         points = row_data[12]
         goals_for = row_data[13]
         goals_against = row_data[14]
         shots_for = row_data[17]
         shots_against = row_data[18]
         power_play_goals_for = row_data[19]
         power_play_opportunities = row_data[20]
         power_play_percent = row_data[21]
         power_play_goals_against = row_data[23]
         penalty_kill_percent = row_data[24]
         faceoff_wins = row_data[25]
         faceoff_losses = row_data[26]
         faceoff_win_pct = row_data[27]row_data = [game_date, team_name, enemy_team, home_away, win,   loss, over_time, points, goals_for, goals_against, shots_for, shots_against, power_play_goals_for, power_play_opportunities, power_play_percent, power_play_goals_against, penalty_kill_percent, faceoff_wins, faceoff_losses, faceoff_win_pct]
    game_data.append(row_data)
    return game_data

这为我们找到了行数据的列表,一次一行。然后,我们可以选择我们想要的信息,对其进行分类并保存。

4-唯一剩下要做的事…省省吧

为了把它包装成一个我们可以使用的漂亮的蝴蝶结,我定义了一个批处理收集方法。这个方法调用 nhl_daily_data() 方法,在一个日期范围内一次调用一天。这将为我们收集的所有内容创建一个图表,然后将其作为 CSV 文件写入您的计算机。

def batch_collection(start_date, end_date):
    season_dates = pd.date_range(start=start_date, end=end_date)
    for date in season_dates:
        print(date)
        year = date.year
        month = date.month
        day = date.day
        chart = array(nhl_daily_data(year, month, day)) # .txt to CSV
        with open('2017-2018season.txt', "a") as output:
            writer = csv.writer(output, lineterminator='\n')
            writer.writerows(chart)

从这里开始,这些数据将需要更多的处理,但我们需要的一切现在都以一种易于阅读的格式集中到一个文件中。

创建一个可解释的机器学习算法

原文:https://towardsdatascience.com/creating-an-explainable-machine-learning-algorithm-19ea9af8231c?source=collection_archive---------12-----------------------

用选股结果构建一个可解释的机器学习算法是什么、如何做以及为什么

何必呢?

几年前,我开始学习 Python 和 R,目标是学习如何应用它们的优化、统计、数据科学、机器学习和数据可视化包和库。

我还购买了股票市场数据(赛马数据不可用),抱着测试各种模型的想法,我有几个目标:

  1. 了解模型的工作原理
  2. 学习 Python 和 R
  3. 找出那些可能是好的投资对象的股票

我有运筹学(任何阅读本文的数据科学家都可以使用的规范分析)背景,并在各种行业中用 PL1、Fortran 和 Fortran 统计和优化库、C 和 SAS 进行了大量建模,以解决各种业务问题。所以目标(1)和(2)并不难实现。

对于我尝试过的所有算法来说,确定要投资的股票是非常具有挑战性的。这就是原因 1。

开发自定义 ML 算法的原因包括:

理由 1: 用现有软件为建模难题提供解决方案。

理由 2: 如果我要投资我的钱,参与这个游戏,我想知道为什么这个模型选择某一只股票作为投资候选,而不是另一只。什么样的特征组合在推动决策?

原因 3: 如果算法有效,我想将它应用于另一个问题,能够向最终用户解释它可以加快其接受程度并降低成本。模型开发成本不仅包括处理数据和估计模型权重、优化功能或模拟策略所花费的时间。它们还包括测试、监控和最终用户变更。变更&假设问题可以将宁滨数据包含到当前使用的区间、首选区间或更直观的区间,甚至可以从模型中添加或删除特征或决策变量。

理由 4: 通过创建自己的机器学习算法,组件和功能很容易修改,因为代码是自己写的。

原因 5: 在再次读到“机器学习模型在 X 行业没有用,因为它们缺乏透明度”后,我决定看看是否可以创建一个“透明的机器学习模型”。我喜欢尝试解决问题的挑战。

**原因六:**我喜欢编码。

建什么?

当我想到这一点时,我决定瞄准最容易理解的有用模型— 记分卡

记分卡

对于那些不熟悉记分卡的人来说,记分卡用于决定是否给申请人贷款。他们对违约风险进行排序——较高的分数比较低的分数风险更小,并且可以根据赔率或概率进行调整。

记分卡构建流程可能包括:

(1)宁滨连续变量(特征)变成一组 0/1 输入。

(2)使用一些度量来评估预测能力——通常是信息值,有时是比率。

(3)选择将用于估计模型的特征。这可以是自动化的,也可以由建模者来完成。

(4)使用线性回归、逻辑回归或数学规划来估计模型权重。

(5)通过将权重放大到整数,将分数缩放或校准到好/坏的赔率或概率。

(6)通过对每次观察的权重(现在是整数点)求和来对数据进行评分。在信用评分中,特征通常被称为特性,特征的 bin 是属性。每个特征只属于一个属性箱,因此评分要么是表查找和求和,要么是矩阵乘法。

一旦模型被估计,它就被呈现给终端用户,终端用户通常希望其他特征被用作预测器或以更直观、更合意或符合商业目标(例如针对特定人群)的不同方式将特征归入模型中。这是一个迭代的过程,如果很容易理解模型是如何工作的,这个过程可能会变得更容易。

何苦呢?

为了提供一个详细的答案,我们去了赛马场,问了这样一个问题:一些赛马赌徒比银行家聪明吗?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

赌马的人可能会考虑这些因素:

  • 赛马获胜次数
  • 马匹速度等级
  • 骑师历史表演
  • 比赛类型
  • 赛跑距离
  • 参加比赛的马的数量
  • 支付赔率
  • 等等。

可能的模型特征,如那些可能用于银行信贷风险模型或选股模型的特征。

银行通常不会直接优化回报。回报赔率不进入记分卡,而是在第二步进行估计,通常是对违约损失进行线性回归。尽管事实上有些违约的客户是有利可图的——他们在还清大部分贷款后才违约,而有些没有违约的账户是无利可图的——他们在所有初始化和处理成本被覆盖之前就还清了贷款。

老练的赛马投注者使用凯利标准来确定他们可用资金的最佳部分来投注一场比赛。

要下注的凯利分数= p 减(1-p) *亏损/盈利

其中 p 是获胜的概率,亏损/盈利是收益几率的倒数。

因此,与银行家不同,老练的赛马投注者在下注时有亏损和盈利,并在每次下注时将亏损和盈利比率融入他们的决策中。

何苦呢?

如果我们只是估计记分卡的权重,以获得概率估计值或对观察值进行分类,我们可以很容易地使用一个可解释的模型(逻辑回归或线性规划等)来完成。)或者更难解释的模型(神经网络、随机森林等)。).

所有这些模型都有一个共同点:

它们对整个人口进行预测。他们的目标函数不是针对最终目标的。

在选择候选股票进行投资的情况下,我们所追求的是每周考虑投资的 N 只股票的列表,并根据它们与凯利标准相关的预期回报进行调查。

我们根本不关心大多数的家畜。那么,为什么要在模型的损失函数中考虑它们呢?

我们可以构建一个模型,让它根据案例的利润和损失,而不仅仅是成功的概率,计算出最大化或最小化案例数量的分数。

这在看股票时尤其重要,因为回报率最高的股票可能看起来很像投资导致灾难的股票。

我们希望有一个算法,传递高回报的股票,其预测特征的配置文件也包括高风险的股票,我们希望有一个分数,而不是 2 个模型。

如何?

我一直找不到一种数字绘画(链接处伟大的音乐插曲)类型的算法来解决这个问题,我们希望生成一个分数,只识别观察的一个子集,并希望用更高的分数来优化选择。

设置步骤:

**第一步:**定义目标函数。在选股的情况下,上面已经做过了。具体来说,我们希望每周产生 10 只具有最高预期回报的股票。

**第二步:**计算模型开发样本中每只股票的表现。

步骤 3: 从模型开发样本中选择所有可能的预测特征。

**第四步:**将数据分割成模型、验证、测试和预测(超时)段。创建一个索引数组或列表,将每个观察值映射到它的段。

步骤 5: 使用模型数据,对每个特征进行分类,将任何缺失值放入它们自己的分类中。对于该特征,使用步骤 2 中的性能定义计算其交互信息值。如果需要,可以使用其他测量方法。箱应该有一些最小数量的观察值或最小百分比的观察值。宁滨过程通常不像人们假设的那样重要,因为优化在非常粗糙/宽的宁滨间隔下仍然工作良好。

**第 6 步:**根据第 5 步的结果,选择将进入模型的一组特征,去掉那些具有低信息值或其他预测能力度量的特征。

步骤 7: 在选择了特征之后,为步骤 5 中的每个箱建立具有 1 列的 X 矩阵。如果观察值不在箱中,则该列包含 0,如果在箱中,则该列包含 1。这将极大地增加 X 矩阵的大小,这也是不为一个特征创建大量条柱的另一个原因。所有线段都应在 X 矩阵中,每次观察一行。

学问

最后,我们到了学习的部分。这是你可以真正获得创意和测试想法的地方。

我采用的方法是实现一种改进的进化算法。有几个选择和定制的任何适应你想测试。

这里的基本思想是重复这些步骤:

(1)生成一个可能的解决方案(在这种情况下是一组整数记分卡权重)。

(2)使用 X 矩阵和权重对数据进行评分

(3)评估解决方案(在这种情况下,根据每周挑选的得分最高的股票数量计算预期回报)

(4)确定是否和/或如何记住好的解决方案并忘记较差的解决方案

(5)基于记忆中的好解集进行探索

(6)时常朝着更好的解决方案前进。当选择前 N 个评分观察值时,优化函数中有一个 if 语句,这使得情况变得复杂。这是通过评估内存中的解决方案,并通过调整搜索区域来确定要探索或收敛的区域来实现的。

可以尝试的可用方法包括:

  • 遗传算法
  • 粒子群优化
  • 贝叶斯优化
  • 随机搜索
  • 禁忌搜索
  • 基于上述内容或其他内容的其他定制方法

可能并入算法的其他模型的组件:

  • 正规化
  • 限制
  • 批量标准化
  • 最终模型的退出或其他特征选择
  • 学习速度和/或动力

超参数

必须设置几个超参数:

  • 每个要素的条柱数量-可以是所有要素的相同数量,也可以是每个要素的不同数量
  • 一个箱中的最小观察数
  • 如果 L1 和 L2 正则化都被使用
  • 要做的最大迭代次数
  • 没有改进的最大迭代次数
  • 保留在学习者记忆中的最大观察次数
  • 实施任何优化所需的其他参数

合奏

如果需要模型解的集合,当算法终止时,可以容易地从存储器中的模型解中产生。

选股结果

部门:技术

细分市场:高波动性

绩效范围:4 周

观察期:52 周

模型中的特征数量:30

X 矩阵的列数:134

唯一股票代码数量:535

限制:

  • 一年中挑选的唯一股票报价机的最小数量= 40
  • 这用于防止算法学习挑选特定的股票

学习模型:简单的概率搜索,每 100 次迭代学习更新一次

最大迭代次数:400 次

合奏:

  • 生成了 10000 个不同的模型
  • 每个模型选择由截止分数确定,截止分数设置为所有库存周模型分数的 90%,即库存周级别的 0/1 分数
  • 库存周级别的得分=模型得分之和/ 10

记分卡的部分样本

下面显示了两个特性的样本特性得分和初始值。这里的下限是仓位的下限,第一个仓位是股票在过去一个季度中低于-31.54%的所有表现值,最后一个仓位高于 48.58%,缺失值为 0 分。

我们可以很容易地理解,该模型喜欢上个季度下跌很多的股票(它们得到 19 点)和上周上涨超过 1.66%的股票。它确实奖励了上周上涨超过 11.61%的账户,给他们 47 个点,而严重惩罚了那些下跌超过 5.93%的账户。

所有 30 个特性都有类似于表中 2 的分数,因为显示的记分卡是所有分数的平均分。

Performance (Quarter) 

        cut    points
     ------    ------
       -inf        19     0.38
     -31.54        -8    -0.13
     -12.02         0     0.01
      48.58         7     0.12
        nan         0     0.00

 Performance (Week) 

        cut    points
     ------    ------
       -inf       -56    -0.71
      -5.93        -6    -0.22
       1.66        27     0.43
      11.61        47     1.11

剧情

该图显示了不同的 50 分区间的综合预期收益和股价上涨的概率。整体方法导致以下分数分布:

42%的观察得分为 0。

24%的人得分在 1 到 25 分之间。

然后,每个分数仓中的观察值数量下降到 450–499 的范围是最后一个范围,至少有 1%的库存周观察值。

最后,950-999 的得分范围只有 0.45%的观察得分那么高。

有趣的是,模型在处理价格上涨的概率价格上涨的百分比减去价格下跌的概率价格下跌的百分比的乘积时,在分数范围内仍然具有几乎单调增加的概率(上涨),同时扩大了损益之间的差距。

通过将一个桶中的平均损耗和增益除以所有桶中的最大增益来计算预期损耗和增益的指数,以便于在同一图表上绘图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最高评级股票 COUP 的回报与得分的关系图。

点数是在 52 周的模型开发样本中,第 120 周得分最高的 10 只股票的不同得分的观察值。

可以看出,随着得分的上升,回报分布(y 轴)的变化和风险降低。还要注意的是,前 10 名的最高回报在 0 分范围内——没有一个模型选择它,因为它看起来太像风险更高的股票周配置文件。基本上 0 分会有一个期望值< the population expected value since both the probability and gain to loss ratio are going up over the score range.

The vertical black line indicates the score for COUP in the current week when the model was run.

The model results can be used to estimate targets for individual observations by tabulating the outcomes in the ranges. The first number after target is the expectation if COUP goes down in price at the end of 4 weeks, the second if it goes up and the probability that COUP will go up.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论:

机器学习可以被合并到一个灵活的简单易懂的模型中,即一个整数值记分卡。

这样做允许建模者通过直接计算结果来提供更适用的解决方案。没有必要估计分类概率,对它们进行排序,然后计算第二个模型来获得特定观察的影响大小。

关于使用什么组件、求解过程和正则化,有大量的选项。

对于那些有此倾向的人来说,创造的机会是敞开的。

像这样的模型可以用于:

  • 识别投资机会,股票市场和其他。
  • 在一天内可以调查的交易数量的任何操作限制内,确定一组预期欺诈损失最高的交易。
  • 生成考虑财务回报的申请分数,对申请被接受的百分比或数量进行约束。
  • 确定表现比预期差的 N 个客户的细分市场,同时最大限度地减少未来因拒绝具有此特征的申请而造成的收入损失。

提问&建议

如果您有任何问题、建议或问题,希望看到像这样的 ML 模型的结果,请随时给我发电子邮件:

bill.fite@miner3.com。

如果你感兴趣的话,我还希望在 minor3.com 的一个页面上更新模型选择和监控结果。

使用 Plotly 的 Dash 创建交互式数据应用程序

原文:https://towardsdatascience.com/creating-an-interactive-data-app-using-plotlys-dash-356428b4699c?source=collection_archive---------2-----------------------

我们来做一个 app,自动出图数据文件。这是一个使用 plotly 的破折号在 python 中创建 web 应用程序的演练,其中有一个我们在 Kyso 创建的示例—现场版本可以在这里找到:

[## 破折号

用 Plotly 的 Dash 编辑自动文件绘图应用程序

dash-app-dx9 g 2r 0 la 6-8000 . cloud . kyso . io](https://dash-app-dx9g2r0la6-8000.cloud.kyso.io/) 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Uploading Multiple File-Types & Automatically Generate Scalar Plots

这是一个用 xy,xyyy 等上传任何文件的应用程序。坐标,然后自动生成一个图。

Dash 是用于构建 web 应用程序的 Python 框架。它建立在 Flask、Plotly.js、React 和 React Js 之上。,使您能够使用纯 Python 构建仪表板和应用程序。在本教程中,我将向您介绍基础知识,并假设您之前有使用 Plotly 的经验。如果你是 plotly 的新手,请查看这些初学者指南:

https://kyso.io/KyleOS/plotly-intro

https://kyso.io/KyleOS/cufflinks-intro

装置

为了开始使用 Dash,你需要安装几个软件包。

  1. 核心 dash 后端。
  2. 仪表板前端
  3. Dash HTML 组件
  4. 仪表板核心部件
  5. Plotly

请注意,如果您想从 Kyso 启动您的应用程序,所有这些都已预装在 Kyso 的工作区中!

pip install dash==0.21.1  
pip install dash-renderer==0.13.0  
pip install dash-html-components==0.11.0
pip install dash-core-components==0.23.0  
pip install plotly --upgrade

Dash 应用程序布局

Dash 应用程序由两部分组成。第一部分是应用程序的“布局”,它描述了应用程序的外观。Dash 为应用程序的所有可视化组件提供了 Python 类,即使用 Python 生成 HTML 内容。为了使用这些类,让我们导入dash_core_componentsdash_html_components库。用下面的代码创建一个名为app.py的文件:

import dash
import dash_core_components as dcc
import dash_html_components as html

像使用 Flask 一样,我们可以通过调用 dash 的 Dash 类来初始化 Dash。一旦完成,我们就可以为我们的应用程序创建布局,使用来自dash_html_components的 Div 类来创建 HTML Divs。请注意,dash_html_components包含了所有的 HTML 标签,可以让你设计应用程序的布局。

为了在我们的布局中创建一个图表,我们使用了来自dash_core_components的图表类。Graph 使用 plotly.js 呈现交互式数据可视化。Graph 类需要一个包含要绘制的数据和布局细节的图形对象。Dash 还允许你改变背景颜色和文本颜色。您可以通过使用 style 属性并传递具有您的特定颜色的对象来更改背景。

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

colors = {
    "graphBackground": "#F5F5F5",
    "background": "#ffffff",
    "text": "#000000"
}

app.layout = html.Div([
    dcc.Upload(
        id='upload-data',
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select Files')
        ]),
        style={
            'width': '100%',
            'height': '60px',
            'lineHeight': '60px',
            'borderWidth': '1px',
            'borderStyle': 'dashed',
            'borderRadius': '5px',
            'textAlign': 'center',
            'margin': '10px'
        },
        # Allow multiple files to be uploaded
        multiple=True
    ),
    dcc.Graph(id='Mygraph'),
    html.Div(id='output-data-upload')
])

请注意,我们正在为我们正在创建的每个组件设置 id,我们将在一秒钟内完成这些。Dash 上传组件允许应用程序的查看者上传文件。该应用程序可以通过监听 dcc 的内容属性来访问上传文件的内容。上传组件,它是一个 base64 编码的字符串,包含文件的内容,与文件类型无关。

所以我们创建了上面的布局;带有一些样式的上传框,以及当我们放入文件时将创建的图形。

熊猫和袖扣

好了,现在我们需要做一些事情,我们需要为以下内容创建函数:

  1. 读入任何文件,无论是 csv,excel 文件或 tsv,并将其转换成熊猫数据帧。
  2. 放下新文件时创建图形。
  3. 打印数据表。

为此我们需要几个库:

import base64
import datetime
import io
import plotly.graph_objs as go
import cufflinks as cf
import pandas as pd

import dash_table

因此,要解析我们的目标数据文件类型:

def parse_data(contents, filename):
    content_type, content_string = contents.split(',')

    decoded = base64.b64decode(content_string)
    try:
        if 'csv' in filename:
            # Assume that the user uploaded a CSV or TXT file
            df = pd.read_csv(
                io.StringIO(decoded.decode('utf-8')))
        elif 'xls' in filename:
            # Assume that the user uploaded an excel file
            df = pd.read_excel(io.BytesIO(decoded))
        elif 'txt' or 'tsv' in filename:
            # Assume that the user upl, delimiter = r'\s+'oaded an excel file
            df = pd.read_csv(
                io.StringIO(decoded.decode('utf-8')), delimiter = r'\s+')
    except Exception as e:
        print(e)
        return html.Div([
            'There was an error processing this file.'
        ])

    return df

使用袖扣——一种便于绘制熊猫和 plotly 的包装——来绘制我们的标量图:

def update_graph(contents, filename):
    fig = {
        'layout': go.Layout(
            plot_bgcolor=colors["graphBackground"],
            paper_bgcolor=colors["graphBackground"])
    }

    if contents:
        contents = contents[0]
        filename = filename[0]
        df = parse_data(contents, filename)
        df = df.set_index(df.columns[0])
        fig['data'] = df.iplot(asFigure=True, kind='scatter', mode='lines+markers', size=1)

        table = html.Div([
            html.H5(filename),
            dash_table.DataTable(
                data=df.to_dict('rows'),
                columns=[{'name': i, 'id': i} for i in df.columns]
            ),
            html.Hr(),
            html.Div('Raw Content'),
            html.Pre(contents[0:200] + '...', style={
                'whiteSpace': 'pre-wrap',
                'wordBreak': 'break-all'
            })
        ])

最后,为每次放入文件创建一个表:

def update_table(contents, filename):
    table = html.Div()

    if contents:
        contents = contents[0]
        filename = filename[0]
        df = parse_data(contents, filename)

        table = html.Div([
            html.H5(filename),
            dash_table.DataTable(
                data=df.to_dict('rows'),
                columns=[{'name': i, 'id': i} for i in df.columns]
            ),
            html.Hr(),
            html.Div('Raw Content'),
            html.Pre(contents[0:200] + '...', style={
                'whiteSpace': 'pre-wrap',
                'wordBreak': 'break-all'
            })
        ])

    return table

交互性— Dash 回调

Dash 应用程序的第二部分涉及定义应用程序交互性的回调。为此,我们需要从 dash.dependencies 导入输入和输出:

from dash.dependencies import Input, Output, State

在这个应用程序中,我们有两个回调:

@app.callback(Output('Mygraph', 'figure'),
            [
                Input('upload-data', 'contents'),
                Input('upload-data', 'filename')
            ])

因此,我们的输入是我们在开始时创建的上传组件,并将其绑定到一个回调,这样每当选择一个文件时,它都会实时更新我们的图形组件Mygraph。Dash 提供了一个 decorator @app,它使得将回调函数绑定到我们的组件成为可能。你会注意到在完整的app.py中,我们在声明 update_graph 函数之前使用了装饰器。

下面是我们的第二个回调,具有相同的输入(即,上传到我们的上传组件的文件,这次输出是包含文件数据的打印表格版本的 HTML Div。同样,装饰器在我们声明 update_table 函数之前被调用。

@app.callback(Output('output-data-upload', 'children'),
            [
                Input('upload-data', 'contents'),
                Input('upload-data', 'filename')
            ])

运行您的应用

为了查看我们的可视化,我们需要像在 Flask 中一样运行我们的 web 服务器。记住 Dash 是建立在烧瓶顶部的。Dash 包括“热重装”,当您使用app.run_server(debug=True)运行应用程序时,默认情况下会激活该功能。这意味着当你修改代码时,Dash 会自动刷新你的浏览器。

if __name__ == '__main__':
    app.run_server(debug=True, host='0.0.0.0', port=8000)

接下来,移动到终端,通过键入下面的代码启动服务器:python app.py——这将在[http://localhost:8000/](http://localhost:8000/.) 启动一个新的 web 服务器。

完整的应用程序

现在,把所有东西放在一起:

import base64
import datetime
import io
import plotly.graph_objs as go
import cufflinks as cf

import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table

import pandas as pd

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
server = app.server

colors = {
    "graphBackground": "#F5F5F5",
    "background": "#ffffff",
    "text": "#000000"
}

app.layout = html.Div([
    dcc.Upload(
        id='upload-data',
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select Files')
        ]),
        style={
            'width': '100%',
            'height': '60px',
            'lineHeight': '60px',
            'borderWidth': '1px',
            'borderStyle': 'dashed',
            'borderRadius': '5px',
            'textAlign': 'center',
            'margin': '10px'
        },
        # Allow multiple files to be uploaded
        multiple=True
    ),
    dcc.Graph(id='Mygraph'),
    html.Div(id='output-data-upload')
])

def parse_data(contents, filename):
    content_type, content_string = contents.split(',')

    decoded = base64.b64decode(content_string)
    try:
        if 'csv' in filename:
            # Assume that the user uploaded a CSV or TXT file
            df = pd.read_csv(
                io.StringIO(decoded.decode('utf-8')))
        elif 'xls' in filename:
            # Assume that the user uploaded an excel file
            df = pd.read_excel(io.BytesIO(decoded))
        elif 'txt' or 'tsv' in filename:
            # Assume that the user upl, delimiter = r'\s+'oaded an excel file
            df = pd.read_csv(
                io.StringIO(decoded.decode('utf-8')), delimiter = r'\s+')
    except Exception as e:
        print(e)
        return html.Div([
            'There was an error processing this file.'
        ])

    return df

@app.callback(Output('Mygraph', 'figure'),
            [
                Input('upload-data', 'contents'),
                Input('upload-data', 'filename')
            ])
def update_graph(contents, filename):
    fig = {
        'layout': go.Layout(
            plot_bgcolor=colors["graphBackground"],
            paper_bgcolor=colors["graphBackground"])
    }

    if contents:
        contents = contents[0]
        filename = filename[0]
        df = parse_data(contents, filename)
        df = df.set_index(df.columns[0])
        fig['data'] = df.iplot(asFigure=True, kind='scatter', mode='lines+markers', size=1)

    return fig

@app.callback(Output('output-data-upload', 'children'),
            [
                Input('upload-data', 'contents'),
                Input('upload-data', 'filename')
            ])
def update_table(contents, filename):
    table = html.Div()

    if contents:
        contents = contents[0]
        filename = filename[0]
        df = parse_data(contents, filename)

        table = html.Div([
            html.H5(filename),
            dash_table.DataTable(
                data=df.to_dict('rows'),
                columns=[{'name': i, 'id': i} for i in df.columns]
            ),
            html.Hr(),
            html.Div('Raw Content'),
            html.Pre(contents[0:200] + '...', style={
                'whiteSpace': 'pre-wrap',
                'wordBreak': 'break-all'
            })
        ])

    return table

if __name__ == '__main__':
    app.run_server(debug=True)

要自己运行这个应用程序,只需将上面的代码复制粘贴到你的app.py文件中,然后从终端运行

python app.py

转到[http://localhost:8000/](http://localhost:8000/)

在 Kyso 上运行 Dash 应用程序

启动一个工作空间(参见此处的指南)并进入 Jupyterlab。您可以从笔记本上运行它(只需执行单元),或者创建一个 app.py 文件并从终端上运行。

要查看正在运行的应用程序,请将工作空间的 URL 复制并粘贴到单独的选项卡中。移除lab?并将-8000(我们在上面启动应用的公共端口)附加到工作区 id 号,在.cloud.kyso.io之前。例如,如果我的工作空间在[https://live-aymycm9bst.cloud.kyso.io/lab?](https://live-aymycm9bst.cloud.kyso.io/lab?)运行

在一个单独的选项卡中,我可以转到https://live-aymycm9bst-8000.cloud.kyso.io/,我的应用将在那里运行。

创建和部署 Python 机器学习服务

原文:https://towardsdatascience.com/creating-and-deploying-a-python-machine-learning-service-a06c341f020f?source=collection_archive---------15-----------------------

用 scikit 构建一个仇恨言论检测系统-通过 Heroku 上的 Docker 学习和部署它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Jon Tyson on Unsplash

介绍

假设你是留言板或评论区的版主。你不想阅读你的用户在网上写的所有东西,但你想在讨论变得不愉快或人们开始到处散布种族诽谤时得到提醒。所以,你决定为自己建立一个自动检测仇恨言论的系统。

通过机器学习进行文本分类是一种明显的技术选择。然而,将模型原型转化为工作服务被证明是一个普遍的挑战。为了帮助弥合这一差距,本四步教程展示了仇恨言论检测应用程序的示例性部署工作流程:

  1. scikit-learn 训练并保持一个预测模型
  2. firefly 创建一个 API 端点
  3. 为这个服务创建一个 Docker 容器
  4. Heroku 上部署容器

该项目的代码可在这里获得。

1.创建预测模型

资料组

该方法基于戴维森、瓦姆斯利、梅西和韦伯的论文 自动仇恨言论检测和攻击性语言问题 。他们的结果是基于超过 20 000 条有标签的推文,这些推文可以在相应的 Github 页面上找到。

的。csv 文件作为数据帧加载:

import pandas as pd
import re**df** = pd.read_csv('labeled_data.csv', usecols=['class', 'tweet'])**df**['tweet'] = **df**['tweet'].apply(lambda tweet: re.sub('[^A-Za-z]+', ' ', tweet.lower()))

最后一行通过将所有文本转换为小写并删除非字母字符来清理 tweet 列。

结果:

class 属性可以假设三个类别值:0表示仇恨言论,1表示攻击性语言,2两者都不表示。

模特培训

在训练机器学习分类器之前,我们必须将我们的预测器,即推文文本,转换为数字表示。我们可以使用 scikit-learn 的 TfidfVectorizer 来完成这项任务,它将文本转换为适合机器学习的术语频率乘以逆文档频率(tf-idf)值的矩阵。此外,我们可以从处理中删除停用词(常用词如*、*、、…)。

对于文本分类,支持向量机( SVMs )是一个可靠的选择。由于它们是二元分类器,我们将使用一对其余策略,其中对于每个类别,训练一个 SVM 来将该类别与所有其他类别分开。

通过使用 scikit-learn 的管道功能并定义相应的步骤,可以在一个命令中执行文本矢量化和 SVM 训练:

from sklearn.pipeline import make_pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
from stop_words import get_stop_words**clf** = make_pipeline(
    TfidfVectorizer(stop_words=get_stop_words('en')),
    OneVsRestClassifier(SVC(kernel='linear', probability=True))
)**clf** = **clf**.fit(X=**df**['tweet'], y=**df**['class'])

现在,应该评估模型的性能,例如,使用交叉验证方法来计算分类度量。然而,由于本教程关注的是模型部署,我们将跳过这一步(在实际项目中从不这样做)。这同样适用于参数调整或自然语言处理的附加技术,在原始论文中有所描述。

测试模型

我们现在可以尝试一个测试文本,让模型预测概率:

**text** = "I hate you, please die!" **clf**.predict_proba([**text**.lower()])# Output:
array([0.64, 0.14, 0.22])

数组中的数字对应于三个类别的概率(仇恨言论、攻击性语言,都不是)。

模型持久性

使用 joblib 模块,我们可以将模型作为二进制对象保存到磁盘。这将允许我们在应用程序中加载和使用模型。

from sklearn import externals**model_filename** = 'hatespeech.joblib.z'
externals.joblib.dump(**clf**, **model_filename**)

2.创建 REST API

创建 API 端点

python 文件app.py加载模型并定义一个简单的模块级函数,该函数封装了对模型的 predict_proba 函数的调用:

from sklearn import externals**model_filename** = 'hatespeech.joblib.z'
**clf** = externals.joblib.load(model_filename)def predict(**text**):
    probas = **clf**.predict_proba([**text**.lower()])[0]
    return {'hate speech': probas[0],
           'offensive language': probas[1],
           'neither': probas[2]}

现在,我们使用 firefly ,这是一个轻量级 python 模块,用于将功能作为服务。对于高级配置或在生产环境中的使用,Flask 或 Falcon 可能是更好的选择,因为它们已经在大型社区中建立了良好的声誉。对于快速原型,我们对 firefly 很满意。

我们将在命令行中使用 firefly 将 predict 函数绑定到本地主机上的端口 5000:

**$** firefly app.predict --bind 127.0.0.1:5000

本地测试 API

通过curl,我们可以向创建的端点发出 POST 请求,并获得一个预测:

**$** curl -d '{"text": "Please respect each other."}' \ http://127.0.0.1:5000/predict# Output:
{"hate speech": 0.04, "offensive language": 0.31, "neither": 0.65}

当然,在一个成熟的实际应用程序中,会有更多的附加功能(日志记录、输入和输出验证、异常处理等等)和工作步骤(文档、版本控制、测试、监控等等),但是这里我们只是部署一个简单的原型。

3.创建 Docker 容器

为什么是 Docker?Docker 容器在一个隔离的环境中运行应用程序,包括所有的依赖项,并且可以作为映像提供,从而简化服务设置和扩展。

构建图像

我们必须在一个名为Dockerfile的文件中配置容器的内容和开始动作:

FROM python:3.6
RUN pip install scikit-learn==0.20.2  firefly-python==0.1.15
COPY app.py hatespeech.joblib.z ./CMD firefly app.predict --bind 0.0.0.0:5000
EXPOSE 5000

前三行是关于将python:3.6作为基础映像,另外安装 scikit-learn 和 firefly(与开发环境中的版本相同)并复制里面的 app 和模型文件。后两行告诉 Docker 启动容器时执行的命令以及应该暴露的端口 5000。

创建图像hatespeechdetect的构建过程通过以下方式开始:

**$** docker build . -t hatespeechdetect

运行容器

run命令启动一个容器,从一个图像派生。此外,我们通过-p选项将容器的端口 5000 绑定到主机的端口 3000:

**$** docker run -p 3000:5000 -d hatespeechdetect

使用预测服务

现在,我们可以发送一个请求并获得一个预测:

**$** curl -d '{"text": "You are fake news media! Crooked!"}' \ http://127.0.0.1:3000/predict# Output:
{"hate speech": 0.08, "offensive language": 0.76, "neither": 0.16}

在本例中,容器在本地运行。当然,实际的目的是让它在一个永久的位置运行,并且可能通过在一个企业集群中启动多个容器来扩展服务。

4.部署为 Heroku 应用程序

让其他人可以公开使用该应用的一种方式是使用平台即服务,如 Heroku ,它支持 Docker 并提供免费的基本会员资格。要使用它,我们必须注册一个帐户并安装 Heroku CLI。

Heroku 的应用程序容器公开了一个动态端口,这需要在我们的Dockerfile中进行编辑:我们必须将端口 5000 更改为环境变量PORT:

CMD firefly app.predict --bind 0.0.0.0:$PORT

在此变更之后,我们就可以开始部署了。在命令行上,我们登录 heroku(它会在浏览器中提示我们输入凭证)并创建一个名为hate-speech-detector的应用程序:

**$** heroku login**$** heroku create hate-speech-detector

然后我们登录到容器注册中心。heroku container:push将基于当前目录中的 Dockerfile 构建一个映像,并将其发送到 Heroku 容器注册表。之后,我们可以将图像发布到应用程序:

**$** heroku container:login**$** heroku container:push web --app hate-speech-detector**$** heroku container:release web --app hate-speech-detector

和以前一样,API 可以通过 curl 来处理。但是,这一次,服务不是在本地运行,而是面向全球!

**$** curl -d ‘{“text”: “You dumb idiot!”}’ https://hate-speech-detector.herokuapp.com/predict# Output:
{"hate speech": 0.26, "offensive language": 0.68, "neither": 0.06}

现在,只需点击几下鼠标或输入几个命令,就可以扩展应用程序。此外,该服务需要连接到留言板,需要设置触发阈值并实现警报。

希望这篇教程能帮助你部署你自己的机器学习模型和应用。有其他想法吗?请在评论中分享你的观点!

使用 fluore Studio 创建出色的地图数据可视化。

原文:https://towardsdatascience.com/creating-awesome-map-data-visualizations-using-flourish-studio-6410a8e01c74?source=collection_archive---------16-----------------------

一个开源数据故事讲述平台

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

空间分析和可视化帮助我们从复杂的地理空间数据中获得易于理解的见解。我们以天气数据、谷歌地图、GPS 坐标和带地理标记的社交媒体帖子等形式生成大量地理空间数据,这些数据正在成为我们生活和业务不可或缺的一部分。麦肯锡的一项研究表明,到 2025 年,基于位置的传感器的加速扩散可能会带来每年超过 11 万亿美元的经济影响。可视化地图数据使见解更清晰、更直观,并获得受众的关注。但是许多人发现,与统计分析相比,空间分析和可视化非常难以执行。在这篇博客中,我们将讨论如何使用开源数据可视化和讲故事平台的繁荣来创建交互式地图数据可视化。

为什么用花枝招展?

有许多专用软件可用于地理空间分析和可视化。QGIS 和 CARTO 是一些广泛使用的地理空间分析软件,用于地理空间数据的高端分析。像 R 和 Python 这样的统计软件也有很多专门用于地理空间分析的包。但是,当您想要快速分析地理空间数据并创建交互式可视化时,这些工具就不那么用户友好了。除了您必须编写的代码之外,使在线出版的可视化交互有点棘手。

蓬勃发展来了六个预加载的模板,使交互式地图可视化。您可以在现有的地理地图模板上上传您的数据,或者上传您自己的地理边界文件。六个地图可视化模板如下:

1.投影地图

2.标记地图

3.弧形地图

4.3D 区域地图

5.连接全球

6.测量图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们将看看如何根据地理空间数据的性质创建三种不同类型的地图可视化。

如何创建针对不同地理区域的动画可视化?

假设您有不同国家/地区的国家级数据,并且想要讲述一个侧重于表现良好的特定地理区域和表现不佳的地理区域的数据故事,那么您可以使用已经存在于 fluore 中的 World 的投影地图模板。当你打开世界模板,点击**‘数据’标签,你可以通过查看已经可用的虚拟数据来理解数据应该是什么格式。以所需格式上传数据后,您可以点击【预览】**数据选项卡,更改页面右侧的可视化设置。

蓬勃发展带来了这个惊人的选择,创建一个数据故事使用您创建的可视化。在可视化页面的右上角有**“创建一个故事”**链接,我们可以使用幻灯片模板讲述您的数据故事,就像 PowerPoint 演示一样。一旦你创建了你的故事,你就可以把它发布在 fluorescent server 上,并把它嵌入到任何在线资源中。这是我根据社交媒体关注度制作的可视化图片,展示了各大洲最受欢迎的足球俱乐部。

目前,fluorescent 没有从创建的可视化图像中创建 gif 或视频的选项。您可以使用一种可用的屏幕转 gif 软件来创建视频或 gif。用于 MAC 的 Giphy Capture 和用于 Windows 的 ScreenToGif是常用的软件。gif 或视频可以通过以下步骤创建:

打开您发布的可视化效果

调整屏幕的大小以适合可视化

录制屏幕相关部分的视频或 gif 截图,在幻灯片之间点击并放大地图的相关部分

根据需要将录像保存为 gif 或视频

与 gif 相比,视频是质量更好的输出,但文件大小会更大,上传时可能会有问题。

如何创建 Connections Globe 地图?

我们面临的情况是,我们希望可视化不同地理区域之间的人员和货物流动——无论是可视化国家之间的人员迁移还是可视化鸟类的迁移模式。大多数统计软件没有可视化分析移动数据的功能。蓬勃发展有这个连接全球模板,让您无缝可视化移动。拥有源和目的地的地理坐标就足以创建连接全球地图。这种可视化是高度交互式的,您可以根据需要旋转和缩放地球。您有许多设计和显示选项可用于自定义地图。

在这里,我创建了一个 connections globe 地图,根据居住在这些国家的非居民印度人的数量来可视化印度国民移民到的前 15 个国家。

如何创建一个简单的气泡图可视化?

使用 fluore 的投影地图模板可以非常容易地创建 choropleth 地图和 bubble 地图。对于某些地区,如世界、美国(州)、美国(县)、印度(州)、英国、西班牙、巴西等,fluorescent 有自己的内置模板。这是我创建的气泡图,显示了印度各邦的人均 GDP 值。

当所需的地理边界文件不可用时该怎么办?

蓬勃发展有限的地理文件,你可以上传你的数据到可视化。如果找不到您所在国家的地图,您可以选择上传自己的地理边界文件。有许多在线资源,你可以从那里下载不同国家的地理形状文件。GADM 是为所有国家和地区提供地图和空间数据的流行资源之一。你可以免费下载这些地理形状文件。

结论

蓬勃发展是一个用户友好的数据可视化平台,以创建强大的和交互式的数据故事。这是一个用最少的努力创建不同类型的地图数据可视化的完美媒介。探索 fluore,了解可以实现哪些其他类型的数据可视化。

创造比特币交易机器人不赔钱

原文:https://towardsdatascience.com/creating-bitcoin-trading-bots-that-dont-lose-money-2e7165fb0b29?source=collection_archive---------1-----------------------

让我们使用深度强化学习来制造加密货币交易代理

在本文中,我们将创建深度强化学习代理,学习如何通过比特币交易赚钱。在本教程中,我们将使用 OpenAI 的gym和来自stable-baselines库的 PPO 代理,后者是 OpenAI 的baselines库的一个分支。

这一系列文章的目的是试验最先进的深度强化学习技术,看看我们能否创造出盈利的比特币交易机器人。现状似乎是迅速关闭任何创建强化学习算法的尝试,因为这是“构建交易算法的错误方式”。然而,该领域的最新进展表明,在相同的问题域内,RL 代理通常能够比监督学习代理学习更多的东西。出于这个原因,我写这些文章是为了看看这些交易代理能给我们带来多大的利润,或者说现状的存在是有原因的。

非常感谢 OpenAI 和 DeepMind 在过去几年里为深度学习研究人员提供的开源软件。如果你还没有看到他们用像 AlphaGo、OpenAI Five 和 AlphaStar 这样的技术完成的惊人壮举,你可能在过去的一年里一直生活在岩石下,但你也应该去看看他们。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

AlphaStar Training (https://deepmind.com/blog/alphastar-mastering-real-time-strategy-game-starcraft-ii/)

虽然我们不会创造任何令人印象深刻的东西,但每天交易比特币并从中获利仍然不是一件容易的事情。然而,正如泰迪·罗斯福曾经说过的,

任何值得拥有的东西都来之不易。

所以,与其学习交易我们自己,不如让一个机器人来替我们做这件事。

[## 更明智地交易和投资——强化学习方式

深入探讨 TensorTrade——一个用于培训、评估和部署稳健交易的开源 Python 框架…

towardsdatascience.com](/trade-smarter-w-reinforcement-learning-a5e91163f315)

当你读完这篇文章后,看看TensorTrade——这篇文章中产生的代码库的后继框架。

这个计划

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 为我们的代理创造一个学习的健身房环境
  2. 呈现简单而优雅环境可视化
  3. 培训我们的代理人学习有利可图的交易策略

如果你还不熟悉如何从头开始创建一个体育馆环境,或者如何呈现这些环境的简单可视化,我刚刚写了关于这两个主题的文章。在继续之前,请随意在此暂停并阅读其中任何一篇。

入门指南

对于本教程,我们将使用由 Zielak 生成的 Kaggle 数据集。如果你想下载代码跟随,我的 GitHub repo 上也有.csv数据文件。好了,我们开始吧。

首先,让我们导入所有必需的库。确保pip install您遗漏了任何库。

**import** gym
**import** pandas **as** pd
**import** numpy **as** np
**from** gym **import** spaces
**from** sklearn **import** preprocessing

接下来,让我们为环境创建我们的类。我们将要求传入一个pandas数据帧,以及一个可选的initial_balance和一个lookback_window_size,它将指示代理在过去的每一步将观察多少时间步。我们将每次交易的commission默认为 0.075%,这是 Bitmex 的当前利率,并将serial参数默认为 false,这意味着默认情况下我们的数据帧将在随机切片中遍历。

我们还调用数据帧上的dropna()reset_index()来首先删除任何带有NaN值的行,然后重置帧的索引,因为我们已经删除了数据。

***class*** BitcoinTradingEnv(*gym*.*Env*):
  *"""A Bitcoin trading environment for OpenAI gym"""*
  metadata = {'render.modes': ['live', 'file', 'none']}
  scaler = preprocessing.MinMaxScaler()
  viewer = None ***def*** __init__(*self*, *df*, *lookback_window_size*=50, 
                         commission=0.00075,  
                         *initial_balance*=10000
                         serial=False):
    *super*(BitcoinTradingEnv, self).__init__() self.df = df.dropna().reset_index()
    self.lookback_window_size = lookback_window_size
    self.initial_balance = initial_balance
    self.commission = commission
    self.serial = serial # Actions of the format Buy 1/10, Sell 3/10, Hold, etc.
    self.action_space = spaces.MultiDiscrete([3, 10]) # Observes the OHCLV values, net worth, and trade history
    self.observation_space = spaces.Box(*low*=0, *high*=1, *shape*=(10, 
                    lookback_window_size + 1), *dtype*=np.float16)

我们的action_space在这里被表示为一个由 3 个选项(买入、卖出或持有)组成的离散集合和另一个由 10 个数量(1/10、2/10、3/10 等)组成的离散集合。当选择买入动作时,我们将买入价值amount * self.balance的 BTC。对于出售行动,我们将出售价值amount * self.btc_held的 BTC。当然,hold 动作会忽略金额,什么都不做。

我们的observation_space定义为 0 和 1 之间的一组连续的浮点数,形状为(10, lookback_window_size + 1)+ 1是为了说明当前的时间步。对于窗口中的每个时间步,我们将观察 OHCLV 值、我们的净值、买入或卖出的 BTC 金额,以及我们在这些 BTC 上花费或收到的美元总额。

接下来,我们需要编写我们的reset方法来初始化环境。

***def*** reset(*self*):
  self.balance = self.initial_balance
  self.net_worth = self.initial_balance
  self.btc_held = 0 self._reset_session() self.account_history = np.repeat([
    [self.net_worth],
    [0],
    [0],
    [0],
    [0]
  ], self.lookback_window_size + 1, *axis*=1) self.trades = [] **return** self._next_observation()

这里我们同时使用了self._reset_sessionself._next_observation,我们还没有定义它们。让我们来定义它们。

交易时段

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们环境的一个重要部分是交易时段的概念。如果我们将这个代理部署到野外,我们可能永远不会一次运行超过几个月。出于这个原因,我们将在self.df中限制我们的代理在一行中看到的连续帧的数量。

在我们的_reset_session方法中,我们将首先将current_step重置为0。接下来,我们将把steps_left设置为1MAX_TRADING_SESSION之间的一个随机数,我们现在将在文件的顶部定义它。

MAX_TRADING_SESSION = 100000  # ~2 months

接下来,如果我们是串行遍历帧,我们将设置要遍历的整个帧,否则我们将把frame_start设置为self.df内的随机点,并创建一个名为active_df的新数据帧,它只是从frame_startframe_start + steps_leftself.df的一部分。

***def*** _reset_session(*self*):
  self.current_step = 0 **if** self.serial:
    self.steps_left = len(self.df) - self.lookback_window_size - 1
    self.frame_start = self.lookback_window_size
  **else**:
    self.steps_left = np.random.randint(1, MAX_TRADING_SESSION)
    self.frame_start = np.random.randint(
         self.lookback_window_size, len(self.df) - self.steps_left) self.active_df = self.df[self.frame_start -   
       self.lookback_window_size:self.frame_start + self.steps_left]

以随机切片遍历数据帧的一个重要副作用是,当我们的代理接受长时间训练时,将有更多的独特的数据要处理。例如,如果我们只是以串行方式(即从0len(df)的顺序)遍历数据帧,那么我们只会拥有与数据帧中一样多的唯一数据点。我们的观察空间甚至只能在每个时间步呈现离散数量的状态。

然而,通过随机遍历数据帧的切片,我们实际上是通过创建帐户余额、进行的交易和我们初始数据集中每个时间步的先前看到的价格行为的更有趣的组合来制造更多独特的数据点。我举个例子解释一下。

在重置串行环境后的时间步骤 10,我们的代理将始终处于数据帧内的同一时间,并且在每个时间步骤将有3 个选择:买入、卖出或持有。对于这三种选择中的每一种,还需要另一种选择:可能金额的 10%、20%、……或 100%。这意味着我们的代理人可以体验(1⁰ ) ⁰所有州中的任何一个,总共可以体验 1⁰ ⁰所有独特的体验。

现在考虑我们的随机切片环境。在时间步长 10,我们的代理可以在数据帧内的任何len(df)时间步长。假设在每个时间步做出相同的选择,这意味着该代理可以在相同的 10 个时间步内经历任何len(df) ⁰可能的唯一状态。

虽然这可能会给大型数据集增加相当多的噪声,但我相信它应该允许代理从我们有限的数据量中了解更多。我们仍将以串行方式遍历我们的测试数据集,以更准确地理解算法对新鲜的、看似“活的”数据的有用性。

代理人眼中的生活

这通常有助于可视化环境的观察空间,以便了解您的代理将使用的功能类型。例如,这是我们使用 OpenCV 渲染的观察空间的可视化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

OpenCV visualization of the environment’s observation space

图像中的每一行代表我们的observation_space中的一行。前 4 行类似频率的红线代表 OHCL 数据,正下方虚假的橙色和黄色点代表容量。下面波动的蓝色条代表代理的净值,下面较亮的点代表代理的交易。

如果你眯着眼睛,你只能看到一个蜡烛图,下面是音量条,下面是一个奇怪的类似莫尔斯电码的界面,显示交易历史。看起来我们的代理应该能够从我们的observation_space中充分了解数据,所以让我们继续。这里我们将定义我们的_next_observation方法,我们将从 0 到 1 缩放 观察数据

重要的是,只缩放代理到目前为止观察到的数据,以防止前瞻偏差。

***def*** _next_observation(*self*):
  end = self.current_step + self.lookback_window_size + 1 obs = np.array([
    self.active_df['Open'].values[self.current_step:end],  
    self.active_df['High'].values[self.current_step:end],
    self.active_df['Low'].values[self.current_step:end],
    self.active_df['Close'].values[self.current_step:end],
    self.active_df['Volume_(BTC)'].values[self.current_step:end],
  ]) scaled_history = self.scaler.fit_transform(self.account_history) obs = np.append(obs, scaled_history[:, -(self.lookback_window_size
                                                     + 1):], *axis*=0) **return** obs

采取行动

现在我们已经建立了我们的观察空间,是时候写我们的step函数了,反过来,采取代理的规定动作。每当self.steps_left == 0我们当前的交易时段,我们将出售我们持有的任何 BTC,并调用_reset_session()。否则,我们将reward设置为我们当前的净值,并且仅在我们没钱的时候将done设置为True

***def*** step(*self*, *action*):
  current_price = self._get_current_price() + 0.01
  self._take_action(action, current_price)
  self.steps_left -= 1
  self.current_step += 1 **if** self.steps_left == 0:
    self.balance += self.btc_held * current_price
    self.btc_held = 0
    self._reset_session() obs = self._next_observation()
  reward = self.net_worth
  done = self.net_worth <= 0 **return** obs, reward, done, {}

采取行动就像得到current_price,确定指定的行动,或者买入或者卖出指定数量的 BTC 一样简单。让我们快速编写_take_action以便测试我们的环境。

***def*** _take_action(*self*, *action, current_price*):
  action_type = action[0]
  amount = action[1] / 10 btc_bought = 0
  btc_sold = 0
  cost = 0
  sales = 0 **if** action_type < 1:
    btc_bought = self.balance / current_price * amount
    cost = btc_bought * current_price * (1 + self.commission)
    self.btc_held += btc_bought
    self.balance -= cost **elif** action_type < 2:
    btc_sold = self.btc_held * amount
    sales = btc_sold * current_price  * (1 - self.commission)
    self.btc_held -= btc_sold
    self.balance += sales

最后,用同样的方法,我们将把交易追加到self.trades,并更新我们的净值和账户历史。

 **if** btc_sold > 0 **or** btc_bought > 0:
    self.trades.append({
      'step': self.frame_start+self.current_step,
      'amount': btc_sold if btc_sold > 0 else btc_bought,
      'total': sales if btc_sold > 0 else cost,
      'type': "sell" if btc_sold > 0 else "buy"
    }) self.net_worth = self.balance + self.btc_held * current_price
  self.account_history = np.append(self.account_history, [
    [self.net_worth],
    [btc_bought],
    [cost],
    [btc_sold],
    [sales]
  ], *axis*=1)

我们的代理现在可以启动一个新环境,遍历该环境,并采取影响该环境的措施。是时候看他们交易了。

看着我们的机器人交易

我们的render方法可以像调用print(self.net_worth)一样简单,但这并不有趣。取而代之的是,我们将绘制一个简单的价格数据的蜡烛图,用量棒和一个单独的净值图来表示。

我们将从我写的最后一篇文章的中提取StockTradingGraph.py中的代码,并重新利用它来渲染我们的比特币环境。你可以从我的 GitHub 中抓取代码。

我们要做的第一个改变是将所有的self.df['Date']更新为self.df['Timestamp'],并删除所有对date2num的调用,因为我们的日期已经以 unix 时间戳格式出现。接下来,在我们的render方法中,我们将更新我们的日期标签以打印人类可读的日期,而不是数字。

**from** datetime **import** datetime

首先,导入datetime库,然后我们将使用utcfromtimestamp方法从每个时间戳获取一个 UTC 字符串,并使用strftime将该字符串格式化为Y-m-d H:M格式。

date_labels = np.array([datetime.utcfromtimestamp(x).strftime(
'%Y-%m-%d %H:%M') **for** x **in** self.df['Timestamp'].values[step_range]])

最后,我们将self.df['Volume']更改为self.df['Volume_(BTC)']以匹配我们的数据集,这样我们就可以开始了。回到我们的BitcoinTradingEnv,我们现在可以编写我们的render方法来显示图形。

***def*** render(*self*, *mode*='human', ***kwargs*):
  **if** mode == 'human':
    **if** self.viewer == None:
      self.viewer = BitcoinTradingGraph(self.df,
                                        kwargs.get('title', None)) self.viewer.render(self.frame_start + self.current_step,
                       self.net_worth,
                       self.trades,
                       *window_size*=self.lookback_window_size)

瞧啊。我们现在可以看到我们的代理商交易比特币。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Matplotlib visualization of our agent trading Bitcoin

绿色虚线标记代表 BTC 的买入,红色虚线标记代表卖出。右上方的白色标签是代理人的当前净值,右下方的标签是比特币的当前价格。简单,却不失优雅。现在,是时候培养我们的代理人了,看看我们能赚多少钱!

训练时间

我的第一篇文章受到的批评之一是缺乏交叉验证,或者将数据分成训练集和测试集。这样做的目的是为了测试您的最终模型在它从未见过的新鲜数据上的准确性。虽然这不是那篇文章关注的问题,但它确实在这里。由于我们使用的是时间序列数据,所以在交叉验证方面我们没有太多选择。

例如,一种常见的交叉验证形式称为 k 重验证,其中您将数据分成 k 个相等的组,并逐一挑出一组作为测试组,并将其余数据用作训练组。然而,时间序列数据高度依赖于时间,这意味着后期数据高度依赖于前期数据。所以 k-fold 是行不通的,因为我们的代理在交易之前会从未来的数据中学习,这是一个不公平的优势。

当应用于时间序列数据时,同样的缺陷也适用于大多数其他交叉验证策略。因此,我们只需简单地从整个数据帧中取出一部分,用作从帧的开头到某个任意索引的训练集,并使用其余的数据作为测试集。

slice_point = *int*(len(df) - 100000)
train_df = df[:slice_point]
test_df = df[slice_point:]

接下来,由于我们的环境仅设置为处理单个数据帧,因此我们将创建两个环境,一个用于训练数据,一个用于测试数据。

train_env = DummyVecEnv([*lambda*: BitcoinTradingEnv(train_df, 
                         *commission*=0, *serial*=False)])
test_env = DummyVecEnv([*lambda*: BitcoinTradingEnv(test_df, 
                        *commission*=0, *serial*=True)])

现在,训练我们的模型就像用我们的环境创建一个代理并调用model.learn一样简单。

model = PPO2(MlpPolicy,
             train_env,
             *verbose*=1, 
             *tensorboard_log*="./tensorboard/")
model.learn(*total_timesteps*=50000)

在这里,我们使用 tensorboard,这样我们可以轻松地可视化我们的 tensorflow 图,并查看有关我们的代理的一些定量指标。例如,下图显示了许多代理在 200,000 个时间步长内的折扣奖励:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

哇,看起来我们的代理商非常赚钱!我们最好的代理人甚至能够在 200,000 步的过程中将他的平衡提高 1000 倍,而其他人平均至少提高 30 倍!

就在这一点上,我意识到环境中有一个错误…这是修复该错误后的新奖励图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如你所见,我们的几个代理做得很好,其余的都破产了。然而,表现良好的代理最多只能达到初始余额的 10 倍甚至 60 倍。我必须承认,所有盈利的代理商都是在没有佣金的环境中接受培训和测试的,所以让我们的代理商真正赚钱仍然是完全不现实的。但是我们正在取得进展!

让我们在测试环境中测试我们的代理人(使用他们从未见过的新鲜数据),看看他们对比特币交易的学习有多好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Our trained agents race to bankruptcy when trading on fresh, test data

显然,我们还有相当多的工作要做。通过简单地将我们的模型切换到使用 stable-baseline 的 A2C,而不是当前的 PPO2 代理,我们可以大大提高我们在这个数据集上的性能。最后,我们可以根据 Sean O’Gorman 的建议稍微更新一下我们的奖励函数,这样我们就可以奖励净值的增长,而不仅仅是获得高净值并保持高净值。

reward = self.net_worth - prev_net_worth

仅这两个变化就大大提高了测试数据集的性能,正如您在下面看到的,我们最终能够在训练集中没有的新数据上实现盈利。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然而,我们可以做得更好。为了改善这些结果,我们需要优化我们的超参数,并对我们的代理进行更长时间的培训。是时候打开 GPU 开始工作了!

然而,这篇文章已经有点长了,我们还有相当多的细节要看,所以我们要在这里休息一下。在我的下一篇文章中,我们将使用 贝叶斯优化 来确定我们问题空间的最佳超参数,并改进代理的模型以实现高利润的交易策略。

结论

在本文中,我们开始使用深度强化学习从零开始创建一个盈利的比特币交易代理。我们实现了以下目标:

  1. 利用 OpenAI 的健身房从零开始创建了一个比特币交易环境。
  2. 使用 Matplotlib 构建了该环境的可视化。
  3. 使用简单的交叉验证对我们的代理进行培训和测试。
  4. 微调我们的代理以实现盈利。

虽然我们的交易代理不像我们希望的那样有利可图,但它肯定有所进展。下一次,我们将通过先进的功能工程和贝叶斯优化来改进这些算法,以确保我们的代理能够持续击败市场。敬请关注我的下一篇文章,以及比特币万岁

[## 利用强化学习交易比特币获取巨额利润

让我们教我们的深度 RL 代理通过特征工程和贝叶斯优化赚更多的钱

towardsdatascience.com](/using-reinforcement-learning-to-trade-bitcoin-for-massive-profit-b69d0e8f583b) [## 更明智地交易和投资——强化学习方式

深入探讨 TensorTrade——一个用于培训、评估和部署稳健交易的开源 Python 框架…

towardsdatascience.com](/trade-smarter-w-reinforcement-learning-a5e91163f315)

很重要的一点是要明白,本文中记录的所有研究都是出于教育目的,不应该作为交易建议。你不应该根据本文定义的任何算法或策略进行交易,因为你很可能会失去你的投资。

感谢阅读!一如既往,本教程的所有代码都可以在我的 GitHub 上找到。如果您有任何问题或反馈,请在下面留下评论,我很乐意收到您的来信!我也可以通过@notadamking 的Twitter联系到。

您也可以通过下面的链接在 Github 赞助商 Patreon上赞助我。

[## GitHub 赞助商

嗨,我是亚当。我是一名开发人员、作家和企业家,尤其对深度…

github.com](https://github.com/users/notadamking/sponsorship)

Github 赞助商目前正在 1:1 匹配所有捐款,最高可达 5000 美元!

[## 亚当·金正在创造改变世界的内容

嗨,我是亚当。我是一名开发人员、作家和企业家,尤其对深度…

patreon.com](https://patreon.com/notadamking)

创建引人注目的饼图替代方案

原文:https://towardsdatascience.com/creating-compelling-pie-chart-alternatives-3a1c2c2889b8?source=collection_archive---------17-----------------------

我最近完成了用数据讲故事,这是一个改善我们如何可视化数据的很好的例子。其中比较直白的一点就是没有饼状图。我以前听过这句话,知道这个话题有些争议。反对饼图的理由相当简单:它们不像人们想象的那样容易解释。人们不能轻易地以饼图的形式直观地分辨出数值之间的差异。角度并不特别适合人眼。你花多少时间挂一个没有水平仪的画框?).你也许能从视觉上分辨出 15 度和 90 度之间的区别,但是 20 度和 30 度之间的区别可能很棘手,这种区别可能很重要。尤其是当你开始在饼图上使用 3D 元素时,随着角度的进一步倾斜,这变得更加令人困惑。

让我们举个简单的例子,看看下面的图表,除了最大的比例,你有多大把握确定每个比例代表多少?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

说“永远不要饼状图”感觉很容易!,但重要的是你如何替代它。仍然有这样的情况,我们想要传达整体的比例,用数据来讲述一个故事。你可能会被迫回到这种甜点形状的美丽,但让我们看看几个不同的选择。

这里有一个案例:你想创建一个主要电影制片厂当前市场份额的可视化。你从票房魔咒中抓取数据,把它放进一个 Jupyter 笔记本里,然后你开始:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

呃。这一切都在那里,但它显然不是超级可解释的或令人信服的,尤其是如果你想说的东西比“布埃纳 Vista 有很大的份额”。

条形图

是的,条形图!这是那种当它和你握手时会看着你的眼睛的图表。它一直是数据可视化的中流砥柱,尽管它可能不是最耀眼的,但它是可靠的,并且更容易理解。为了更清楚,你可以把它放在水平位置,这样便于区分值:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

只是在直接比较中,你可以很快看出每个工作室之间的区别,而不仅仅是最大的工作室。那些在饼状图中看起来大小相同的电影公司(如华纳、环球和索尼)的比例要清晰得多。如果你喜欢的话,你也可以试试堆积条形图,但是一个基本的条形图做得好的话会有很大的帮助。

树形图

处理饼图角度读数问题的另一种方法是将数据分成方块,这样可以更清楚地理解。树状图主要用于显示数据的层次结构,最近作为饼状图的替代物受到青睐。你必须注意你的数据有多少段,因为标注可能会很棘手。我们的数据有 11 个值,您可以看出它们就在边缘,我通常会尽量保持在这 11 个值以下,但这里的示例是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

华夫饼图表

华夫饼图表本质上是树形图的一种变体。它不是大块的,而是把它分成美味的华夫饼干形状的均匀部分。基于我们的数据的一个总体示例可能是这样的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我发现华夫格图在视觉上更有帮助的是对某些值的标注。这里有一个例子,列出三个不同的工作室进行比较:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

像这样的小版本可以作为比较的快速展示,在我看来,有时比一大块华夫饼更有帮助。

只显示数字!

有时候,你所拥有的数据并不会显得可笑,即使这是你想要表达的观点。假设您经营一家电影院,拥有如下数据:

------------
Proportion of snack purchase sales at the movie theater
Popcorn: 98%
Fountain drinks: 1%
Candy: .5%
The super combo pack: .25%
Bottled water: .25%
------------

不是你特别想按比例比较的东西,因为它没有讲述一个伟大的故事。退后一步,想想是否有其他方法可以传达这些数据告诉你的信息。对于这个例子,也许只是指出爆米花销售的巨大数量:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你使用什么将最终取决于你的观众和你试图讲述的故事。尝试一些东西,也在其他人身上尝试。通过观察你创造的形象来思考别人可能回答的问题。如果你想找个地方玩玩,就从这里开始吧,这里有一本 Jupyter 笔记本,上面有这篇文章中用到的所有例子。

使用 Doc2Vec 创建产品标签

原文:https://towardsdatascience.com/creating-great-product-tags-f3d2c7607dba?source=collection_archive---------16-----------------------

面向企业的实用方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Too many tags. Photo Credit: Adi Goldstein.

产品标签给用户一个期望的快照,并帮助他们探索相关产品。如果标签创建的准确度不高,用户会发现很难信任它们,交互也会受到限制。然而,随着产品数量的增加,创建准确的标签变得越来越困难。为了解决这个问题,我们可以利用各种机器学习技术。特别是,我们将讨论如何通过结合人工标记和机器学习技术来创建产品标签。

作为一个例子,我们将使用www.govoyagin.com,其中产品由活动表示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

As we can see, the tags used on these products need some work. Credit: Voyagin.

选择标签

选择正确的标签并不一定是显而易见的。有多种方法:

  • 基于用户的:用户最关心什么标签?对于这种方法,第一步是与用户交谈或进行调查,找出他们对哪些标签感兴趣,以及什么对他们有意义。
  • 机器学习:数据中内置了哪些标签?聚类算法(如 k-means)可用于将产品分组在一起,然后主题建模技术可以得出代表聚类的标签。
  • 市场调查:竞争对手在做什么?无论什么行业,都有可能找到以某种方式使用标签的竞争对手。通常,他们会做各种类型的研究和测试,以提出他们的标签,这些可以是一个很好的起点。它还可以表明用户期望的行业标准是什么。
  • 内功:你觉得什么最好?在你的公司里应该有各种各样的业内专家,他们可能有很好的方法根据他们的经验来设置标签。这是另一个很好的起点,尽管你应该对基于少数人的想法做出产品决策保持警惕。

当然,这些只是其中的一些方法,有必要将它们结合起来以获得最佳效果。例如,你可以运行机器学习算法来计算出一组初始聚类,然后利用你的内部专家来选择精确的标签,最后从用户那里获得反馈,看看它们是否有意义,是否能与市场产生良好的共鸣。

在本例中,我们将使用与主要产品类别相对应的标签列表:

'Culture', 'Nature', 'Relaxation', 'Crazy', 'Celebration', 'Adventure', 'Food', 'Romantic', 'Socializing', 'Instagrammable', 'Family', 'Theme Parks'

一旦确定了标签列表,就必须给产品贴标签。

标记产品

对于拥有数百种产品的公司来说,手动标记产品是可行的,但是随着产品规模的扩大,维护起来就变得非常困难。在这种情况下,最好转向自动化流程。

下面详细介绍的方法是:

  • 手动标记一些产品
  • 将产品描述转换成机器可读的数字
  • 建立对标签含义的理解
  • 使用这种一般理解来给产品分配标签

这是监督学习的一个例子,我们提供输入-输出对的例子,模型学习在给定输入的情况下预测输出。

手动标记

第一步是手动标记一些产品。通过首先手动标记活动,我们引入了一些“专家指导”来提高性能。应该选择一组有代表性的产品来为模型提供最多的信息。对于所讨论的技术,我们将在每个类别中只标记 10 种产品。

手动标记也可以使用单词匹配来实现。例如,如果你的产品标签是衬衫,那么衬衫这个词很可能在产品描述中。这种技术在这种情况下工作得很好,但是对于更一般的标签将会失败。

例如,我们可以手动分配产品,如下所示:

34% OFF Robot Restaurant Shinjuku Tokyo Discount E-Tickets (899)
 => Crazy
Studio Ghibli Museum Tickets — Preorder & Last-Minute Tickets (186)
 => Culture
Tokyo Disneyland Tickets — Maihama Station Pickup (10069)
 => Theme Parks
Reservation for Sushi Jiro Roppongi Michelin 2-star Tokyo (1690)
 => Food

给我们一个最终的 JSON 对象,带有标签和产品 id:

{
  "Crazy": [123, 98, 899, etc.],
  "Culture": [186, 1200, 323, etc.],
  ...
}

虽然这些都是由一个人准备的,但至少有三个人来检查每个产品是有帮助的,这是为了消除任何可能存在的偏见。

标签的含义

一旦我们有了一套描述我们产品的标签,我们就需要弄清楚它们到底是什么意思。我们将用机器学习来做这件事。对于理解产品的机器学习算法来说,它需要一种方法来将这些产品简化为数字。在这种情况下,我们将这些数字称为向量,因为我们经常用一组数字来表示乘积。我们将输入模型的典型内容是产品描述或产品图片。对于产品描述,我们有一些技术可供选择,包括:

  • 一袋单词
  • TF-IDF
  • Doc2Vec

Doc2Vec 是一项伟大的技术,使用 Gensim 在 Python 中实现非常容易。这个模型将把产品描述简化为一个向量,其中有一定数量的数据点代表产品的质量。这些都是未知的,但往往可以看到与特定的质量,如颜色,形状,大小或在我们的情况下,标签或类别,我们正在使用。

from gensim.models.doc2vec import Doc2Vec# Create a model with some pre-defined parameters.
model = Doc2Vec(vector_size=50, min_count=2, epochs=40)# Build the vocabulary from some training data.
model.build_vocab(train_corpus)# Train the model.
model.train(train_corpus, total_examples=model.corpus_count, epochs=model.epochs)

在产品图像的情况下,可以应用图像识别技术。例如,根据每个像素的颜色将图像转换为数据,然后训练神经网络来预测某个图像属于哪个标签(类别)。这些模型可以与下面讨论的产品描述模型相结合。

随着产品描述被简化为向量,我们可以思考某个标签的定义意味着什么。对于独立标签(一个产品属于一个标签,但不属于另一个标签)来说,一种简单的方法是对具有某个标签的产品取向量的平均值。结果是一个向量,它表示该标签的平均乘积。

下面的图表显示了一些产品标签的示例。我们看到类似的标签,如庆典和 Instagrammable(中左)是如此相似,以至于几乎完全重叠。我们可能要重新考虑这些标签,因为它们太相似了。“疯狂”这个标签与其他标签明显不同,这是有道理的,这些产品一定非常独特!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The vertical and horizontal axis represent some underlying meaning, such that the tags closer together are most similar.

分配标签

现在我们有了平均产品,我们可以通过找到任何附近的向量来找到应该被相应标记的产品。如果一个向量在附近,它应该是相似的。我们可以限制距离,以确保我们只捕捉与相关标签足够相似的产品。这个距离可以被称为相似性度量。

在这一点上,绘制产品与标签相似性的直方图有助于了解什么是好的分界点。你要确保你标记了大量的活动,但不是每个产品都有特定的标签!

在下面显示的四个示例中,我们有:

  • 自然:很多产品与这个标签不相关,峰值在 0.1 左右的相似度,然后自然相关产品稳步下降。
  • 松弛:与自然相反,似乎有一个次高峰,许多产品的相似度在 0.4 左右。我们希望有一个比这更高的截止值,以避免捕获所有这些产品,这些产品必须有一些相似的方面,但并不完全相关。
  • 食物:与张弛相似,我们可以看到第二个峰值,但这次相似度要高得多,在 0.6 左右。
  • 主题 公园:在 0.5 之后的最右边有一个清晰的平台,因为我们看到相似性下降得相当快。这可能是因为主题公园的标签很简单,意思是某样东西可以很容易地被说成是主题公园或者不是。对比一下之前的一些标签,比如放松。

我们可以选择 0.6 作为一个分界点,以平衡好的含义,但不要有太多的产品标签。从图表中可以看出,这并不完美,我们应该能够做得更好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Product similarities for different tags. The height of each column represents the number of products that have a certain range of similarity. Similarity of 0 means the products are completely unrelated, -1 means the products are actively different and 1 means the products are very similar. A solid line is shown at 0.6 representing a potential cutoff point for tagging.

验证标签

一旦准备好标签,下一步就是验证它们是否有意义。最简单的方法是浏览每个标签下的随机产品列表,并检查它们是否有意义。最终,这取决于用户如何回应你的标签。在线测试你的标签并观察用户如何与之互动是很有用的。他们在用标签研究产品吗?在这一点上,他们是否从标签或落客处查看许多产品?

后续步骤

在本文中,我们使用基本的数据处理和机器学习技术创建了一个标签产品列表。有了这些技术,就有可能快速建立并运行一个质量良好的标签系统。

我们有各种方法可以改进我们的方法。我们可以应用机器学习算法,如支持向量机(SVM)或多项式朴素贝叶斯,学习以更复杂的方式预测标签,而不是选择离我们的标签最近的产品。对于这些模型,需要更多的训练数据,但作为回报,我们将拥有更大的预测能力。

如何为放射学人工智能创建高质量的带注释的训练数据?

原文:https://towardsdatascience.com/creating-high-quality-annotated-training-data-for-radiology-ai-d23ca4b85f00?source=collection_archive---------22-----------------------

使用神经网络的深度学习有可能对放射学的医学成像产生非常高的生产力提升影响。虽然人工智能可能永远不会取代放射科医生,但人工智能将有助于以一种非常深刻的方式提高放射科医生的生产力。

四种类型的组织参与在放射学中实现人工智能:

  1. 通用电气、飞利浦、西门子、Nuance technologies、Teracon 等现有公司正在建立市场,以分发来自不止一家供应商的人工智能算法。
  2. 人工智能初创公司正在建立深度学习算法,以将人工智能商业化用于放射学。
  3. 像英伟达这样的 GPU 公司正在通过免费的软件开发工具包加速人工智能的开发,这使得所有其他玩家都可以使用他们的 GPU 硬件和 GPU 云。
  4. 斯坦福机器学习小组俄亥俄州立大学医学院梅奥诊所放射科这样的研究小组正在给放射学人工智能带来最新的研究。

在医学成像领域,人工智能面临着一些重大挑战:

  1. 放射学成像数据通常包含个人健康信息(PHI)。它要求遵守严格的法规和 HIPAA 合规法律。这里有一些指导方针用于指导 HIPAA 合规性下的 PHI 构成,以及保护 PHI 的常见策略
  2. 由于数据的敏感性,数据需要存放在本地网络或 VPN 控制的网络中。

解决办法

人们普遍需要可扩展的数据管理基础设施。为了帮助这一努力,TrainingData.io 创建了一套工具,以帮助数据科学团队为放射学人工智能创建和管理大量训练数据。

一个好的培训数据管理平台是由什么组成的?

在 TrainingData.io,我们构建了世界上第一个注释工具,能够为 DICOM 格式的放射学图像创建像素精确的注释,如下图所示:

1.标签工具中的本地 Dicom 支持

Dicom 图像格式实际上是来自不同供应商的所有放射设备的标准。Dicom 数据损失少,信息丰富。它允许放射科医生查看捕捉到的图像中的细节。Web 浏览器不像支持 Png 和 Jpeg 那样支持 dicom 解码。标签工具需要支持 dicom 数据格式,具有窗口级预设、多平面视图等功能。

2.像素精确的注释工具

在 TrainingData.io,我们建立了世界上第一个注释工具,能够为 DICOM 格式的放射学图像创建像素精确的注释,如下图所示

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.网络浏览器中 MRI / CT / DICOM / NIFTI 的三维分割

放射学数据集有两种主要的文件格式 a) DICOM 和 b) NIFTI。一些 MRI / CT 研究包括成千上万的图像(切片)。很难单独注释每个切片。3D 可视化对于加速为大型数据集创建注释的过程非常重要。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3D-Segmentation in Web Browser

4.模型辅助注释

英伟达克拉拉:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

NVIDIA Clara Model Training Framework

为了生成任何新数据集的自动分割, TrainingData.io 已经建立了一个用户界面,如下面的视频所示:

NVIDIA Clara web server 以虚拟化服务的形式提供了与 TensorRT 的接口,可以接收 DICOM 格式或 nifti 格式的数据,并返回注释的结果。

5.注释者的绩效管理

测量、记录和分析注释者在每个任务、资产和标签上的表现。比较多个注释者在同一任务上的表现。在多个贴标机之间分配贴标工作,并观察他们工作中的共识。黄金数据集的种子注释任务。报告注释器在黄金数据集上的性能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Quality Management Workflow

6.标签说明管理

为了将标注任务交给自由注释者,数据科学团队需要定义标注任务的规范。这些规范需要转化为用户体验。在 TrainingData.io 应用规范生成器中称为标注指令。标签指令是数据科学家希望人类标签员在图像中找到的对象列表。对象可以有颜色、大小、形状等属性。Data-scientist 希望将这些属性以问答的 HTML 形式呈现给注释者。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Labeling Instruction Builder at TrainingData.io

7.数据安全和隐私:内部隐私保护托管

为了支持严格的安全要求,TrainingData.io 建立了一个混合工作流,其中成像训练数据和注释工具作为 Docker 映像在防火墙网络内运行。带有数据集管理的质量控制工作流托管在云中。这使得数据科学家可以与全球员工一起管理注释工作流,同时保证他们自己网络内的数据安全。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

On-Premises Hosting with Docker Containers

这个故事最初发表在 TrainingData.io 博客上。

创建机器学习模型

原文:https://towardsdatascience.com/creating-machine-learning-models-b48bb72a791f?source=collection_archive---------22-----------------------

使用、测试和比较多种机器学习模型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: Pixabay

现在,我们已经成功地完成了每个数据科学项目中最困难的部分——数据清理和争论,我们将进入有趣的部分,建模!

虽然本文可以自成体系,但最好先经过 第 1 部分第 2 部分

机器学习中的建模是一个迭代阶段,在这个阶段,数据科学家不断地训练和测试机器学习模型,以发现最适合给定任务的模型。

存在不同的机器学习模型,选择使用哪一个通常取决于手头的问题。没有机器学习模型对所有类型的问题都是最好的。因此,在这个阶段,您的工作是测试多个模型并微调参数,以挤出每一点准确性。

:虽然我们通常追求性能更高的模型,但通常更明智、更好的选择是性能几乎和复杂模型一样好的更简单的模型。

为您的机器学习竞赛节省 .0001 增加的性能,因为在现实世界的大部分时间里,这些微小的差异并不重要,因为我们需要更简单的可解释模型。

有鉴于此,我们开始工作吧。从一个简单的基础模型开始总是好的,这样你就可以得到一个基线来衡量性能。

由于我们的数据集很小,我们将使用交叉验证,对于性能指标,我们将使用平均绝对误差。交叉验证有助于衡量我们模型的真实性能。

我们创建了一个交叉验证函数,如下所示。

对于回归任务,从简单的线性回归开始

我们从简单的线性回归开始建模,交叉验证并打印分数。

我们能调谐什么

线性回归很简单,因此没有太多要调整的参数。所以我们只需使用默认参数。

MAE Sccore:  0.42615411746170206

使用决策树

接下来,我们使用另一种简单但有效的算法,称为决策树

我们能调谐什么

决策树包含许多超参数,但我们可以快速调整的最重要的超参数是:

  1. 最大深度:最大深度参数表示树的深度。树越深,模型就越复杂,它就能获取更多关于数据的信息。如果您的模型太简单,请尝试增加 max_depth,反之亦然。
  2. min_samples_leaf :这是一个叶节点所需的最小样本数。较高的叶片数导致更简单的模型,并可能有助于过拟合,而较小的叶片数可能导致欠拟合。
  3. min_samples_split: 这是分割内部节点所需的最小样本数。该参数增加导致更简单/受约束的模型。
  4. max_features :这是模型在分割一个节点之前考虑的特征数量。
MAE Sccore:  0.4280371717119684

使用 K-最近邻

接下来,我们尝试一种流行的基于距离的算法,称为 k-最近邻算法

我们能调什么

KNN 包含几个超参数。最重要的一项调整是:

  1. n_neighbors :这是投票时使用的邻居数量。数字越大,它就越精确(有时是这样),但代价是速度。
**MAE Sccore:  0.431624658307474**

查看简单模型的 MAE(平均绝对误差)分数,我们看到决策树是迄今为止最好的。这将是我们的基本模型。任何表现更好的模型都将成为下一个要超越的底线。

现在,我们将从简单模型转向高级模型。许多高性能的机器学习模型通常基于集成。集成是一种结合多种机器学习算法的方法,以获得比任何单一算法都更好的预测性能。

下面我们将使用一些流行的合奏方法并比较它们的性能。

打包算法

随机森林

随机森林算法是 bagging 的一种流行而有效的实现,它从一个引导样本构建多棵树。它有很高的预测能力,开箱即用。

我们能调什么

随机森林包含许多超参数,但最重要的优化参数是:

  1. n_estimators :这是要创建的决策树的数量。正如我们可能猜测的那样,更多的树会产生更好的模型,但代价是更长的训练时间。
  2. 最大深度:这是单棵树的最大深度。数字越大,树越简单,因此随机森林集合也越简单。
  3. max_features: 定义了允许分割的最大特征数。
  4. min_samples_split: 这是分割前叶节点所需的最小样本数。
MAE Sccore:  0.41512597643232896

额外的树

额外树算法是 bagging 的另一个流行的实现,它类似于随机森林,但构建其基础树的方式不同,并且通常更快。它还具有很高的预测能力,有时甚至超过随机森林。

我们能调什么

额外的树包含与随机森林相似的超参数。要调整的重要参数有:

  1. n_estimators :这是要创建的决策树的数量。正如我们可能猜测的那样,更多的树会产生更好的模型,但代价是更长的训练时间。
  2. 最大深度:这是单棵树的最大深度。数字越大,树越简单,因此随机森林集合也越简单。
  3. max_features: 定义了允许分割的最大特征数。
  4. min_samples_split: 这是分割前叶节点所需的最小样本数。
MAE Sccore:  0.4131678014407999

BAGGING 元估计量

sklearn 中的 bagging 估计器允许您从任何选择的模型中创建 Bagging 系综。也就是说,你可以从线性回归这样的单一模型中创建 bagging 系综,甚至是像随机森林或额外树这样的系综。

我们能调什么

这里要调整的重要超参数是:

  1. base_estimator: 这是在执行装袋时使用的估计值。bagging 元估计器从指定的基本估计器构建多个模型。
  2. n_estimators :这是要创建的基本估计数。较高数量的估计器将导致更好的模型,但是也以更长的训练时间为代价。
  3. max_samples :指定训练每个基本估计器的最大样本数。
  4. max_features :这是训练每个基本估计器时从数据集中提取的最大特征数
MAE Sccore:  0.4045400489482442

从误差指标来看,我们的下一个最佳模型是 bagging 回归器,它基于额外的树回归器。这成为我们新的基线模型。

接下来,我们来尝试一些 boosting 算法。

助推算法

Boosting 是另一种流行且有效的集合技术。在 Boosting 中,多个模型被顺序训练。目标是训练比他们的前辈做得更好的模型。这意味着我们必须考虑以前的模型表现不佳的领域,并在这些领域进行改进。

adaboost 算法

我们从称为 AdaBoost 的升压的普通实现开始。这是一种古老但广泛使用的 boosting 技术,在回归任务中表现良好,尽管众所周知它会过度拟合。

我们能调什么

这里要调整的重要超参数是:

  1. n_estimators :这是要使用的基本估计数。通常,值越高,性能越好。
  2. learning_rate :该参数控制训练权重的更新。它通常与 n 估计器一起调整。一个流行的经验法则是“当你将 n_estimator 增加 10 倍时,你也将学习速率降低 10 倍。
  3. base_estimator :指定要提升的基本模型。
  4. max_depth :指定基本估计值的深度。
MAE Sccore:  0.4243339946387083

梯度推进

另一种流行的提升算法是梯度提升。

我们能调什么

这里要调整的重要超参数是:

  1. n_estimators :这是要使用的基本估值器的数量。通常,值越高,性能越好。
  2. max_depth :指定基本估算器的深度。
  3. min_samples_split :指定分割一个内部节点所需的最小样本数。
  4. max_features :训练每个基本估计器时从数据集中提取的最大特征数
MAE Sccore:  0.4063934439500354

XGBOOST

“当有疑问时,使用 XGBoost”是近年来 kaggle 平台上最流行的名言之一。

XGBoost 高效、快速,开箱即用。这是梯度增强的高级实现,确实非常有效。

我们能调什么

这里要调整的重要超参数是:

  1. eta :只是学习率的不同叫法。它有助于模型权重更新。
  2. min_child_weight:这个指定一个子节点中所需的所有特性的最小权重和。它主要用于控制过度拟合。
  3. max_depth: 该用于定义每个树节点的最大深度。深度越大,模型越复杂,反之亦然。
  4. max_leaf_nodes: 指定一棵树的最大叶子数。
  5. Gamma:Gamma 值指定进行分割所需的最小损失减少量。只有当产生的分裂给出损失函数的正减少时,节点才被分裂。这些值可能因损失函数而异,应该进行调整。
  6. 子样本:指定为每棵树随机选择的特征部分。较低的值使算法更简单,并防止过度拟合。
MAE Sccore:  0.4099352064907469

LIGHTGBM

LightGBM 是微软的 boosting 算法。这是最快的助推算法之一;高效的开箱即用,目前是大型结构化数据的首选。

我们能调什么

这里要调整的重要超参数是:

  1. num_iterations :指定要执行的增强迭代次数。
  2. 叶子数量:指定一棵树要形成的叶子数量。注意 : 在轻型 GBM 中,由于分裂发生在叶方向而不是深度方向,因此 num_leaves 必须小于 2^(max_depth,否则可能导致过拟合。
  3. min_data_in_leaf :它是处理过拟合最重要的参数之一。
  4. max_depth :指定一棵树可以生长的最大深度。此参数的值非常高会导致过度拟合。
  5. bagging_fraction :用于指定每次迭代使用的数据的分数。该参数通常用于加速训练。
MAE Sccore:  0.4084352064907469

CATBOOST

Catboost 是最近出现的 boosting 算法。它快速、高效且容易处理分类特征(它最好的特征之一)。

CatBoost 可以自动处理分类变量,不需要像其他机器学习算法那样进行大量的数据预处理

我们能调什么

这里要调整的重要超参数是:

  1. loss_function: 指定用于训练的度量。
  2. **迭代次数:**可以构建的最大树数。
  3. learning_rate: 指定用于减少梯度步长的学习率。
  4. **深度:**指定要创建的树的深度。
MAE Score: 0.4123613834195344

最终想法

在这篇文章中,我们学习了如何获取预处理过的数据集,并尝试不同的机器学习模型。虽然本文基于回归任务,但是同样的步骤也可以应用于分类任务。这篇文章的一些要点是:

  1. 选择一个好的验证策略。(小型数据集的交叉验证,大型数据集的拆分)
  2. 从简单开始,得到一个基线模型。
  3. 通过调整和测量性能来不断改进模型。

手动调整最佳模型后,更高级的技术是使用自动超参数搜索算法,如网格或随机搜索。

记住,尽可能让你的模型简单易懂。

如果你从这一系列的帖子中学到了什么,别忘了鼓掌和分享。

在 GitHub 上链接到带有代码和解释的完整笔记本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Twitter 上和我联系。

LinkedIn 上与我联系。

用蟒蛇和熊猫创造我自己的“蒙佐年”

原文:https://towardsdatascience.com/creating-my-own-year-in-monzo-using-python-pandas-e866a17c3509?source=collection_archive---------37-----------------------

深入分析

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

拥有 Monzo 账户的 nyone 只需简单调用一个 API 就能访问他们的全部交易历史。交易历史数据集非常丰富,可以为您的消费习惯提供独特的见解,对于任何学习数据科学和分析的人来说都是一个很好的资源。在本文中,我将探索一些我自己的消费习惯统计数据,并向您展示如何使用一些基本的 Python 编程来做同样的事情。

数据科学工具包

在开始分析之前,先简单介绍一下我将使用的工具:

  • jupyter Notebook——一个在线笔记本,它使运行代码和探索数据比在一个大脚本中编写更容易。
  • python——一种具有许多自定义数据科学库的通用编程语言。
  • Pandas——最强大、应用最广泛的数据科学与分析库。

我已经在我的 GitHub 中嵌入了作为这个分析的一部分而编写的所有代码。

加载并清理数据

首先,你需要将数据放入你的 Jupyter 笔记本,并以一种更友好的方式格式化,这可以通过 7 个步骤实现:

  1. 登录 Monzo for Developers 门户,并遵循 API 文档中的认证指南来访问您的数据。
  2. 通过在本地机器上请求 JSON 形式的“事务列表”来点击 API,并将其保存为 JSON 文件。重要提示:在您必须请求另一个访问令牌之前,您只有 5 分钟的时间来完成此操作,因此请在您访问门户时尽快完成。
  3. 在 Jupyter 笔记本中,导入 pandas 和 matplotlib(用于创建图表的库),然后将 JSON 数据文件加载到 dataframe 中。

4.扁平化数据框架,使数据分析更容易。

5.将列中的事务“created”转换为 datetime 序列,并将其设置为 dataframe 的索引。

6.将交易金额从便士转换为英镑,并强制正金额与购买相对应。这是通过对列应用 lambda 函数来实现的。

7.过滤数据框架,排除内部“现金”转账,因为我们只对实际支出感兴趣。

每个事务都存储为一个 JSON 对象(见下面的例子),并包含许多键值对,我们稍后将使用它们来提取一些有趣的见解。

{
  "id": "tx_00009T3RKKR0B36laVzJh4",
  "created": "2018-01-28T12:33:46.54Z",
  "description": "TfL Travel Charge      TFL.gov.uk/CP GBR",
  "amount": -450,
  "fees": {},
  "currency": "GBP",
  "merchant": {
    "id": "merch_000092jBCaq2cHlL8pLVkP",
    "group_id": "grp_000092JYbUJtEgP9xND1Iv",
    "created": "2015-12-03T01:24:14.372Z",
    "name": "Transport for London",
    "logo": "https://mondo-logo-cache.appspot.com/twitter/@TfL/?size=large",
    "emoji": "🚇",
    "category": "transport",
    "online": true,
    "atm": false,
    "address": {
      "short_formatted": "The United Kingdom",
      "formatted": "United Kingdom",
      "address": "",
      "city": "",
      "region": "",
      "country": "GBR",
      "postcode": "",
      "latitude": 51.49749604049592,
      "longitude": -0.13546890740963136,
      "zoom_level": 17,
      "approximate": false
    },

探索性数据分析(EDA):交易金额

现在,数据作为数据帧加载到笔记本电脑中,我们可以开始进行一些探索性的数据分析(EDA)。EDA 有助于生成一些基本的数据统计摘要,并且是让自己熟悉新数据集的好方法。

我想知道关于我的数据集中 2,464 个正交易的交易金额( )的一些统计数据。(请记住,在第 6 步中,我强制正值表示购买,负值表示付款或退款。)

我过滤金额为正数的交易,并将它们分配到一个新的数据框trans_pos_amount:

trans_pos_amount = trans[trans['amount'] > 0]

然后使用内置的 Pandas 方法.describe()在新数据帧的金额列上获得 2018、2019 和 2018–2019(合并)的交易汇总统计数据:

trans_pos_amount.loc['2018'].amount.describe()
trans_pos_amount.loc['2019'].amount.describe()
trans_pos_amount.amount.describe()

生成的 3 个汇总表返回一些标准统计数据,包括平均值、中值、标准差、四分位距和最大值:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

考虑到整个数据集(2018 年至 2019 年),似乎我每笔交易的平均支出金额为 14.50,标准差为 44.50。这表明我的支出有很大程度的可变性,这是有道理的,因为我使用 Monzo 进行日常生活,如旅行和食物,但也支付大额项目,如账单,这通常是更大的交易金额。

有趣的是,我每笔交易的平均消费金额是 2.60 英镑,几乎等同于一杯咖啡的价格(在伦敦)。稍后,我将探索哪些是我最常去的商店,看看咖啡是否真的会影响中值交易额。但是,现在很清楚的是,我用我的 Monzo 账户进行许多小交易。

还可以使用 matplotlib 库来可视化这些统计数据。可视化形式的 EDA 通常比数字形式的 EDA 更容易理解。使用.plot()方法可从trans_pos_amount数据帧中获得直方图和箱线图:

#plot a histogram and boxplot side by side
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(10,5))
trans_pos_amount.plot(kind='hist', bins=600, grid=False, edgecolor = 'black', ax=ax1)
trans_pos_amount.plot(kind='box', ax=ax2)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Histogram (left) and boxplot (right) of my transaction amounts over 2018 & 2019

正如数字数据所暗示的,我们可以看到,我的大多数交易通常金额较小,但少数大额交易会使整体平均交易金额偏高。

探索性数据分析(EDA):消费类别&商户

通过了解我的消费习惯,我知道我可以在哪里改变我的生活方式,这样从长远来看我可以节省更多的钱。使用 Monzo 数据集的一种方法是按类别过滤我的交易,例如账单、外出就餐和交通。虽然我可能无法显著改变我在必要支出(如账单和交通)上的花费,但我可以调整可自由支配的支出,如外出就餐、购物和度假。

Pandas 中非常方便的.groupby()方法可用于按类别对交易进行分组。然后很简单地按该类别的总支出来绘制分组数据:

#plot the amount spent in each category over 2018 & 2019
trans_pos_amount.groupby('category').amount.sum().sort_values().plot(kind='barh')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Total amount spent by category over 2018 & 2019

正如我预料的那样,我花在账单上的钱最多,包括房租、电话费、市政税(你知道,所有无聊的成人用品)。让我感到惊讶和尴尬的是,外出就餐是我的第二大支出类别,在两年时间里高达 6700 英镑。外出就餐肯定是可自由选择的一类,因此,我可以减少下班后外出就餐和喝酒的次数。

通过调查我与哪些商家交易最多,我可以更深入地了解我的消费习惯。在可能的情况下,Monzo 会向我们提供详细的商家信息,包括名称、位置和社交媒体信息。我只对merchant_name字段感兴趣,它可以从 dataframe 中访问。我创建了一个名为merch_freq的新数据框架,并使用.value_counts()方法产生一个按交易数量排序的商家列表(调用.head()返回最后的前 5 个值):

merch_freq = trans['merchant_name'].value_counts()
merch_freq .head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Top 5 merchants by number of transactions

直观地看这些信息会更容易理解,但我只想包括我的前 10 名商户,所以我在数据帧上使用了.nlargest()方法,然后按照频率顺序绘制出我的前 10 名商户:

merch_freq.nlargest(10).sort_values().plot(kind='barh')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Top 10 merchants by number of transactions

注意:出于保密原因,我编辑了其中一个商家的名字

从这张图表中可以清楚地看出,我的前 10 名商户中有一半可以归为“外出就餐”一类。毫不奇怪,我最受欢迎的商家是伦敦交通局,因为我几乎每天都用我的 Monzo 进出 TfL 网络。

早些时候,我质疑我的平均消费金额 2.60 英镑(相当于伦敦一杯咖啡的价格)能否用我去咖啡店的次数来解释。事实上,从图表上看,有两家咖啡店(Boulangerie Jade & Pret A Manger)创下了令人震惊的 392 笔交易。我的交易中大约有 16%涉及咖啡!我认为假设我的咖啡瘾确实影响了我每笔交易的平均花费是公平的。

虽然我有 10 个最频繁交易的商家,但我想知道当我检查哪些商家我花了最多的钱时,列表是否会有很大变化?为了研究这一点,我创建了一个名为merch_amount的新数据帧,并再次使用.groupby()方法,这次按merchant_name字段分组。我计算了每个商家的总消费金额,然后首先按最大金额对数据框进行排序:

merch_amount = trans.groupby(trans['merchant_name'], sort=True).sum().sort_values('amount', ascending=False)

之后,创建一个情节就很简单了:

merch_amount['amount'].nlargest(10).sort_values().plot(kind='barh')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Top 10 merchants by amount spent

幸运的是,在我的金额排名前 10 名中,我看到了更多与账单和费用相关的商家。然而,令人失望的是,我无法使用这个数据集透露更多关于我的美国运通交易的信息。我使用我 Monzo 帐户来支付我的美国运通,因此关于这些交易的任何信息基本上都落入了黑洞(尽管我可以利用他们的 API 来获取数据)。

我还没探索完我的咖啡假说。当我合计在 Boulangerie Jade 和 Pret A Manger 的消费总额时,我发现两年多来我在咖啡因上浪费了 1037 英镑。分布在总共 392 个事务上,得出的平均值为 2.62,这几乎等于我在整个数据集上的中值事务量。

对比我的 2018 年和 2019 年

最后,我想检查一下我对 Monzo 的使用在 2018 年和 2019 年之间发生了什么变化,并潜在地看看未来是否有我可以预期的特别昂贵的月份。我在这里的目标是创建一个条形图,比较 2018 年和 2019 年之间每月的支出总额。

在开始清理数据时,我确保用日期时间标记索引每个事务。这一步现在将开始得到回报,因为我可以更容易地过滤数据,并使用.resample()方法按月对每笔交易进行分组。

首先,我按年份过滤trans_pos_amount数据帧,然后在新的df_2018数据帧上使用.resample().sum()方法:

df_2018 = trans_pos_amount.loc['2018']
df_2018_monthly_resample = df_2018.resample('M').sum()

本质上,通过重采样然后求和,我得到了一个月内的所有交易(当我将‘M’解析到方法中时指定),并将它们组合成一个数字。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Re-sampling allows me to group transactions by month

df_2018_monthly_resample数据框包含 2018 年每个月花费的总额。但是,这个数据帧的索引不是我想要的。数据帧不是被索引为有序的月份列表,例如“一月”、“二月”、“三月”,而是被索引为日期时间戳,例如“2018–01–31 00:00:00+00:00”。不要担心,只要新索引的长度与数据帧的长度匹配,我可以将数据帧的索引设置为我想要的任何值。我简单地创建了一个月份列表(labels_2018labels_2019),然后将该列表解析为set.index()方法:

df_2018_new_index = df_2018_monthly_resample.set_index([labels_2018])df_2019_new_index = df_2019_monthly_resample.set_index([labels_2019])

现在,我可以将新索引的 2018 年和 2019 年数据帧合并为一个,方法是创建一个新的数据帧,并使用键值对将年份与其各自的数据帧进行匹配:

df_2018_vs_2019 = pd.DataFrame({'2018':df_2018_new_index.amount, '2019':df_2019_new_index.amount}, index=labels_2018)

现在有了一个整洁的数据框架,我可以绘制数据来实现我的目标:

df_2018_vs_2019.plot(kind='bar')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Comparing 2018 and 2019 spending amounts

从图表中可以明确的是,2019 年我对 Monzo 的使用量远远高于 2018 年。这可能有两个原因:1 .我花了一些时间才把 Monzo 作为我的主要银行。2.我在 2019 年赚了更多的钱,这可能会反映在我花费的金额上。

就月度趋势而言,随着夏季(5 月至 9 月)的临近,2019 年的趋势肯定会有所上升,但随着我们进入冬季,这一趋势似乎会有所下降。这是合乎逻辑的,因为夏天有更长的白天,并且提供了更多的机会去做我根据我的数据最常做的事情:出去吃和喝!

最终外卖

在这个小项目开始时,我对如何花钱有一个粗略的想法,但现在我有了一些真正的见解。很明显,我需要减少我在外面吃饭和喝酒的习惯,但我也可能会寻找更具成本效益的方式在伦敦四处游览。伦敦的交通对我来说是一个巨大的支出,所以使用城市地图绘制者通行证或简单地获得月票可能是有益的。

Monzo 提供了一个非常干净和可访问的数据集,可以用来做比简单的 EDA 复杂得多的事情。在一个这样的示例中,商家位置信息用于创建吸引人的交易地图。虽然这些地图很吸引人,但也可以用来帮助用户识别欺诈活动,因为用户更有可能以这种新颖的格式与他们的数据进行交互。

事实上,这个数据集的潜在用例是无限的,这是为什么开放银行的黎明将为初创公司和现有金融服务提供商提供新的有价值的想法的一个例子。

自己试一试

我强烈推荐使用数据营来提升自己在数据科学和分析方面的技能。通过跟随他们的视频,然后用他们的指导教程练习,我在几周的时间里从一个初学者变成了分析真实世界数据的人。

提醒:链接到对您自己的数据进行分析所需的代码。

使用 Google 云平台创建 MySQL 实例

原文:https://towardsdatascience.com/creating-mysql-instance-using-google-cloud-platform-353c36803cee?source=collection_archive---------13-----------------------

在谷歌云中创建和管理 MySQL 数据库。

在本文中,我们将总结如何使用 Google Cloud Platform 创建 MySQL 数据库实例,从 Google 的 cloud shell 连接到创建的实例以测试它,然后在我们的本地机器上使用 MySQL workbench 连接到同一个实例。有很多方法可以在云中的数据库中工作,类似于微软 Azure 或 AWS。在这种情况下,我们将专注于基本的 Google 云平台,不包括高级配置选项。

1-前往https://cloud.google.com/,创建一个免费试用的谷歌云平台账户。这将给予 12 个月或 300 美元的免费积分(以先到者为准)

2-去 https://cloud.google.com/的然后去你的控制台。

3-转到 SQL 仪表板部分,并选择创建实例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4-选择选择第二代(推荐)

5-创建实例 id 和 root 密码。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6-选择创建。这将需要一些时间,但在谷歌云平台中创建 MYSQL 实例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

8-完成后,实例 ID 旁边会有一个复选标记。

9-单击创建的 MSQL 实例。

10-记下服务器 IP 地址并使用云外壳进行连接。将客户端 IP 地址列入白名单需要一些时间。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

11-云壳会提示你输入密码。输入密码后,实例连接将完成。我们可以进一步执行 SQL 语句,并通过云外壳访问 MYSQL 实例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

12-去 google.com 并获得公共 IP 地址。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

13-转到实例详细信息/连接,添加一个网络,并在网络名称下添加此 IP 地址,然后单击保存。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

14-转到本地机器上的 MYSQL workbench。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

15-创建新连接。

16-添加连接名称。

17-使用步骤 10 中记录的服务器 IP 地址更新主机名。

18-创建用户名和最佳实践来创建非 root 密码。

19-保留默认模式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

20-测试连接将提示您输入密码。输入您的实例密码。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

21-成功地建立了 MySQL 连接。单击确定。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

22-Google 云平台 MYSQL 创建并连接到本地 MySQL workbench。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个过程非常简单易懂。我们可以进一步创建关系数据库和表,使用 GCP 实例从本地 MySQL 工作台执行查询。我们还可以将数据库中创建的任何表加载到我们的本地 R 或 Python 中,并执行分析。

使用 NLP 创建新的复合生物砖

原文:https://towardsdatascience.com/creating-new-composite-biobricks-using-nlp-812126992a94?source=collection_archive---------29-----------------------

结合合成生物学和人工智能

生物砖是合成生物学中用于创造新的复合结构的基本单元。他们首先提取 DNA 的基本核苷酸:A、T、G 和 C,然后从中形成一种具有特定功能的合成蛋白质。例如,如果我想让我的蛋白质负责让一个细胞发绿光,我会创建一个编码这一特性的序列(或者通过提取让水母发光的蛋白质序列来模仿它)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

An example of a bio brick structure. Source: http://2016.igem.org/wiki/images/6/6f/T–Minnesota–diagram3.png

然后,我会根据细胞成功产生这些蛋白质的需要,通过添加更多的结构来优化它,如 RBS(核糖体结合位点)。当提到生物砖时,经常会用乐高积木来类比,因为用来制造蛋白质的结构是“堆叠”的。

生物砖不仅仅具有制造蛋白质的能力,而且整个系统都依赖于所制造的复合蛋白质的功能。

生物砖之所以备受争议,是因为理论上任何蛋白质都可以由计算机制造出来。这一点的影响是巨大的,因为它们在未来也可以应用于人类细胞,这意味着如果我们继续追求这一知识,改变人类基因组以获得我们想要的特征可以比仅仅使用 CRISPR 技术(简单的基因编辑)更快地成为现实。

然而,目前为了获得结果,通常将生物砖部分注入空的细菌细胞,主要是大肠杆菌细胞中进行观察。但是生物砖也有非常有用的积极意义。例如,使用生物砖,我们可以创造自己的蛋白质,产生人类兼容的胰岛素,这表明没有必要再从其他动物中提取胰岛素并将其转化为可用的蛋白质。

缩短开发人类兼容胰岛素的过程将对糖尿病患者极为有益,因为药物将变得更便宜、更容易获得,更不用说所有其他需要蛋白质来缓解症状的疾病了。

但是我们如何从单一的生物砖部件发展到在细菌中培养胰岛素工厂呢?例如,我们如何有效地利用这些部分来生产更多的复合蛋白质,比如更理想的胰岛素分子?换句话说,在 syn bio 领域有这么多机会,我们从哪里开始呢?

我如何利用人工智能和合成生物

通过 spaCy + NLTK 库使用自然语言处理(NLP ),我能够操纵 BioBrick 部件数据库来产生各种全新的复合蛋白质。

通过提供复合结构各部分的顺序,而不是各部分的具体名称,我的应用程序生成了一个复合砖块,可以用于所需的功能。例如,如果我想制造一个发绿色光的完整蛋白质,并且与细菌细胞相容,我会输入对启动子、RBS、GFP 基因(发绿色荧光)等的要求。

结果是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

起初有许多无意义的核苷酸模式,但当仔细汇编和分析时,你会发现这正是我们所需要的。

它是如何工作的

我的程序通过匹配 DNA 的粘性末端来优化复合蛋白质的最佳结果,这种排列包含在细菌中成功实现的最高机会。使用 NLP 是这个过程不可或缺的一部分,因为它允许您指定在新零件中包含哪些而不是

例如,通过向程序投掷随机单词,它将输出一个随机部分,该随机部分有机会与其他部分匹配,但不是很高。但是,如果您指定了哪些零件可以挑选,哪些不可以挑选的条件,您就大大增加了零件装配在一起并按预期运行的机会。

NLTK 和 spaCy 库非常适合这种情况,因为它们使 NLP 处理变得非常简单。基于这些输入,你现在可以处理与单词相关的否定,某些蛋白质的形容词,等等。

BioBrick 零件数据库包括约 500,000 行测序零件,其中包含每个类别的绝大多数选项。程序创建的每一个新部分都试图根据规范包含启动子、RBS、报告子、终止子等。

该程序还包括使用一个简单的分类器来分类哪些砖块最适合哪些砖块。这个项目中人工智能的另一个相对简单的应用表明,从简单的输入和过程中创造出复杂的输出是多么容易。

未来应用

更多的想法可以从这个中产生。另一个 AI + syn bio 项目的一个例子可能是使用 GANs 生成新的部分,类似于科学家使用相同技术开发新药的方式。

砖块也可以用人工智能来测试。ML 具有从任何数据中学习的潜力,这意味着如果它在成功的复合砖块的要求中找到模式并不断地从它们中学习,那么它就具有测试未来砖块所需的准确性。这将非常有帮助,因为中间的所有处理工作都可以被消除,从而产生一个更高效的系统。

我们试验的部分越多,我们就越能理解人工智能和 syn bio 能走多远。通过将 ML 与任何科学相结合,我们可以有效地加速理解当前未知事物的过程,并开发应用程序来帮助我们作为一个社会成长。

使用 StyleGAN 创建新脚本

原文:https://towardsdatascience.com/creating-new-scripts-with-stylegan-c16473a50fd0?source=collection_archive---------8-----------------------

我将 StyleGAN 应用于 Unicode 字符的图像,看看它是否能发明新的字符。我发现了一些有趣的结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

New characters generated by StyleGAN from Unicode

世界的剧本

世界上的语言使用大约 400 种不同的书写系统。这包括今天使用最广泛的拉丁文字:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Simple Latin Characters

The Unicode Consortium aims to map every character in the world to an underlying number so that they can be easily used across different computer systems. For example, hash “#” is mapped to the number 35, a-acute “á” is 225, and the Chinese character for fog “雾” is mapped to 38,654. The first ~65,000 characters in Unicode cover most scripts in current use and are divided into ~140 blocks, with Simple Latin being one of those blocks. See the Wikipedia Page on Unicode Blocks for the full list.

我在 Unicode 协会工作过一段时间。我被美国语言学会任命为候补委员,关注那些未被充分代表的语言。我着迷于亲眼目睹脚本如何被形式化和编码的过程,以便世界上的每个人都可以利用信息时代,无论他们选择如何交流。我在 Unicode Consortium 的时候,表情符号第一次被添加到 Unicode 中,这可能是他们最有争议的决定。你可以在这里阅读我关于见证表情符号被添加到 Unicode 的文章:

[## 艾萨克·牛顿 vs 数百万日本青少年

medium.com](https://medium.com/@robert.munro/isaac-newton-vs-millions-of-japanese-teens-6d952801f6f2)

最困难的决定之一是在 Unicode 标准中如何命名给定的脚本。按照 Unicode 的定义,简单拉丁语包括常见的标点符号、字符和数字。显然,使用这种文字的语言比拉丁语多,你可以争论标点符号是否是文字的一部分。你指出除了 0 以外的所有数字都来自阿拉伯语也是对的。因此,Unicode 中的“块”试图映射到脚本中有意义的部分,承认边界可能是模糊的,并且脚本通常会有多个可能具有政治含义的名称。因此,这些名称对于 Unicode 中的块来说是方便的简写,但并不打算成为使用该语言的人的主要或唯一的名称。

带着这个警告,这里有一些有趣的 Unicode 脚本,我用它们作为用 StyleGAN 创建新脚本的基础:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Armenian

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Arabic

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Devanagari

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Bengali

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Gujarati

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Tamil

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Kannada

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Malayalam

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Thai

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Hangul Symbols

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

CJK Compatibility Ideographs (CJK = Chinese Japanese Korean)

我承认在我上面的例子中,我过分强调了南亚的语言。在早起观看印度和巴基斯坦在板球世界杯中的比赛后,我写了这篇文章,所以我强调了他们国家内部的多样性,可能也包括了他们球队内部的多样性。如果你对语言和体育感兴趣,你也应该在这里看到我对足球世界杯球员名字的分析:

[## 世界杯人物

medium.com](https://medium.com/@robert.munro/world-cup-characters-6c8d003b0274)

数据准备

我用 python Pillow 库和 MAC 自带的“Ariel unicode”字体为每个 Unicode 字符生成了一个 JPG 图像。如果你想重新创建这个,让我知道,我会分享我的代码。

更新:代码在这里:【https://github.com/rmunro/unicode_image_generator】T2

我用不同的颜色对每个区块(与一个脚本相关的每个字符范围)中的图像进行编码,这样我就可以很容易地看到最终字符集中的最大影响。上面图像中的颜色反映出:拉丁语是黑色,泰米尔语是亮绿色,等等。

最初,这产生了大约 40,000 张图像。这是 65,000 个字符中有多少经过 Ariel Unicode 字体的某种渲染。尝试一种覆盖面更大的字体会很有趣,尤其是在不再使用的旧字体和表情符号等其他字符之间。使用多种不同的字体生成字符也是很有趣的。如果你这样做,让我知道!

在这 40,000 个汉字中,大部分是中国和日本汉字。我很快放弃了一个实验,在这个实验中,StyleGAN 只生成看起来像中国和日本汉字的新字符。

对于每个超过 256 个字符的块,我随机选择了 256 个字符的子集。这使得数据从 40,000 个字符增加到大约 7,000 个字符。我用这 7000 来训练这个模型,我在本文中分享了它的结果。

为了查看每个区块的前 20 个字符及其颜色,我在我的个人网站上列出了它们:

  • 【http://robertmunro.com/research/unicode/show.html

StyleGAN

StyleGAN 是一个在 TensorFlow 中实现的图像生成系统,它使用生成式对抗网络(GANs)。它是由 NVidia 开发的,并在此作为开源代码发布:

有关他们方法的更多信息,请参见本文:

  • 一种基于风格的生成式对抗网络生成器架构。泰罗·卡拉斯、萨穆利·莱恩和蒂莫·艾拉。http://stylegan.xyz/paper

StyleGAN 最著名的用途是为实际不存在的人创建“逼真”的照片:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Examples of fake faces generated by styleGAN, from https://github.com/NVlabs/stylegan

人们一直在用这个来生成其他的假图像,我受到了其中一些的启发,包括迈尔斯·布伦戴奇使用 StyleGAN 来创建新的《太空堡垒卡拉狄加》图像:

Because Cylons look like people, but they are not real people?

实验

我对 7000 张图片进行了分层采样,并根据它们的 Unicode 编码进行了颜色编码,我在 P2 AWS 实例上运行了 styleGAN 整整一周。我使用了深度学习 AMI,我需要安装的唯一附加库是用于从字体生成图像。

同样,如果你感兴趣,让我知道,我会上传代码。这是对 styleGAN 代码的一个小修改。最困难的部分是让图像和字体库在 python 中运行良好,这样我就可以以编程方式为每个 Unicode 字符生成图像并给图像着色。

结果

理想情况下,结果应该看起来像实际的字符,但是而不是看起来像当今 Unicode 中的任何字符。

下面是系统训练过的一些真实的例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

首先,结果不太令人信服。在 10 个样本图像(styleGAN 系统中的“刻度”)之后,它们变得模糊不清:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Example fakes after 10 ticks

但是在 30 次滴答之后,我们开始看到一些清晰的例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Example fakes after 30 ticks

30 个刻度后的示例在缩小时看起来很真实,但在放大时有点奇怪,因为直线和曲线之间没有明显的区别:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Alien-looking character after 30 ticks

这也是本文开头的图片,是在 78 次滴答之后,现在有了一些非常清晰的例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Example fakes after 78 ticks

直线和曲线之间的区别现在很明显,重音和音调符号现在与字符本身更加明显。在 StyleGAN 的训练中,分辨率增加了一倍,在 30 到 78 个刻度之间,这也有所帮助。

以下是我最喜欢的《78 滴答》,颜色告诉我们它们的影响来自哪里:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Latin influenced

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Arabic influenced

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Thai influenced

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

CJK (Chinese Japanese Korean) influenced

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Enclosed CJK influenced

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Malayalam influenced

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Devanagari influenced

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Tamil influenced

我真的对这些角色的逼真印象深刻!除了几个例外,看起来它们都属于某种语言的脚本。

有一些例子表明已经是 Unicode 中的字符。这些例子可能不是随机选择的 256 块中的一部分,或者它们可能以不同的方式偏移或缩放。我还没有研究为什么这些会错误地出现。

到第 78 个滴答时,训练还没有完成。我把这限制在一周的训练中,主要是为了适应我的个人时间表。我敢肯定,如果它能持续更长时间,它会创造出更有趣、更有说服力的角色。

只花了半天时间进行实验,花了几个小时进行分析和记录。或者用板球世界杯的术语来说,它花了一局时间来编写代码和启动流程,然后花了 27 局时间来分析结果和写这篇博文。如果你也是一个喜欢板球的程序员,这是一个在观看世界杯时进行多任务处理的好方法!

只有一个方面的结果没有达到我的预期:我希望一些新角色会是彩虹色的,并同时显示出来自多个剧本的影响。经过思考,我明白了为什么情况不是这样:在训练数据中没有彩色的例子,因此彩色的例子不会是令人信服的对立例子。

为什么要生成新字符?

除了有趣的因素,这里还有一些实际的使用案例:

  • 为新脚本识别新字符。世界上只有一半的语言采用了文字。对于一个语言社区来说,采用前殖民者或入侵者的文字往往是有争议的。这种方法可以提供一个候选字符列表,我们已经知道这些字符并不存在,但是在风格上与世界范围内的文字一致。
  • **理解文字的视觉属性。**生成的赝品都告诉我们一些关于文字视觉属性的有趣事情:曲线和线条的选择,字符空间不同部分的信息分布,等等。因此,它们告诉我们一些有趣的事情,关于我们如何在不同的脚本中以相似或不同的方式编码信息。
  • 为创造性用例创建新的脚本。从《指环王》到《星际迷航》,在书籍和电影中有许多有趣的假剧本例子。如果你没有预算雇用大卫·J·彼得森,这种方法可以产生比你有时在低成本科幻电影中看到的随机符号更真实的剧本。

如果你知道 StyleGAN 的任何其他有趣的应用,或者其他生成新字符的方法,请告诉我!

更新:代码在这里:https://github.com/rmunro/unicode_image_generator

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值