TowardsDataScience-博客中文翻译-2016-2018-二百九十五-

50 阅读1小时+

TowardsDataScience 博客中文翻译 2016~2018(二百九十五)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

第 1 部分:将 YouTube 的 Python API 用于数据科学

原文:towardsdatascience.com/tutorial-us…

搜索 YouTube 庞大目录的简单技巧

上周,我写了一篇使用谷歌语音识别 API 的快速指南,我将其描述为“有点-有点-真的令人困惑。”你猜怎么着?他们的 YouTube 数据 API 也不是非常清晰。

如果你是一个有几十年经验的编程专家,你可能现在就可以停止阅读了。然而,如果你是一个中级或自学的程序员(像我一样),这个指南应该可以帮助你快速使用 YouTube 进行数据科学研究。

出于时间和整体可读性的考虑,我决定将本教程分成多个部分。在第一部分中,除了进行简单的关键字查询之外,我们将重点关注 API 库的安装和认证。

接下来的部分将关注其他类型的任务,比如评论收集、地理查询和使用频道。

要完成本教程,您需要以下工具:

  • Python 2.7
  • 一个谷歌账户

入门指南

1)克隆 GitHub 库

git clone [https://github.com/spnichol/youtube_tutorial.git](https://github.com/spnichol/youtube_tutorial.git)
cd youtube_tutorial

2)安装 YouTube 官方 Python 客户端库

pip install --upgrade google-api-python-client

3)激活 YouTube API

**注意:**为了完成这一步,您需要创建一个“项目”。如果你不确定如何做到这一点,查看我的语音识别教程作为快速指南。

前往谷歌云控制台,点击左上角的汉堡菜单,选择“API 管理器”。

从 YouTube APIs 中选择“YouTube 数据 API”。

单击“启用”

从左侧导航面板中单击“凭据”,然后选择“创建凭据”您需要从下拉列表中选择 API 键。您应该会看到一条带有字母数字 API 密钥的消息,上面写着“API 密钥已创建”。复制并保存在一个安全的地方!

Click "Enable"

设置我们的 Python 脚本

在代码编辑器中打开 youtube_videos.py。这是 YouTube 的样本代码的大规模修改版本。

将第五行的 DEVELOPER_KEY 变量替换为我们之前创建的 API 密钥,并保存文件。

DEVELOPER_KEY = "REPLACETHISWITHYOURKEY_GOTIT?" 

酷,酷,酷。我们准备开始编写代码来进行关键字查询。继续创建一个新的 python 脚本,并将其保存在相同的目录中。

设置我们的 Python 脚本

我们希望能够使用保存 API 密钥的 youtube_search.py 文件中的函数。一种方法是将该目录附加到我们的 Python 路径中。

1)将目录追加到 Python 路径

import sys
sys.path.append("/home/your_name/youtube_tutorial/")

2)导入 **youtube_search** 功能

既然我们已经设置了路径,我们可以用一个简单的 import 语句从 youtube_videos.py 文件中引入youtube_search函数。

from youtube_videos.py import youtube_search

让我们也导入 json 库,因为它在解析 API 的 json 输出时会派上用场。

import json

太好了。我们已经准备好使用我们的 youtube_search 功能来尝试快速关键字搜索。

4)测试出 **youtube_search** 功能。

假设我们喜欢坐立不安的纺纱工(我们不喜欢),我们想看看 YouTube 上有什么关于他们的视频。

test = youtube_search("spinners")
test

您的输出应该如下所示:

我们的youtube_search的输出是一个 len = 2 的元组。第一项是一些奇怪的六字符字符串。第二项是一堆 JSON。让我们暂时忽略这个奇怪的六字符字符串,只选择 JSON。

just_json = test[1]
len(just_json)

现在你应该有这个:

现在我们可以看到我们有一个 len = 50 的 JSON 对象。每个条目都是一个 YouTube 视频,包含该视频的详细信息,如 ID、标题、发布日期、缩略图 URL、持续时间等。

假设我们想要获得一个视频的标题,我们可以很容易地用 JSON 库循环并解析它。

for video in just_json:
    print video['snippet']['title']

这给了我们:

坐立不安旋转披萨?啊?

好的,继续。现在,我们早些时候发现我们的输出由 50 个不同的视频组成。这很好,当然,关于 spinners 的视频比我想看的要多,但是,这不可能是全部,对吗?

没错。如果我们想要超过 50 个视频,这是我们在一个请求中可以得到的最大值,我们必须要求另一轮 50 个。我们可以通过使用我们前面看到的奇怪的六字符字符串来做到这一点…也称为令牌。

如果我们在下一次请求时发送令牌,YouTube 将知道它停止的位置,并向我们发送接下来的 50 个最相关的结果。让我们试试。

token = test[0]
youtube_search("spinners", token=token)

现在我们有:

太棒了。五十多个关于纺纱工的视频。另外,如果你注意到了,我们得到了另一个令牌。如果我们想继续下去,我们只需用这个令牌冲洗并重复。

显然这样做真的很糟糕。相反,我们可以编写一个函数来稍微自动化这个过程。

自动化流程

  1. 实例化一个字典来存储结果

在我们写函数之前,让我们用我们想要保存的变量名实例化一个字典。

video_dict = {'youID':[], 'title':[], 'pub_date':[]}

2)定义我们的功能

我们可以将我们的函数命名为 grab_videos ,并添加两个参数。第一个是关键字,第二个是令牌的可选参数。

def grab_videos(keyword, token=None):

3)添加 **youtube_search** 并保存我们的变量

就像之前一样,我们将使用youtube_search函数进行简单的搜索,并分别保存我们的令牌和 JSON 结果。

res = youtube_search(keyword)
token = res[0]
videos = res[1]

4)循环遍历结果,追加到字典&返回标记

for vid in videos:
  video_dict['youID'].append(vid['id']['videoId'])
  video_dict['title'].append(vid['snippet']['title'])
  video_dict['pub_date'].append(vid['snippet']['publishedAt'])
**print** "added " + str(len(videos)) + " videos to a total of " + str(len(video_dict['youID']))return token 

我还在这里添加了一个小的 print 语句,用于在每次调用该函数时更新我们收集的视频数量。

最后,我们返回令牌,这样我们可以在下次调用函数时使用它。

5)用 while 语句调用函数

既然我们已经编写了函数,我们可以编写几行简短的代码来使它工作。

首先,我们将使用我们的关键字调用函数,将结果保存到变量令牌

然后,我们可以使用 while 语句来检查函数是否返回了一个有效的令牌(即有更多的结果)或者我们是否已经遍历了所有内容。如果它看到“last_page”,就会停止代码的执行。

token = grab_videos("spinners")
**while** token != "last_page":
    token = grab_videos("spinners", token=token)

输出应该如下所示:

结论

好了,现在你至少部分准备好开始在 YouTube 上收集你自己的数据了。

如果这篇文章有帮助,请通过电子邮件或在评论区告诉我。如果没有,我会从事一些其他的爱好!请继续收看第二和第三部分。

第 2 部分:将 YouTube 的 Python API 用于数据科学

原文:towardsdatascience.com/tutorial-us…

执行基于位置的视频查询

第 1 部分中,我们为 Python 设置了 YouTube API,并学习了如何对视频进行简单的关键字查询。现在,我们想更进一步。

关键字查询对于探索性分析来说是很棒的,但是它们太宽泛了,不能对我们正在研究的主题做出任何有意义的结论。相反,让我们尝试一项新技术:地理查询

地理查询

当在数据分析或数据科学中使用任何类型的社交媒体时,我们不仅关注“是什么”——识别有趣现象的存在——还关注“在哪里”——发现我们数据行为的地理差异。

例如,我们在教程的第 1 部分中看到,显然有一个现象需要研究:人们确实录制并上传了关于坐立不安者的 YouTube 视频(可悲的是)。

但是如果有一些我们没有考虑到的地理差异呢?如果美国东海岸的人比西海岸的人更热衷于坐立不安旋转者的粉丝会怎么样?

使用 YouTube API 的 location-radius 查询参数,我们可以很容易地研究这个研究问题。这是一个附加的查询,将返回与我们指定的参数相匹配的视频的纬度和经度。

然而,在我们开始之前,指出位置半径参数的一个主要缺点是很重要的:不是所有的 YouTube 视频都有位置信息。事实上,我敢说大多数人都不知道——这是一个可选功能,用户可以选择激活它。

记住这一点,让我们开始吧!

1)克隆 GitHub 库

git clone [https://github.com/spnichol/youtube_tutorial.git](https://github.com/spnichol/youtube_tutorial.git)
cd mapping_tutorial

如果您已经完成了本教程的前一部分,您可以跳过这一步,只需将新代码添加到现有文件中。

2)修改 **youtube_search** 功能

为了执行基于位置的搜索,我们需要向位于 youtube_videos.py 文件中的youtube_search函数添加一些额外的参数。这些参数是位置位置-半径

位置参数是我们半径中心的纬度和经度,作为字符串传递。例如,如果我们想要搜索位于纽约市 25 公里范围内的 spinners 的视频,那么位置参数的值将是“40.730610,-73.935242”。

位置-半径参数,正如你可能已经猜到的,是半径的大小,以英里或公里为单位(最大为 1000 公里)。在上面的例子中,传递给这个参数的值应该是“25km”。

首先,让我们将这些作为可选参数添加到youtube_search函数中。

def youtube_search(q, max_results=50, order="relevance", token=None, location=None, location_radius=None):

现在我们可以将参数添加到包含在 YouTube Python 库中的youtube.search().list()方法中。

def youtube_search(q, max_results=50, order="relevance", token=None, location=None, location_radius=None):
  search_response = youtube.search().list(
    q=q,
    type="video",
    pageToken=token,
    order = order,
    part="id,snippet",
    maxResults=max_results,
   ** location=location,
    locationRadius=location_radius**

  ).execute()

不幸的是,将这些参数添加到函数中实际上不会给我们提供位置信息。它只保证youtube_search函数返回的视频落在我们指定的半径范围内。烦人…我知道。

3)创建 **geo_query** 功能

为了得到好东西,我们需要使用另一个T4,但是这次我们将为part参数传递记录详细信息统计信息。我们还需要运行我们的build函数,让 API 知道我们是谁。

为了简单起见,让我们用一个叫做geo_query的独立函数来做这件事。

def geo_query(video_id):
    youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=DEVELOPER_KEY)

    video_response = youtube.videos().list(
        id=video_id,
        part='snippet, recordingDetails, statistics'

    ).execute()

    return video_response

要运行这个函数,我们向它传递一个视频 ID,它应该返回视频的纬度和经度,以及关于文件的其他有用的详细信息。让我们试一试。

4)测试我们的 **geo_query** 功能

继续创建一个新的 Python 文件,我们将在其中编写本教程的其余代码。

我们可以从导入我们的库开始,设置工作目录并测试我们对youtube_search函数所做的修改。

让我们执行我在上面使用的纽约市示例查询。

import sys
sys.path.append('/home/you/youtube_tutorial/')
from youtube_videos import youtube_search
import pandas as pd
import json

test = youtube_search("spinners", location="40.730610, -73.935242", location_radius="50km")

您的输出应该与之前的教程没有任何不同——一个带有 nextPageToken 的元组和我们查询的 JSON 结果。

现在我们可以真正测试我们的geo_query函数了。从上面的 JSON 结果中随机选择一个 videoId ,并将其用作函数的参数。

geo_test = geo_query('r2GYzQvfARo')

输出应该是这样的:

Seriously?

酷毙了。如你所见,我们的结果包含了大量的信息,包括纬度和经度。

我们可以从初始查询开始遍历 videoIds ,并将它们的纬度和经度存储在一个 dictionary 对象中。

location_dict = {"youID":[], "lat":[], "lon":[]}
for video in test[1]:
    location_dict['youID'].append((video['id']['videoId']))
    geo = geo_query(video['id']['videoId'])
    location_dict['lat'].append(geo['items'][0]['recordingDetails']['location']['latitude'])
    location_dict['lon'].append(geo['items'][0]['recordingDetails']['location']['longitude'])

结论

现在,您可以开始在未来的数据挖掘项目中整合位置半径功能了。

如果你想了解一个项目可能会是什么样子,看看下面的地图。互动 D3 版本可在我的网站上获得。我通过对美国 200 个最大的城市进行半径为 25 公里的“旋转”地理查询来收集这张地图的数据

每个城市的总数反映了该半径范围内上传的独特视频的数量。我对这些数字如此之小感到有点惊讶…但话说回来,我在现实生活中从未见过坐立不安的人。

感谢阅读!

Check out the interactive D3 version on my site.

教程:使用 OpenCV 的网络摄像头绘画应用程序

原文:towardsdatascience.com/tutorial-we…

这是一个关于如何构建 OpenCV 应用程序的教程,该应用程序可以跟踪对象的移动,用户可以通过移动对象在屏幕上绘图——我称之为网络摄像头绘画。

项目描述

给定实时网络摄像头数据,这个类似 paint 的 python 应用程序使用 OpenCV 库来跟踪感兴趣的对象(在本例中是一个瓶盖),并允许用户通过移动对象来绘制,这使得绘制简单的东西既令人敬畏又具有挑战性。

您可以在此访问完整的项目代码:

[## acl21/Webcam_Paint_OpenCV

更新]:我将不再关注与回购相关的问题或邮件,因为我目前非常忙…

github.com](github.com/acl21/Webca…)

工作示例

代码要求

这个应用程序是用 Python 3.6 编写的,它使用了非常著名的 OpenCV 库。OpenCV 是一个计算机视觉和机器学习软件库,包括许多常见的图像分析算法,可以帮助我们构建定制的智能计算机视觉应用程序。

按照这篇中帖在 Python 3 中安装 OpenCV。

视频跟踪快速介绍

视频跟踪

为了执行视频跟踪,一种算法分析连续的视频帧,并输出帧之间的目标运动。算法多种多样,各有优缺点。在选择使用哪种算法时,考虑预期用途很重要。视觉跟踪系统有两个主要组成部分:目标表示和定位,以及过滤和数据关联。

视频跟踪是使用摄像机在一段时间内定位一个移动对象(或多个对象)的过程。它有多种用途,其中一些是:人机交互、安全和监控、视频通信和压缩、增强现实、交通控制、医学成像和视频编辑。

更多信息,

什么是等高线?

如果你是 OpenCV 的新手,在阅读本文中的代码之前,最好先浏览一下这个关于轮廓的教程页面。也看看这个 Jupyter 笔记本的轮廓。需要明确的是,术语“边缘”和“轮廓”经常互换使用,但这是不对的。如果你对这种差异的理解模糊不清,请浏览一下 ResearchGate 网站上的这个问题帖子

代码解释

第一步:初始化一些东西

首先,我们导入必要的库。

然后,我们初始化在以下步骤中使用的变量。

blueLowerblueUpper numpy 阵列帮助我们找到蓝色的帽子。一旦发现蓝帽,内核有助于使其平滑。 bpointsgppointsrpoints 和 ypoints deques 分别用于存储蓝色、绿色、红色和黄色屏幕上绘制的点。

步骤 2:设置绘画界面

这是一件痛苦的事情。我们必须手动设置框架上每个彩色框的坐标。我们使用 OpenCV 函数***cv2 . rectangle()***来绘制盒子。

第三步:开始阅读视频(一帧一帧)

现在我们使用 OpenCV 函数 cv2。VideoCapture() 从视频文件或网络摄像头实时逐帧读取视频(使用 while 循环)的方法。在这种情况下,我们将 0 传递给方法以从网络摄像头读取数据。

为了使用方便,我们可以添加完全相同的画图界面。

步骤 4:找到感兴趣的轮廓(瓶盖)

一旦我们开始读取网络摄像头馈送,我们就会借助***cv2 . in range()***方法不断在帧中寻找蓝色对象,并使用在步骤 0 中初始化的 blueUpperblueLower 变量。一旦我们找到轮廓,我们做一系列的图像操作,并使其平滑。它们让我们的生活变得更轻松。如果你想知道更多关于这些操作——腐蚀、变形和扩张,请查看这个

一旦我们找到轮廓(当找到轮廓时,如果 条件通过,则为 ),我们使用轮廓的中心(蓝色帽)在屏幕上绘制它的移动。下面的代码做了同样的事情。

上面的代码找到轮廓(最大的一个),使用***cv2 . minenclosingcircle()cv2.circle() 方法围绕它画一个圆,借助cv2 . moments()***方法得到找到的轮廓的中心。

第五步:开始绘图并存储绘图

现在我们开始跟踪轮廓中心接触屏幕的每一个点的坐标,以及它的颜色。我们将这些不同颜色的点存储在不同的 deques 中(b 点g 点等)。).当轮廓的中心接触到我们在步骤 1 中放在屏幕上的一个彩色框时,我们将这些点存储在其各自的颜色队列中。

第六步:在屏幕上显示图画

到目前为止,我们将所有点存储在它们各自的颜色队列中。现在我们用他们自己的颜色加入他们。OpenCV 函数 cv2.line() 为我们做到这一点提供了便利。下面的代码做了同样的事情。

一旦我们用一条线连接每一帧中的所有点,并把它放在我们用 cv2.imshow() 方法创建的两个窗口上,它就像一个绘画应用程序一样完美地工作了。当我们进入 循环从网络摄像头读取数据时,从 循环中掉出后,我们释放摄像头并使用以下代码行销毁所有窗口。

就是这样!我们在 OpenCV 中成功地使用了一堆基本的图像处理工具和操作,创建了一个类似绘画的应用程序——网络摄像头绘画!

执行

> python Webcam_Paint_OpenCV.py

结论

这是 OpenCV 图像处理能力的简单演示。如果你觉得这很有趣或容易或无聊,或者认为这没有什么挑战性,我建议你尝试添加更多的绘画功能,如橡皮擦,不同类型的笔刷,颜色填充选项等。为了真正感受 OpenCV 有多有趣。

希望这个教程是有趣的。感谢阅读。

活也让别人活! 答

Photo by Kelli Tungay on Unsplash

向您的支持团队提交推文—使用机器学习进行情感分析

原文:towardsdatascience.com/tweet-escal…

用于航空公司支持请求升级的自动推文情感处理解决方案

Source: Pixabay

我将解释端到端技术解决方案,它将有助于简化您的公司支持流程。我将重点关注从 Twitter 收到的航空公司支持请求。如果支持部门能够提前知道哪个请求更重要并且必须以更高的优先级处理,那么他们可以节省大量的时间和金钱。

本文将涵盖哪些内容:

  • 用例解释
  • 预测推文文本情感的机器学习解决方案—检查是否需要支持请求上报
  • 在 AWS SageMaker 中访问机器学习模型
  • Node.js 和 Express 的后端实现
  • 使用 JavaScript 和 Oracle JET toolkit 实现客户端 UI

图表解释了所有技术位是如何连接在一起的。

Solution architecture

让我们从用例解释开始。我认为实现用例会很有趣也很有用,它将允许报告人们向航空公司发送的推文,人们在那里寻求帮助。航空公司每天肯定会收到很多这样的推文,其中一些根本不相关。我的目标是只挑选那些需要升级和人工审核的推文。这应该会改善支持团队的结果,也许有助于保持更多的忠诚客户。

受本书(第 4 章)中给出的指导的启发,我实现了用于推特情感分析的机器学习模型— 商业机器学习。我强烈推荐任何人阅读这本书,他们正在寻找如何在他们的公司实施机器学习的实用方法。

基于航空公司(不仅限于航空公司,可以是任何 Twitter 账户)账户,我们获取 100 条写到该账户的最新 tweets。只有那些需要上报并且必须由人工处理的推文才会显示在列表中。即使 tweet 被归类为要升级的那个,我们也可以通过概率得分来确定它升级的可能性有多大(见红黄绿点)。这有助于进一步过滤掉推文,甚至在选择升级的推文列表中。

AmericanAir 结果— 24%的推文需要升级并由人工处理:

American Air

Delta 结果— 21%的推文需要升级并由人工处理:

Delta

阿联酋结果——19%的推文需要升级并由人工处理:

Emirates

英国航空公司的结果——32%的推文需要升级并由人工处理:

British Airways

Lufthansa 结果— 28%的推文需要升级并由人工处理:

Lufthansa

大约 20%-30%的推文需要所有航空公司升级,这似乎是一种常见的模式。

支持人员可以点击 twitter 帐户名称或更多链接,以获得关于推文的更多详细信息,并做出相应的回应。

我使用 AWS SageMaker 和 BlazingText 机器学习算法来建立一个情感分析模型。你可以在本书(第 4 章)——商业机器学习中阅读 BlazingText 以及如何在 AWS SageMaker 中运行它,所有这些都是一步一步描述的,非常简单易懂。你不需要购买这本书来下载源代码(从源代码链接获得)。在我之前的帖子中阅读更多技术细节— 亚马逊 SageMaker ML 情绪分析的 API

BlazingText 情感分析模型是使用 Stuart Axelbrooke 从思维向量(【www.thoughtvector.io/】)上传到 Kaggle 的数据集来训练和构建的。原始数据集可以在这里查看:www . ka ggle . com/thought vector/customer-support-on-Twitter/home。除了源代码,您还可以下载经过处理的数据集。图书作者处理了原始数据集——他们删除了除原始推文之外的所有推文,并使用回复将原始推文标记为升级或未升级。大约有 50 万条推文用于构建支持升级情绪模型。

当在 AWS SageMaker 中构建机器学习(ML)模型时,您需要创建一个端点,这将允许从外部访问模型并调用预测函数。端点创建包含在 Jupyter 笔记本中。

有了活动端点,我们就可以创建 AWS Lambda 函数,作为 ML 模型和 REST API 之间的代理。Lambda 允许在调用 ML 模型之前建立数据转换逻辑,并在将结果发送回 REST API 之前处理由 predict 函数返回的结果。点击此处了解更多信息— 来自 Oracle JET 的 Amazon SageMaker 模型端点访问

Lambda 函数的示例代码:

ENDPOINT_NAME 变量指向运行 Jupyter notebook 时创建的客户支持端点名称。下一步是在 AWS 中定义 REST API(在上面引用的文章中阅读更多相关内容):

AWS REST API

确保为此 API 启用 CORS 支持。CORS 允许从外部主机调用 API,例如从 JavaScript 应用程序:

AWS REST API CORS

总结机器学习部分:

  • 您需要运行 Jupyter 笔记本、培训/验证模型。模型构建完成后,创建 AWS 端点
  • 定义 AWS Lambda 函数以访问 ML 模型
  • 定义 AWS REST API 将传入的请求传递给 AWS Lambda

接下来,我们继续讨论 Node.js 和 Express 的后端实现。我已经用快速应用程序生成器生成了 Node.js 应用程序。点击阅读更多可用命令。您得到 app.js 文件,它充当中央路由器——在这里您可以定义后端处理的所有 REST 端点。每个端点都可以映射到一个单独的模块——在下面的例子中是 invoicerisk.jstwitter.js 。这带来了更大的灵活性,并允许将代码构建到单独的模块中:

Backend app structure

快速路由代码由快速生成器创建。在 app.js 中,我们可以定义 Node.js 模块的路径。我们将使用这个路径从 UI 执行 REST API 调用。

您可以使用以下命令运行使用 Express 生成的 Node.js 应用程序:

DEBUG =: NPM start*

我们为什么要使用 Node.js 后端?原因很明显——要访问 Twitter API,我们需要提供映射到 Twitter 帐户的键,我们不能将这些键保存在客户端。一旦请求来自客户端,它将转到 Node.js 后端 POST handler 方法。在这个方法中,我们将通过 Twitter API 获取最新的 tweets,准备用于分类的数据集,并通过 REST API 调用将其传递给 AWS SageMaker。响应将被解析以构造结果,该结果将被发送回客户端。检查代码段内的注释:

后端的主要任务是帮助获取推文,将它们发送到机器学习模型进行分类,并构建客户端可以处理的响应。

UI 客户端是用 Oracle JET 工具包和 JavaScript 创建的。我使用 Oracle JET 是因为它提供了一套很好的开箱即用的 UI 组件,允许构建美观实用的企业应用程序。

您可以从命令行运行 Oracle JET app:

发球

JavaScript 代码,用于执行后端调用,并构建带有支持升级请求的 tweets 数组。

这段代码使用了许多 Oracle JET 库。我建议浏览一下 Oracle JET cookbook ,它为每个 UI 组件提供了一个交互式示例列表。

图表和列表组件由 Oracle JET 标记呈现:

我的目标是展示用于情感分析的机器学习模型如何适应企业应用架构,包括后端和客户端 UI 实现。我希望这个航空公司支持请求升级的实际用例有助于在您的组织中应用机器学习,并给出如何解决您自己的业务挑战的想法。

像特朗普一样用 One2Seq 模型发推特

原文:towardsdatascience.com/tweet-like-…

在本文中,我将向您介绍我的项目的大部分内容,我创建了一个一对一的模型,可以生成类似于 Trump 的推文。实际模型与我在我的“如何构建你的第一个聊天机器人”文章中构建的模型非常相似。这个模型的两个关键区别是输入和不包括注意力。注意力被排除在外,因为它没有显著提高生成的推文的质量。创建输入的步骤将是本文的重点。作为预览,我们将遵循以下路径:

  • 清理特朗普的推文。
  • 使用预先训练的单词向量创建单词向量( GloVe — Twitter 200d) )。
  • 平均一条推文的词向量的维度。
  • 使用主成分分析将维数减少到 1。
  • 根据主成分分析值对推文进行排序。
  • 通过文字的质量来限制推文。

我真正喜欢这个模型的地方是,我希望你也会喜欢,我们如何使用这样一个简单的输入,一个值,来生成一条推文。此外,从我们如何创建输入数据,我们将能够在某种程度上控制我们生成的推文的风格。

为了设定你的期望,这里有几个你可以用这个模型创建的推文的例子:

  • 谢谢你亚利桑那!# makamericagreatagain # trump 2016
  • 必须阻止希拉里
  • 记得出来投票!#杂志#特朗普 2016

注意:我将从我的代码中删除注释,以帮助保持简短。如果你想看评论和我的完整代码,请访问这个项目的 GitHub 页面

我们开始吧!

这个项目的数据来自 Kaggle 上的数据集,它包含了 7375 条推文。我们需要做的第一件事是清理我们的推文。

def clean_tweet(tweet):
    tweet = tweet.lower()
    tweet = re.sub(r'https?:\/\/.*[\r\n]*', '', tweet, flags=re.MULTILINE)
    tweet = re.sub(r'[_"\-;%()|.,+&=*%]', '', tweet)
    tweet = re.sub(r'\.', ' . ', tweet)
    tweet = re.sub(r'\!', ' !', tweet)
    tweet = re.sub(r'\?', ' ?', tweet)
    tweet = re.sub(r'\,', ' ,', tweet)
    tweet = re.sub(r':', ' : ', tweet)
    tweet = re.sub(r'#', ' # ', tweet)
    tweet = re.sub(r'@', ' @ ', tweet)
    tweet = re.sub(r'd .c .', 'd.c.', tweet)
    tweet = re.sub(r'u .s .', 'd.c.', tweet)
    tweet = re.sub(r' amp ', ' and ', tweet)
    tweet = re.sub(r'pm', ' pm ', tweet)
    tweet = re.sub(r'news', ' news ', tweet)
    tweet = re.sub(r' . . . ', ' ', tweet)
    tweet = re.sub(r' .  .  . ', ' ', tweet)
    tweet = re.sub(r' ! ! ', ' ! ', tweet)
    tweet = re.sub(r'&amp', 'and', tweet)
    return tweet

这段代码将删除任何链接和无用的字符,并重新格式化文本,以便我们可以最大限度地利用 GloVe 的预训练单词向量。例如,所有的标签都与文本分开。这是因为 GloVe 没有针对 hashtagged 单词的预训练单词向量,所以如果我们想要利用这些预训练向量,我们需要进行这种分离。

注意:我们将使用 GloVe 的 Twitter 矢量。

以下是一些干净的推文示例:

  • 今天,我们向所有曾在我们的军队中服役的人表达最深切的感谢
  • rt @ ivankatrump:投票给我父亲竞选美国总统真是一个超现实的时刻!发出你的声音并投票!#选择 2
  • 晚上 9 : 45 看投票结果#选举之夜#杂志

为了生成单词向量,我们首先需要从 GloVe 的单词向量中创建一个嵌入索引。

embeddings_index = {}
with open('/Users/Dave/Desktop/Programming/glove.twitter.27B/
           glove.twitter.27B.200d.txt', encoding='utf-8') as f:
    for line in f:
        values = line.split(' ')
        word = values[0]
        embedding = np.asarray(values[1:], dtype='float32')
        embeddings_index[word] = embedding

在这个文件中有 1,193,514 个单词嵌入,每个嵌入有 200 个维度。

我们将使用这个嵌入指数为每条推文创建一个“平均”嵌入。为此,我们将从“空”嵌入开始(所有 200 个值[对于 200 个维度]将为 0)。如果 tweet 中的一个单词在索引中,它的嵌入将被添加到“空”嵌入中。如果 tweet 中的一个单词不在索引中,那么“空”嵌入中将不会添加任何内容。在考虑了推文中的每个单词后,我们将根据推文中的单词数对每个维度进行平均。这些平均维度将为每条推文创建我们的“平均”嵌入。

以下是相关的代码:

embedding_dim = 200 embed_tweets = [] # Contains the 'average' embedding for each tweetfor tweet in clean_tweets:
    avg_embed = np.zeros(embedding_dim) 
    for word in tweet.split():
        embed = embeddings_index.get(word)
        if embed is not None:
            avg_embed += embed 
    embed_tweets.append(avg_embed/len(tweet.split()))

为了创建这些 *tweet 嵌入,*我们可以使用其他方法,比如 Word2Vec。Word2Vec 的好处是不会有任何空嵌入,但考虑到我们正在处理的数据量,只有 7375 条推文,我认为利用 GloVe 更大的数据集会更好。你很快就会看到,使用手套效果很好。

我们的下一步是将数据的维度从 200 减少到 1。我们将 reduction 设置为 1,以简化和组织我们的输入数据,并使其易于生成我们想要的 tweet 类型,例如。如果我们想要一条有更多标签或者只有文字的推文。

正如你可能已经预料到的,我们将使用 PCA(主成分分析)来降低数据的维度。

pca = PCA(n_components=1, random_state = 2)
pca_tweets = pca.fit_transform(embed_tweets)

现在,我们的每条推文都有一个 PCA 值,我们将从最小值到最大值对它们进行排序,这样类似的推文将更加接近。

pca_tweets_list = [] # Contains the pca values
for tweet in pca_tweets:
    pca_tweets_list.append(tweet[0])order = np.array(pca_tweets_list).argsort()
pca_labels = order.argsort()
pca_labels *= 2 

我们将我们的pca_labels乘以 2,以便更简单地生成新的推文。虽然我们不会使用所有的 tweet 来训练我们的模型,但是所有的训练 tweet 都是偶数。为了确保生成新的 tweet,你需要做的就是使用一个奇数作为输入。这个生成的 tweet 应该类似于训练数据中的 tweet,其值接近您的输入值。

为了了解 Trump 发布的推文的类型,我们将使用 KMeans 将推文分组。pca_tweets将是我们对 KMeans 的输入,在使用 3-10 个聚类检查该函数的结果后,我认为 4 个聚类最好地将 Trump 的推文分成不同的组。

kmeans = KMeans(n_clusters=4, max_iter = 1000, n_init = 20, random_state=2).fit(pca_tweets)
labels = kmeans.labels_

每组包含以下数量的推文:

1(红色):315,2(橙色):2600,3(黄色):1674,4(蓝色):2782

推文由它们的 KMeans 标签着色,但是输入到 TSNE 的数据是embed_tweets。这张图表明,你可以将推文分成一些合理的不同类别。它并不完美,如果你愿意,你可以为自己创造一些情节,但我认为这是最好的结果。

接下来,我们可以看看 PCA 标签与 tweet 组相比有多好。

I’d make this graph bigger, but Medium won’t let me

正如所料,鉴于 tweet 组是使用 PCA 数据创建的,我们可以看到四个明显的组。这也提供了一个很好的可视化来比较不同大小的推文组,并可以帮助您在想要生成推文时选择推文类型。

在我的 iPython 笔记本中,我会更详细地介绍每个组中的单词和推文,但为了给你一个示例,这里是每个组的一些推文:

Group # 1 - short tweets with hashtags
#1: # electionday 
#2: rt  @ donaldjtrumpjr :  thanks new hampshire ! !
    # nh  # newhampshire  # maga 
#3:  # draintheswamp !

Group # 2 - long tweets that are retweeted
#1: rt  @ ivankatrump :  such a surreal moment to vote for my father 
    for president of the united states ! make your voice heard and 
    vote !  # election2
#2: rt  @ erictrump :  join my family in this incredible movement to  
    # makeamericagreatagain ! now it is up to you ! please  # vote 
    for america ! https : 
#3: rt  @ donaldjtrumpjr :  final push ! eric and i doing dozens of 
    radio interviews we can win this thing ! get out and vote !  # 
    maga  # electionday ht

Group # 3 - typically involve a data/time/location
#1: watching the returns at 9 : 45 pm # electionnight  # maga 
#2: monday  11/7/2016 
    scranton pennsylvania at 5 : 30 pm 
    grand rapids michigan at 11 pm  
#3: rt  @ ivankatrump :  thank you new hampshire !  

Group # 4 - longer tweet, mostly just text
#1: today we express our deepest gratitude to all those who have  
    served in our armed forces  # thankavet 
#2: busy day planned in new york will soon be making some very 
    important decisions on the people who will be running our 
    government !
#3: love the fact that the small groups of protesters last night 
    have passion for our great country we will all come together and 
    be proud !

为了帮助模型生成最佳推文,我们将通过一些措施来限制我们的训练数据。我们要做的第一件事是建立一个词汇到整数(vocab_to_int)字典和 int_to_vocab 字典,其中只包括在特朗普的推文中出现 10 次或更多次的单词。为什么是 10?我对此没有任何“硬”的理由,但这将有助于我们生成的推文听起来更像特朗普的典型推文,而且这将有助于模型更好地理解每个单词的意思,因为它会看到至少 10 次。如果阈值只是 2 或 3,模型将很难理解和使用很少出现的单词。

threshold = 10vocab_to_int = {}value = 0
for word, count in word_counts.items():
    if count >= threshold:
        vocab_to_int[word] = value
        value += 1int_to_vocab = {}
for word, value in vocab_to_int.items():
    int_to_vocab[value] = word

接下来,我们将限制我们将使用的推文的长度。在训练数据中,我选择了 25 作为 tweet 的最大长度。选择该值是因为它是模型仍能很好学习的最大长度。再长一点,模型就很难学习推文,再短一点,我们就会进一步限制我们的训练数据。

我们还将设置一个限制。是一个标记,用于表示不包括在我们的训练词汇中的单词。如果一条推文中出现多个令牌,则该推文将不会用于训练模型。我尝试将限制增加到 2,但这导致在生成的 tweets 中出现太频繁。

max_tweet_length = 25
min_tweet_length = 1
unk_limit = 1short_tweets = []
short_labels = []for i in range(len(int_tweets)):
    unk_count = 0
    if len(int_tweets[i]) <= max_tweet_length and \
       len(int_tweets[i]) >= min_tweet_length:
        if len(int_tweets[i]) == 1:
            if int_tweets[i][0] != vocab_to_int['<UNK>']:
                short_tweets.append(int_tweets[i])
                short_labels.append(pca_labels[i])
        else:
            for word in int_tweets[i]:
                if word == vocab_to_int['<UNK>']:
                    unk_count += 1
            if unk_count <= unk_limit:
                short_tweets.append(int_tweets[i])
                short_labels.append(pca_labels[i])

作为为模型准备数据的最后一步,我们将按长度对推文进行排序。这样做将有助于我们的模型训练得更快,因为早期的批次将包含更短的推文。每批中的推文需要具有相同的长度,因此通过对推文进行排序,将避免长推文与短推文一起被批量处理。

sorted_tweets = []
sorted_labels = []for length in range(1,max_tweet_length+1):
    for i in range(len(short_tweets)):
        if length == len(short_tweets[i]):
            sorted_tweets.append(short_tweets[i])
            sorted_labels.append([short_labels[i]])

这就是创建我们的训练数据!这需要做一些工作,但是可以说你的输入数据是模型中最重要的部分。没有好的训练数据,模型将无法生成好的输出。

本文的最后一部分是如何生成推文。有两种不同的方法可以使用。

选项 1:找一条类似的推文

通过这种方法,你可以输入与最相似的推文匹配的单词或短语。

create_tweet = "I need your help to make america great again! #maga"create_tweet = clean_tweet(create_tweet)create_tweet_vect = vectorize_tweet(create_tweet)create_tweet_pca = pca.transform(create_tweet_vect)similar_tweet = min(pca_tweets_list, 
                    key=lambda x:abs(x-create_tweet_pca))for tweet in enumerate(pca_tweets_list):
    if tweet[1] == similar_tweet:
        print("Most similar tweet:", pca_labels[tweet[0]])
        break
  • create_tweet中,输入您想要匹配的任何文本。
  • 这条推文将被清理,然后使用与我们进行“平均”嵌入时输入数据相同的方法转换为向量。
  • 推文的“平均”嵌入将被用于找到其 PCA 值。这个值将与最接近的 tweet 匹配。
  • 匹配的 tweet 的 PCA 值将用于查找其 PCA 标签。这个标签是模型的输入。

如果你对这条最接近的推文的内容感到好奇,那么下面是给你的代码!

tweet_type = 3464closest_type = min(short_labels, key=lambda x:abs(x-tweet_type))
words = []
for tweet in enumerate(short_labels):
    if tweet[1] == closest_type:
        for num in short_tweets[tweet[0]]:
            words.append(int_to_vocab[num])
print(" ".join(words))

tweet_type可以认为是 PCA 标签。该值将与用于训练模型的最接近的标签相匹配。将打印出与最近标签相关的文本。

作为这种方法局限性的一个例子,我用了这样一句话“我需要你们的帮助,让美国再次伟大!#maga "作为我的create_tweet,返回的tweet_type和文字是:3464,“希拉里是有史以来竞选美国总统最腐败的人# draintheswamp”。

这些文本差别很大,但是它们的结构是相似的,多个普通的单词和一个标签。我同意这是第四组风格的推文的模式。

选项 2:输入一个值

这是更简单的选择,包含了更多的随机性。你需要做的就是选择一个tweet_type,我建议你参考推文组的范围来控制推文的风格。您还可以通过设置 sequence_length 的值来控制您想要生成的 tweet 的长度,但我将其设置为随机整数,因为我喜欢危险地生活。

tweet_type = 3464checkpoint = "./best_model.ckpt"loaded_graph = tf.Graph()
with tf.Session(graph=loaded_graph) as sess:
    loader = tf.train.import_meta_graph(checkpoint + '.meta')
    loader.restore(sess, checkpoint) input_data = loaded_graph.get_tensor_by_name('input:0')
    logits = loaded_graph.get_tensor_by_name('logits:0')
    sequence_length = 
        loaded_graph.get_tensor_by_name('sequence_length:0')
    keep_prob = loaded_graph.get_tensor_by_name('keep_prob:0')tweet_logits = sess.run(logits, 
                        {input_data: [[tweet_type]], 
                         sequence_length: np.random.randint(3,15),
                         keep_prob: 1.0})[0]# Remove the padding from the tweet
pad = vocab_to_int["<PAD>"]print('Tweet')
print('  Word Ids: {}'.format(
         [i for i in np.argmax(tweet_logits, 1) if i != pad]))
print('  Tweet: {}'.format(" ".join([int_to_vocab[i] for i in 
                          np.argmax(tweet_logits, 1) if i != pad])))

这个项目到此为止!我希望你喜欢了解它,如果你想看到整个过程,那么就去我的 GitHub 吧。如果您有任何问题、意见或建议,请在下面发表。

如果你对扩展这项工作感兴趣,我的一个想法是对生成的推文提供更大的控制。我认为如果我们可以在输入数据中包含一个关键字(或多个单词)会很好。这应该有助于我们控制我们想要生成的推文的风格和上下文。

感谢阅读!

你需要人类对人工智能的适当信任

原文:towardsdatascience.com/twiml-ai-me…

TWiML & AI meetup talk:信任人工智能

我很高兴能在 TWiML 人工智能会议上发表关于人工智能信任的演讲。这个话题的核心是人类如何使用机器,以及他们如何将机器融入他们的团队。正如我们将看到的,这是一个非常重要但难以理解的话题。

“信任促进合作行为”

为了开始讨论,我们回顾了关于信任和自动化主题的四篇论文:

所有这些论文的关键在于,它们讨论了过多(误用)和过少(不用)之间的信任平衡。有许多因素可以增加信任度,但是我们应该总是构建具有最大信任度的系统吗?

在回顾了论文之后,我们开始深入研究在将人和机器结合起来时应该考虑的问题。这不是人在回路中(HITL)对人在回路外(OOTL)的人工智能。事物的本来面目也不一样。

说到 HITL,它不再仅仅是一个人和一台机器。它是与智能生态系统一起工作的人类组织。我们需要了解他们如何最好地合作。

如果你认为任何系统对人类来说都是真正的 OOTL,那么你就没有正确设定系统的边界。总有人类以某种方式参与其中。即使只是你的客户受到影响。你需要将他们纳入你的考虑范围。

在考虑信任时,责任是一个重要因素。当事情确实出错时,谁需要对此负责?

That is my exit!

如果上面的车是一辆自动驾驶汽车,从技术上讲它没有发生事故,但它确实需要对它的所作所为负责而不是其他人类卡车司机

如何为您的应用程序确定合适的信任度?这可以在不投入月复一月的数据清理和模型训练时间的情况下完成。你可以用非编码原型来做,就像我们在各种项目中做的那样

最后,有太多的因素影响信任,你需要用真实的人来测试系统,了解他们需要什么。机器不会取代人类的目的。

资源

幻灯片:

[## TWiML & AI:信任与人工智能

信任与爱克里斯巴特勒@ philosophie.is @克里斯博特·goo.gl/m1PaVi

docs.google.com](docs.google.com/presentatio…)

其他参考:

关于克里斯·巴特勒

我帮助团队理解他们应该用以人工智能为中心的解决方案解决的真正的商业问题。我们工作的团队通常被要求用他们拥有的数据“做一些有趣的事情”。我们通过偶发事件相关性帮助他们避免局部极值,并专注于解决巨大的业务问题。我的背景包括在微软、KAYAK 和 Waze 等公司超过 18 年的产品和业务开发经验。在 Philosophie,我创造了像机器移情映射困惑映射这样的技术,以在构建人工智能产品时创建跨团队对齐。如果你想了解更多或者通过邮箱LinkedIn 联系,或者访问philosophie.is/human-cente…

Twitter 广告

原文:towardsdatascience.com/twitter-adv…

介绍

这是我在大会数据科学沉浸式项目中的顶点项目的非技术性报告。顶点计划是指参加该计划时所学一切的高潮。我选择对 Twitter 数据执行自然语言处理(NLP ),以便协助广告活动。这个项目更多地面向广告商、市场营销和任何想要扩展他们的客户关系平台以与他们的追随者交流的公司。

目标

通过推文的 NLP,公司可以衡量人们对他们产品的感受。我的目标之一是创建一个模型,对一条信息是否具有积极或消极的情感价值进行分类。这种分类的一部分是过滤掉那些正面/负面的推文,看看问题源自哪里。一个公司可以直接联系那些对他们的产品有问题的顾客,同时奖励那些忠诚于这个品牌的顾客。

数据

出于介绍的目的,所有的工作都是用 python 编写的,使用了几个库。这些库包括 Numpy、Pandas、Matplotlib、Scikit Learn 和 Keras。通过使用 Twitter API,tweets 被挖掘和收集。推文以压缩的 JSON 格式返回。如下例所示,信息是嵌套的,通常难以阅读。

通过一个自动化的过程,某些特征被选中,数据被保存到一个熊猫数据框架中。

本项目中使用了以下功能:

  • 创建时间:创建推文的时间戳。
  • 收藏次数:这条推文被“收藏”的总次数
  • 标签:与 tweet 相关联的标签。
  • 位置:用户声明的位置。
  • 挖掘时间:tweet 被挖掘的时间戳。
  • 转发次数:这条推文被“转发”的总次数。
  • 屏幕名称:用户的屏幕名称。
  • 来源:推文的来源(即:设备)。
  • 文本:推文的文本。
  • 字数:一条推文中的总字数。
  • tweet Length:tweet 的字符长度。

返回的数据不干净。我说它不干净是因为为了让我处理数据,我需要一种特定的格式。有许多函数是为处理这个过程而编写的。我清理数据的过程如下:

  • 使用位置变量提取 tweet 的坐标。如果没有,我将它设置为加州旧金山。为什么是 SF?因为 Twitter 总部位于旧金山。
  • created_at 和 mined_at 变量被转换为 datetime 对象以执行与时间相关的函数。
  • hashtags 变量在开头接收' # ',空格被删除。这是为了让所有的标签保持相同的格式。
  • 源变量删除了 html 代码。
  • 文本变量移除了超链接,移除了“@”提及,单词被标记化。示例:

# 纹身 sForShawn 我是 思维 点歌 耳机 ,然后那根线就是歌迷们歌唱生活的声波聚会@ Shawn Mendes

变成了:‘纹身 sforshawn’,‘思考’,‘耳机’,‘电线’,‘声音’,‘海浪’,‘粉丝’,‘唱歌’,‘生活’,‘派对’

下图显示了数据清理后数据帧的外观:

特征工程

除了从 twitter 中挖掘出来的特性,还有其他一些特性是为了更好地理解数据而创建的。VADER(用于情感推理的效价感知词典)库包括情感强度分析器,该分析器是确定给定推文的情感值的基础。这是一个基于规则的情绪分析工具,专门针对社交媒体中表达的情绪。给定一条消息,分析器返回可测量的值:

  • 消极情绪
  • neu:中性情绪
  • 积极情绪
  • 复合:复合(即综合得分)

Nodebox 英语语言学图书馆允许通过回归意象词典进行心理内容分析。RID 对文本中主要、次要和情感过程思想进行评分。这是一个有趣的包,因为它开辟了一种查看信息的新方式。

  • 初级:涉及梦和幻想的自由形式联想思维
  • 二级:逻辑性强,以现实为基础,注重解决问题
  • 情绪:恐惧、悲伤、憎恨、喜爱等的表达。

探索数据

探索性数据分析(EDA)是一种分析数据集以总结其主要特征的方法。我选择从两个不同的角度来看这些数据。第一种是对收集到的所有公共信息进行更全面的概述。第二个通过更具体的观点,好像我是一个对我的信息感兴趣的公司。我们先来看一个大概的看法。

我选择查看每个特性,并查看数据的整体视图。time_created 变量显示,大多数推文是在下午发送的,然后是在午夜之后的几个小时。请注意,这些时间是以太平洋标准时间为基准的。标签聚集了挖掘过程中讨论的主要话题。

收集的推文主要集中在美国,因为情感库是在英语语言上训练的。这也是看外国字符时的编码问题。如果没有命名城市,加利福尼亚州旧金山是默认城市,因此在其他位置中很突出。许多用户在他们的个人资料中没有位置,在他们的推文中也没有。Twitter 的总部在旧金山市中心,所以推文是从那里发出的。

sources 变量显示 twitter 的移动使用占据了首位。前三名依次是 iPhone、Android 和 Twitter 网络客户端。web 客户端指的是通过 web 浏览器在桌面上使用 twitter,以及在移动设备上使用 web 浏览器。

在将推文分成各自的情绪值后,我决定看看字数分布。负面和正面推文的字数分布峰值都是每条推文 15 个字。中性的推文大多在 10 个字及以下。

对于 VADER 情绪分析,我将着眼于复合值。下图中的复合金额是 VADER 情绪分析的聚合值。复合值的范围从-1 到 1;消极情绪,到中性情绪,到积极情绪。大多数推文被评为中性。我认为这是因为 VADER 情绪分析器没有对 2017 年的新词进行训练,即:fleek。

#万豪

在对数据进行总体概述后,我想看看与万豪品牌相关的具体推文。获取数据的过程与之前相同,只是我将标签“#Marriott”传递给一个搜索参数,因此只返回与该标签相关的信息。

我想看的第一件事是#万豪在世界上的什么地方被谈论。使用坐标变量,我可以在地图上画出推文的来源。

通过观察一段时间内的情绪值,我能够衡量与万豪相关的正面或负面推文的数量。大多数推文都是对万豪的正面评价,只有少数是负面评价。

一条复合得分高达 0.951 的推文示例:

一条复合得分为-0.6551 的推文示例:

作为万豪的员工,我能够联系有问题的客户,并提供某种解决方案。同样的道理也适用于奖励评论最好的酒店。

数据建模

VADER 情感分析器是对推文情感价值进行分类的基础。我想看看我是否能利用课堂上学到的模型对推文进行分类。在继续之前,我需要将文本数据转换成 python 可以理解的格式。我用 word2vec 从单词中创建向量。在 word2vec 中,使用了单词的分布式表示。取一个有几百维(比如 300 维)的向量。每个单词都由这些元素的权重分布来表示。因此,向量中的元素和单词之间不是一对一的映射,而是单词的表示分布在向量中的所有元素上,向量中的每个元素都有助于许多单词的定义。单词“dog”的 300 维向量示例:

# creates a vector given a sentence/tweet
# takes a list of words, and array size of w2v vector
# tokens == a list of words (the tokenized tweet)
# size == the dimensional size of the vectorsize = 300def buildWordVector(tokens, size):
    vec = np.zeros(size).reshape((1, size))
    count = 0.
    for word in tokens:
        try:
            vec+= w2v[word].reshape((1,size))
            count += 1.
        except BaseException: # handling the case where the token is not
            try:
                continue

    if count != 0:
        # get centroid of sentence
        vec /= count
    return vec

一旦每个单词都被矢量化,下一步就是创建推文本身的矢量。tweet 中的每个单词向量相加在一起,除以 tweet 中的单词总数,这为 tweet 创建了一个向量,它是相加向量的质心。这是我遇到的强大的东西。通过创建这些向量,您可以执行矩阵数学运算并找到新的模式。可以对这些向量执行余弦相似性,这使你能够看到相似的推文/词以及最相反的推文/词。一旦用户的推文被矢量化,就可以用同样的步骤为用户创建向量。

作为参考,有三类被分类:消极,中立和积极。数据被分成 85/15 的比例,用于训练和测试数据。我的基本估计是多项式逻辑回归。我正在查看更具体的回忆分数,因为回忆是“结果有多完整”。高召回率意味着算法返回了大部分相关结果。如你所见,中性分类高于其他分类。

额外树分类器是尝试的第二个模型。“额外树”分类器,也称为“极度随机化树”分类器,是随机森林的变体。与随机森林不同,在每一步都使用整个样本,并随机选取决策边界,而不是最佳边界。还是那句话,中性分类高于其余。负面分类的表现很糟糕。

我最后一次分类的尝试是用神经网络来完成。Keras 是用 Python 编写的开源神经网络库。我对 Keras 的第一次尝试是创建一个又深又宽的神经网络。它有 5 个致密层,分别含有 500、800、1000、300 和 3 个神经元。以及设置为 0.1、0.5、0.2、0.2 和 0.2 的每个密集层之前的下降层。前四层的激活是“relu”,最后一层是“softmax”。

# in order for keras to accurately multi-classify, must convert from # 1 column to 3 columns
y_train = keras.utils.np_utils.to_categorical(y_train,       num_classes=3)
y_test = keras.utils.np_utils.to_categorical(y_test, num_classes=3)# MULTI-CLASSIFICATION
# Evaluating with a Keras NN# fix random seed for reproducibility
seed = 7
np.random.seed(seed)from keras.constraints import maxnorm# Keras neural network deep and wide.
model_keras = Sequential()
model_keras.add(Dropout(0.1, input_shape=(train_vecs_w2v.shape[1],)))
model_keras.add(Dense(500, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.5))
model_keras.add(Dense(800, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.2))
model_keras.add(Dense(1000, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.2))
model_keras.add(Dense(300, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.2))
model_keras.add(Dense(3, activation=’softmax’))epochs = 20model_keras.compile(loss=’categorical_crossentropy’,
 optimizer=’adam’,
 metrics=[‘accuracy’])history = model_keras.fit(train_vecs_w2v, y_train, epochs=epochs, validation_data=(test_vecs_w2v, y_test), batch_size=32, verbose=2)score = model_keras.evaluate(test_vecs_w2v, y_test, batch_size=128, verbose=0)print ‘Evaluated score on test data:’, score[1]# summarize history for accuracy
plt.figure(num=None, figsize=(8, 6), dpi=100, facecolor=’w’, edgecolor=’k’)
plt.plot(history.history[‘acc’])
plt.plot(history.history[‘val_acc’], c=’r’, ls=’dashed’)
plt.title(‘model accuracy’)
plt.ylabel(‘accuracy’)
plt.xlabel(‘epoch’)
plt.legend([‘train’, ‘test’], loc=’upper left’)
plt.hlines(y=score[1], xmin=0, xmax=epochs)
plt.show()# summarize history for loss
plt.figure(num=None, figsize=(8, 6), dpi=100, facecolor=’w’, edgecolor=’k’)
plt.plot(history.history[‘loss’])
plt.plot(history.history[‘val_loss’], c=’r’, ls=’dashed’)
plt.title(‘model loss’)
plt.ylabel(‘loss’)
plt.xlabel(‘epoch’)
plt.legend([‘train’, ‘test’], loc=’upper left’)
plt.show()

所有的分类模型似乎都有一个模式。负面分类总是比其余的低。再看数据,负面情绪值的推文大概占整个数据集的 20%。中性的占 44%,积极的占 33%。下一步是将所有推文限制在相同的数据量。我决定从每个班级随机抽取 4000 个数据点。该数据然后被放入 70/30 的训练测试分割中;70%的数据用于训练,30%用于测试。我的下一步是尝试短而浅的神经网络设置。三个致密层,分别为 32、16 和 3 个神经元。每个密集层之前的三个下降层设置为 0.1、0.3 和 0.2。纪元已更改为 50,批次大小已更改为 2048。

# df is the pandas dataframe object which contains all the clean data# Function to create targets based on compound score
def get_targets(row):
    if row < 0:
        return 0
    elif row == 0:
        return 1
    else:
        return 2# Creating the targets based of the compound value
df['target'] = df['compound'].map(lambda x: get_targets(x))
neg = df[df.target == 0]
neu = df[df.target == 1]
pos = df[df.target == 2]# Randomly sampling tweets to a limit of 4000 each
neg_sampled = neg.sample(4000)
neu_sampled = neu.sample(4000)
pos_sampled = pos.sample(4000)# concating all sampled datasets together
df_test = pd.concat([neg_sampled, neu_sampled, pos_sampled])
df_test.shape# Creating training/testing data, 70/30 split
X_train, X_test, y_train, y_test = train_test_split(df_test.token_text, df_test.target, train_size=0.7)# For every tweet, creating a word vector array for tweet
X_train = np.concatenate([buildWordVector(z, num_features) for z in X_train])
X_train = scale(X_train)X_test = np.concatenate([buildWordVector(z, num_features) for z in X_test])
X_test = scale(X_test)# in order for keras to accurately multi-classify, must convert from 1 column to 3 columns
y_train = keras.utils.np_utils.to_categorical(y_train, num_classes=3)
y_test = keras.utils.np_utils.to_categorical(y_test, num_classes=3)# MULTI-CLASSIFICATION
# Evaluating with a Keras NN# fix random seed for reproducibility
seed = 7
np.random.seed(seed)leng = X_train.shape[1]
X_train = X_train.reshape(X_train.shape[0], 1, leng)
X_test = X_test.reshape(X_test.shape[0], 1, leng)# Keras neural network short and shallow
model_keras = Sequential()
model_keras.add(Dropout(0.1, input_shape=(X_train.shape[1],)))
model_keras.add(Dense(32, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.3))
model_keras.add(Dense(16, activation=’relu’, kernel_constraint=maxnorm(1)))
model_keras.add(Dropout(0.2))
model_keras.add(Dense(3, activation=’softmax’))# SGD Parameters
learning_rate = 0.01
decay_rate = learning_rate / epochs
momentum = .95
sgd = SGD(lr=learning_rate, momentum=momentum, decay=decay_rate, nesterov=True)model_keras.compile(loss=’categorical_crossentropy’,
 optimizer=’adam’,
 metrics=[‘accuracy’])# Model parameters
epochs = 50
batch = 2048history = model_keras.fit(X_train, y_train, 
 validation_data=(X_test, y_test), 
 epochs=epochs, 
 batch_size=batch, 
 verbose=0)score = model_keras.evaluate(X_test, y_test, 
 batch_size=batch, verbose=0)print ‘Evaluated score on test data:’, score[1]# summarize history for accuracy
plt.figure(num=None, figsize=(8, 6), dpi=100, facecolor=’w’, edgecolor=’k’)
plt.plot(history.history[‘acc’])
plt.plot(history.history[‘val_acc’], c=’r’, ls=’dashed’)
plt.title(‘model accuracy’)
plt.ylabel(‘accuracy’)
plt.xlabel(‘epoch’)
plt.legend([‘train’, ‘test’], loc=’upper left’)
plt.hlines(y=score[1], xmin=0, xmax=epochs)
plt.show()# summarize history for loss
plt.figure(num=None, figsize=(8, 6), dpi=100, facecolor=’w’, edgecolor=’k’)
plt.plot(history.history[‘loss’])
plt.plot(history.history[‘val_loss’], c=’r’, ls=’dashed’)
plt.title(‘model loss’)
plt.ylabel(‘loss’)
plt.xlabel(‘epoch’)
plt.legend([‘train’, ‘test’], loc=’upper left’)
plt.show()

使用 Keras 分类器的试验比以前的模型表现得更好。从回忆分数来看,负数看起来没有以前那么糟糕了。即使每个情感值都有 4000 个数据点,也可能是中性类有更多独特的词。进一步的测试将尝试添加一个 LSTM 层,以便添加一个记忆层,以及一个卷积层,以便找到隐藏的模式。

结论

获得更好的分类器分数所需的数据必须是特定的。它不可能是随机的推文。从字面上看,最负面的词和最正面的词都要被搜索和收集。这样做之后,我相信这个分类器会像 VADER 情感分析一样出色。

汽车品牌的推特情感分析

原文:towardsdatascience.com/twitter-sen…

Twitter 数据是一个丰富的来源,可以用来获取任何可以想象的话题的信息。这些数据可用于不同的用例,例如寻找与特定关键字相关的趋势、测量品牌情感以及收集关于新产品和服务的反馈。

在这篇文章中,我将从 twitter 中提取各种汽车品牌的数据。然后,我们将应用情感分析来了解在最近一段时间内,人们对不同汽车品牌的正面/负面看法。情感分析是确定一条内容是正面的、负面的还是中性的过程。这也被称为意见挖掘,得出一个发言者的意见或态度。这项技术的一个常见用例是发现人们对某个特定话题的感受。在我们的例子中,我们使用最近推文中的文字来发现人们对不同汽车品牌的感受。

我发现这篇文章和这段视频有助于弄清楚如何从 twitter api 中提取、过滤和处理数据。

#Import the necessary methods from tweepy library
from tweepy import Stream
from tweepy import OAuthHandler
from tweepy.streaming import StreamListener
import time#Variables that contain the user credentials to access Twitter API
#(Note: replace with your own values from [https://apps.twitter.com/](https://apps.twitter.com/))
consumer_key="consumer key"
consumer_secret="consumer secret"
author_token="author token"
author_secret="author secret"class listener(StreamListener):#This is a basic listener that just prints received tweets
def on_data(self, data):
   try:
     #writing data to file
     saveFile = open('tweetDBcars.csv','a')
     saveFile.write(data)
     saveFile.close()
     return(True)
   except BaseException, e:
     print 'failed ondata,',str(e)
     time.sleep(5)def on_error(self, status):
        print statusauth = OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(author_token, author_secret)twitterStream = Stream(auth, listener())# getting tweets that have any of these words
twitterStream.filter(track=['car' 
 'chevy','ford','toyota',
    'acura','kia','audi',
    'chrystler','dodge','ferrari'
    'fiat','buick','cadillac','chevrolet',
    'bmw','honda','jeep','lexus','mazda',
    'mini','nissan','tesla''volvo','saab','porshe'])

我让这个脚本运行了 6 天,累积了大约 115,000 条推文。Twitter api 在类似于 python 字典的 json 数据结构中为我们提供了关于每条 tweet 的大量数据。我们对 tweet 本身的内容感兴趣,可以通过键[“text”]访问它。

在处理大型数据集时,在 try/except 子句中捕获 tweet = json.loads(line)语句非常重要。尽管从 Twitter api 返回的数据通常是干净的,但可能会有错误,如果遇到一行坏数据,您希望避免破坏脚本。try/except 子句允许脚本跳过一行坏数据,继续处理剩余的 tweets。

tweets_data_path = 'twitDBcars.csv'tweets_data = []
tweets_file = open(tweets_data_path, "r")
for line in tweets_file:
    try:
        tweet = json.loads(line)
        tweets_data.append(tweet)
    except:
        continue

现在我们用微博创建一个熊猫数据框架

tweets = pd.DataFrame()index = 0
for num, line in enumerate(tweets_data):
  try:
     print num,line['text']
     tweets.loc[index,'text'] = line['text']
     index = index + 1 
 except:
     print num, "line not parsed"
     continue

为了提取关于特定品牌的推文,我们将每条推文中的单词与我们感兴趣的每个品牌的名称进行比较。如果我们找到了我们正在寻找的品牌,我们会在数据框中的新列“品牌名称”中对其进行跟踪。

def brand_in_tweet(brand, tweet):
    brand = brand.lower()
    tweet = tweet.lower()
    match = re.search(brand, tweet)
    if match:
        print 'Match Found'
        return brand
    else:
        print 'Match not found'
        return 'none'

下一步是评估每条推文的情绪。有几种方法可以进行情感分析。

从业者最常描述的有两种方法:

  • 一种方法是收集一堆推文,让人们给它们贴上积极或消极的标签。然后使用已标记的数据集来训练算法,如朴素贝叶斯或随机森林。然后,训练好的模型可以用于新的数据,以估计情绪。
  • 第二种方法是使用词典,我们将推文中的单词与词典中的单词(或 n-grams)进行比较,以对每个单词的积极/消极情绪进行评分。然后,我们将每条推文的单词分数相加,得出推文的情感分数。

在本帖中,我们将通过使用 TextBlob 包来使用第二种方法。我们使用 TextBlob 的极性方法来查找每条推文的情感得分,并将其记录在 dataframe 中的新列“sentscore”中。(关于 TextBlob 如何计算情感得分的更多详细信息,请点击查看。)

from textblob import TextBlobfor index, row in tweets.iterrows():
    temp = TextBlob(row['text'])
    tweets.loc[index,'sentscore'] = temp.sentiment.polarity

我喜欢使用 ggplot 进行数据可视化,因为它强大而灵活,所以我将把数据帧写入一个 csv 文件,该文件可以导入到 r。

 for column in tweets.columns:
    for idx in tweets[column].index:
        x = tweets.get_value(idx,column)
        try:
            x = unicode(x.encode('utf-8','ignore'),errors ='ignore')          
            if type(x) == unicode:
                unicode(str(x),errors='ignore')
            else: 
                df.set_value(idx,column,x)
        except Exception:
            print 'encoding error: {0} {1}'.format(idx,column)
            tweets.set_value(idx,column,'')
            continue
tweets.to_csv('tweets_export.csv')

让我们读取 R 中的数据,并直观地检查这些数据

df_tweets = read.csv("tweets_export.csv")#let us look at the mean of sentiment scores for all brands
data_brand = df_tweets %>%
   group_by(brand) %>%
   summarise(mean_sentiment_score = mean(sentscore))ggplot(data=data_brand, aes(x=brand, y=mean_sentiment_score))+
  geom_bar(stat = "identity", aes(fill = brand))

我们注意到雷克萨斯的正面喜好度最高,丰田的负面喜好度最高。假设我们代理的客户是一家汽车经销商,他们想决定增加对哪些品牌的投资,这种从经销商身边的人那里收集的信息可能非常有用。

现在让我们更仔细地研究 3 个品牌:

#We subset the data for the brands ford, mini and kia to drill down into the variance of their sentiment over timedata_week <- df_tweets[df_tweets$brand %in% c("ford","mini","kia"),]ggplot(aes(x = day, y = sentscore), data = data_week) + 
  geom_smooth(aes(colour = brand))

随着时间的推移,起亚的正面喜好度有所上升,而福特的正面喜好度有所下降。假设我们是一家咨询公司,福特是我们的客户之一,我们需要进一步挖掘细节,以了解为什么积极情绪正在减少。

这是非常初步的分析。为了实现情感分析的高准确度,需要考虑几个因素,例如语言、领域、人口、年龄、俚语、词汇分析等。脸书和 AOL 面临的一些挑战和采取的方法分别在这里这里讨论。我希望在不久的将来进一步研究这一分析。

同一主题的其他重要资源:

  1. 用 twitter 分析大数据 —来自伯克利分校的视频和幻灯片——由来自 twitter 的员工演示的讲座。
  2. 分析推文中表情符号的情感
  3. 如何构建 twitter 情感分析器
  4. 用 python 挖掘 twitter 数据(图书)
  5. twitter 用户对薄荷烟的看法:内容和情感分析(研究论文)

我的其他项目很少在这里

Python NumPy 的两个很酷的特性:通过切片和广播进行变异

原文:towardsdatascience.com/two-cool-fe…

NumPy 是纯金。它快速、易学、功能丰富,因此是 Python 世界中几乎所有流行科学包的核心(包括 SciPyPandas ,这两个包在数据科学和统计建模领域应用最广泛)。在本文中,让我们简要讨论 NumPy 的两个有趣的特性,即。切片突变

切片突变

事实证明,如果使用 NumPy 的简单切片/索引来创建子数组,子数组实际上指向主数组。简单地说,内存中的图表看起来像,

因此,如果切片数组被更改,它也会影响父数组。这可能是一个有用的特性,可以将所需的链传播到食物链的上游,但有时也可能是一个麻烦,因为您需要保持主数据集不变,并且只对子集进行更改。在这些情况下,您必须显式调用 np.array 方法来定义切片数组,而不仅仅是通过索引来切片。下面的代码说明了这一点,

说明性代码

mat = np.array([[11,12,13],[21,22,23],[31,32,33]])
print("Original matrix")
print(mat)
**mat_slice = mat[:2,:2] # *Simple indexing***
print ("\nSliced matrix")
print(mat_slice)
print ("\nChange the sliced matrix")
mat_slice[0,0] = 1000
print (mat_slice)
print("\nBut the original matrix? WHOA! It got changed too!")
print(mat)

结果看起来像是,

Original matrix
[[11 12 13]
 [21 22 23]
 [31 32 33]]

Sliced matrix
[[11 12]
 [21 22]]

Change the sliced matrix
[[**1000**   12]
 [  21   22]]

But the original matrix? WHOA! **It got changed** too!
[[**1000**   12   13]
 [  21   22   23]
 [  31   32   33]]

为了阻止这种事情发生,这是你应该做的,

# Little different way to create a copy of the sliced matrix
print ("\nDoing it again little differently now...\n")
mat = np.array([[11,12,13],[21,22,23],[31,32,33]])
print("Original matrix")
print(mat)
**mat_slice = np.array(mat[:2,:2]) *# Notice the np.array method***
print ("\nSliced matrix")
print(mat_slice)
print ("\nChange the sliced matrix")
mat_slice[0,0] = 1000
print (mat_slice)
print("\nBut the original matrix? NO CHANGE this time:)")
print(mat)

现在,子矩阵中的任何变化都不会改变原始矩阵,

Original matrix
[[11 12 13]
 [21 22 23]
 [31 32 33]]

Sliced matrix
[[11 12]
 [21 22]]

Change the sliced matrix
[[**1000**   12]
 [  21   22]]

But the original matrix? **NO CHANGE** this time:)
[[**11** 12 13]
 [21 22 23]
 [31 32 33]]

广播

NumPy 操作通常是在逐个元素的基础上对数组对进行的。在一般情况下,两个数组必须具有完全相同的形状(或者对于矩阵乘法,内部维度必须一致)。

当数组的形状满足某些约束 时,NumPy 的 广播规则放松了这个约束。当操作两个数组时,NumPy 按元素比较它们的形状。它从尾部维度开始,向前推进。在以下情况下,二维是兼容的

  • 它们相等,或者
  • 其中一个是 1

如果不满足这些条件,就会抛出一个value error:frames not aligned异常,表明数组具有不兼容的形状。结果数组的大小是沿着输入数组的每个维度的最大大小。

更多详情请查阅:https://docs . scipy . org/doc/numpy-1 . 10 . 1/user/basics . broadcasting . html

下面的代码块按部就班地说明了这个想法,

用零初始化“开始”矩阵

start = np.zeros((4,3))
print(start)[[ 0\.  0\.  0.]
 [ 0\.  0\.  0.]
 [ 0\.  0\.  0.]
 [ 0\.  0\.  0.]]

创建一个行矩阵(向量),

# create a rank 1 ndarray with 3 values
add_rows = np.array([1, 0, 2])
print(add_rows)[1 0 2]

将零矩阵(4x3)与(1x3)向量相加。自动地,1×3 向量被复制 4 次以使匹配零矩阵的行尺寸,并且这些值被添加到 4×3 矩阵中。

y = start + add_rows  # add to each row of 'start'
print(y)[[ 1\.  0\.  2.]
 [ 1\.  0\.  2.]
 [ 1\.  0\.  2.]
 [ 1\.  0\.  2.]]

创建列矩阵(向量),

# create an ndarray which is 4 x 1 to broadcast across columns
add_cols = np.array([[0,1,2,3]])
add_cols = add_cols.T
print(add_cols)[[0]
 [1]
 [2]
 [3]]

将零矩阵(4x3)与(4x1)向量相加。自动地,4x1 向量被复制 3 次以使匹配零矩阵的列维度,并且这些值被添加到 4x3 矩阵中。

# add to each column of 'start' using broadcasting
y = start + add_cols 
print(y)[[ 0\.  0\.  0.]
 [ 1\.  1\.  1.]
 [ 2\.  2\.  2.]
 [ 3\.  3\.  3.]]

最后,标量被视为 1x1 矩阵,并精确复制到加法矩阵的大小以执行运算。

# this will just broadcast in both dimensions
add_scalar = np.array([100])  
print(start+add_scalar)[[ 100\.  100\.  100.]
 [ 100\.  100\.  100.]
 [ 100\.  100\.  100.]
 [ 100\.  100\.  100.]]

当您使用 NumPy 数组为像梯度下降这样的算法编写矢量化代码时,广播的效用得到了最好的实现。吴恩达 花了一个全视频讲座 **在他新的深度学习课程中用 Python 解释广播的概念。**它使得深度神经网络的前向和反向传播算法的实现相对无痛。

你也可以看看这个关于广播功能演示的视频…

Numpy Broadcasting explanation video

如有问题或想法分享,请联系作者tirthajyoti【AT】Gmail . com。你也可以查看作者的 GitHub 知识库 中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。也可以在 LinkedIn 上关注我

佛罗里达大学学生政府选举二十年:使用机器学习获得更深刻的见解

原文:towardsdatascience.com/two-decades…

三年前,我上了一堂统计学课,这门课涉及回归技术,除了统计学,我什么都不想。像班上的大多数人一样,我发现统计学很无聊、乏味,在我的日常生活中毫无用处。

怀着一丝希望,我问我的教授,我是否可以在我们刚刚被分配的回归项目中调用 audible,并尝试预测学生会选举的结果。从那以后,随着我在数据科学职业生涯中的进步,我从越来越学术和技术的角度零星地参与了这个项目。

这篇文章的其余部分将包含我的发现,我的失败,它们背后的数据,以及如何自己尝试这种类型的工作的说明。希望在我今年 12 月毕业后,其他学生可以利用这些数据,创建更好的模型和更有趣的见解。

数据

对于任何参与过地方选举的人来说,这并不奇怪,但是选举结果却保存在不同格式的几乎无法阅读的 pdf 文件中。通过 pdf 到文本转换器和手抄结果的结合,创造了整个 21 世纪 SG 选举的历史。

关于数据需要注意一些事情(在我的 github 上找到)。“Est”代表建立,我也称之为系统。该系统已经在学术上得到广泛研究,最突出的工作来自大卫·布拉德肖,他在 2013 年写了一篇关于它的论文。他(恰当地)将这一体系定义为“一个令人惊讶的复杂的赞助和讨价还价体系”,即“佛罗里达大学希腊社区的绝大多数和校园内几个最著名的非希腊学生组织的联盟,其中许多组织代表特定的少数群体,通常被称为“社区”。这些社区主要由亚裔美国学生联合会(AASU)、西班牙裔学生联合会(HSA)和黑人学生联合会(BSU)组成。学生政府的职位在希腊各学院之间进行交易,并给予社区的杰出成员,以创造多样性和包容性的外观。该系统在整个 20 世纪 70 年代和 80 年代在佛罗里达大学掌权,以确保除了上层阶级的白人男性,尤其是当时正在整合佛罗里达大学的有色人种,任何人都不能获得校园中重要和有声望的职位。你可以在这里或阅读更多关于系统的信息,甚至可以在这里观看一个关于它的视频,但这个项目的主旨是通过一个统计镜头来探索 SG。

通过探索性数据分析的独立机会

探索性数据分析(或 EDA)在技术上是“分析数据的过程,解释这些过程的结果的技术,以及规划数据收集以使其分析更容易的方法”,这只是“对数据提出问题”的一种更长的说法

数据库完成后,我的第一个问题是“这个系统在 21 世纪的主导地位如何?”系统党赢得了每一次总统选举,除了两次,一次是在 2004 年与贾迈勒·索维尔,另一次是在 2015 年与约瑟林·帕德隆-拉辛斯,但更细致的分析可能吗?我看了一下参议院,并绘制了自 2000 年以来春季选举的胜率,发现独立政党平均只赢得了他们竞选的 21.5%的选票,而系统政党赢得了令人震惊的 81.5%的选票(T3)。这是因为有些年份有多个独立政党,而有些年份则有无竞争的选举。

这张图显示了不同时间的差异。

Winning percentage over the years

事实证明,除了几场选举,这个系统已经成功赢得了绝大多数的选举。有鉴于此,独立政党什么时候表现得好?下面是一张成功聚会的图表,按机构、聚会时间(聚会在校园里有多长时间)分类。

Winning percentage by age of party

独立党派在 T4 的第一个学期和第二个学期表现最好,随着年龄的增长,他们的表现越来越差。随着时间的推移,建制派似乎也变得越来越差,但下降速度要慢得多。

很明显,当权派会赢(在很大程度上是因为贿赂有职位的学生和酒精,以及扣留 食物直到他们投票)。那么独立党派如何才能获胜呢?显然,一个答案是在校园的第一个学期集中精力进行选举,那时的投票率平均要高得多。但另一个潜在的努力是针对个别参议院席位。

SG 选举分为秋季和春季选举,秋季参议员按地理区域(宿舍或邮政编码)选举,春季参议员按学院(工程、商业)或年级(大一、大二)选举。就像在全国选举中一样,有些席位选举系统候选人的比率远远高于已经相当高的平均比率,即使经过一段时间。例如,在 A 区(校园东面的区域,包括所有的女生联谊会和附近的公寓楼),几乎从来没有一个席位是由非体制或独立党派赢得的。根据年份的不同,A 区控制着参议院的大约 5% 到 10% 的席位。

也有倾向独立投票的席位。下面是独立党派的席位胜率图,给出了一个(伪)权力排名。在收集数据时,无穷大的样本大小是 1,平均值肯定是失真的。除此之外,独立党派赢得 50%以上的席位只有两个,家庭住房和毕业。

选举建模

在选举建模领域,学者和媒体机构经常使用所谓的基本面来预测选举结果。大卫·拜勒目前正在为 2018 年 11 月的参议院模型工作,他比我更好地定义了基本面,他说

“基本面基本上涵盖了直接投票之外的一切——总统的批准,……该州过去的选举结果,候选人的信息。”

这基本上是我们所拥有的数据。当处理这样的问题时,我想到了两种主要的方法。

支持向量机

首先,我想创建一个算法,如果数据被投射到二维空间,将能够创建一个超平面(在二维空间,这看起来像一条线。在我们的例子中,它作为一个多维平面存在,具有与数据相同的维数,将每次选举(给定年份、政党年龄、以前的选举结果、候选人数量等)分为两类,即获胜和失败。在数据科学中,我们称之为线性分类器。这项工作有很多潜在的算法,从 K-Nearest Neighbors 到 Perceptron,K-Nearest Neighbors 可以在训练集中找到 K 个最近的点,并允许每个点对预测进行投票,Perceptron 可以根据获得的每个新数据更新算法的权重。我最终选择了 SVM(支持向量机)分类器,因为我从理论上认为,有大量的选举很容易预测,而有少量的选举要困难得多。这让我想到了 SVM 分类器,因为 SVM 在线性分类器中最大化了相近案例之间的间隔。如果最后一段对你来说没有意义,那 100%没关系,因为一些聪明的人制作了一个图表,使这更容易理解。

有相当多的线可以将这两个类别分开,但是 SVM 找到了最大化这两个类别之间差距的线,这正是我们想要的。

在对数据进行大规模清理之后,我使用了 caret 包(用于预测建模/机器学习/统计分析,无论你喜欢怎么称呼它)来实现 SVM 算法。结果呢?回溯测试的准确率约为 80%。附上混淆矩阵(顶行是预测,第一列是实际结果。因此,这可以理解为“对于 SVM 预测参议员将会失败的选举,它得到了 130 个正确和 34 个不正确”)。

这个在 2018 年春季选举前创建的算法预测,Inspire(独立党)将赢得研究生参议院席位,并将输掉所有其他竞争性选举。在这种情况下,它预测了一个行政门票清扫和一个 38/50 参议院系统崩溃。事实证明这几乎是真的,Inspire 赢得了研究生院、牙科和美术院的席位,失去了所有其他竞争席位。参议院的总结果是 36/50 加上行政人员的票数,大约是 96% 准确。还不错!然而,我们得到的精确度超出了 95%的置信区间(精确度在 76%和 84%之间),这可能是 2018 年选举中有第三个政党(尽管相当无组织和草率)而不是通常的两个政党的作用。有一点也是肯定的,政党数量的增加对独立政党赢得的参议院席位数量有显著的影响,对 2018 年春季的选举有影响。

随机森林

我想尝试的第二种方法是使用决策树(到目前为止,我最喜欢的决策树可以在这里找到)。同样,决策树有几十种不同的实现和评分机制,包括经典的分类和算法树,以及像 Boosted 树和 Random Forest 这样的集合树(可以在这里找到一篇很好的背景实现文章)。从图形上看,决策树是这样的。

What should I do with my night? A analysis with decision trees

这是一个相当简单,但非常有用的方法。一个更健壮的模型被称为随机森林,它将大量决策树与随机选择的变量相结合,并使用一组(可能相当糟糕)预测算法来创建一个新模型(这被称为集成学习)。我认为这个模型会表现得更好,因为决策树通常是我对选举的看法。候选人在商学院竞选吗?他们在系统中运行吗?那么他们很可能会赢。

实施后,我们得到了这个混淆矩阵,它转化为 89%的准确率,远远高于 SVM 方法。

随机森林算法的另一个好处是,由于它选择不同变量的方式,我们可以推导出每个变量的重要性(注意:X 轴上的 MeanDecreaseGini 是衡量类别杂质的一种方式。基尼系数的平均降幅越高,意味着该变量越重要)。

不出所料,影响最大的两个变量是席位和候选人是否是体制的一部分。考虑到这一点,仍然有人说这个系统不存在,因为它似乎能很好地预测选举结果,这确实显得很愚蠢。

在 2018 年春季选举中使用随机森林方法,随机森林在 SVM 分类器上的表现完全相同(96%),但在测试数据上的准确率更高,为 89%。尽管如此,我还是决定在推特上发布一个略有改动的预测,说我认为 Inspire 将与工程学和 CLAS 一起赢得毕业生奖。不出所料,人类的表现远不如算法,工程和 CLAS 都受到了影响。吸取教训。

结论:事实证明机器学习是可行的

在整个项目中,我一直着迷于了解联合阵线选举的可预测性,即使是通过前美国参议员兼佛罗里达州州长鲍勃·格雷厄姆描述的选举

"在州和联邦政治中,我从未遇到过像佛罗里达大学那样咄咄逼人的活动."

我最初的目标是预测选举结果,在理解了数据并尝试了几次之后,我对结果非常满意。同样,数据和脚本都是公开的,我随时可以回答关于数据科学、用友 SG、它们的交集或者具体这个项目的问题。通过电子邮件联系我,或者在推特上找到我。

最后一点,我试图用所有领域的专业知识创建这些模型,但没有对系统如何积极地使佛罗里达大学成为一个更糟糕的地方发表意见,并且没有任何好的理由让任何人参与到 20 世纪 70 年代的活遗迹中。但我确信我的偏见会渗透进来。

我想公开感谢 William Ferra,他在该项目的数据收集和清理部分发挥了不可估量的作用。如果没有他,这个项目是不可能的,或者至少要花更长的时间。

两个比一个好:集合模型

原文:towardsdatascience.com/two-is-bett…

组装起初听起来像是一个非常吓人的词,但实际上看起来很简单…让我用一个类比来解释集合

Ensembling algorithms to obtain the cake of accuracy

集成有点像整个周末都在看网飞(通用 ML 算法),这很好,但结合一些披萨或一个特殊的朋友,你就可以放松了,我说的“放松”是指达到 90%的准确率

因此,基本上集成/组合两个或更多的算法可以改善或提高你的性能。但是在组合的背后有一个逻辑…你不能只是随机地组合两个模型,并要求提高精确度…每件事背后都有一个数学…..因此,让我们深入探讨几种您可以尝试的组装方法…(如果你喜欢那种东西)

简单平均/加权法:

名字说明了一切…这种组合方法只取两个模型的平均值。但是这是怎么做到的…是山达基吗?

假设你已经使用了名为的算法将和结果是

*Actual_targets: 1 0 1 1 0 1**Predicted vals: 1 0 1 0 1 0*

现在你使用另一种叫做格雷斯的算法,结果是

*Actual_targets: 1 0 1 1 0 1**Predicted vals: 0 1 0 1 0 1*

威尔正确预测了前三个目标,而格雷斯正确预测了后三个目标

如果我们结合这两种算法(WILL & GRACE ),我们会得到一个相当不错的情景喜剧,我们的准确性肯定会增加。这是一个平均模型背后的想法,它是一个非常基本的集合案例。

你可以使用 Sklearn 的投票分类器轻松实现这一点,它甚至允许你为每个算法分配权重。

from sklearn.ensemble import VotingClassifier
ensemble=VotingClassifier(estimators=[('Decision Tree', decisiontree), ('Random Forest', forest)], 
                       voting='soft', weights=[2,1]).fit(train_X,train_Y)
print('The accuracy for DecisionTree and Random Forest is:',ensemble.score(test_X,test_Y))

我们可以根据性能分配权重或取平均值,即给算法设置相等的权重。

装袋方法:

装袋方法和前面的很像,但是我们不用威尔和格蕾丝,而是用速度和激情 1,2,3,4,5,6。这意味着我们不用不同的模型,而是用同一个模型的不同版本。

随机森林是一个著名的 bagging 模型,它使用了多棵树的变种。如果使用相同的树,那么它就是一个袋装决策树。

但是为什么装袋有效呢?我们不是又在做同样的事情吗?

让我们考虑一个模型正在训练,它注意到一个实例,一个蓝眼睛、红衬衫、带着笔记本电脑的白人男子坐在星巴克,我们需要找出他是一个有抱负的编剧的概率…现在,该模型似乎已经深入到无法预测它开始证明这种流行刻板印象的每一个实例的概率。每个符合上述描述的白人都不是编剧…..(他可能是 tho)

总的来说,当一个模型概括了一些它不应该概括的东西时,它有很高的方差,打包可以减轻这个问题

使用 Bagging 确保预测不会读取高方差。

bagging 模型中的每个模型(bag)彼此略有不同,并确保我们不会停留在非常深的表示上,并输出一个对测试集更友好的预测。

下面是随机森林的代码,一种装袋方法

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y = train_test_split(dataset.drop('target'),dataset['target'])
trained_model = random_forest_classifier(train_x, train_y)
predictions = trained_model.predict(test_x)

增压方法:

因此,在前面的示例中,我们要么采用几个独立的模型并计算它们的平均值,要么计算它们的加权平均值,但如果我们考虑我们之前的模型表现如何,并将其合并到我们的下一个模型中,会怎么样呢…..有点像用以前模型的预测来推动新模型…好了,你知道了…这就是助推的作用。

此外,重要的是要注意,模型是按顺序添加到集合中的。Boosting 有时会通过减少偏差、方差和许多 kagglers 微调 boosting 算法来获得非常棒的结果。

基于重量的助力:

假设您正在训练一个模型,其中根据预测为每个预测的标签分配一个权重(好的预测意味着权重较小,坏的预测意味着权重较大)。这有点像因果报应,除了升压不是一个婊子。

这些权重在集合中的每个模型上累加,随着权重的增加,你明白你需要更好地预测它们,并且你开始将你的模型集中在它们上,而不是那些权重较低的模型上。这一直持续到达到最大精确度或最大模型数量。

这些重量有点像现实生活中的重量,一个人收获越多,自尊越低,因此需要去健身房,这里健身房是助推算法…..你总是需要在健身房得到激励…:)

例如:Adaboost,强分类器是权重低的地方,弱分类器是权重高的地方。Adaboost 旨在通过添加模型和纠正以前模型的错误,将弱分类器转换为强分类器(必修教科书定义)

*class* sklearn.ensemble.**AdaBoostClassifier**(*base_estimator=None*, *n_estimators=50*, *learning_rate=1.0*, *algorithm=’SAMME.R’*, *random_state=None)*

残基助推:

在这种类型的提升中,我们分配权重的绝对值(预测和实际标签之间的差异),并将其作为新变量分配给下一个模型。但是为什么呢?。…..考虑以下情况

Actual value : 1
Predicted Val: 0.75
Weight       : 0.25For next model let use this weight to minimize the error in the next model where we predict the value

Whaaaaat 所以只要插入一个损失函数,像梯度下降…是的…这种方法也可以被称为梯度推进

这里梯度指的是有限差分,而不是导数

这种方法的一些优点

  • 没有过度拟合(使用学习率)
  • 我们不依赖单一的预测树(估计数)

为了防止过度拟合,我们可以采用深度学习的辍学概念,并将其应用于集成,这确保了随机性和正则化,并确保我们的模型能够很好地推广。即。如果我们在集合中构建了 4 棵树,那么在构建第五棵树时,我们会故意忽略 2 棵随机的树。例如:DART(漏失符合多重可加回归树)。

很多开发者用来赢得比赛的超级棒的助推算法是

  • Xgboost (极限梯度提升),
  • Lighbgm (垂直增长的非常快速的梯度推进)
  • Catboost(带有良好的初始参数,可以自动编码分类变量)。

希望你觉得这篇文章有用和有趣…..

两个月探索深度学习和计算机视觉

原文:towardsdatascience.com/two-months-…

I’ve been reading/note taking is using an iPad Pro and LiquidText

我决定熟悉计算机视觉和机器学习技术。作为一名 web 开发人员,我发现这个不断发展的领域令人兴奋,但是我没有任何使用这些技术的相关经验。我将开始为期两年的旅程来探索这个领域。如果你还没有读过,你可以在这里看到第 1 部分:从 webdev 到计算机视觉和地理

I️最终通过探索 I️拥有的任何激发自己学习的机会来让自己动起来。我最初并没有停留在研究机器学习上,但我想回到对某个主题感到兴奋的状态。I️通过参加为期一天的加密货币学术会议开始了我的研究,到下午会议开始时,我意识到机器学习和计算机视觉对我来说更有意思。

入门指南

大约在一本关于深度学习和计算机视觉交叉领域的伟大著作出版的时候,I️启动了我的探索。来自 PyImageSearch.com 的作者Adrian rose Brock汇编了一部关于计算机视觉和深度学习的高级思想和低级应用的三卷巨著。在探索深度学习的过程中,I️遇到了对线性回归、朴素贝叶斯应用(I️现在意识到,I️已经听到这个名字有很多不同的发音)、随机森林/决策树学习以及所有其他我正在屠杀的东西的无数解释。

I️花了几周时间阅读这本书,并感觉 I️可以将我迄今为止阅读的所有不同的博客帖子与一系列数学概念、抽象概念和实际编程应用联系起来。我快速通读了这本书,并且对如何将这个领域作为一个整体有了更好的理解。我最大的收获是得出了这样的结论:I️想要巩固我自己的工具和硬件,以构建计算机视觉软件。

硬件实现

I️受到启发,得到了一台 Raspberry Pi 和 RPI 相机,I️可以用它来分析视频流。我一点也不知道设置树莓酱会花很长时间。最初,I️希望简单地启动并运行一个视频流,然后在我的电脑上处理视频。I️努力让树莓 Pi 操作系统工作起来。然后,一旦 I️意识到什么是错的,I️不小心安装了错误的图像驱动程序,并意外地安装了冲突的软件。I️最初认为这个过程会充满对相机图像的处理,结果却变成了一场耗时数小时的调试噩梦。

到目前为止,I️已经意识到这是机器学习的一个重要开始,而计算机视觉的“东西”是关于调试的。

第一步。得到一个想法。 第二步。开始寻找做这件事的工具。 第三步。安装所需的软件。 第四步。淹没在冲突和意外的包版本问题中。

aiyprojects.withgoogle.com/vision#list…

树莓派背后我最初的灵感是建立一个简单的设备,有一个摄像头和 GPS 信号的想法。这个想法是基于对未来有多少车辆,自动驾驶或车队车辆,将需要许多摄像头进行导航的思考。无论是出于保险目的还是为了基本功能,I️设想将会有大量的视频素材被创建和使用。在这个过程中,将会有大量的媒体储存库闲置不用,成为了解世界的丰富数据源。

I️最终探索了树莓派的计算机视觉能力,但从未像我希望的那样成功地获得任何有趣的工作。I️发现有许多更便宜的类似树莓派的设备,它们在比全尺寸树莓派更小的 PCB 板上同时具有互连性和相机功能。后来,I️意识到,与其走硬件路线,I️还不如用一部旧 iPhone,开发一些软件。

我在探索深度学习的硬件组件方面的短暂尝试让我意识到,我应该尽可能坚持软件。当软件部分没有解决时,包含一个新的变量只会增加复杂性。

开源工具

在寻找机器学习资源的第一个月,我发现了许多开源工具,它们使启动和运行变得非常容易。我知道方科技公司提供了许多专有服务,但我不确定他们如何与开源软件竞争。可以作为 SAAS 工具使用的图像识别和 OCR 工具来自 IBM、Google、Amazon 和 Microsoft,非常容易使用。令我惊讶的是,有很好的开源替代方案值得配置,以避免不必要的服务依赖。

例如,几年前,我推出了一个 iOS 应用程序,用来收集和分享涂鸦照片。我从带有地理标签的公开 API 中检索图片,比如 Instagram 和 Flickr。利用这些来源,我使用基本特征,如标签和位置数据,来区分图像是否真的是涂鸦。最初,我开始每周拉几千张照片,很快就增加到一个月几十万张。我很快注意到,我索引的许多图像不是涂鸦,而是对我试图培养的社区具有破坏性的图像。我无法阻止人们自拍的低质量照片或对工作不安全的糟糕标记的图像加载到人们的订阅源中。因此,我决定关闭整个项目。

#graffiti results on instagram

现在,有了机器学习服务和用于对象检测和裸体检测的开源实现,我可以推出自己的服务,轻松检查每张被索引的照片。以前,如果我支付一项服务来进行质量检查,我会在 API 费用上花费数百美元,如果不是数千美元的话。相反,我现在可以从一些“数据科学”AWS 盒子下载一个 AMI,并创建自己的 API 来检查不想要的图像内容。这对我来说遥不可及,甚至就在两年前。

概观

在很高的层面上,在经历这个过程之前,我觉得自己理论上理解了大部分的物体识别和机器学习过程。在开始将我一直在消费的所有机器学习内容之间的点连接起来的过程之后,我觉得我对我需要学习的概念更加清楚了。例如,我不仅仅知道线性代数对机器学习很重要,我现在理解了问题如何被分解成多维数组/矩阵,并被大量处理以寻找仅在理论上可表示的模式。之前,我知道在特性之间有一些抽象,以及它们如何被表示为可以在一系列评估项目之间进行比较的数字。现在,我更清楚地理解了在机器学习的背景下,维度是如何通过纯粹的事实来表示的,即有许多因素直接或间接相互关联。特征检测和评估的多维方面的矩阵数学对我来说仍然是一个谜,但是我能够理解高层次的概念。

The previously illegible network architecture graphs are now seemingly approachable.

具体来说,阅读 Adrian Rosebrock 的书给了我解读机器学习算法的盒线图的洞察力。深度学习网络架构的崩溃现在有些可以理解了。我还熟悉常用于测试各种图像识别模型的数据集(MNIST、CIFAR-10 和 ImageNet),以及图像识别模型之间的差异(如 VGG-16、Inception 等)。

时机——公共资金

我认为现在学习机器学习和计算机视觉很重要的一个原因与我从这本书中学到的一个概念有关:政府在研究方面投入大量资金的领域将会有巨大的创新。目前,除了分配给特定机器学习相关项目的特定资金外,还有数亿美元以赠款和奖学金的形式花费在研究项目上。

Example of pix2pix algorithm applied to “cat-ness”. distill.pub/2017/aia/

除了政府支出,来自私人机构的公开研究似乎也在增长。目前存在的研究形式,来自大型科技公司和公共基金会,正在推动整个机器学习领域。我个人从未见过像 distill.pub 这样的出版物和 OpenAI foundation 这样的集体形式的私人机构资助的公共项目如此集中。他们所做的工作是无与伦比的。

可行的任务

回顾我一直在阅读的材料,我意识到我的记忆力已经开始衰退了。从现在开始,我要做更多的行动导向的阅读。我现在有一个装有 GPU 的盒子,所以我觉得在训练模型和处理数据集方面没有任何限制。

最近,我参加了一个由 Carto 主办的关于空间数据科学的大型会议。在那里,我非常清楚地意识到我在空间数据科学领域有多少知识。在会议之前,我只是把整个领域称为“地图定位数据的东西”。

我会继续努力在网上结识有相似兴趣的不同的人。我已经能够对我找到的住在纽约并写了与我当前搜索相关的中型帖子的人这样做了。最近,在探索如何构建一个 GPU 盒子时,我得以与一位机器学习探索伙伴共进早餐。

到一月中旬,我希望熟悉围绕涂鸦图像训练模型的技术框架。我认为至少,我希望有一组要处理的图像,将图像关联到的标签,以及对照已训练的标签交叉检查未索引图像的过程。

感谢 Jihii Jolly 纠正我的语法。

深度学习中不同类型卷积的介绍

原文:towardsdatascience.com/types-of-co…

让我给你一个快速概述不同类型的卷积和他们的好处。为了简单起见,我只关注 2D 卷积。

回旋

首先,我们需要就定义卷积层的几个参数达成一致。

2D convolution using a kernel size of 3, stride of 1 and padding

  • 内核大小:内核大小定义卷积的视野。2D 的常见选择是 3,即 3x3 像素。
  • 步幅:步幅定义了内核遍历图像时的步长。虽然其默认值通常为 1,但我们可以使用步幅 2 对图像进行缩减采样,类似于 MaxPooling。
  • 填充:填充定义如何处理样本的边框。(一半)填充卷积将保持空间输出维度等于输入维度,而如果内核大于 1,未填充卷积将裁剪掉一些边界。
  • 输入&输出通道:卷积层取一定数量的输入通道(I),计算出特定数量的输出通道(O)。这种层所需的参数可以通过 IOK 来计算,其中 K 等于内核中值的数量。

扩张的回旋

(又名 atrous 卷积)

2D convolution using a 3 kernel with a dilation rate of 2 and no padding

膨胀卷积为卷积层引入了另一个参数,称为膨胀率。这定义了内核中值之间的间距。膨胀率为 2 的 3×3 内核将具有与 5×5 内核相同的视野,同时仅使用 9 个参数。想象一下,取一个 5x5 的内核,每隔一行删除一列。

这以相同的计算成本提供了更宽的视野。膨胀卷积在实时分割领域特别流行。如果你需要一个宽广的视野并且不能负担多重卷积或者更大的内核,使用它们。

转置卷积

(又名去卷积或分数步长卷积)

有些资料来源使用反卷积这个名称,这是不恰当的,因为它不是反卷积。更糟糕的是,反进化确实存在,但它们在深度学习领域并不常见。实际的反卷积反转了卷积的过程。设想将一幅图像输入到一个卷积层中。现在拿出输出,把它扔进一个黑盒子里,你的原始图像又出来了。这个黑盒做反卷积。这是卷积层的数学逆运算。

转置卷积有些类似,因为它产生的空间分辨率与假设的反卷积图层相同。然而,对这些值执行的实际数学运算是不同的。转置卷积层执行常规卷积,但恢复其空间变换。

2D convolution with no padding, stride of 2 and kernel of 3

在这一点上你应该很困惑,所以让我们看一个具体的例子。一个 5x5 的图像被送入卷积层。步幅被设置为 2,填充被停用,并且内核是 3x3。这会产生一个 2x2 的图像。

如果我们想逆转这个过程,我们需要逆向数学运算,这样我们输入的每个像素就产生 9 个值。之后,我们以步长 2 遍历输出图像。这将是一个反卷积。

Transposed 2D convolution with no padding, stride of 2 and kernel of 3

转置卷积不会这样做。唯一的共同点是,它保证输出也将是 5x5 图像,同时仍执行正常的卷积运算。为了实现这一点,我们需要对输入进行一些花哨的填充。

正如你现在所能想象的,这一步不会逆转上面的过程。至少不考虑数值。

它仅仅从以前重建空间分辨率并执行卷积。这可能不是数学上的逆运算,但对于编码器-解码器架构来说,它仍然非常有用。这样,我们可以将图像的放大与卷积结合起来,而不是进行两个独立的过程。

可分卷积

在可分离卷积中,我们可以将核操作分成多个步骤。让我们将一个卷积表示为 y = conv(x,k) 其中 y 为输出图像, x 为输入图像, k 为内核。简单。接下来,我们假设 k 可以通过: k = k1.dot(k2) 来计算。这将使它成为一个可分离的卷积,因为我们可以通过对 k1 和 k2 进行 2 次 1D 卷积来得到相同的结果,而不是对 k 进行 2D 卷积。

Sobel X and Y filters

以图像处理中常用的 Sobel 核为例。通过将 vector [1,0,-1]和[1,2,1].T 相乘,可以得到相同的内核。在执行相同的操作时,这将需要 6 个而不是 9 个参数。上面的例子显示了所谓的空间可分卷积,据我所知,它没有用于深度学习。

编辑:实际上,人们可以通过堆叠 1xN 和 Nx1 内核层来创建非常类似于空间可分离卷积的东西。这是最近在一个叫做EffNet的架构中使用的,显示出有希望的结果。

在神经网络中,我们通常使用一种叫做**深度方向可分离卷积的东西。**这将在保持通道分离的同时执行空间卷积,然后执行深度卷积。在我看来,用一个例子最能理解。

假设我们在 16 个输入通道和 32 个输出通道上有一个 3×3 卷积层。具体发生的情况是,32 个 3×3 内核遍历 16 个通道中的每一个,从而产生 512(16×32)个特征图。接下来,我们通过将每个输入通道相加来合并 1 个特征图。因为我们可以这样做 32 次,我们得到了我们想要的 32 个输出通道。

对于同一个例子中的深度方向可分离卷积,我们遍历 16 个通道,每个通道具有 1 个 3×3 内核,给我们 16 个特征图。现在,在合并任何东西之前,我们用 32 个 1x1 卷积遍历这 16 个特征图,然后开始将它们加在一起。这导致 656 (16x3x3 + 16x32x1x1)个参数,而不是上面的 4608 (16x32x3x3)个参数。

该示例是深度方向可分离卷积的具体实现,其中所谓的深度乘数是 1。这是迄今为止此类层最常见的设置。

我们这样做是因为假设空间和深度信息可以分离。从例外模型的表现来看,这个理论似乎是可行的。深度方向可分离卷积也用于移动设备,因为它们有效地使用参数。

有问题吗?

这就结束了我们通过不同类型的回旋的小旅行。我希望这有助于对这件事有一个简要的了解。如果你还有任何问题,请发表评论,并查看GitHub 页面获取更多卷积动画。

市场组合建模中交互效应的类型

原文:towardsdatascience.com/types-of-in…

Source: Pixabay

在这篇文章中,我想谈谈在市场组合模型中变量之间的各种类型的相互影响。

这篇文章是我在 MMM 上写的系列文章的延续。关于 MMM 的前三篇文章可以在这里这里这里找到

那么,回归中的交互作用效应是什么呢?

交互效应是两个或多个自变量对至少一个因变量的同时效应,其中它们的联合效应显著大于(或显著小于)各部分的总和。它有助于理解两个或多个自变量如何协同工作来影响因变量。

首先理解两个组成部分很重要——主效应和交互效应。

主要效果:

主效应是单个自变量对因变量的影响——忽略所有其他自变量的影响。

交互效果:

如上所述,两个或多个自变量对至少一个因变量的同时效应,其中它们的联合效应明显大于(或明显小于)各部分的总和。

我将把这篇文章限制在讨论两个变量之间的相互作用。

交互效果可以在两者之间:

I. 分类变量

二。 连续变量

三。 一个分类变量和一个连续变量

对于每一种情况,解释都会略有不同。

1。分类变量之间:

想象有人在努力减肥。减肥可能是锻炼或遵循饮食计划的结果,也可能是两者协同作用的结果。

以上数字表示以千克为单位的重量损失。

以上结果说明了什么?

结果表明,单独锻炼比节食计划更有效,体重减轻了 5 公斤

**二。**与锻炼和节食计划同时进行的情况(你的节食计划不起作用)相比,只有锻炼才能减轻更多体重

以上结果说明了什么?

这表明,当运动和饮食计划一起实施时,体重下降更高。所以,我们可以说,锻炼和饮食计划之间存在着相互作用。

**2。**连续变量间的

让我们来看一个显示主效应和交互效应分量的回归方程。

Y =β0+β1 * X1+β2 * X2+β3 * X1 x2

上述等式解释如下:

i. β1 是当 X2 等于 0 时 X1 对 Y 的影响,即当 X2 等于 0 时,X1 增加一个单位导致 Y 增加β1 个单位。

二。类似地,当 X1 等于 0 时,β2 是 X2 对 Y 的影响,即当 X1 等于 0 时,X2 增加一个单位导致 Y 增加β2 个单位。

三。在 X1 和 X2 都不为零的情况下,X1 对 Y 的影响取决于 X2,而 X2 对 Y 的影响取决于 X1。

为了更清楚,让我们用另一种格式重写上面的等式。

Y =β0+(β1+β3 * X2)X1+β2 * X2

=>Y =β0+β1 * X1+(β2+β3 * X1)X2

=> (β1 + β3 X2)是 X1 对 Y 的影响,它取决于 X2 的值*

=> (β2 + β3 X1)是 X2 对 Y 的影响,它取决于 X1 的值*

请注意,本文是针对用于市场组合建模的输入/变量而写的。上述概念是 MMM 的一种可能情况,其中输入值可能为零。

对于输入变量不能为零的情况,采取一些其他措施。一个例子可以是一个模型,其中一个人的体重被认为是一个回归变量。一个人的体重不能为零:)

3。 一个连续变量和一个分类变量

一个分类变量和一个连续变量之间的相互作用类似于两个连续变量。

让我们回到我们的回归方程:

Y =β0+β1 * X1+β2 * X2+β3 * X1 x2

其中 X1 是分类变量,比如说(女性= 1,男性= 0)

X2 =连续变量

  • 当 X1 = 0 时,Y = β0 + β2X2*

= > X2 增加一个单位将导致男性 Y 增加β2 个单位

  • *当 X1 = 1 时,Y = β0 + β1 + (β2 + β3)X2

= >女性在 X2 增加一个单位将导致 Y 增加β2 + β3 个单位

X2 对 Y 的影响女性高于男性(请参考下图 1)

Figure 1

MMM 中交互的解释:

1。两个分类变量:

让我们来看两个分类变量——季节性和一些产品的推出。

假设季节性和产品投放都与销售有积极的关系。季节性和以个人身份推出产品会带来销售。如果他们之间有互动效应,这可能会增加销售额。

Y = β0 + β1季节性+β2 产品投放+ β3季节性产品投放

=>Y =β0+β1+β2+β3

其中季节性和产品投放= 1

如果没有相互作用,Y = β0 + β1 + β2

2。两个连续变量:

MMM 中两个连续变量之间相互作用的例子可以是电视广告和数字广告一起对销售的影响。

因此,当存在交互项时,电视广告对销售的影响取决于数字广告,而数字广告对销售的影响取决于电视广告。

Y = β0 + β1电视广告+β2 数字广告+ β3电视广告数字广告- >正向互动术语

如果交互项为正,那么这两个变量的联合效应是协同的,因为它会导致额外的销售。建议这两种类型的广告应该同时进行,以获得更高的销售额。

Y = β0 + β1电视广告+β2 数字广告- β3电视广告数字广告- >负面互动术语

如果交互项是负的,那么交互组件会拿走一部分销售额,从而降低总销售额。在这种情况下,建议不要同时开展这两项活动,因为这会影响销售。(您的活动在客户中制造混乱:P)

请注意,这两种投入的主要影响是积极的,但综合影响具有负的β值,导致总销售额减少。

3。一个连续变量和一个分类变量

其中 X1 是分类变量,比如季节性(如果有季节性,则为 1,否则为 0)

X2 =连续变量:电视广告

Y =销售额

销售受到季节性和电视广告的影响,当它们一起作用时。

Y =β0+β1 季节性+ β2电视广告+ β3电视广告季节性**

在这种情况下,当季节性因素存在时,则:

Y =β0+β1+β2 电视广告+ β3电视广告

*=>Y =β0+β1+(β2+β3)电视广告

电视和季节性之间的相互作用导致了额外的销售。

这是一篇关于变量间交互作用的简介。互动效应本身就是一个巨大的话题。还有更多微妙之处。

请继续关注 MMM 上的更多文章…..

参考:

** [## 相互影响

对于不知情的人来说,调查似乎是一种容易设计和进行的研究,但是当学生和…

methods.sagepub.com](methods.sagepub.com/reference/e…)

如果你喜欢我的文章,给它一些掌声,或者更好地与你的朋友或同事分享。

页(page 的缩写)最近,很多人问我是否做市场组合建模/营销分析方面的咨询。

答案是肯定的。您可以将您的咨询问题发布到www.arymalabs.com/

你也可以在 LinkedIn 上联系我

www.ridhimakumar.com】版权所有 2018 版权所有 版权所有。**

你应该知道的机器学习算法的类型

原文:towardsdatascience.com/types-of-ma…

应我的朋友 Richaldo 的要求,在这篇文章中,我将解释机器学习算法的类型以及何时应该使用它们。我特别认为,了解机器学习算法的类型就像了解人工智能的全貌,以及该领域正在做的所有事情的目标是什么,并让你处于更好的位置来分解一个真正的问题并设计一个机器学习系统。

本帖中经常使用的术语:

  • 标记数据:由一组训练示例组成的数据,其中每个示例是由输入和期望输出值组成的(也称为监控信号、标签等
  • **分类:**目标是预测离散值,例如{1,0}、{True,False}、{spam,not spam}。
  • **回归:**目标是预测连续值,例如房价。

机器学习算法的类型

如何定义机器学习算法的类型有一些变化,但通常它们可以根据它们的目的分成几类,主要类别如下:

  • 监督学习
  • 无监督学习
  • 半监督学习
  • 强化学习

监督学习

  • 我喜欢用函数逼近的概念来考虑监督学习,基本上我们训练一个算法,在过程的最后,我们选择最好地描述输入数据的函数,对于给定的 X,它对 y (X -> y)做出最好的估计。大多数时候,我们无法找出总是做出正确预测的真正函数,其他原因是算法依赖于人类关于计算机应该如何学习的假设,这种假设引入了偏差,偏差是我将在另一篇文章中解释的主题。
  • 在这里,人类专家充当教师,我们向计算机提供包含输入/预测的训练数据,我们向它显示正确的答案(输出),计算机应该能够从这些数据中学习模式。
  • 监督学习算法试图对目标预测输出和输入特征之间的关系和依赖性进行建模,这样我们就可以根据它从以前的数据集中学习到的那些关系来预测新数据的输出值。

起草

  • 预测模型
  • 我们已经标记了数据
  • 监督学习问题的主要类型包括回归和分类问题

常用算法列表

  • 最近邻
  • 朴素贝叶斯
  • 决策树
  • 线性回归
  • 支持向量机(SVM)
  • 神经网络

无监督学习

  • 用未标记的数据训练计算机。
  • 这里根本没有老师,实际上计算机在学习了数据模式后可能会教你新的东西,这些算法在人类专家不知道在数据中寻找什么的情况下特别有用。
  • 是机器学习算法家族,主要用于模式检测描述性建模。然而,这里没有输出类别或标签,算法可以基于它们来尝试对关系进行建模。这些算法尝试对输入数据使用技术来挖掘规则检测模式,以及汇总和分组数据点,这些数据点有助于获得有意义的见解并向用户更好地描述数据。

起草

  • 描述性模型
  • 无监督学习算法的主要类型包括聚类算法和关联规则学习算法。

常用算法列表

  • k-均值聚类,关联规则

半监督学习

在前两种类型中,要么数据集中的所有观察值都没有标签,要么所有观察值都有标签。半监督学习介于这两者之间。在许多实际情况下,标记的成本相当高,因为这需要熟练的人类专家来做。因此,在大多数观察值中没有标签但在少数观察值中存在标签的情况下,半监督算法是建模的最佳候选。这些方法利用了这样的思想,即使未标记数据的组成员是未知的,该数据也携带关于组参数的重要信息。

强化学习

方法的目的是利用从与环境的相互作用中收集的观察结果来采取行动,使回报最大化或风险最小化。强化学习算法(称为代理)以迭代的方式不断地从环境中学习。在这个过程中,代理从它的环境经验中学习,直到它探索所有可能的状态。

R 强化学习是机器学习的一种,因此也是人工智能的一个分支。它允许机器和软件代理自动确定特定上下文中的理想行为,以最大化其性能。需要简单的奖励反馈让代理学习它的行为;这就是所谓的强化信号。

这里有许多不同的算法来解决这个问题。事实上,强化学习是由特定类型的问题定义的,其所有解决方案都被归类为强化学习算法。在这个问题中,一个代理应该根据他当前的状态来决定最佳的行动。当这个步骤被重复时,这个问题被称为马尔可夫决策过程

为了产生智能程序(也称为代理),强化学习经历以下步骤:

  1. 代理观察输入状态。
  2. 决策功能用于使代理执行一个动作。
  3. 行动完成后,行动者从环境中获得奖励或强化。
  4. 存储关于奖励的状态-动作对信息。

常用算法列表

  • q 学习
  • 时差
  • 深层敌对网络

使用案例:

强化学习算法的一些应用是计算机玩的棋盘游戏(象棋、围棋)、机器人手和无人驾驶汽车。

最终注释

有可能使用不同的标准来分类机器学习算法的类型,但我认为使用学习任务是很好的,以可视化 ML 的大画面,我相信根据你的问题和你手中的数据,你可以很容易地决定你将使用监督,无监督或强化学习。在接下来的文章中,我会给出更多关于每种机器学习算法的例子。

下面这张来自 en.proft.me 的图片或许能帮到你。

进一步阅读

让我知道你对此的想法,如果你有你想看的主题的建议,请联系我们。

最后做的事

如果你喜欢这些作品,请留下你的掌声👏推荐这篇文章,让其他人也能看到。

优步司机调度优化

原文:towardsdatascience.com/uber-driver…

这个模型实现和图形可以在我的 Github 库中找到。

此外,非常感谢我的团队成员 Deep Prasad、Emily Xu 和 Sharlene Peng 为这个项目做出的贡献。

第 1 部分:导言

优步的关键价值主张之一是为他们的司机合作伙伴提供调度灵活性。根据 Beneson Strategy Group 的一份报告,73%的司机更喜欢有一份可以让他们选择时间表的工作。司机可以利用这种灵活性,在可用时间内最大化他们的预期收入。为此,优步提供了客户需求热图,使司机能够瞄准高需求区域,提供更高的出行概率,从而获得更高的预期收入。

然而,没有现成的方法来确定从特定位置开始的行程是否值得为该行程花费时间。例如,由于交通而花费较长时间但需求较高的行程可能会导致总行程较少,价值较低。另一方面,需求较少但持续快速的旅行可能更有价值。因此,平衡某个位置的需求和从该位置出发的行程所需时间最符合驾驶员的利益。

为了解决这一缺口,我们试图使用混合整数规划(MIP)创建一个调度优化模型。

第 2 部分:数据收集

两个数据集用于确定需求行程持续时间。因为优步的需求数据不可用,所以 DC 出租车载客数据被用作需求的替代数据。持续时间由优步运动数据集确定。

DC 出租车数据-需求

数据集来自 DC 开放数据中心。它描述了以坐标表示的特定位置的单个出租车行程。从 1 月到 3 月,该数据集包含 10,843 个不同位置的总共 5,546,786 次拾取。

为了将数据离散化并缩小问题的规模,我们需要将皮卡分类到高需求区域。首先,计算每个位置的取货数量。然后,为了定义区域,我们选择了提货次数最多的前 100 个位置(见图 1–1 ),因为它们占提货总数的 30%。MATLAB 的 kmeans 函数用于将计数聚类成 5 个区域质心(见图 1–2)。基于到其他四个区域的最小欧几里德距离计算每个区域的半径。

Table 1: High-Demand Region Parameters

Figure 1–1: Taxicab Pickups in D.C.

Figure 1–2: High Demand Pickup Regions in D.C.

由于我们只比较区域内的行程,因此接货计数被过滤为只包括从五个区域之一始发且目的地与始发地在同一区域内的行程。然后对一天中的时间、一周中的日期和地区的计数进行平均和汇总。下面是一个经过清理的离散化数据集的示例。

Table 2: Sample of Demand Data (cleaned) used for Model

优步移动数据—行程持续时间

该数据集来自优步的“优步运动”倡议(见附录 A)。它描述了每个始发地-目的地区域对的平均、最小和最大行程持续时间。优步运动的区域小于之前确定的五个高需求区域。为了使这两个数据集具有可比性,对起点-目的地对进行了过滤,以仅包括完全落在五个区域之一内的区域,并且这些区域的目的地与起点在同一区域内(见图 2)。然后计算五个区域中每个区域的平均、最小和最大旅行持续时间。与需求数据类似,这些值是按一天中的时间、一周中的日期和地区聚合的。数据集的样本可以在下面找到。

Figure 2: High Demand regions over-laid over Uber Regions

Table: Sample of Trip Duration Data (cleaned) used for the model

第 3 部分:方法

使用需求和行程持续时间数据,开发了一个混合整数规划模型来为驾驶员找到最佳驾驶计划。MIP 是线性优化程序,一旦得到一个解,其中一些变量可以是整数,而另一些则不可以。

最著名的 MIP 和我们的类似:T2 背包问题。在我们的例子中,背包的容量代表了优步司机为他们的日程安排分配的“总时间”。我们希望最大化预期收入。开发了以下 MIP:

目标函数

该模型的目标函数是使司机在一周的工作时间内获得的收入最大化。这是通过最大化每个推荐区域 j 和时间段 I 的预期收入之和来实现的。预期收入项 R_{ij}的计算公式如下:

其中我们假设新出行的概率均匀分布在 0.5 和 1 之间,因为这 5 个区域是基于高需求选择的。基于这一假设,可以使用需求来分配概率(见附录 B)。

通过使用每组区域 j 和时间段 I 中可能的最小行程次数,找到了最坏情况下给定时间的行程次数。因为时间段被细分为 2 小时时间段,所以最小行程次数可以近似为:

决策变量和参数

模型中的决策变量为X_{ij},其中 I 和 j 分别表示对应的时间和区域。X_{ij}是布尔变量,其中 1 表示选择了时间 I 的区域 j。模型中使用了以下参数:

  • R_{ij} —时间 I 期间驾驶员在区域 j 可获得的预期收入
  • _{i} —布尔变量,用于指示驱动程序在块 I 期间是否可用
  • B_{j} —布尔变量,表示驱动器是否能够在区域 j 中工作
  • T_{max} —驾驶员一周可以工作的最大小时数

限制

优步因其日程安排的灵活性而具有吸引力。优步司机可以随时随地工作。为了准确地模拟灵活性,MIP 受到以下限制:

  • 约束条件 1 和 2 确保生成的最佳排班不包括驾驶员不愿意工作的区域或他们不可用的时间。
  • 在约束 1 中,A _ { i } =表示驾驶员可以在时间段 I 驾驶,否则为 0。
  • 在约束 2 中,B _ { j } =表示驾驶员愿意在区域 j 中驾驶,否则为 0。
  • 常数 Tmax 确保排班的总小时数不会超过驾驶员每周愿意工作的最大小时数。
  • 约束条件 4 确保每个时间段只推荐一个区域。
  • 约束 5 确保决策变量 X_{ij}和参数 A_{i}和 B_{j}是二进制的。

MATLAB 实现

为了实际实现该模型,在 MATLAB 中编写了一个中央程序,该程序准备 MIP 并使用 intlinprog 函数求解它。中央程序需要 6 个参数,每个参数对应于上面列出的决策变量。该问题必须为 intlinprog 公式化,它解决以下形式的问题:

代码可以在 Launch_IP.mSolve_IP.m 中找到

MATLAB:数据提取方法

首先,从Taxi Pickup DataUber Movement Data提取的两个数据集在工作日、小时和地区上被连接。数据集的每一行代表给定地区在给定工作日给定小时的交通状况。使用readtable()函数提取所需的子集数据。

MATLAB:约束

使用这些数据,通过分三步构建 A 和 b 矩阵,为 intlinprog 制定了约束条件。第一步创建维度为1 x n的向量 A1,b1,表示优步司机愿意工作的小时数。第二步构建矩阵 A2、b2,确保不会同时推荐两个区域。最后,A1 被附加到 A2,b1 被附加到 b2,以形成最终的矩阵 A 和 b。

第二个约束要求推荐的区域在驾驶员愿意前往的区域内。如果驾驶员不愿意在特定区域驾驶,则在创建约束矩阵之前,该区域的所有持续时间、交通和约束参数将被移除。因此,没有必要将区域偏好纳入约束矩阵。该模型还假设从一个区域到下一个区域的时间可以忽略不计。在时间段i期间,驾驶员可能预期在区域 B,但是对于时间段i+1,驾驶员在 12 英里之外的区域 C。在区域之间旅行的时间成本可以在未来的迭代中实现。

MATLAB:目标函数

为了表示目标函数,建立两个向量并相乘。第一个向量表示在时间 I 期间在当前区域获得客户的概率,第二个向量表示时间段i中的估计行程数。使用以下代码行找到最终的目标函数:

f = transpose(P_new_customer.*Min_Trips).*avg_revenue_trip;

其中avg_revenue_trip根据 2014 年优步研究得出的每小时收入中值和每小时出行信息,约为 12 美元。

现在,使用适当的公式,可以通过intlinprog()用构建的 A、b 和 f 向量找到最优解。上限和下限分别设置为 1 和 0。

第 4 部分:结果

该模型能够在给定一个驾驶员的指定参数的情况下生成周计划。例如:

Model Inputs — Driver’s Availability

Model Outputs — Ranked Recommendation to the Driver

为了评估模型性能,考虑了两个指标:模型性能优化。具体来说,该团队想知道当最大工作时间(Tmax)、时间段和区域的数量增加时,收入和计算时间会受到怎样的影响。

模型性能

为了确保稳定的结果,该模型对于每个实例运行 500 次,并且记录平均目标值和计算时间。为避免偏差,每个实例的时间段和区域都是随机选择的。发现计算时间随着时间段数量的增加而增加,但随着最大小时数的增加而减少(见附录 C)。

最佳性

随着可用时间段的数量在 1-42 之间变化,最佳收入在 450-545 美元/周之间变化(见图 3)。可用时间段数量的增加代表了驾驶员对我们定义的时间段的调度灵活性的增加。这种正相关关系表明,司机的时间安排越灵活,他们期望获得的收入就越多

Figure 3: Optimal Revenue/Week Increases as Driver Availability Increases

只有当包含多个区域时,可用区域数量的增加才会导致收入的增加,这表明更多的可用区域不会对收入产生重大影响(参见附录 C)。

第五部分:讨论

随着可用时间段数量的增加,收入增加有两个潜在的原因。

首先,是“偶然收入”。这意味着收入的增加是由于服务时间的多样性增加,平均而言,在更多的高收入产生时间内驾驶的结果。

或者,人们可以简单地赚更多的钱,因为他们开车更频繁了。为了确定原因,团队绘制了每周最大工作时间增加时的收入图(见图 4)。增加最大工作时间似乎显著增加了司机的收入,这表明一个人驾驶的时间段对收入的影响远不如他们驾驶的频率大。

此外,通过比较预期收益和实际收益,验证了模型的有效性。根据众包信息,一名优步司机每周工作 30 小时,每周收入约为 772 美元。根据我们的模型,最佳最坏情况下的预期收入约为 1900 美元。这明显更高,表明我们的模型是对当前驾驶员驾驶模式的显著改进。

延长

该模型的结果有直观的意义,并显示了更广泛的应用潜力。可以将该模型推广到任何城市,而不仅仅是华盛顿。该团队还希望将“竞争”组件纳入该模型。如果几个司机同时被推荐到同一个地区,竞争将会增加,每个司机得到一次旅行的可能性会降低。根据团队建立的公式,这明显降低了预期收入,并且会将最佳解决方案错误地呈现为“最佳”。一个更先进的模型将能够平衡它在给定地区和时间给出的建议数量,并“重新安排”司机,以平衡某个地区有建议的司机数量。

第六部分:结论

基于 MIP 模型的结果和解释,该团队能够宣称它在预期收入方面为优步驱动程序带来了有意义的价值。模型规定的时间段数与司机的预期收入之间存在正相关关系。为了增加他们的收入,司机应该在尽可能多的时间段可用。现在,司机通过做出数据驱动的决策,而不是使用试探法来选择“最佳”位置为客户服务,从而比其他司机更胜一筹。有了模型规定的可行和方便的时间表,司机们现在可以把他们的工作想象成一个具有竞争优势的有利可图的行业。

第 7 部分:参考

[1]优步新闻编辑室,“BSG 报告:驱动者路线图”。【在线】。可用:https://news room . Uber . com/WP-content/uploads/2015/01/BSG _ 优步 _Report.pdf 。[访问时间:2017 年 4 月 16 日]。

[2]Opendata.dc.gov,“出租车旅行”。【在线】。可用:【opendata.dc.gov/datasets?q=… 年 4 月 16 日]。

[3]Movement.uber.com,“优步运动:让我们找到更聪明的前进方式”,2017 年。【在线】。可用:【movement.uber.com/cities】T4。[… 年 4 月 16 日]。

[4] J. Hall 和 A. Krueger,“优步在美国的司机伙伴的劳动力市场分析”,2017 年。【在线】。可用:https://time dot com . files . WordPress . com/2015/01/Uber _ driver-partners _ hall _ kreuger _ 2015 . pdf。[访问时间:2017 年 4 月 16 日]。

[5]我和优步一起开车,《家——我和优步一起开车》,2017。【在线】。可用:www.idrivewithuber.com。[访问时间:2017 年 4 月 16 日]。

第八部分问答

为什么是 matlab?

更多的是个人喜好。Matlab 在解决优化问题方面非常专业(也很快),就像这种情况下的 MIP 模型,我熟悉它的语法。Python 确实有几个 MIP 的库,但是我不熟悉。项目中的数据处理和分析主要是用 Python 实现的。从技术上讲,用 Python 可以完成从处理到优化的整个循环。

如果所有的司机都遵循“最优解”,会发生什么

随着越来越多的司机采用这种“工具”,竞争优势将逐渐消失。在一个边缘案例中,如果我们达到了一个均衡,在这个均衡中,所有需求水平相同的区域的拥挤状态都是相同的,那么这个工具将变得无用。然而,这在现实中永远不会发生,至少现在是这样,所以总有一些改进的空间。

这只是概念层面。我希望看到我们能够在现实中实现这种智能和优化的资源配置。

附录

附录 A

以下是团队访问优步旅行持续时间数据时必须使用的优步移动接口。因为界面限制团队必须手动选择时间段和位置,所以团队必须缩小所选位置的范围。

附录 B

以下是在 MATLAB 中实现的公式,用于计算新行程的概率:

  • P_{min}和 P_{max}是用于计算新出行概率的均匀分布的下限和上限(在我们的例子中,为 0.5 和 1)
  • D_{min}和 D_{max}是该区域和时间段的最大和最小拾取计数。

附录 C

以下是补充图表,描述了给定变化参数的计算时间和目标函数的分析。

Increase in revenue with more regions leveling off after two regions

Increasing computation time with more time blocks

Decreasing computation time with higher T_{max}

Decreasing computation time with more regions

优步地图技术讲座

原文:towardsdatascience.com/uber-maps-t…

Pic Credit

除非你是出于某种神秘或其他原因远离科技生活的人,否则你一定非常习惯我所说的地图对话——“你能分享位置吗?”,“地图显示路上交通繁忙!”等等。数字和网络地图服务是一个随着时间和技术不断发展和完善的领域。虽然其中一个原因是技术和计算的进步,但另一个主要原因是这是一个非常具有挑战性且尚未解决的问题。这就是有趣的地方,也是这个优步地图技术演讲非常有趣的地方。

在我们今天进行的两次信息丰富的谈话之前,有一个关于优步·班加罗工程团队中从事技术工作的女性的视频,还有一个为答对的人准备的奖品。如果你想知道,不,我没有赢过!首先发言的是地图团队的产品经理 Ankit。在几个月前的一次早期演讲中,演讲者解释了用户打开优步应用程序到旅程结束之间发生的事件和操作的数量。定位骑手和驾驶员并提供准确的导航路线对于平稳的骑行非常重要。Ankit 带我们经历了每一步,从估计用户位置开始,搜索地点和地址,计算费用和预计到达时间。当用户打开应用程序时,首先需要的是他/她的位置。这涉及到许多需要考虑的特征,比如用户是在室内还是室外,用户是否在地面以上的某个建筑中,或者其他类似的场景。这是通过使用 GPS、位置预测模型和 WiFi 指纹识别来实现的。所有这些都是为了让那个小蓝点出现在优步地图的正确位置上!

为了便于搜索放置地点或地址,应该考虑许多因素。该地图可以使用用户的历史数据(如果有的话),显示具有准确位置的热门地点,显示附近的优步游乐设施的快照等。当涉及到 Uber Eats 时,还有其他不同的情况需要考虑。下一步是票价计算,必须非常准确。估计行程时间、行程距离、通行费的存在、当前用户位置周围优步乘车的供应以及当前乘车的需求都是估计费用的决定因素。如果这听起来很复杂,那么想想不同类型的乘车会有什么不同——UberGo、UberPool 和最近的 ExpressPool。虽然 UberPool 和 ExpressPool 都允许拼车,但 ExpressPool 从最近的上车点提供乘车服务,乘客可以步行到该地点。这不仅有助于骑车人到达一个可以乘坐的地方,而且也更便宜。

Pic Credit

每一步都建立在前一步的基础上,并增加了一些复杂性。ETA 预测是下一步,对于不同的乘坐模式是不同的。对于 UberGo/UberPool,只有一个司机到达骑手的预计到达时间。在快速拼车的情况下,还应考虑骑车人到达上车点所需的时间。ETA 计算几乎没有挑战。如果交通发生不可预见的变化怎么办?还是突然的路障?如果司机的网络不稳定怎么办?前两个导致 ETA 的重新计算。为了处理不稳定的网络,缓存的路径在驾驶员端被重用。因此,即使司机失去连接,也有办法让地图在没有连接的情况下工作。一旦驾驶开始,后台会不断优化路线,帮助驾驶员选择最佳路线到达目的地。骑手和所选路线的历史路线记录都用于此目的。在结束演讲之前,Ankit 透露了优步的多式联运计划,该计划适应使用不同模式的乘坐,不仅包括四轮车,还包括自行车、滑板车等。(以防你不知道,优步正在投资滑板车租赁初创公司 Lime,这家公司也有谷歌的支持)

"在座有多少人研究过地图?"Gaurang Khetan 开始讲话时问道。很少有人举手。因此,如果你想做一些有挑战性的、有趣的、对流行产品有直接影响的事情,那么地图就是你的了。是什么使它成为如此困难和具有挑战性的问题?地图和收集的数据一样好,好的数据很难得到。有不同的来源可以获取开发地图所需的数据,其中包括多家供应商。随着物理世界的不断变化,地图需要不断更新和改进。世界上不同的国家有不同的分配地址的惯例和结构。此外,很难衡量地图和路线的正确性。跟随数字地图时迷路并不罕见。除了所有这些原因,用于最佳路线和基于地理的搜索的算法需要非常快速、高效和可扩展。

地图数据来自不同的图层、不同的来源,包括多种类型,如道路网络、商业地点、地址、物理空间(如商场和建筑)以及自然特征(如湖泊)。数据量不仅巨大,而且非常多样化。这使得使用地图进行全球展示成为一个永无止境的过程。另一个问题是,“我们如何为一个没有地图数据的国家或地方建立地图数据?”你应该花几分钟思考一下,然后自己回答。邮政数据、政府数据、GPS 跟踪、多个供应商、手动驾驶和路线、卫星视图、众包等是收集/创建地图数据的一些方式。多少数据才够?随着城市化的发展和技术的扩展,城市的位置必须被很好地绘制,路线必须被完全理解,对吗?虽然这在某种程度上可能是真的,但有一个问题是城市地区特有的——城市峡谷。

Pic Credit

在市区或高楼林立的地方,卫星信号在直接到达 GPS 接收器之前可能会受到阻碍。如果有高层建筑在卫星的视线范围内,就会发生这种情况。简而言之,GPS 使用许多围绕地球轨道运行的卫星(30 颗或更多),并传输 GPS 接收器用于位置识别的信号。这些信号会被传播路径上的建筑物阻挡或反射。当这种情况发生时,会导致位置信息出错。这种误差从几米到 50 米或更大不等。上面的图像就是这样一个例子。

Pic Credit

为了克服这个问题,优步地图使用信噪比(SNR)。如果卫星的 SNR 值较低,这意味着没有到相应卫星的直接视线,并且位置信息会有一些误差。当它很高时,必须有一个清晰的卫星视线,因此位置信息将是准确的。在上图中,我们可以看到左侧的点在卫星 C 和 D 的视线范围内,但不在卫星 B 的视线范围内。同样,右侧的点在卫星 B 和 C 的直接视线范围内,但不在卫星 D 的视线范围内。此信息非常有用,同样可用于确定该位置位于道路的左侧还是右侧。

很明显,在地图方面,有太多的东西需要了解、学习、尝试和改进,而这正是优步正在做的事情。它不仅仅使用谷歌地图和 GPS 提供的原始信息。地图是优步大学的一个活跃的研究领域,他们正在不断完善它。作为一个例子来了解优步如何使位置信息更好,见下面的原始 GPS 提供的位置信息(红色的)和优步的改进 GPS(蓝色)的比较。虽然改进后的 GPS 提供了更好的导航,但原始的 GPS 却无处不在。

这是我今年参加的第三次优步科技讲座,这些讲座非常有趣。虽然众所周知,地图和图表不容易解决问题,而且还在不断改进,但了解这么多关于一个非常依赖这些领域的公司目前如何在这些领域工作和研究的信息真的很好。会谈结束后,我们还愉快地进行了交流。演讲者和其他几个目前在优步工作的人加入了我们,帮助我们解答问题和疑惑。感谢优步组织了这次技术讲座。

顺便说一句,他们的办公室很酷!!

这是我写的关于我参加的第一次优步科技演讲的博客的链接

如果你喜欢到目前为止在这篇文章中读到的内容,并且想了解优步发生的一切,我推荐你查看这个来自优步的博客,并且在 Twitter 上关注 @ubereng ,他们在 Twitter 上发布了关于他们最近的研究工作和开源工具的消息。

感谢阅读!!!

连接:LinkedInTwitter和我的 博客