TowardsDataScience 博客中文翻译 2020(七百零一)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

Python 中的池限制队列处理

原文:https://towardsdatascience.com/pool-limited-queue-processing-in-python-2d02555b57dc?source=collection_archive---------6-----------------------

如何使用预定义数量的线程并行处理数据

我最近遇到了一个问题:我需要构建大量(大约 100 个)Docker 容器,然后将它们推送到注册中心。Docker SDK for Python 提供了一个很好的处理方法,再加上“多重处理”库,可以非常有效地并行处理任务。然而,经过一些初步测试后,我发现将多个图像推送到注册表可能由于同时上传的过载而停止。在我的测试中,我只能同时运行 2-3 个docker push命令,直到我添加的所有新命令都停止。在这一点上,我决定将同步上传限制在少量的并行线程上,同时仍然利用大量的线程来促进映像构建。将工作从构建线程传递到推进线程的队列(multiprocessing.Queue)和线程池(multiprocessing.Pool)的组合看起来是一个最佳选择。然而,文档中有一些细微差别和空白,这让我花了一些时间去理解(尤其是在 Windows 上使用multiprocessing的时候)。下面,我提供了一个关于如何使用这些数据结构和对象的小教程。

问题公式化

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

算法设计

在这个玩具问题中,我们有大量并行进程将结果写入队列。除了它们之外,还有一个单线程读取器进程检查队列中的新项目,并将它们分配给池中的新进程,这样,只有一小部分固定数量的进程同时运行。让我们看一下下面的所有元素。

Process

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

弗兰克·麦肯纳在 Unsplash 上拍摄的照片

对于左侧的大量并行线程,我们将使用multithreading.Process()。来自官方参考:

Process对象表示在独立进程中运行的活动。

启动一个进程需要两件事:调用目标函数**Process** 调用本身。让我们来看看:

from multiprocessing import Processdef proc(i):
    print(f'I am Process {i}')if __name__ ==  '__main__':
    for i in range(10):
        Process(target=proc, args=(i,)).start()

在上面的例子中,我们创建了 10 个Process es 并同时启动它们。每个进程都运行一个proc()函数的实例,其参数来自arg。因为执行的顺序没有得到保证,所以当我们运行它时,我们会得到类似这样的结果:

I am Process 6
I am Process 2
I am Process 0
I am Process 3
I am Process 7
I am Process 4
I am Process 8
I am Process 1
I am Process 5
I am Process 9

还要注意args=(i,)有趣的语法。Process要求args是可迭代的,所以把它改成args=(i)或者args=i就会产生一个TypeError

长队

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

照片由哈尔·盖特伍德Unsplash 上拍摄

现在,是时候介绍一个multithreading.Queue()了。根据参考:

Queue()返回一个使用管道和一些锁/信号量实现的进程共享队列。

队列允许我们将对象放入队列,并在别处异步处理它们。重要的是,队列是线程和进程安全的。让我们修改前面的例子,添加Queue对象,并将其传递给我们的并行Process es:

from multiprocessing import Process, Queuedef writer(i,q):
    message = f'I am Process {i}'
    q.put(message)if __name__ ==  '__main__':
    # Create multiprocessing queue
    q = Queue()

    # Create a group of parallel writers and start them
    for i in range(10):
        Process(target=writer, args=(i,q,)).start() # Read the queue sequentially
    for i in range(10):
        message = q.get()
        print(message)

记住Queue.get()是一个阻塞方法,所以我们不会错过队列中的任何消息。

解决我们问题的下一步是切换到从队列中并行读取。我们可以像产生写进程一样产生读进程,但是这将允许 10 个线程并行运行。如果像原问题描述中那样受限于较小的读者数量,该怎么办?

泳池

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

李中清Unsplash 上的照片

输入[multithreading.Pool()](https://docs.python.org/3.7/library/multiprocessing.html#multiprocessing.pool.Pool):

"一个进程池对象,它控制一个可以提交作业的工作进程池。它支持带有超时和回调的异步结果,并具有并行映射实现”。

使用Pool,我们可以分配尽可能多的并行进程,但是在任何给定的时刻,只有“进程”数量的线程是活动的。

让我们看看,如果我们把所有的读者都扔到“池子”里,情况会怎样:

from multiprocessing import Process, Queue, Pooldef writer(i,q):
    message = f’I am Process {i}’
    q.put(message)def reader(i,q):
    message = q.get()
    print(message)if __name__ == ‘__main__’:
    # Create multiprocessing queue
    q = Queue() # Create a group of parallel writers and start them
    for i in range(10):
        Process(target=writer, args=(i,q,)).start() # Create multiprocessing pool
    p = Pool(10) # Create a group of parallel readers and start them
    # Number of readers is matching the number of writers
    # However, the number of simultaneously running
    # readers is constrained to the pool size

    for i in range(10):
        p.apply_async(reader, (i,q,))

然而,如果我们运行上面的代码,我们将不会得到任何输出。发生了什么事?当我们调用apply_async时,代码执行立即继续,因为主函数中没有留下任何东西,所以退出。谢天谢地,multiprocessing提供了一种等待执行结果的参考方式:

from multiprocessing import Process, Queue, Pooldef writer(i,q):
    message = f’I am Process {i}’
    q.put(message)def reader(i,q):
    message = q.get()
    print(message)if __name__ == ‘__main__’:
    # Create multiprocessing queue
    q = Queue() # Create a group of parallel writers and start them
    for i in range(10):
        Process(target=writer, args=(i,q,)).start() # Create multiprocessing pool
    p = Pool(10) # Create a group of parallel readers and start them
    # Number of readers is matching the number of writers
    # However, the number of simultaneously running
    # readers is constrained to the pool size readers = []
    for i in range(10):
        readers.append(p.apply_async(reader, (i,q,))) # Wait for the asynchrounous reader threads to finish
    [r.get() for r in readers]

这一次,如果我们运行代码,我们将得到下面的错误:RuntimeError: Queue objects should only be shared between processes through inheritancemultiprocessing.Manager将使我们能够管理队列,并使不同的工作人员也可以访问它:

from multiprocessing import Process, Queue, Pool, Managerdef writer(i,q):
    message = f’I am Process {i}’
    q.put(message)def reader(i,q):
    message = q.get()
    print(message)if __name__ == ‘__main__’:
    # Create manager
    m = Manager() # Create multiprocessing queue
    q = m.Queue() # Create a group of parallel writers and start them
    for i in range(10):
        Process(target=writer, args=(i,q,)).start() # Create multiprocessing pool
    p = Pool(10) # Create a group of parallel readers and start them
    # Number of readers is matching the number of writers
    # However, the number of simultaneously running
    # readers is constrained to the pool size readers = []
    for i in range(10):
        readers.append(p.apply_async(reader, (i,q,))) # Wait for the asynchrounous reader threads to finish
    [r.get() for r in readers]

最后,我们能够得到我们期望的结果:

> python pl.pyI am Process 1
I am Process 4
I am Process 9
I am Process 8
I am Process 0
I am Process 5
I am Process 7
I am Process 2
I am Process 6
I am Process 3

与 Windows 相关的怪癖

我最初在基于 Linux 的机器上着手解决这个问题,但后来在 Windows 上继续。不幸的是,许多事情并没有立即见效。以下是你需要知道的事情:

1.对于上面的代码,中断程序执行(Ctrl+C)不会立即生效。解决方法是添加初始化器工人:

def init_worker():
    """
    Pool worker initializer for keyboard interrupt on Windows
    """ signal.signal(signal.SIGINT, signal.SIG_IGN)p = Pool(num_readers, init_worker)

2.我无法在 Windows 上运行 Jupyter 笔记本中的代码,除非我将工人函数移动到单独的.py文件中,并将它们导入我的笔记本。与此相关,如果不将主代码打包到if __name__ == ‘main':中,您将无法运行上面的脚本。

决赛成绩

作为收尾工作,让我们添加以下内容:
延迟以模拟读取器和写入器上 CPU 受限的工作
等待读取线程完成时的异常处理
可配置的写入器和读取线程数量
一些函数文档

以下是最终结果:

from multiprocessing import Pool, Queue, Process, Manager
import random
import signal
import timenum_writers = 10
num_readers = 3def writer(i,q):
    # Imitate CPU-bound work happening in writer
    delay = random.randint(1,10)
    time.sleep(delay)

    # Put the result into the queue
    t = time.time()
    print(f’I am writer {i}: {t}’)
    q.put(t)def init_worker():
    """
    Pool worker initializer for keyboard interrupt on Windows
    """
    signal.signal(signal.SIGINT, signal.SIG_IGN)def reader(i, q):
    """
    Queue reader worker
    """

    # Read the top message from the queue
    message = q.get()

    # Imitate CPU-bound work happening in reader
    time.sleep(3)
    print(f’I am reader {i}: {message}’)if __name__ == ‘__main__’:
    # Create manager
    m = Manager()

    # Create multiprocessing queue
    q = m.Queue() # Create a group of parallel writers and start them
    for i in range(num_writers):
        Process(target=writer, args=(i,q,)).start()

    # Create multiprocessing pool
    p = Pool(num_readers, init_worker) # Create a group of parallel readers and start them
    # Number of readers is matching the number of writers
    # However, the number of simultaneously running
    # readers is constrained to the pool size
    readers = []
    for i in range(10):
        readers.append(p.apply_async(reader, (i,q,)))

    # Wait for the asynchrounous reader threads to finish
    try:
        [r.get() for r in readers]
    except:
        print(‘Interrupted’)
        p.terminate()
        p.join()

如果您运行它,您将得到类似如下的结果:


python final.pyI am writer 8: 1580659076.783544
I am writer 3: 1580659076.783544
I am reader 0: 1580659076.783544
I am reader 1: 1580659076.783544
I am writer 7: 1580659079.7990372
I am writer 2: 1580659080.7971141
I am writer 1: 1580659081.785277
I am writer 4: 1580659082.7955923
I am reader 2: 1580659079.7990372
I am reader 3: 1580659080.7971141
I am writer 6: 1580659083.800029
I am writer 0: 1580659084.7862694
I am reader 4: 1580659081.785277
I am writer 9: 1580659085.7819643
I am writer 5: 1580659085.7919443
I am reader 5: 1580659082.7955923
I am reader 6: 1580659083.800029
I am reader 7: 1580659084.7862694
I am reader 8: 1580659085.7819643
I am reader 9: 1580659085.7919443


这篇文章最初发表在[我的博客](https://taletskiy.com/posts/python-pool-limited-queue-processing/)上。

# 爆米花数据——分析电影院座位模式(上)

> 原文:<https://towardsdatascience.com/popcorn-data-analysing-cinema-seating-patterns-part-1-a0b2a5c2c19a?source=collection_archive---------44----------------------->

## 数据分析能揭示你的观影习惯的哪些方面?

诺埃尔·马修·艾萨克和[万什卡·阿格拉瓦尔](https://medium.com/u/19e9504cf53f?source=post_page-----a0b2a5c2c19a--------------------------------)

*在* [*第二部分*](https://medium.com/popcorndata/popcorn-data-analysing-cinema-seating-patterns-part-ii-987fbde9d363) *中,我们分析数据,将其可视化,然后为我们的发现建立一个网站。*

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/3b21e9ec72d5273e17e5813a7832ac28.png)

*作者图片*

# 第一部分——获取分析数据

## 发现你最喜欢的剧院座位已经被预订时,你有没有感到极度失望?

## 你最喜欢的座位到底有多受欢迎?

我们想更多地了解新加坡的电影趋势——人们喜欢从哪个座位观看不同的电影。所以我们创建了[PopcornData](https://popcorn-data.herokuapp.com/)——一个通过搜集数据、发现有趣的见解并将其可视化来一窥新加坡电影趋势的网站。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/127801a2cb52d0d61fdab0c9aaa01978.png)

照片由 [Krists Luhaers](https://unsplash.com/@kristsll?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 拍摄

在网站上,你可以看到人们如何在不同的大厅、剧院和时间观看不同的电影!一些独特的方面包括**热图**显示**最受欢迎的座位**和**动画**显示购买座位的顺序**。这两篇文章详细阐述了我们是如何获得网站数据的,以及我们对数据的分析。**

# **抓取数据**

**为了实现我们的想法,第一步,也许是最关键的一步是收集数据。我们决定删除新加坡最大的连锁影院之一**邵氏影院**的网站。**

**从 python 中抓取的基础知识开始,我们最初尝试使用 python 的 **requests** 库来获取网站的 HTML,并使用 **BeautifulSoup** 库来解析它,但很快意识到我们需要的数据在我们请求的 HTML 中并不存在。这是因为网站是动态的— ***它使用 Javascript 从外部来源请求数据,并动态呈现 HTML***。当我们直接请求 HTML 时,网站的动态部分没有被呈现,因此丢失了数据。**

**为了解决这个问题,我们使用了**Selenium**——一种 web 浏览器自动化工具,它可以在获取 HTML 之前首先呈现网站的动态内容。**

## **硒的问题**

**让 selenium 驱动程序工作并解决一些小问题是一个很大的学习过程。在无数次 StackOverflow 搜索和多次“放弃”后,我们设法勉强通过(双关语)并让它工作。**

**我们面临的主要问题是:**

1.  **滚动到屏幕的特定部分单击按钮,以便在 HTML 中找到数据。**
2.  **弄清楚如何在云上运行 headless Selenium。**
3.  **在 Heroku 上部署脚本后,当脚本在本地机器上正常运行时,一些数据没有被擦除。绞尽脑汁之后,我们发现 Selenium 加载的一些页面默认为移动版本的页面。我们通过明确提到屏幕尺寸来解决这个问题。**

*****有了 Selenium 和 BeautifulSoup,我们终于能够获得某一天所有可用电影会话的数据了!*****

## **电影会话数据示例:**

{
“theatre”:“Nex”,
“hall”:“nex Hall 5”,
“movie”:“Jumanji: The Next Level”,
“date”:“18 Jan 2020”,
“time”:“1:00 PM+”,
“session_code”:“P00000000000000000200104”
}


**我们已经成功了一半!现在,我们需要收集每个电影时段的座位数据,以查看哪些座位被占用以及何时被购买。在开发者工具中浏览了网站的网络选项卡后,我们发现 Shaw 的 API 正在请求座位数据。**

**可以通过请求 URL*https://www.shaw.sg/api/SeatingStatuses?recordcode=<session _ code>*来获得数据,其中 session code 是我们之前已经搜集的每个电影会话的唯一代码。**

**我们得到的数据是 JSON 格式的,我们对其进行解析,并按照座位购买时间的升序对座位进行重新排序,以获得一个 JSON 对象数组,其中每个对象都包含关于电影厅中每个座位的信息,包括 seat_number、seat_buy_time 和 seat_status。**

## **样本座位数据:**

[
{
“seat_status”:“AV”,
“last_update_time”:“2020-01-20 14:34:53.704117”,
“seat_buy_time”:“1900-01-01T00:00:00”,
“seat_number”:“I15”,
“seat_sold_by”:“”
},
…,
{
“seat_status”:“SO”,
“last_update_time”:“2020-01-20 14:34:53.705116”,
“seat_buy_time”:“2020-01-18T13:12:34.193”,
“seat_number”:“F6”,
“seat_sold_by”:“”
}
]


*   ****座位号**:大厅座位的唯一标识符**
*   ****seat_status** :表示有座位可用(**SO**-座位已被占用,**AV**-可用)**
*   ****seat_buy_time** :客户购买座位的时间**
*   ****last_update_time:** 座位数据最后被删除的时间**

**大厅有 28 到 502 个座位,每个座位对应于数组中的一个 JSON 对象。此外,一天之内有超过 350 个电影时段,产生的数据量相当大。存储一天的数据大约需要 10MB。电影会话数据与座位数据相结合,并存储在 MongoDB 数据库中。**

****我们设法从肖那里收集了 2020 年 1 月的所有电影数据。****

## **数据库中的单个文档**

{
“theatre”:“Nex”,
“hall”:“nex Hall 5”,
“movie”:“Jumanji: The Next Level”,
“date”:“18 Jan 2020”,
“time”:“1:00 PM+”,
“session_code”:“P00000000000000000200104”
“seats”:[
{
“seat_status”:“AV”,
“last_update_time”:“2020-01-20 14:34:53.704117”,
“seat_buy_time”:“1900-01-01T00:00:00”,
“seat_number”:“I15”,
“seat_sold_by”:“”
},
…,
{
“seat_status”:“SO”,
“last_update_time”:“2020-01-20 14:34:53.705116”,
“seat_buy_time”:“2020-01-18T13:12:34.193”,
“seat_number”:“F6”,
“seat_sold_by”:“”
}
]
}


**要查看完整文档,请点击此链接:[https://gist . github . com/noelmathewisac/31 a9d 20 a 674 f 6 DD 8524 ed 89d 65183279](https://gist.github.com/noelmathewisaac/31a9d20a674f6dd8524ed89d65183279)**

**收集的完整原始数据可在此下载:**

 **[## 原始电影数据. zip

drive.google.com](https://drive.google.com/file/d/1K7Vv88SnmWarf6rOre2ijA-Qq7Dv2sNp/view?usp=sharing)** 

# **是时候把手弄脏了**

**![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/65aff36a08d34d911e01389ba5d399f4.png)**

**由[马库斯·斯皮斯克](https://unsplash.com/@markusspiske?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄**

***现在是通过**清理数据**并提取相关信息来弄脏*我们的手的时候了。使用 pandas,我们解析了 JSON,清理了它,并用数据制作了一个 DataFrame,以提高可读性并方便过滤。**

**由于座位数据占用了大量内存,我们无法将所有数据包含在数据帧中。相反,我们使用 python 聚合座位数据,以获得以下内容:**

1.  ****总座位数** : 电影时段的总座位数**
2.  ****售出座位数**:一场电影的售出座位数**
3.  ****座位购买顺序**:显示座位购买顺序的二维数组**

[[‘A_10’, ‘A_11’], [‘A_12’], [‘B_4’, ‘B_7’, ‘B_6’, ‘B_5’], [‘C_8’, ‘C_10’, ‘C_9’], [‘B_1’, ‘B_2’], [‘C_6’, ‘C_7’], [‘C_5’, ‘C_4’], [‘B_8’, ‘B_10’, ‘B_9’], [‘D_8’], [‘A_15’, ‘A_14’, ‘A_13’]]


**数组中的每个元素代表同时购买的座位,元素的顺序代表座位购买的顺序。**

**4.**座位分布**:显示一起购买的座位数量的字典(1、2、3 或更多组)**

{
‘Groups of 1’: 8,
‘Groups of 2’: 30,
‘Groups of 3’: 9,
‘Groups of 4’: 3,
‘Groups of 5’: 1
}


**5.座位频率:显示大厅中每个座位在一个月内被购买的次数的字典**

{‘E_7’: 4, ‘E_6’: 5, ‘E_4’: 11, ‘E_5’: 9, ‘E_2’: 2, ‘E_1’: 2, ‘E_3’: 7, ‘D_7’: 15, ‘D_6’: 17, ‘C_1’: 33, ‘D_2’: 15, ‘D_1’: 14, ‘B_H2’: 0, ‘B_H1’: 0, ‘D_4’: 45, ‘D_5’: 36, ‘D_3’: 32, ‘C_3’: 95, ‘C_4’: 94, ‘A_2’: 70, ‘A_1’: 70, ‘B_2’: 50, ‘B_1’: 47, ‘C_2’: 37, ‘C_6’: 53, ‘C_5’: 61, ‘B_4’: 35, ‘B_3’: 40}


**6.**购买率** : 两个字典,第一个字典显示电影放映的剩余时间(以天为单位),第二个字典显示相应的累积购票数。**

{“1917”: [4.1084606481481485…, 2.566423611111111, 2.245578703703704, 2.0319560185185184, 1.9269907407407407, 1.8979513888888888…],
…}
{“1917”: [1, 3, 8, 10, 11, …],
…}


**可以在此处查看清理的数据:**

**[](https://docs.google.com/spreadsheets/d/1pLNbwfnrmfpyA7sxtRyB1P6iHuSFyUPEerwW7f3fEWU/edit?usp=sharing) [## 清理的电影数据

docs.google.com](https://docs.google.com/spreadsheets/d/1pLNbwfnrmfpyA7sxtRyB1P6iHuSFyUPEerwW7f3fEWU/edit?usp=sharing)** 

# **最后,我们完成了!(完成 20%的工作)**

**我们的数据被收集和清理后,我们现在可以进入有趣的部分了— *分析数据*在爆米花垃圾中寻找模式。**

**要找到我们对数据的分析和我们发现的有趣模式,请查看本文的第二部分:**

**[](https://medium.com/popcorndata/popcorn-data-analysing-cinema-seating-patterns-part-ii-987fbde9d363) [## 爆米花数据——分析电影院座位模式(下)

### 数据分析能揭示你的观影习惯的哪些方面?

medium.com](https://medium.com/popcorndata/popcorn-data-analysing-cinema-seating-patterns-part-ii-987fbde9d363)** 

**刮刀的代码可以在下面的 GitHub repo 中找到:**

**[](https://github.com/PopcornData/shaw-scraper) [## PopcornData/肖氏刮刀

### 在 GitHub 上创建一个帐户,为 PopcornData/shaw-scraper 的开发做出贡献。

github.com](https://github.com/PopcornData/shaw-scraper) 

**别忘了查看我们的网站:http://popcorn-data.herokuapp.com**[](http://popcorn-data.herokuapp.com/)****!******

# Windows 上的 Poppler

> 原文:<https://towardsdatascience.com/poppler-on-windows-179af0e50150?source=collection_archive---------7----------------------->

## Python、pdf 和 Window 的 Linux 子系统

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/958ae7c818b09b1b5e0e1825780f8f7d.png)

Windows 上的 Poppler

# 简介:

[可移植文档格式(pdf)](https://en.wikipedia.org/wiki/PDF)无处不在,导入一个流行的 python 包,如 [PDF2Image](https://pypi.org/project/pdf2image/) 、[pdf text](https://pypi.org/project/pdftotext/)或 [PopplerQt5](https://pypi.org/project/python-poppler-qt5/) 是处理它们的常用方法。不幸的是,除非您使用的是 Linux 机器,否则许多用户都报告说这些包返回了错误,因为它们依赖于 Poppler。

没听说过[波普勒](https://en.wikipedia.org/wiki/Poppler_(software))?

Poppler 是一个用于渲染 pdf 的工具,在 Linux 系统中很常见,但在 Windows 中并不常见。因此,自然地,如果您想使用 Poppler 及其相关的包,我们需要弥补这个差距。

让我们访问谷歌,看看我们有什么选择…

在谷歌上快速搜索一下,就会发现还有很多人有这个问题,他们仍在寻找解决方案。

*   [PDF 到 JPG(波普勒)](https://stackoverflow.com/questions/46184239/extract-a-page-from-a-pdf-as-a-jpeg)
*   [在 Windows 上安装 Poppler?](https://stackoverflow.com/questions/18381713/how-to-install-poppler-on-windows)
*   [无法在 Windows (Poppler)上安装“PDFtoText”](https://stackoverflow.com/questions/52336495/cannot-install-pdftotext-on-windows-because-of-poppler)
*   [在 Windows 上运行 PyPDFOCR 需要 Poppler?](https://stackoverflow.com/questions/31817070/running-pypdfocr-on-windows-via-python-requiring-poppler)
*   [ModuleNotFoundError —没有名为‘SipDistUtils’(Poppler)的模块](https://stackoverflow.com/questions/51420803/modulenotfounderror-no-module-named-sipdistutils-while-install-python-poppler)

# 问题是:

Poppler 和 Python 的 PDF 库利用了 Linux 实用程序,但不能很好地与 Windows 兼容。

当我们寻找解决方案时,许多方案已经过时、无效、太难了,等等…

# **解决方案:**

在提出的解决方案中,有一个解决方案似乎效果不错。

**Windows Linux 子系统(WSL)。**

实际上,由于 Linux 的 Windows 子系统是如此强大,它对于需要在 Windows 机器上使用 Linux 工具的其他问题是一个很好的解决方案。

# **那么,WSL 是什么?**

Windows Subsystem for Linux 是 Windows 10 上的 Linux 二进制可执行文件的兼容层。它最近进入了版本二(WSL 2)并引入了真正的 Linux 内核。简单地说,WSL 让你感觉像是在一台真正的 Linux 机器上工作(你确实是)。

# **安装和使用指南— WSL**

[**参考**](https://docs.microsoft.com/en-us/windows/wsl/install-win10)

在本节中,我们将通过五个简短的步骤来安装和设置 WSL。之后,我们将通过几个简单的步骤来安装和设置 Poppler。

## **第一步:**

以管理员身份运行 Window 的 Powershell。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/06d3636fdfd1131edc97d64e7dc13897.png)

## **第二步:**

通过执行“Enable-WindowsOptionalFeature”命令启用 WSL:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/48408833d408362b69184e62e612cbd9.png)

启用 WSL

## **第三步:**

通过重新启动计算机来激活更改。

注意,微软说,“为了确保 WSL 能够启动一个可信的执行环境,这个重启是必需的”

## **第四步:**

现在,您从重启中回来了,您的系统的 WSL 已经启用,并且您已经准备好安装 Linux 发行版了。

去橱窗商店搜索 WSL。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/c99c502c38ee323634fe4d7c4ff1f38b.png)

从 Windows 应用商店获取 WSL

## **第五步(最终):**

点击 Ubuntu,选择安装。注意,我的已经安装了,所以你必须在这里做一些想象。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/d9a93a7e7433d08c4e8ff840bfdebda8.png)

安装 Ubuntu

# **安装和使用指南— Poppler:**

## 第一步:

在 VS 代码中,通过类似这样的终端输入 WSL。注意,一旦输入 WSL,终端提示符将会改变。您现在正在 Linux 机器中操作!激动人心!

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/114749c95088c2eecfe4e789e726effb.png)

输入 WSL

## **第二步:**

在 WSL-prompt 中执行以下命令。请注意,您可以忽略一些处理 Tesseract-OCR 和 PyTesseract 的步骤。这些是我在文章结尾分享的演示项目。

## **步骤 3——测试(最终):**

使用新获得的现成 Poppler 实用程序运行程序。

我已经创建了这个**演示脚本**,所以如果你没有自己的也可以用。虽然你需要一个 PDF 文件来处理。

这段代码的工作原理是将 PDF 转换成 JPG。然后,它进行 OCR,并将 OCR 结果写入输出文件。

# **结论:**

就是这样。你通过了 Windows 上的 Poppler 认证。

享受战利品吧!你已经获得了一些全新而强大的技能。你正在成为一个更灵活的开发人员(如果你还没有的话)。

**新获得的技能:**

*   用 Python 成功操作 pdf 的能力。
*   访问 PDF2Image、PDFToText 或其他 Poppler-utils。
*   Linux 的 Windows 子系统。**非常强大的开发工具**

# 现在,你能建造什么?

尝试这些新技能并巩固你的理解是非常重要的。真正的理解来自经验。

## 我的 Poppler-On-Windows 项目:

我构建了一个 OCR 应用程序来帮助记录退休教授和著名计算机科学家【Kenneth E. Batcher 博士的历史工作。它使用一个 PDF 到图像的 JPEG 转换工具。然后,它对图像进行 OCR,并将结果写入输出文件。由于这种概念证明工作得足够好,它最终将被用于文档扫描,而不是 pdf。

你可以在这里找到[的项目。](https://github.com/matmill5/KenBatcherPP-OCR)

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/a2858d417db08958518a0bc63383a364.png)

OCR 应用程序—开发中

# 流行的 NumPy 函数以及在哪里可以找到它们

> 原文:<https://towardsdatascience.com/popular-numpy-function-and-where-to-find-them-6d170b7e6ba1?source=collection_archive---------31----------------------->

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/420e13ab84f5d73263ac8147f482b8ed.png)

最流行的 NumPy 函数(图片由作者提供)

探索,还是剥削?

如果有用,那就足够了。如果你能把事情做好,为什么要寻找其他方法来解决同样的问题呢?这是看待事物的一种方式。反对这种做法的理由是,这样你会错过更有效、更易读的选择。

即使在与 NumPy、Pandas 和其他相关库一起工作了近三年之后,我仍然经常找到解决问题的替代方法,至少可以说,这些方法大大减少了运行时间或者可读性更好。

那么,在开始工作之前,我们应该努力探索其他功能吗?绝对不行!浏览整个文档会花很多时间。

那我们该怎么办?

我决定看看最常用的函数,看看我是否知道它们。假设是**最有用的功能可能会被大多数人使用**。

让我们来了解一下这些功能是什么!我们将分三步走。

1.  使用 Github 搜索 API 来查找使用 NumPy 的存储库
2.  从这些存储库中,下载相关的文件
3.  浏览代码库,找到最常用的函数

## 使用 Github 搜索 API 来查找使用 NumPy 的存储库

要使用 Github API,首先需要创建一个 [API 令牌](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token)。我们将把这个令牌放入请求的头部。

I put the API token in a txt file, which I read in the next line

with open(‘…/…/api_keys/github.txt’, “r”) as f:
API_KEY = f.read()

headers = {‘Authorization’: ‘token %s’ % API_KEY}


现在我们来声明一些变量。

We will look for python codebases that use the NumPy library

LIBRARY = ‘numpy’
LANGUAGE = ‘python’# This is how the basic search URL looks like. We need to append the page number with it in order to get the paginated search results
URL = 'https://api.github.com/search/repositories?q=%s+language:%s&sort=stars&order=desc&page=’ % (LIBRARY, LANGUAGE)


现在,我们将使用请求库发送一个 GET 请求,然后检查响应。

r = requests.get(URL + ‘1’, headers=headers)
json_response = r.json()print(json_response.keys())
print(‘Total Repositories:’, json_response[‘total_count’])
print(‘Total number of items in a page:’, len(json_response[‘items’]))print(‘Keys in a item:’, json_response[‘items’][0].keys())


输出:

dict_keys([‘total_count’, ‘incomplete_results’, ‘items’])
Total Repositories: 10853
Total number of items in a page: 30
Keys in a item: dict_keys([‘id’, ‘node_id’, ‘name’, ‘full_name’, ‘private’, ‘owner’, ‘html_url’, ‘description’, ‘fork’, ‘url’, ‘forks_url’, ‘keys_url’, ‘collaborators_url’, ‘teams_url’, ‘hooks_url’, ‘issue_events_url’, ‘events_url’, ‘assignees_url’, ‘branches_url’, ‘tags_url’, ‘blobs_url’, ‘git_tags_url’, ‘git_refs_url’, ‘trees_url’, ‘statuses_url’, ‘languages_url’, ‘stargazers_url’, ‘contributors_url’, ‘subscribers_url’, ‘subscription_url’, ‘commits_url’, ‘git_commits_url’, ‘comments_url’, ‘issue_comment_url’, ‘contents_url’, ‘compare_url’, ‘merges_url’, ‘archive_url’, ‘downloads_url’, ‘issues_url’, ‘pulls_url’, ‘milestones_url’, ‘notifications_url’, ‘labels_url’, ‘releases_url’, ‘deployments_url’, ‘created_at’, ‘updated_at’, ‘pushed_at’, ‘git_url’, ‘ssh_url’, ‘clone_url’, ‘svn_url’, ‘homepage’, ‘size’, ‘stargazers_count’, ‘watchers_count’, ‘language’, ‘has_issues’, ‘has_projects’, ‘has_downloads’, ‘has_wiki’, ‘has_pages’, ‘forks_count’, ‘mirror_url’, ‘archived’, ‘disabled’, ‘open_issues_count’, ‘license’, ‘forks’, ‘open_issues’, ‘watchers’, ‘default_branch’, ‘permissions’, ‘score’])


我们看到响应是一个包含三个键的字典:total_count、incomplete_results 和 items。

我们观察到有 10853 个存储库匹配我们的查询。但是我们不会深入研究这么多的存储库!假设我们将只研究 N 个最流行的。怎样才能找到最受欢迎的?嗯,我们已经在我们的 **URL** 中指定了根据**星星**对结果进行排序,按照**降序**的顺序。

URL = 'https://api.github.com/search/repositories?q=%s+language:%s&sort=stars&order=desc&page=’ % (LIBRARY, LANGUAGE)


现在我们只需要这些存储库的 URL,这样我们就可以克隆它们了。你可以看到每一项都有一个“ **clone_url** ”键,它服务于这个目的。我们将为每个存储库保留一些额外的密钥,以防我们以后需要它们。现在,我们将迭代前 35 页。

keys = [‘name’, ‘full_name’, ‘html_url’, ‘clone_url’, ‘size’, ‘stargazers_count’]
NUMBER_OF_PAGES_TO_ITERATE = 35# We will declare a dictionary to store the items
repo_dict = dict([(key, []) for key in keys])


我们需要发送每个页面的请求,并保存结果!不要忘记在每个请求之间等待几秒钟,以免 API 不堪重负。

for page_num in tqdm(range(0, 35)):
r = requests.get(URL + str(page_num))
contents = r.json()

for item in contents['items']:
    for key in keys:
        repo_dict[key].append(item[key])

if page_num % 5 == 0:
    time.sleep(60)

现在我们已经有了存储库信息,让我们把它保存在一个数据帧中,我们稍后会用到它。

repo_df = pd.DataFrame(repo_dict)
repo_df.to_csv(‘…/…/data/package_popularity/numpy/repo_info.csv’)repo_df.head()


在下面的要点中,您可以查看搜索查询返回的存储库。

## 从这些存储库中下载相关文件

如果您运行下面的命令,您将会看到一些存储库不止一次出现在那里。我还没有发现为什么会发生这种情况。如果你知道任何关于这件事的情况,请让我知道。

repo_df[‘full_name’].value_counts()


现在,我们将只考虑这些存储库中的一个,最先出现的那个。

您可以编写一个 bash 脚本来克隆这些存储库,或者使用 Github 库。要使用 Github 库,您必须提供 Github API。

with open(‘…/…/api_keys/github.txt’, “r”) as f:
API_KEY = f.read()

g = Github(API_KEY)


在这些文件中,我们将只下载那些带有。py 或者。ipnyb 扩展。

ext_set = set([‘ipnyb’, ‘py’])

The directory where we will store the repositories

REPO_DIR_PARENT = ‘…/…/data/package_popularity/numpy/clones/’


接下来,我们将只考虑至少有 100 颗星的存储库。

repo_df = repo_df[repo_df[‘stargazers_count’] >= 100]


要获得回购的文件,我们可以使用下面的代码片段。这将返回目录中的所有文件,作为 int get_contents 函数的参数。例如,下面的代码片段将返回根目录中的文件。

repo = git_client.get_repo(full_name)
contents = repo.get_contents(“”)


我们需要从目录结构中递归收集所有文件。让我们编写一个助手函数来处理这个问题。

def get_relevant_files (full_name, git_client, ext_set):
repo = git_client.get_repo(full_name)
contents = repo.get_contents(“”)
files = []

while contents:
    file_content = contents.pop(0)
    if file_content.type == "dir":
        contents.extend(repo.get_contents(file_content.path))
    elif file_content.name.split('.')[-1] in ext_set:
        files.append((file_content.name, file_content.download_url))

return files

让我们调用存储库,看看会发生什么。

files = get_relevant_files(‘ddbourgin/numpy-ml’, git_client, ext_set)
print(len(files))
print(files[0])


输出:

89
(‘setup.py’, 'https://raw.githubusercontent.com/ddbourgin/numpy-ml/master/setup.py’)


存储库中有 89 个文件。py 或者。ipnyb 扩展。该列表包含文件的 URL,我们可以使用请求库轻松下载这些文件。

for name, download_url in files:
r = requests.get(download_url, allow_redirects=True)


最后,我们需要将文件的内容保存在本地目录中。我们将简单地使用存储库的全名来创建一个目录,然后将所有文件放在这个特定的目录中。

os.path.join(REPO_DIR_PARENT, ‘_’.join(full_name.split(‘/’)))


你可以在下面的要点中找到完整的代码。

## 探索仓库

现在我们将深入挖掘下载的文件。首先,让我们看看 import 语句,了解 NumPy 库通常是如何导入的。我们已经知道流行的“import numpy as np”语句。但是有没有人把它进口当 pd,甚至熊猫?🤔

查看导入语句,我发现有三种最常用的类型。

1.  import numpy
    处理这个问题非常简单。我们将只看形式为 **numpy 的语句。***
2.  import numpy.abc
    这个也很直接。
3.  从 numpy 导入 abc
    我们将通过处理每个实例 **abc 来处理这个问题。*** 为 **numpy.abc.***
4.  从 numpy.abc 导入 xyz
    我们将处理 **xyz。*** 为 **numpy.xyz.abc.***

所有这些语句都可以用“as”来修改,如“import numpy as np”或“from numpy import abc as def”我们也需要解决这个问题!

我们将保留一本字典,在那里我们将记录这些缩写以及它们代表什么。然后看到 def,就用 numpy.abc 代替,以此类推。

导入的模块实例可以有两种类型。

1.  它们可以是函数,我们可以通过寻找左括号来识别。
2.  它们可以是类,我们可以通过检查它们的属性是否被访问来识别它们。

我们现在非常接近最终解决方案。

对于每个文件,我们将首先构建一组导入的实例。

然后我们将遍历每一行,并检查“numpy.xyz.abc.*(”,这是一个简单的正则表达式,其中星号可以由任意数量的字符替换。

如果我们找到一行包含“numpy.xyz.abc.*(”,我们就知道这一行使用的是“numpy.xyz.abc.*()”函数。

**限制**:我们只看单行语句。如果一个函数调用或导入语句跨越多行,这段代码不会计算在内。我没处理过一些边缘案件。如果你想的话,可以随意修改代码!

现在我们有了 20 个最常用的函数!

1.  numpy.array()
2.  numpy.arange()
3.  numpy.zeros()
4.  numpy.ones()
5.  numpy . testing . assert _ array _ equal()
6.  numpy.dtype()
7.  numpy.random.uniform()
8.  numpy.asarray()
9.  numpy.empty()
10.  numpy.testing.assert_equal()
11.  numpy.linspace()
12.  numpy.all()
13.  numpy.sum()
14.  numpy.random.randint()
15.  numpy.random.rand()
16.  numpy.allclose()
17.  numpy.random.random()
18.  numpy . testing . assert _ almost _ equal()
19.  numpy.dot()
20.  numpy.testing.assert_allclose()

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/aad6ad97e6d1600213425d5e827d42cd.png)

图一。最常用的 NumPy 函数(图片由作者提供)

结果,我用了 18 个。我不知道 [numpy.all_close()](https://numpy.org/doc/stable/reference/generated/numpy.allclose.html) 函数和它的断言变量。看起来很有帮助!

你知道多少?

感谢阅读!

# 我附近的热门地点—使用 Python 和 FourSquare API 的数据可视化

> 原文:<https://towardsdatascience.com/popular-places-near-me-data-visualization-using-python-and-foursquare-api-4d1683cd62d1?source=collection_archive---------43----------------------->

## 本文教你如何使用 python 和 FourSquare API 可视化你所在位置附近指定半径范围内的所有热门地点,在本文结束时,你将能够创建如下所示的地图

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/9c94f093cc5814ce16a271fc49a46220.png)

作者图片

# A.介绍

人们往往倾向于从一个地方旅行到另一个地方,探索新事物,在旅途中,他们需要了解周围所有受欢迎的地方,这样他们就不会错过任何地方。所以这个应用程序是为那些需要知道他们周围所有人口密集地区的人准备的。

这个模型的输入是你当前的位置和你需要的推荐地点的搜索半径。我们使用 FourSquare API,它给出了给定位置周围所有受欢迎的地方,并用 python 来可视化这些东西。

# B.数据要求:

为了构建这个应用程序,我们采用了 FourSquare API 的帮助,所以你需要在 FourSquare 开发者门户有一个开发者帐户,不要担心它是免费使用的。

下面是如何获得 FourSquare API 证书的方法

1.  访问 [FourSquare 开发者网站](https://developer.foursquare.com/places)。
2.  创建一个帐户,它是免费使用的(你可以找到一步一步的指南[这里](https://docs.mageplaza.com/social-login-m2/how-to-configure-foursquare-api.html)
3.  因此,最终您将拥有一个**客户端 ID** 和**客户端秘密**凭证,它们将在后续步骤中使用。

因此,为了探索一个位置,我们使用 FourSquare API 提供的 URL

https://api.foursquare.com/v2/venues/explore?client_id={CLIENT ID}&client_secret={CLIENT SECRET}&ll={Latitude},{Longitude}&v={VERSION}&radius={RADIUS}&limit={LIMIT}


1.  您将从您的 FourSquare 开发者帐户获得客户 ID 和客户密码。
2.  纬度和经度是您当前的位置坐标,您可以使用 python **geopy** 库获得这些坐标,该库将位置转换为坐标。
3.  半径是用户给出的输入之一。
4.  LIMIT 是您希望从 API 获取的结果数

现在我们已经准备好了我们的需求,所以让我们开始编码…

# C.模型开发

## 1.导入所有重要的 python 库

## 2.定义四方 API 凭证

## 3.从用户处读取当前位置,并将其转换为坐标

.

## 4.从 FourSquare API 获取数据,结果是一个 JSON 数据

## 5.从 JSON 文件中获取相关数据,

原始数据是从 FourSquare API 获取的,如下所示

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/c00a04b59df315ba7213585f8b8e278e.png)

作者图片

## 6.清洗数据并转换成数据帧

终于!我们的数据已经可以可视化了,看看吧...

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/8bbe812bb8239fcc9615d3b1fc7ee0a7.png)

作者图片

## 7.我附近的热门地点的可视化

万岁!我们成功了,这是我们的最终输出

1.  位置的名称
2.  它以什么类别而闻名
3.  位置的地址
4.  离当前位置的距离

**注**:红色标记显示当前位置,而蓝色标记显示附近的著名地点

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/5ca32ebf7aaeee41800bcc1d9d7d96ab.png)

作者图片

# 摘要

1.  我们创建了一个 FourSquare API 帐户,并获得了我们唯一的凭证。
2.  我们将用户提供的地址转换为位置坐标。
3.  我们从 FourSquare API 获取数据,并将其转换为数据帧。
4.  最后将数据框可视化在地图上。

# 结论

本文展示了找到您附近所有热门地点的最佳和明智的方法,这可能是初学者开始数据科学项目的最佳方法之一。

你可以在这里获得完整的源代码

## **感谢阅读😃**

[](/impact-of-covid-19-data-visualization-using-python-6f8e3bdc860b) [## 新冠肺炎的影响-使用 Python 进行数据可视化

### 使用 python 在印度地图上可视化冠状病毒爆发的初级方法。当你到达…的终点时

towardsdatascience.com](/impact-of-covid-19-data-visualization-using-python-6f8e3bdc860b)

# 编程语言流行度排名

> 原文:<https://towardsdatascience.com/popularity-ranking-of-programming-languages-72bcf697ea20?source=collection_archive---------36----------------------->

## Python 和 JavaScript 争夺桂冠

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/d1369e746c7de02a4f22611522b502d0.png)

图片由 [ILLUSTRIS](https://illustris.ca/)

对于什么是最流行的编程语言,从来没有一致的意见,也许永远也不会有一致的意见。然而,我们认为,尝试找出对编程语言的流行程度进行排名的方法是有价值的。它有助于我们看到一段时间内的趋势,并提示我们应该关注什么。在不断变化的技术世界中,保持领先是非常重要的。

接下来的分析是关于堆栈溢出(SO)的数据。SO 网站可以说是开发者社区中最大、最受欢迎的问答网站(“开发者”是任何写代码的人的一般意义)。目前,该网站每天的访问量约为 1,000 万次,除了简单的访问外,还有 1,260 万用户活跃在该网站上(例如,张贴问题/答案或发表评论/编辑)。我们相信基于编程语言在 SO 上的受欢迎程度来对它们的实际受欢迎程度进行排名是一个很好的估计。

我们已经为编程语言计算了一个**流行指数**,它是三个因素的平均值:每天问的问题数量、每天不同用户的数量和问题的查看次数。为了识别一种语言,我们考虑分配给帖子的标签。例如,对于 JavaScript,我们考虑以下标签:

tags like ‘%javascript%’
or tags like ‘%jquery%’
or tags like ‘%js>%’ — tag ends with ‘js’ e.g. ‘node.js’
or tags like ‘%extjs%’ — includes ‘extjs4’ and others


对于每日问题计数,我们计算每种编程语言每天被问到的问题数量。

为了计算不同用户数,我们计算每天针对每种编程语言提问/回答问题、发表评论或编辑问题/答案的不同用户的数量。

SO 中的每个帖子都有一个属性,显示该帖子被查看了多少次。我们通过将这个数字除以帖子可见的天数来标准化这个数字。这为我们提供了该帖子的归一化视图计数。然后,我们对每种编程语言每天的视图计数求和。请注意,由于最近帖子的标准化视图计数的方差很高,我们没有将这些帖子包括在计算中。因此,这项措施比其他两项措施晚了两个月。

关于指数如何计算的更多细节,请参见 [GitHub 知识库](https://github.com/vvaezian/Popularity-of-Programming-Languages)。

现在让我们使用一些折线图来探索趋势。请注意,您可以使用这个 [**交互式仪表板**](http://metabase.intellimenta.com/public/dashboard/f9b5e04b-9755-489d-9f5d-6adc3e3806fd) (从右上角选择所需的过滤器。)

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/ffa87df7f2938fb0b46e67fb8456879e.png)

人气指数仪表板(作者图片)

*注:以下分析基于截至 2020 年 7 月底的 SO 数据。交互式仪表盘背后的数据将每季度更新一次。*

# 前五名

从最受欢迎的五种编程语言(基于我们的指数)开始,如果我们看一下年度数据,我们会发现 JavaScript 在过去 10 年中一直占据冠军宝座,尽管 Python 现在紧随其后,正在迅速赶上。其他三个,即 Java、SQL 和 HTML/CSS,在过去的七年中受欢迎程度略有下降。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/04fa072c3816acd498e5d57f593318cf.png)

当前年度前五名(图片由作者提供)

如果从季度数据来看,JavaScript 虽然与 Python 并驾齐驱,但仍然位居榜首。有趣的部分是月度数据。【2020 年 6 月是过去 10 年来 JavaScript 第一次失去榜首位置。鉴于 Python 的发展速度,Python 似乎将在一段时间内成为顶级竞争者。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/bf28705dcebf295eea92e26c9512651e.png)

当前前五名—每月(图片由作者提供)

# 数据科学

数据科学是近年来的热门话题。在下面的图表中,我们可以看到 Python 和 R 在过去几年中有了很高的增长率。Scala 或多或少保持了它的受欢迎程度,而 Julia 的受欢迎程度到目前为止微乎其微。注意,为了进行公平的比较,本次比较只考虑了 Python 的数据科学部分(更多细节请参见 GitHub 资源库)。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/1482453e680189b49f69d94a3dbda2df.png)

数据科学(作者图片)

# 关系型数据库管理系统

在关系数据库管理系统(RDBMS)中,MySQL 仍然是最受欢迎的,尽管它的受欢迎程度一直在下降。这同样适用于 SQL Server。另一方面,PostgreSQL 的受欢迎程度在过去十年中不断增加。甲骨文的受欢迎程度没有太大变化。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/6a6fb09f3f9c8e01a1e84510110e106c.png)

RDDMS(图片由作者提供)

# 移动开发

关于移动开发语言,我们看到了一些相当大的变化。Swift 于 2014 年 6 月推出,对 Objective-C 的受欢迎程度造成了重大打击。类似的故事也发生在 Kotlin 和 Java(移动)上。2017 年,谷歌将 Kotlin 纳入 Android Studio,自 2019 年 5 月以来,它是 Android 应用程序开发者的首选编程语言。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/58c504af3bc604f76fb4d31f463d7283.png)

移动开发(图片由作者提供)

# 我们比赛吧!

要查看计算出的过去 10 年的流行指数,请点击下方图表左下角的播放按钮。您也可以使用底部的滑块移动到特定的时间范围。

*注意:图表将在每个季度开始后一个月用新数据更新(如上所述,ViewCount 指标落后于其他两个指标两个月,这导致指数也落后两个月,因为它是三个指标的平均值)。*

(用繁荣条形图比赛创建)

如果你有改进索引的建议,请让我知道,或者在评论中或者在 GitHub 库中创建一个问题。

*   [交互式仪表盘](http://metabase.intellimenta.com/public/dashboard/f9b5e04b-9755-489d-9f5d-6adc3e3806fd)
*   [GitHub 资源库](https://github.com/vvaezian/Popularity-of-Programming-Languages)

# 用命名实体填充网络图

> 原文:<https://towardsdatascience.com/populating-a-network-graph-with-named-entities-fb8e3d2a380f?source=collection_archive---------31----------------------->

## 数据科学/ Python NLP 片段

## 使用 networkx 可视化自然语言处理结果的早期尝试。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/218285007d87a94daaade6cad6553651.png)

照片由 [Unsplash](https://unsplash.com/s/photos/news?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上的 [Utsav Srestha](https://unsplash.com/@utsavsrestha?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 拍摄

*我做了很多自然语言处理,通常结果看起来很无聊。当我了解网络图时,我开始思考,为什么不用关键词作为节点,把它们连接起来,创建一个网络图呢?*

*Yupp,有何不可!*

在这篇文章中,我们会做到这一点。我们将从关于冠状病毒的新闻文章中提取命名实体,然后使用它们的关系在网络图中将它们连接在一起。

# 简介

网络图是包含节点(顶点)和边(线)的很酷的视觉效果。它经常用于社交网络分析和网络分析,但数据科学家也将其用于自然语言处理。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/6d2432bb4d2788221c16fc99d66db972.png)

安德斯·桑德伯格在[闪烁](https://www.flickr.com/photos/arenamontanus/268427309/in/photolist-pHL64-pHM2v-6tMfEz-4WFXny-869jFp-5RKqLt-cAT173-bWngsQ-5UT2bk-a1Jv37-a1Kpgb-22X1B-QmWPYi-c19Geu-2N9Z6h-6UVCQJ-pNWn9-44h6ju-btejyK-9M2QU4-7A9A3C-74oaKo-jR9gc-pNUDF-dHMZYj-t7tgKB-29KdY5-bkztuc-66JvbF-4CS4g3-5RKqMK-bWN8Sm-33Nf4C-7UYR2T-x9m1S-2N5zxK-bS9WnP-ciKZHy-5J95ED-n3DZZ-aFhJjH-THTRQG-SxKctc-btTTPU-TDNAMg-7yZcaX-29Kted-9pT4Ni-91471X-26ary2u)上拍摄的照片

自然语言处理或 NLP 是人工智能的一个分支,它处理编程计算机来处理和分析大量文本并从中获取意义。换句话说,就是教计算机如何理解人类语言……像个老板一样!

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/f9ab583c24bab054cbdb3a9a82c4e050.png)

照片由 [brewbooks](https://www.flickr.com/photos/brewbooks/) 在 [Flickr](https://www.flickr.com/photos/brewbooks/10805411174/in/photolist-UKMdza-hsQyhE-2iCStmP-2iStoUE-2e5EAr1-2iw1pBb-2iUPEcB-2iXqdWL-PaWqhd-2iJbARo-2iNM3hT-FdCYsS-2iQNUxy-Jec8po-2iMvVpU-2iL4DjL-2iARgAa) 上拍摄

介绍够了,开始编码吧!

首先,让我们确保处理好所有的依赖关系。打开终端并执行以下命令:

pip install -U spacy
python -m spacy download en
pip install networkx
pip install fuzzywuzzy


这将安装 spaCy 并下载英语的训练模型。第三个命令安装 networkx。这应该适用于大多数系统。如果它对你不起作用,检查一下[空间](https://spacy.io/usage)和[网络 x](https://networkx.github.io/documentation/stable/install.html) 的文档。此外,我们使用 [fuzzywuzzy](https://pypi.org/project/fuzzywuzzy/) 进行一些文本预处理。

解决了这个问题,让我们启动 Jupyter 笔记本,开始行动吧!

# 进口

将下面的代码块运行到一个单元格中,以将所有必需的导入内容导入到我们的 Python 环境中。

import pandas as pd
import numpy as np
import pickle
from operator import itemgetter
from fuzzywuzzy import process, fuzz# for natural language processing
import spacy
import en_core_web_sm# for visualizations
%matplotlib inline
from matplotlib.pyplot import figureimport networkx as nx


# 获取数据

如果您想跟进,您可以在这里下载样本数据集。该文件是使用[报纸](https://newspaper.readthedocs.io/en/latest/)从[npr.org](https://www.npr.org/sections/coronavirus-live-updates)导入新闻文章而创建的。如果你喜欢冒险,可以使用下面的代码片段来构建你自己的数据集。

让我们得到我们的数据。

with open(‘npr_coronavirus.txt’, ‘rb’) as fp: # Unpickling
corpus = pickle.load(fp)


# 提取实体

接下来,我们将从加载 spaCy 的英文模型开始:

nlp = en_core_web_sm.load()


然后,我们将提取实体:

entities = []for article in corpus[:50]:
tokens = nlp(‘’.join(article))
gpe_list = []
for ent in tokens.ents:
if ent.label_ == ‘GPE’:
gpe_list.append(ent.text)
entities.append(gpe_list)


在上面的代码块中,我们创建了一个名为`entities`的空列表来存储包含从每篇文章中提取的实体的列表。在 for 循环中,我们循环了语料库的前 50 篇文章。对于每一次迭代,我们将每篇文章转换成单词,然后遍历所有这些单词,得到国家、州和城市的标记为`GPE`的实体。我们使用`ent.text`来提取实际的实体,并将它们一个一个地附加到`entities`中。

结果如下:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/3c07f1757ff24fd3fd06772c4c43d69b.png)

请注意,北卡罗来纳州的名称有几种变体,有些名称中带有“the”前缀。让我们摆脱他们。

articles = []for entity_list in entities:
cleaned_entity_list = []
for entity in entity_list:
cleaned_entity_list.append(entity.lstrip('the ').replace(“'s”, “”).replace(“’s”,“”))
articles.append(cleaned_entity_list)


在上面的代码块中,我们简单地遍历列表列表`articles`并逐个清理实体。每次迭代,我们都去掉前缀“the ”,去掉`'s.`

# 可选:FuzzyWuzzy

在查看实体时,我注意到“美国”也有变化。存在着“美利坚合众国”,而有些只是“美国”。我们可以把这些精简成一个更标准的命名约定。

FuzzyWuzzy 可以帮助解决这个问题。

被[pypi.org](https://pypi.org/project/fuzzywuzzy/)描述为“像老板一样的字符串匹配”,FiuzzyWuzzy 使用 Levenshtein 距离来计算单词之间的相似度。关于如何使用 FuzzyWuzzy 的真正好的教程,请查阅 Thanh Huynh 的文章。

[](/fuzzywuzzy-find-similar-strings-within-one-column-in-a-pandas-data-frame-99f6c2a0c212) [## FuzzyWuzzy:用 Python 在一列中查找相似的字符串

### 令牌排序比率与令牌集比率

towardsdatascience.com](/fuzzywuzzy-find-similar-strings-within-one-column-in-a-pandas-data-frame-99f6c2a0c212) 

下面是使用 FuzzyWuzzy 的可选代码:

在创建网络图之前的最后一步,让我们去掉列表中的空列表,这些列表是由没有任何`GPE`实体类型的文章生成的。

articles = [article for article in articles if article != []]


# 创建网络图

下一步,我们将创建图形存在的世界。

G = nx.Graph()


然后,我们将手动添加带有`G.add_nodes_from()`的节点。

for entities in articles:
G.add_nodes_from(entities)


让我们看看这个图表是什么样子的:

figure(figsize=(10, 8))
nx.draw(G, node_size=15)


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/dc4f4a56efd3a3068a2a802e78ee34bb.png)

接下来,让我们添加将连接节点的边。

for entities in articles:
if len(entities) > 1:
for i in range(len(entities)-1):
G.add_edges_from([(str(entities[i]),str(entities[i+1]))])


对于上面代码的每一次迭代,我们都使用了一个条件,该条件将只处理包含两个或更多实体的实体列表。然后,我们用`G.add_edges_from()`手动连接每个实体。

让我们看看现在的图表是什么样的:

figure(figsize=(10, 8))
nx.draw(G, node_size=10)


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/f94963054cf92a35f753617c661d7cf8.png)

这张图让我想起了蜘蛛!LOL。

为了便于组织,我决定使用 shell 版本的网络图:

figure(figsize=(10, 8))
nx.draw_shell(G, node_size=15)


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/4b2a2efd2d502327dc03cf878b479efb.png)

我们可以看出一些节点的连接比其他节点重。要查看哪些节点拥有最多的连接,让我们使用`G.degree()`。

G.degree()


这给出了以下度数视图:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/635ab6bea64a9253f4abfc27dab43bc0.png)

让我们找出哪个节点或实体拥有最多数量的连接。

max(dict(G.degree()).items(), key = lambda x : x[1])


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/5a226153448f71abdd30e4e1542f6080.png)

为了找出拥有最多连接数的其他节点,让我们来看看前 5 个:

degree_dict = dict(G.degree(G.nodes()))
nx.set_node_attributes(G, degree_dict, ‘degree’)sorted_degree = sorted(degree_dict.items(), key=itemgetter(1), reverse=True)


上面,`sorted_degrees`是一个包含所有节点及其度数值的列表。我们只希望前 5 名是这样的:

print(“Top 5 nodes by degree:”)
for d in sorted_degree[:5]:
print(d)


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/f941b1b482605b4a5f676598d13c3339.png)

# 奖励回合:Gephi

Gephi 是一个开源的免费桌面应用程序,让我们可以可视化、探索和分析各种图形和网络。

让我们将图形数据导出到一个文件中,这样我们就可以将它导入到 Gephi 中。

nx.write_gexf(G, “npr_coronavirus_GPE_50.gexf”)


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/0d6f8e1b56bde500415dae35f49120cf.png)![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/8e71e9d3f3135e4b0ffd09b985b0f210.png)

酷豆!

# 后续步骤

这次,我们只处理了来自 npr.org[的 50 篇文章。如果我们处理数据集的所有 300 篇文章,会发生什么?如果我们将实体类型从`GPE`改为`PERSON`,会看到什么?还能怎么用网络图来可视化自然语言处理结果?](https://npr.org)

总是有更多的事情要做。可能性是无限的!

我希望你喜欢今天的帖子。代码并不完美,我们还有很长的路要走,才能从数据中获得洞察力。我鼓励你更深入地了解[空间](https://spacy.io/)、[网络](https://networkx.github.io/)、 [fuzzywuzzy](https://pypi.org/project/fuzzywuzzy/) ,甚至 [Gephi](https://gephi.org/) 。

*敬请期待!*

你可以通过 [Twitter](https://twitter.com/ecdedios) 或 [LinkedIn](https://www.linkedin.com/in/ednalyn-de-dios/) 联系我。

[1]:维基百科。(2020 年 5 月 25 日)。*自然语言处理*https://en.wikipedia.org/wiki/Natural_language_processing

[2]: Gephi。(2020 年 5 月 25 日)。*打开图 Viz 平台*[https://gephi.org/](https://gephi.org/)

# 用测试数据填充员工数据库

> 原文:<https://towardsdatascience.com/populating-the-employee-database-with-test-data-aa76419eebb6?source=collection_archive---------49----------------------->

## 从雇员数据库的例子开始,这一次我们将弄清楚如何用测试数据填充数据库。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/77da07e56870ddf1d2d852cc67cfec0e.png)

图片来自 [Piqsels](https://www.piqsels.com/en/public-domain-photo-frpof) (CC0)

在本文中,我们将研究用虚拟数据填充雇员数据库的过程,我们在[的上一篇文章](/sql-database-design-basics-with-example-8dcce4b0c687)中设计了虚拟数据的模式。当我们想要运行一些测试时,用虚拟数据填充 SQL 数据库会非常有用。最方便的方法是借助可视化数据生成工具用随机数据填充 SQL 表。

# 借助 SQL Server 数据生成器生成数据

为此,我们将使用 SQL Server 的[数据生成器](https://www.devart.com/dbforge/sql/data-generator/)工具,它被集成到 SSMS 中,也包含在 [dbForge Studio](https://www.devart.com/dbforge/) 中。应该注意,真实的测试数据是基于列名、维度和数据类型生成的。除此之外,还考虑了表之间的关系,因为数据生成过程依赖于它们。

要打开该组件,在 [SSMS](https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-2017) 中的必要数据库上右击“新数据生成…”:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/a7aab7741cd15650210131bcc23bad30.png)

Img。1.在 SSMS 运行 SQL Server 工具的数据生成器

如果您使用的是 dbForge Studio,请在主菜单中选择工具\新数据生成…:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/cb18124828f3e679f6b349248cdceff3.png)

Img.2 .在 dbForge Studio 中运行 SQL Server 工具的数据生成器

在出现的窗口中,在“Connection”选项卡上,您可以看到当前的 MS SQL Server 实例和为数据生成选择的数据库,可以对其进行编辑(如果需要)。然后单击“下一步”按钮:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/812034fb482fe9cb9de861ac2a2b9d80.png)

Img.3 .设置“连接”选项卡

接下来,在“选项”选项卡上,让我们设置数据库的数据生成选项:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/015a57bcc68508411fae10c9b5678668.png)

Img.4 .设置数据生成选项

请注意,您可以在不同的模式下生成 SQL 测试数据:

1.  按指定的行数(默认为 1000 行)
2.  按现有数据在总量中所占的百分比(默认为 10 %)
3.  按时间生成数据(默认为 10 秒)

您也可以通过设置“生成前从表中截断数据”参数,在生成前清除数据。

您可以通过以下方式之一设置值分配模式:

1.  按时间戳随机
2.  按种子随机(默认为 1)
3.  连续的

此外,您可以设置列属性:

1.  将值设置为唯一
2.  包括空值(默认为 10%的行)
3.  包括空值(默认为 10%的行)

您可以按下位于数据生成设置窗口左下角的“保存命令行…”按钮,将设置保存到. bat 文件中。

完成设置后,在数据生成设置窗口的右下角,按下“打开”按钮。

然后,您将看到一个进度条,显示表元数据加载。之后,将出现一个窗口,其中包含每个选定表格的详细数据生成设置:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/42c8e911dbfb4b864a8672772790a5bc.png)

Img.5 .每个选定表格的详细数据生成设置

在左边,您应该选择想要填充的表和列,在右边,您应该为所选的表设置表生成模式。

同时,下面是生成数据的实例(注意代表真实姓名)。

在右上角,有一个上面描述的数据生成设置按钮。

要开始数据生成过程,请单击窗口顶部中间的绿色箭头。然后,您将看到用于选择附加设置的窗口。在这里,在 Output 选项卡上,您需要准确地选择生成数据的位置,以脚本的形式,将其保存到文件或数据库。让我们选择最后一个选项,然后按下一步:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/c66b861900e0ebc6104c92916f6ba5ac.png)

Img。6.设置“输出”选项卡

然后,您可以在“选项”选项卡上设置其他参数。在这种情况下,您需要取消选中数据库备份选项,然后按“下一步”:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/dc288e57366b9710af1e0b89b7f74383.png)

Img.7 .设置“选项”选项卡

在“附加脚本”选项卡上,您可以设置附加脚本。在我们的例子中,我们只需按“下一步”:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/8c8d5e9275d953201c8050c5dec44e0e.png)

Img.8 .设置“附加脚本”选项卡

在“Summary”选项卡上,我们可以看到关于设置和警告的信息。在这里,您也可以将所有设置保存为. bat 文件,方法是按下左下角的“保存命令行…”按钮。要运行数据生成流程,您需要按“生成”按钮:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/ecc8fa143ae5a8eec69833679ef06886.png)

Img.9 .摘要选项卡上的一般信息和警告

出现数据生成过程窗口:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/d7195e3a29baf4d6bca7578b0af8bceb.png)

Img.10 .数据生成流程

然后,这些表将被数据填充。例如,Employee 表具有以下生成的数据:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/ada15a76b8d1b8b2b62500780dfdfe01.png)

Img.11 .雇员表中生成数据的示例

# 结论

总之,我们用真实的数据填充了数据库,用于测试功能和负载。可以为负载测试生成更多的随机数据。除此之外,测试的过程可以通过 dbForge 单元测试工具来加速。

此外,通过使用 SQL 数据生成,您不仅可以计算数据库增长率,还可以计算数据量增加导致的查询性能差异。

*原载于 2020 年 7 月 22 日 https://blog.devart.com*[](https://blog.devart.com/generate-test-data-with-sql-data-generator.html)**。**

# 基于 NumPy 的投资组合优化

> 原文:<https://towardsdatascience.com/portfolio-optimization-with-numpy-93e1428525a5?source=collection_archive---------15----------------------->

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/7b0f766f2c8158ef782abdc4955d2feb.png)

在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上由 [Austin Distel](https://unsplash.com/@austindistel?utm_source=medium&utm_medium=referral) 拍摄的照片

## 你所需要的只是一些矩阵代数来做出最优投资组合

***来自《走向数据科学》编辑的提示:*** *虽然我们允许独立作者根据我们的* [*规则和指导方针*](/questions-96667b06af5) *发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的* [*读者术语*](/readers-terms-b5d780a700a4) *。*

*如果你想看我的代码,* [*你可以在我的 GitHub 这里找到*](https://github.com/yiuhyuk/portfolio_optimization) *。*

上次我们讨论了投资组合优化的工作方式和原因:

[](/understanding-portfolio-optimization-795668cef596) [## 了解投资组合优化

### 从概念上理解优化投资组合意味着什么

towardsdatascience.com](/understanding-portfolio-optimization-795668cef596) 

今天,我们将深入实际优化投资组合的技术细节。关于投资组合优化的冷静思考是,它可以完全用矩阵代数来完成,不需要优化软件。

开始之前,让我们重温一下我们的目标。引用我之前的帖子:

> 我们希望(尽可能)确定的是,对于特定的风险水平,我们投资的投资组合能够最大化我们获得正回报的机会。做到这一点的投资组合,也称为最优投资组合,是具有最高预期回报的**(或者用统计学术语来说,是具有最高 Z 值的投资组合)。**

For a given level of risk, solve for the weights, W, that:Maximize W.T @ E****Subject to:
W.T @ Cov @ W = (target risk)^2
and sum(W) = 1
Where W is a vector representing the weights of the asset in our portfolio.
E is a vector representing the expected returns of the asset.
Cov is the covariance matrix of the asset’s returns.
@ denotes matrix multiplication.
.T denotes the transpose operation.


1.  W @ E 是投资组合的预期收益。
2.  投资组合的方差计算为 W.T @ Cov @ W)。方差是投资组合标准差的平方(也称为风险)。在我们的目标函数中,我们希望投资组合的方差等于目标方差(目标风险水平的平方)。

# 翻转问题

最小化问题通常比最大化问题更容易解决,所以让我们把问题反过来:

For a given level of risk, solve for the weights, W, that:Minimize W.T @ Cov @ W****Subject to:
W.T @ E = target return = mu
and sum(W) = 1
Where W is a vector representing the weights of the asset in our portfolio.
E is a vector representing the expected returns of the asset.
Cov is the covariance matrix of the asset’s returns.
@ denotes matrix multiplication.
.T denotes the transpose operation.


现在,我们不是最大化给定方差水平的收益(也就是风险的平方),而是最小化给定收益水平的方差。

为了解析地解决这个问题,我们可以利用[拉格朗日乘数](https://en.wikipedia.org/wiki/Lagrange_multiplier)并将我们的问题改写如下:

L(W,h1,h2)
= W.T@Cov@W + h1
(W.T@E - mu) + h1
(W.T@ones - 1)**ones denotes a vector of ones with the same length as W


请注意,我们现在有一个等式,其中包括我们想要最小化的东西( **W.T@Cov@W** )以及我们的两个约束条件——投资组合的预期回报必须等于目标回报( **W@E — mu** ),投资组合权重总和必须为 1 ( **W@ones — 1** )。

我们可以通过解决以下问题来解决这个问题:

gradient{L(W,h1,h2)} = 0


这基本上是梯度下降,我们想找到关于每个变量的偏导数(也叫斜率)为零的点。当我们到达那一点时,我们知道我们是最小的。

# 一些矩阵代数

我们可以用矩阵代数来解前面的方程。首先让我们写出每个偏导数:

gradient L with respect to W = 2Cov@W + h1mu + h2*ones = 0
gradient L with respect to h1 = W.T@E - mu = 0
gradient L with respect to h2 = W.T@ones - 1 = 0


我们可以将方程组改写为:

2Cov@W + h1mu + h2*ones = 0
W.T@E = mu
W.T@ones = 1


矩阵的好处在于,它让我们可以很容易地表示像这样的方程组(并且很容易求解)。在 Python 矩阵表示法中,前面的三个等式是:

[[2*Cov h1 h2], [[W ], [[0 ],
[E.T. 0 0 ], @ [h1], = [mu],
[ones.T 0. 0 ]] [h2]] [1 ]] A @ X = b


所以我们可以用三个矩阵 A、X 和 b,用矩阵方程 A@X=b,来解决整个问题。

现在我们需要做的就是解出 X,我们可以很容易地将 b 乘以 A 的倒数:

X = inverse(A)@bThe first n elements of X are the optimal weights where n is the number of different assets whose weights we are optimizing for.


# 用 Python 把它们放在一起

首先我们从一些回报开始。我通过 QUANDL API 从 Shardar 下载了我的。我的返回数据存储在名为 **final** 的数据帧中,如下所示:

S&P 500 Treasury Bonds TIPS Gold
date
2020-10-07 0.017407 -0.007293 -0.000080 -0.000451
2020-10-08 0.008863 0.005400 0.003977 0.003555
2020-10-09 0.008930 -0.000187 0.000317 0.018161
2020-10-12 0.016088 0.003186 0.000634 -0.002872
2020-10-13 -0.006526 0.007161 0.000000 -0.01572


有四种资产,我有每种资产几年的日收益。我们可以使用以下代码计算优化所需的输入:

final is a dataframe of daily returns for the assets# I use the historical mean return for my expected return

E = np.array(final.mean(axis=0)).reshape(-1,1)# Calculate the covariance matrix of the asset’s returns
cov_matrix = np.array(final.cov())# Ones vector
ones = np.ones((E.shape[0],1))zeros = np.zeros((2,2))


接下来,我们根据等式(A@X=b)创建矩阵:

Put together the A matrix

A = 2*cov_matrix
A = np.append(A, E.T, axis=0)
A = np.append(A, ones.T, axis=0)
temp = np.append(E, ones, axis=1)
temp = np.append(temp, zeros, axis=0)
A = np.append(A, temp, axis=1)# Put together the b vector
b = np.array([[0],
[0],
[0],
[0],
E[0], # I set the target return to be
[1]]) # the expected return of stocks# So in essense, I am looking for an optimal portfolio

that is expected to give the same return as I get from

investing in stocks (but with lower risk)


这是他们每个人的样子:

A =
0.000237 -0.000096 -0.000015 0.000004 0.000555 1.0
-0.000096 0.000170 0.000046 0.000038 0.000371 1.0
-0.000015 0.000046 0.000024 0.000022 0.000154 1.0
0.000004 0.000038 0.000022 0.000200 0.000228 1.0
0.000555 0.000371 0.000154 0.000228 0.000000 0.0
1.000000 1.000000 1.000000 1.000000 0.000000 0.0b =
0.000000
0.000000
0.000000
0.000000
0.000555
1.000000# The 0.000555 number in b is the historical daily mean return of

the S&P 500


最后,我们可以通过对矩阵 A 求逆并将其乘以矩阵 b 来计算最佳权重:

Optimize using matrix algebrafrom numpy.linalg import invresults = inv(A)@b# Grab first 4 elements of results because those are the weights

Recall that we optimize across 4 assets so there are 4 weights

opt_W = results[:final.shape[1]]


让我们来看看我们的最佳体重。最佳投资组合主要包括股票和债券,做空 TIPS,少量配置黄金。解析解只能产生无约束权重(意味着允许短重)。如果我们只想要正的权重,我们将不得不使用梯度下降。

***这些权重是使用非常天真的假设和纯粹的历史数据计算出来的。这些绝对不应该作为投资建议!***

Optimal Weights
S&P 500 0.602329
Treasury Bonds 0.726293
TIPS -0.357301
Gold 0.028680


最后,让我们看看我们所谓的最优投资组合实际上是否是最优的。我们应该期望我们的最优投资组合的回报与股票(标准普尔 500)相似,但波动性更小。我们可以看到,我们的最优投资组合的回报(紫色线)比股票的回报(蓝色线)更高,波动性更小。

请记住,这个简单的分析是非常偏颇的。目的是向您展示如何用矩阵代数进行投资组合优化。**我优化了投资组合,并在相同的时间框架内对其进行了回溯测试**(没有训练测试分割),因此投资组合当然会看起来非常好。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/f47391e76e406f7d63de93e817eaa381.png)

最优投资组合与组成资产类别(来源:Sharadar,图形由作者创建)

# 结论

一旦你计算完最佳权重,还有更多工作要做。众所周知,投资组合优化过程对输入(尤其是预期回报)的微小变化非常敏感。

因此,震撼优化输入(通过重采样或甚至添加一些人工噪声)来查看权重如何变化是一个好主意。

最后,思考一下最优投资组合真正代表的是什么是有好处的。这是一个旨在长期持有(几年)的投资组合。这是因为我们用来估计投入的数据(回报的时间序列)需要覆盖尽可能多的时间,最好是多个商业周期。

这不是一个旨在帮助你在短期内把握市场时机的过程。短期内估计的预期收益和协方差矩阵会带来估计错误的巨大风险——记住,垃圾进垃圾出。干杯!

# 使用 SciPy 优化投资组合

> 原文:<https://towardsdatascience.com/portfolio-optimization-with-scipy-aa9c02e6b937?source=collection_archive---------7----------------------->

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/d59bccba961165ac49c9f2bfe11a98ad.png)

[活动发起人](https://unsplash.com/@campaign_creators?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

## 使用 Python 计算带约束的最优投资组合

***来自《走向数据科学》编辑的提示:*** *虽然我们允许独立作者根据我们的* [*规则和指导方针*](/questions-96667b06af5) *发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的* [*读者术语*](/readers-terms-b5d780a700a4) *。*

*无意成为投资建议。你可以在我的 GitHub 上找到我的代码。*

是时候写另一篇关于投资组合优化的文章了,因为我最近一直在做这方面的工作。如果你需要复习,这里是我以前写的关于这个话题的文章:

[](/understanding-portfolio-optimization-795668cef596) [## 了解投资组合优化

### 从概念上理解优化投资组合意味着什么

towardsdatascience.com](/understanding-portfolio-optimization-795668cef596) [](/portfolio-optimization-with-numpy-93e1428525a5) [## 基于 NumPy 的投资组合优化

### 你所需要的只是一些矩阵代数来做出最优投资组合

towardsdatascience.com](/portfolio-optimization-with-numpy-93e1428525a5) 

尽管仅仅用矩阵代数和 NumPy 来优化投资组合很有趣,但有时我们需要添加约束。例如,许多投资者不想或不被允许做空投资。我们不能保证使用矩阵代数产生的最优投资组合不包括空头头寸(负权重)。因此,我们转而求助于**优化**。

如果你没有阅读我以前关于优化的文章,**优化是指在给定风险水平下最大化回报(或最小化特定回报水平下的风险)的资产组合的求解过程**。优化的期望输出是一组能够产生最优投资组合的投资组合权重(针对每项资产)。

# 运行投资组合优化

投资组合优化的两个关键输入是:

1.  **被考虑的每项资产的预期收益**。
2.  资产收益的**协方差矩阵**。嵌入其中的是关于 [**交叉资产相关性**](/understanding-correlation-and-diversification-661c19a26555) 和 [**每个资产的波动率**](/understanding-investment-risk-3882c58e00e0) y(对角线)的信息。

预期回报很难估计——有些人喜欢使用历史平均值(因为过去往往不代表未来,这很危险),其他人有自己的方法来估计回报预测。我计划写一整篇关于这个的文章,所以这次我不会详细讨论。今天我们将关注优化过程本身。因此,我们将假装我们从一个顾问那里得到了预期回报估计。顺便说一句, ***这些都是我非常粗略的估算,绝对不应该作为投资建议*** 。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/8e9d1730f5ed1821bfdafcd11faadf9e.png)

我们优化的预期回报(图形由作者创建)

正如你从上面的图表中所看到的,我们有一个包含八种投资的投资组合,从股票、债券到大宗商品。对于那些不熟悉这个缩写的人来说,TIPS 是财政部通货膨胀保值证券——换句话说,是没有通货膨胀风险的国债。

以下是用过去 10 年的回报率估算的相关性。越低越好,所以蓝色阴影的单元格代表多样化的潜在机会。从技术上来说,优化需要协方差矩阵,但是相关矩阵提供的信息更多。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/222b10640615e282b9ec0ec464d29ad9.png)

相关矩阵(图形由作者创建)

现在我们有了输入,让我们来看看代码。

# 编码投资组合优化

我使用了与我在[之前的优化文章](/portfolio-optimization-with-numpy-93e1428525a5)中相同的数据集,除了现在有八个资产而不是四个。每项资产的标签是:

factors = [‘S&P 500’,‘Emerging Markets’,‘Small Cap’,
‘Treasury Bonds’,
‘High Yield’,‘TIPS’,‘Gold’,‘Oil’]


我将每日收益存储在一个名为 **factor_returns** 的熊猫数据框架中。计算我们资产的协方差矩阵非常简单:

cov = factor_returns.cov()


正如我上面提到的,我们将使用我创建的退货预测(退货的指定顺序与它们在因子中列出的顺序相同):

expected_returns = np.array([[ 0.080],
[ 0.092],
[ 0.092],
[-0.017],
[ 0.034],
[ 0.001],
[ 0.010],
[ 0.079]])


现在让我们导入优化所需的 Python 库:

from scipy.optimize import minimize, Bounds, LinearConstraint


我将稍微不按实际编码的顺序来解释,因为这样更容易理解。下一个代码块显示了一个名为 **optimize** 的函数,它使用 SciPy 的 **minimize** 函数运行优化。

看看调用 minimize 的地方(我加粗了)。第一个参数 **func** 是我们想要最小化的函数。第二个参数 **W** 是允许优化器改变的输入— **W 是我们正在求解的,对应于我们投资组合中资产的权重**。我们需要从猜测开始——没有任何强有力的先验,我只是对每项资产进行同等加权。

**args** 参数中的 **exp_ret** (预期回报)和 **cov** (协方差)变量是提供给优化器的不允许改变的输入。

**因此,优化器所做的是,在给定我们提供的预期回报和协方差矩阵的情况下,搜索使 func 最小化的投资组合权重向量(W)。**

在函数的最后,你会看到我返回了 **optimal_weights['x']** 。这是因为在优化器对象中,我们从 mimimize 返回的‘x’属于优化的权重 w。

W = np.ones((factor_moments.shape[0],1))*(1.0/factor_moments.shape[0])# Function that runs optimizer
def optimize(func, W, exp_ret, cov, target_return):
opt_bounds = Bounds(0, 1)
opt_constraints = ({‘type’: ‘eq’,
‘fun’: lambda W: 1.0 - np.sum(W)},
{‘type’: ‘eq’,
‘fun’: lambda W: target_return - W.T@exp_ret}) optimal_weights = minimize(func, W,
args=(exp_ret, cov),
method=‘SLSQP’,
bounds=opt_bounds,
constraints=opt_constraints)

return optimal_weights[‘x’]


您可能会注意到,minimize 还可以接受两个可选参数— **边界**和**约束**。这些很重要,所以让我们一个一个地看。界限很简单。我们希望 W 中的每个权重介于 0 和 1 之间,换句话说,没有负权重或杠杆:

opt_bounds = Bounds(0, 1)


对于约束条件,我们有两个——**我们希望我们的权重总和为 1** (为了使它成为一个合适的投资组合),以及**我们希望实现预先指定的目标回报**(你也可以将其设置为目标风险,或者完全不考虑)。我们设定回报目标的原因是为了避免这样的情况:我们优化并获得了一个甜蜜而多样化的投资组合,但该投资组合的预期回报是 3%或其他一些太低的值。

opt_constraints = ({‘type’: ‘eq’,
‘fun’: lambda W: 1.0 - np.sum(W)},
{‘type’: ‘eq’,
‘fun’: lambda W: target_return - W.T@exp_ret})


现在让我们来看看我之前跳过的那部分代码。一、什么是 **func** ?当我们求解最优投资组合时,我们试图找到每单位风险回报最高的投资组合(其中风险是投资组合的标准差)。

**所以我们要最大化回报率,我们可以计算为 W.T@exp_ret** (这将每项资产的回报率乘以其权重并求和)**和风险,我们可以计算为 W . T @ cov @ W .**@字符表示矩阵乘法。

由于我们使用了一个优化函数来最小化事物,我们需要在我们的风险回报率上加上一个负号——这样当我们最小化它时,我们实际上是在最大化它。

Function to optimize

def ret_risk(W, exp_ret, cov):
return -((W.T@exp_ret) / (W.T@cov@W)**0.5)


现在剩下要做的就是优化我们的产品组合:

x = optimize(ret_risk, W, expected_returns, cov,
target_return=0.055)


以下是最佳重量的样子:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/f8d97880a2793e4164ea4586ccb10a1f.png)

最佳投资组合权重(作者制作的图表)

重量方面突出的几件事:

*   小型股和新兴市场的预期回报率最高,但权重不高。这是因为它们的波动性(又称风险)明显高于标准普尔 500(见下图)。此外,它们与标准普尔 500 高度相关,因此很少提供多样化。
*   美国国债的预期回报率为负,但却是权重第二高的资产类别。这是因为它也是与股票相关性最小的资产类别(负相关性约为-0.40)。因此,实际上,当股市崩盘时,投资组合的回报依赖于股票和高收益债券,保险依赖于美国国债。
*   尽管石油回报率相对较高,与其他资产的相关性较低,但它的波动性太大,因此权重较低。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/8fd3b9d040ae3b5230bb2a7c29e014c7.png)

每个资产类别的年化标准差(由作者创建的图表)

# 结论

这就是 SciPy 的优化。投资组合策略过程的下一步将是尽最大努力来衡量模型和估计误差的影响。也就是说,我们想知道哪些输入可能是错误指定的(测量误差),以及我们的模型输出对这种误差有多敏感。提示:预期收益是非常嘈杂的,优化的输出对预期收益的微小变化都非常敏感。下一次,我们将看看如何解决这个问题。干杯!

[***如果你总体上喜欢这篇文章和我的写作,请考虑通过我在这里的推荐链接注册 Medium 来支持我的写作。谢谢!***](https://tonester524.medium.com/membership)

# 将想法移植到数学:图形套索的逐步推导

> 原文:<https://towardsdatascience.com/porting-ideas-to-math-a-step-by-step-derivation-of-graphical-lasso-2e01f7165d95?source=collection_archive---------31----------------------->

TLDR:如果你像我一样对数学一无所知,你可能会发现大多数关于图形套索的教程文章第一眼看上去很难理解,而且推导步骤通常是不存在的。为了使它更容易理解,这篇文章将分解这个算法,带领读者通过可口的片段,并帮助发展对算法理论基础的直观理解。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/8235b0e1117994af89ecac5529199c13.png)

JESHOOTS.COM 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上[的照片](https://unsplash.com/@jeshoots?utm_source=medium&utm_medium=referral)

正如诺姆·乔姆斯基所说,我解释说:人类的认知过程实际上是符号操作,以不同的方式发泄出来(想想语法)会产生不同的语言。数学只是另一种让我们简洁描述事物的语言。

以下部分将使用图形套索来说明如何直观地将您的想法转换为数学语言,作为我上一篇关于图形套索的文章的续篇([https://towardsdatascience . com/machine-learning-in-action-in-finance-using-graphical-lasso-to-identify-trading-pairs-in-fa 00d 29 c 71 a 7](/machine-learning-in-action-in-finance-using-graphical-lasso-to-identify-trading-pairs-in-fa00d29c71a7?source=your_stories_page---------------------------))。

# 问题是

假设我们有 p 个股票代号,每个代号都记录了 N 天的收盘价,我们希望计算出股票代号之间的部分相关性,用精度矩阵表示,并从中绘制出一个无向图。这是我们要解决的问题。

# 假设

所有的模型或算法都基于一组假设,这些假设往往会简化问题,使问题与我们已经有解决方案的问题相似。因此,几乎没有模型以像素完美的方式反映现实,但请记住这句老话:“所有的模型都是错的,但有些是有用的”。

因此,为了重新表述我们的问题,我们说有 N 个观测值,每个都是 p 维正态分布的;换句话说,现在我们有了一个 N*p 矩阵。

显然,我们这里的大假设是多维常态。对于那些好奇的人来说,这里有一些对常态普遍偏爱的理由/论据:

1.  它使数学变得简单——用你我这样的平民的话说,这意味着试图避开复杂/混乱的数学。是的,它导致更容易的几何解释和更容易的参数估计。
2.  *还记得中心极限定理吗?许多独立统计分布的和最终收敛于正态分布。如今单子很难找到,我们所使用的功能(价格等)对 CLT 也不例外。*
3.  *还记得热力学第二定律吗?孤立系统的总熵从来不会减少,在非理想条件下总是增加(读,在几乎所有现实世界的条件下)。正态分布是所有具有特定均值和协方差的实值分布中熵最大的一种分布。*

注意上面的 2 和 3 之间似乎有一些有趣的联系。一定要深入挖掘。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/76157d652a5407e440a421c284c84d96.png)

一条钟形曲线(来源:[https://en . Wikipedia . org/wiki/File:Standard _ deviation _ diagram . SVG](https://en.wikipedia.org/wiki/File:Standard_deviation_diagram.svg))

现在,我们已经制定了数据矩阵和数据的分布,我们如何从这里开始解决我们的问题?关键是从我们数据的精度(逆协方差)矩阵到我们想要的无向图有一个映射。

# 用精确矩阵连接无向图

让我们看一个假设的无向图:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/acf739bc4130423f972319b6c6212208.png)

重点放在顶点 A、B 和 c 上,通过无向图或马尔可夫场更正式的性质,它们的联合分布可以分解为:

*P(A,B,C) = P(A,B|C)P(C) = P(A|C)P(B|C)P(C)*

即给定 c,A 和 B 是条件独立的。

在无向图中,如果 C 阻塞 A 和 B,那么给定 C,A 和 B 是条件独立的。

注意,我们也有 P(A,B,C,D,E) = P(A|C,D,E)P(B|C,D,E)P(C,D,E),因为 C,D,E 可以看成是把 A 和 B 堵在一起。

关于精度矩阵,条件独立变量告诉我们什么?

结论首先:**我们可以说明,给定图中所有其他变量,两个变量条件独立对应精度矩阵中对应单元格的值 0。**

为了说明这一点,让我们首先回顾一下关于条件高斯分布的一些事实:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/9198069f44bfa00622a2668a2149f7b8.png)

对角矩阵的逆也是对角的。现在我们已经表明,如果两个维度 I 和 j 是条件独立的,它们在精度矩阵中的对应项将是 0。

有了所有这些假设和事实,我们现在准备处理估计精度矩阵的问题。

# 数学公式

现在我们能够对这个问题进行数学表述了:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/c79c1a128cec54a955a2a87f4148d65c.png)![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/2c4d9c0b1cc167d56df191eb02d991d6.png)

我们走了很长一段路才找到这种形式,它更容易使用,也更清晰。**现在让我们不要忘记我们最初的目标:估计精度矩阵**。为此,我们将首先尝试估计协方差矩阵,从中我们将最终得到精度矩阵。

# 更深入

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/2bd7551eeb25f0c2b2b99f05975ef4c7.png)![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/294fbe720869a4d4c947ec9c783d83c5.png)![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/432e13224b66f507bc3a5daf738d5ba8.png)

# 解决方案

我们快到了。在制定算法之前,让我们再看一些东西。首先,请注意,如果我们在目标函数中对 X 取次梯度:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/eabbaf1af1c8af0a9084b24d87cee3e9.png)![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/bb934afd32dcf6a1b979bc6b9da09f28.png)

# 结束了

这就是我如何冗长地推导图形套索算法,我希望血淋淋的细节不会让我的读者感到厌烦,并实际上有助于消除一些疑虑,填补一些空白,而不是涵盖在这个主题的其他地方。如果你发现一些错误或对此有任何疑问,请务必告诉我。

最后,我为不得不从我自己的笔记中复制粘贴而道歉,因为 Medium 似乎不太支持数学方程。

# 使用 RNN 的词性标注

> 原文:<https://towardsdatascience.com/pos-tagging-using-rnn-7f08a522f849?source=collection_archive---------1----------------------->

## 了解如何使用 rnn 在英语语料库中使用词性(POS)标签来标记单词

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/799a788787795b65112af261b948770f.png)

安格尔·坎普在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

做**词性标注**的经典方式是使用**隐马尔可夫模型的某种变体。**在这里,我们将看到如何使用递归神经网络来实现这一点。最初的 RNN 建筑也有一些变化。它有一个新颖的 RNN 架构——**双向 RNN** ,能够以“逆序”读取序列,并已被证明可以显著提高性能。

然后是 RNN 的两个重要的前沿变体,它们使得在真实数据集上训练大型网络成为可能。尽管 rnn 能够解决各种序列问题,但是由于在 rnn 的训练期间出现的爆炸和消失梯度的问题,它们的架构本身是它们最大的敌人。这个问题由两个流行的**门控 RNN 架构**—**长、短时记忆(LSTM)** 和**门控递归单元(GRU)解决。**我们将在这里研究所有这些与词性标注相关的模型。

# 词性标注—概述

将单词分类到它们的**词性**并相应地标注它们的过程被称为**词性标注**,或者简称为**词性标注**。NLTK 库有许多包含单词及其词性标签的语料库。我将使用来自 NLTK 的带词性标记的语料库,即 **treebank** 、 **conll2000、**和 **brown** 来演示关键概念。为了直接进入代码,Kaggle 上发布了一个附带的[笔记本](https://www.kaggle.com/tanyadayanand/pos-tagging-using-rnn)。

[](https://www.kaggle.com/tanyadayanand/pos-tagging-using-rnn) [## 使用 RNN 的词性标注

### 使用 Kaggle 笔记本探索和运行机器学习代码|使用来自单词嵌入的数据

www.kaggle.com](https://www.kaggle.com/tanyadayanand/pos-tagging-using-rnn) 

下表提供了一些主要标签的信息:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/11d4c8670bfb939bea657164e6777166.png)

**位置标记**

# 文章布局

1.  预处理数据
2.  单词嵌入
3.  香草 RNN
4.  LSTM
5.  苏军总参谋部情报总局
6.  双向 LSTM
7.  模型评估

# 导入数据集

让我们从导入必要的库和加载数据集开始。这是每一个数据分析过程中必不可少的一步(完整的代码可以在[这里](https://www.kaggle.com/tanyadayanand/pos-tagging-using-rnn)查看)。我们将首先使用三个著名的文本语料库加载数据,并对它们进行合并。

***# Importing and Loading the data into data frame

load POS tagged corpora from NLTK***

treebank_corpus = treebank.tagged_sents(tagset=‘universal’)
brown_corpus = brown.tagged_sents(tagset=‘universal’)
conll_corpus = conll2000.tagged_sents(tagset=‘universal’)

# Merging the dataframes to create a master df tagged_sentences = treebank_corpus + brown_corpus + conll_corpus


# **1。预处理数据**

作为预处理的一部分,我们将执行各种步骤,例如将数据分成单词和标签,对 X 和 Y 进行矢量化,以及填充序列。

我们先来看数据。对于下面的每个单词,都有一个与之相关的标签。

# let’s look at the data
tagged_sentences[7]


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/e4b3dc569690ac0fceb7b731d42280ec.png)

## 将数据分为单词(X)和标签(Y)

由于这是一个**多对多**问题,每个数据点将是语料库的不同句子。每个数据点在**输入序列**中都有多个字。这就是我们所说的 **X** 。每个单词在**输出序列**中都有相应的标签。这就是我们所说的 **Y** 。样本数据集:

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/500f135428f523118d33f0f0d1a34259.png)

X = [] # store input sequence
Y = [] # store output sequencefor sentence in tagged_sentences:
X_sentence = []
Y_sentence = []
for entity in sentence:
X_sentence.append(entity[0]) # entity[0] contains the word
Y_sentence.append(entity[1]) # entity[1] contains corresponding tag

X.append(X_sentence)
Y.append(Y_sentence)num_words = len(set([word.lower() for sentence in X for word in sentence]))
num_tags = len(set([word.lower() for sentence in Y for word in sentence]))print(“Total number of tagged sentences: {}”.format(len(X)))
print(“Vocabulary size: {}”.format(num_words))
print(“Total number of tags: {}”.format(num_tags))


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/a536d53e8561941168dfd72e60dc5e6c.png)

***# let’s look at first data point

this is one data point that will be fed to the RNN***

print(‘sample X: ‘, X[0], ‘\n’)
print(‘sample Y: ‘, Y[0], ‘\n’)


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/c8bae8c7766324377a1eeffc8b706da2.png)

***# In this many-to-many problem, the length of each input and output sequence must be the same.

Since each word is tagged, it’s important to make sure that the length of input sequence equals the output sequence***print(“Length of first input sequence : {}”.format(len(X[0])))

print(“Length of first output sequence : {}”.format(len(Y[0])))


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/d3abff1cb78fb8ec6166254dc3e96feb.png)

我们需要解决的下一件事是,我们如何将这些输入提供给 RNN。如果我们必须把单词作为神经网络的输入,那么我们必须把它们转换成数字。我们需要创建一个单词嵌入或一个热点矢量,即每个单词的数字形式的矢量。首先,我们将首先对输入和输出进行编码,这将为输入数据的整个语料库中的每个单词提供一个盲唯一 id。另一方面,我们有 Y 矩阵(标签/输出数据)。我们这里有 12 个 pos 标签,将它们中的每一个视为一个类,每个 POS 标签都被转换为长度为 12 的独热编码。我们将使用 Keras 库中的 Tokenizer()函数将文本序列编码为整数序列。

## 向量化 X 和 Y

# encode X word_tokenizer = Tokenizer() # instantiate tokeniser
word_tokenizer.fit_on_texts(X) # fit tokeniser on data***# use the tokeniser to encode input sequence***
X_encoded = word_tokenizer.texts_to_sequences(X) # encode Y tag_tokenizer = Tokenizer()
tag_tokenizer.fit_on_texts(Y)
Y_encoded = tag_tokenizer.texts_to_sequences(Y)# look at first encoded data point print(“** Raw data point *", “\n”, "-"100, “\n”)
print('X: ', X[0], ‘\n’)
print('Y: ', Y[0], ‘\n’)
print()
print("
Encoded data point **”, “\n”, “-”*100, “\n”)
print('X: ', X_encoded[0], ‘\n’)
print('Y: ', Y_encoded[0], ‘\n’)


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/d3a3bce25fb066f8963e8f768f029cd9.png)

确保每个输入和输出序列的长度相同。

## 填充序列

语料库中的句子长度不同。在我们输入 RNN 模型之前,我们需要确定句子的长度。我们不能动态分配处理语料库中每个句子所需的内存,因为它们的长度不同。因此,数据编码后的下一步是**定义序列长度**。我们需要要么填充短句,要么把长句截成固定长度。然而,这个固定长度是一个**超参数**。

***# Pad each sequence to MAX_SEQ_LENGTH using KERAS’ pad_sequences() function.

Sentences longer than MAX_SEQ_LENGTH are truncated.

Sentences shorter than MAX_SEQ_LENGTH are padded with zeroes.******# Truncation and padding can either be ‘pre’ or ‘post’.

For padding we are using ‘pre’ padding type, that is, add zeroes on the left side.

For truncation, we are using ‘post’, that is, truncate a sentence from right side.***# sequences greater than 100 in length will be truncated MAX_SEQ_LENGTH = 100X_padded = pad_sequences(X_encoded, maxlen=MAX_SEQ_LENGTH, padding=”pre”, truncating=”post”)

Y_padded = pad_sequences(Y_encoded, maxlen=MAX_SEQ_LENGTH, padding=”pre”, truncating=”post”)# print the first sequence
print(X_padded[0], “\n”*3)
print(Y_padded[0])


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/cdd366d91d3bca0ce3861c2fbef37b5f.png)

# 2.单词嵌入

你知道一种更好的表示文本的方式是**单词嵌入**。目前,每个单词和每个标签都被编码为一个整数。我们将使用一种更复杂的技术来表示输入单词(X ),这就是所谓的单词嵌入。

然而,为了表示 Y 中的每个标签,我们将简单地使用独热编码方案,因为数据集中只有 12 个标签,并且 LSTM 在学习这些标签的自己的表示时没有问题。

要使用单词嵌入,您可以使用以下任一模型:

1.  [**word2vec 型号**](https://code.google.com/archive/p/word2vec/)
2.  [**手套型号**](https://nlp.stanford.edu/projects/glove/)

我们使用 word2vec 模型没有特别的原因。这两者在表示单词方面都非常高效。你可以两个都试试,看看哪个效果更好。

**一个单词嵌入的维数是:(词汇 _ 大小,嵌入 _ 维数)**

## 对输入序列使用单词嵌入(X)

# word2vec path = ‘…/input/wordembeddings/GoogleNews-vectors-negative300.bin’# load word2vec using the following function present in the gensim library
word2vec = KeyedVectors.load_word2vec_format(path, binary=True)***# assign word vectors from word2vec model

each word in word2vec model is represented using a 300 dimensional vector***EMBEDDING_SIZE = 300

VOCABULARY_SIZE = len(word_tokenizer.word_index) + 1**# create an empty embedding matix**
embedding_weights = np.zeros((VOCABULARY_SIZE, EMBEDDING_SIZE))# create a word to index dictionary mapping
word2id = word_tokenizer.word_index**# copy vectors from word2vec model to the words present in corpus**
for word, index in word2id.items():
try:
embedding_weights[index, :] = word2vec[word]
except KeyError:
pass


## 对输出序列使用一键编码(Y)

use Keras’ to_categorical function to one-hot encode Y

Y = to_categorical(Y)


所有的数据预处理现在都完成了。现在让我们通过**将数据分割为训练、验证和测试集**来跳转到建模部分。

在使用 RNN 之前,我们必须确保数据的维度是 RNN 所期望的。一般来说,RNN 人期望以下形状

**X 的形状:(#样本,#时间步长,#特征)**

**Y 的形状:(#样本,#时间步长,#特征)**

现在,根据建筑的类型,你可以用不同的形状来制作 RNN。由于我们正在研究的问题具有多对多的架构,输入和输出都包括时间步长的数量,而时间步长就是序列长度。但是注意张量 X 没有第三维度,也就是特征数。这是因为在将数据输入 RNN 之前,我们将使用单词嵌入,因此没有必要明确提到第三个维度。这是因为当您在 Keras 中使用 Embedding()图层时,训练数据将自动转换为( **#samples、#timesteps、#features** ),其中 **#features** 将是嵌入维度(请注意,嵌入图层始终是 RNN 的第一个图层)。使用嵌入层时,我们只需要将数据整形为我们已经完成的(#samples,#timesteps)。但是,请注意,如果不使用 Keras 中的 Embedding()层,您需要将其调整为(#samples、#timesteps、#features)。

# 3.香草 RNN

接下来,让我们建立 RNN 模型。我们将使用单词嵌入来表示单词。现在,在训练模型的同时,你也可以**训练单词嵌入**和网络权重。这些通常被称为**嵌入权重**。训练时,嵌入权重将被视为网络的正常权重,在每次迭代中更新。

在接下来的几节中,我们将尝试以下三种 RNN 模型:

*   具有任意初始化的**的 RNN,不可训练的嵌入**:在这个模型中,我们将任意初始化嵌入权重。此外,我们将**冻结嵌入**,也就是说,我们将不允许网络训练它们。
*   RNN 与**任意初始化,可训练的嵌入**:在这个模型中,我们将允许网络训练嵌入。
*   具有**可训练 word2vec 嵌入的 RNN:**在这个实验中,我们将使用 word2vec 单词嵌入*和*也允许网络进一步训练它们。

## 未初始化的固定嵌入

让我们从第一个实验开始:一个普通的 RNN,带有任意初始化的、不可训练的嵌入。对于这个 RNN,我们不会使用预先训练的单词嵌入。我们将使用随机初始化的嵌入。此外,我们不会更新嵌入权重。

# create architecture rnn_model = Sequential()***# create embedding layer — usually the first layer in text problems

vocabulary size — number of unique words in data*** rnn_model.add(Embedding(input_dim = VOCABULARY_SIZE,

# length of vector with which each word is represented
output_dim = EMBEDDING_SIZE,
# length of input sequence
input_length = MAX_SEQ_LENGTH,
# False — don’t update the embeddings
trainable = False
))***# add an RNN layer which contains 64 RNN cells

True — return whole sequence; False — return single output of the end of the sequence*** rnn_model.add(SimpleRNN(64,

return_sequences=True
))# add time distributed (output at each sequence) layer
rnn_model.add(TimeDistributed(Dense(NUM_CLASSES, activation=’softmax’)))#compile model
rnn_model.compile(loss = ‘categorical_crossentropy’,
optimizer = ‘adam’,
metrics = [‘acc’])# check summary of the model
rnn_model.summary()


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/c03d4e6bfddb2e40bcb5936cc776da2e.png)

#fit model
rnn_training = rnn_model.fit(X_train, Y_train, batch_size=128, epochs=10, validation_data=(X_validation, Y_validation))


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/8c0bf5529971ceca14141bd5d6b0b8e7.png)

我们可以在这里看到,在十个纪元之后,它给出了大约 95%的相当不错的**准确度。**此外,我们在下图中看到了一条健康的增长曲线。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/841f7fb3c181b7acdc2248b8822cbff2.png)

## 未初始化的可训练嵌入

接下来,尝试第二种模型——带有任意初始化的**的 RNN,可训练的嵌入**。这里,我们将允许嵌入与网络一起训练。我所做的只是将参数**trainiable 改为 true,即 trainable = True。**其余一切同上。在检查模型摘要时,我们可以看到所有的参数都是可训练的。即可训练参数等于总参数。

# check summary of the model
rnn_model.summary()


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/961c59bdaa603264334ea0bf68b62ef4.png)

在拟合模型时,精确度显著提高。通过允许嵌入权重训练,它已经上升到大约 98.95%。因此,嵌入对网络的性能有着重要的影响。

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/73dfb647d8cdf455296ea0306244fb75.png)

我们现在将尝试 word2vec 嵌入,看看它是否能改进我们的模型。

## 使用预先训练的嵌入权重

现在让我们尝试第三个实验——使用**可训练 word2vec 嵌入的 RNN。**回想一下,我们已经在一个名为‘embedding _ weights’的矩阵中加载了 word2vec 嵌入。使用 word2vec 嵌入就像在模型架构中包含这个矩阵一样简单。

网络架构与上面相同,但是我们将使用来自 word2vec 的预训练嵌入权重(**weights =【embedding _ weights】**),而不是从任意嵌入矩阵开始。在这种情况下,精确度进一步提高到了**大约 99.04%。**

![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/675a7a0e50a8041156ca3bb66ccbb015.png)

在这种情况下,结果略有改善。那是因为这个模型已经表现得很好了。在没有如此好的模型性能的情况下,通过使用预先训练的嵌入,您将看到更多的改进。预训练的嵌入在许多应用中提供了真正的提升。

# 4.LSTM

为了解决渐变消失的问题,人们已经做了很多尝试来调整传统的 RNNs,使得当序列变长时,渐变不会消失。这些尝试中最受欢迎和最成功的是**长短期记忆网络**,或 **LSTM** 。LSTMs 被证明是如此有效,以至于它们几乎取代了普通的 rnn。

因此,RNN 和 LSTM 之间的一个根本区别是,LSTM 有一个**外显记忆** **单元**,它存储与学习某些任务相关的信息。在标准 RNN 中,网络记忆过去信息的唯一方式是随着时间的推移更新隐藏状态,但它没有显式的内存来存储信息。

另一方面,在 LSTMs 中,即使序列变得很长,存储单元也能保留信息片段。

接下来,我们将建立一个 LSTM 模型,而不是 RNN。我们只需要用 LSTM 层替换 RNN 层。

# create architecture lstm_model = Sequential()
***# vocabulary size — number of unique words in data

length of vector with which each word is represented*** lstm_model.add(Embedding(input_dim = VOCABULARY_SIZE,

output_dim = EMBEDDING_SIZE,
# length of input sequence input_length = MAX_SEQ_LENGTH,
# word embedding matrix weights = [embedding_weights],
# True — update embeddings_weight matrix trainable = True
))***# add an LSTM layer which contains 64 LSTM cells

True — return whole sequence; False — return single output of the end of the sequence***

lstm_model.add(LSTM(64, return_sequences=True))
lstm_model.add(TimeDistributed(Dense(NUM_CLASSES, activation=’softmax’)))#compile model
rnn_model.compile(loss = ‘categorical_crossentropy’,
optimizer = ‘adam’,
metrics = [‘acc’])# check summary of the model
rnn_model.summary()


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/368ca68f9947c6712220b119fb54fc3e.png)

lstm_training = lstm_model.fit(X_train, Y_train, batch_size=128, epochs=10, validation_data=(X_validation, Y_validation))


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/d886093e98ecbceb09b73000cf7d374c.png)

LSTM 模式也提供了一些边际改进。然而,如果我们在其他任务中使用 LSTM 模型,如语言翻译、图像字幕、时间序列预测等。那么您可能会看到性能的显著提升。

# 5.苏军总参谋部情报总局

考虑到计算开销和过度拟合的问题,研究人员试图提出 LSTM 单元的替代结构。这些替代方案中最受欢迎的是**门控循环单元(GRU)。作为一个比 LSTM 更简单的车型,GRU 总是更容易训练。LSTMs 和 GRUs 在实践中几乎完全取代了标准的 RNNs,因为它们比普通的 RNNs 更有效,训练速度更快(尽管参数数量更多)。**

现在让我们建立一个 GRU 模型。然后,我们还将比较 RNN、LSTM 和 GRU 模型的性能。

# create architecture lstm_model = Sequential()
***# vocabulary size — number of unique words in data

length of vector with which each word is represented*** lstm_model.add(Embedding(input_dim = VOCABULARY_SIZE,

output_dim = EMBEDDING_SIZE,
# length of input sequence input_length = MAX_SEQ_LENGTH,
# word embedding matrix weights = [embedding_weights],
# True — update embeddings_weight matrix trainable = True
))***# add an LSTM layer which contains 64 LSTM cells

True — return whole sequence; False — return single output of the end of the sequence***

lstm_model.add(GRU(64, return_sequences=True))
lstm_model.add(TimeDistributed(Dense(NUM_CLASSES, activation=’softmax’)))#compile model
rnn_model.compile(loss = ‘categorical_crossentropy’,
optimizer = ‘adam’,
metrics = [‘acc’])# check summary of the model
rnn_model.summary()


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/59ab6e0c537cc6f2694ffc2fb39e87ab.png)

与 LSTM 相比,GRU 的参数有所减少。因此,我们在计算效率方面得到了显著的提高,而模型的性能几乎没有任何下降。

gru_training = gru_model.fit(X_train, Y_train, batch_size=128, epochs=10, validation_data=(X_validation, Y_validation))


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/a6fe3945b0f35c1ca5d533758e2cc52b.png)

该模型的精度与 LSTM 相同。但是我们看到 LSTM 花费的时间比 GRU 和 RNN 要长。这是意料之中的,因为 LSTM 和 GRU 的参数分别是正常 RNN 的 4 倍和 3 倍。

# 6.双向 LSTM

例如,当你想**给一段文字(比如一篇客户评论)分配一个情感分数**时,网络可以在给它们分配分数之前看到整个评论文字。另一方面,在给定先前几个键入的单词的情况下,在诸如**预测下一个单词**的任务中,在预测下一个单词时,网络不能访问未来时间步中的单词。

这**两类任务**分别称为离线**和在线**序列处理。

现在,你可以用一个巧妙的技巧来处理**离线任务**——既然网络在做出预测之前可以访问整个序列,为什么不使用这个任务来让网络在训练时“查看序列中的未来元素”,希望这将使网络学习得更好?

这就是所谓的**双向 RNNs** 所利用的想法。

通过使用双向 RNNs,几乎可以肯定你会得到更好的结果。然而,由于网络参数的数量增加,双向 rnn 花费几乎两倍的时间来训练。因此,您需要在训练时间和性能之间进行权衡。使用双向 RNN 的决定取决于您拥有的计算资源和您想要的性能。

最后,让我们再构建一个模型——一个**双向 LSTM** ,并与之前的模型在准确性和训练时间方面进行比较。

# create architecturebidirect_model = Sequential()
bidirect_model.add(Embedding(input_dim = VOCABULARY_SIZE,
output_dim = EMBEDDING_SIZE,
input_length = MAX_SEQ_LENGTH,
weights = [embedding_weights],
trainable = True
))
bidirect_model.add(Bidirectional(LSTM(64, return_sequences=True)))
bidirect_model.add(TimeDistributed(Dense(NUM_CLASSES, activation=’softmax’)))#compile model bidirect_model.compile(loss=‘categorical_crossentropy’,
optimizer=‘adam’,
metrics=[‘acc’])# check summary of model
bidirect_model.summary()


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/6eb8288aeb9ce3c3d5b38103619517a8.png)

您可以看到参数的数量增加了。它确实大大提高了参数的数量。

bidirect_training = bidirect_model.fit(X_train, Y_train, batch_size=128, epochs=10, validation_data=(X_validation, Y_validation))


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/2116747b0cd3d3cc342375bf1337c874.png)

双向 LSTM 确实大大提高了精确度(考虑到精确度已经达到顶点)。这显示了双向 LSTMs 的威力。然而,这种精度的提高是有代价的。所花的时间几乎是普通 LSTM 网络的两倍。

# 7.模型评估

下面是我们尝试的四种模式的快速总结。当我们从一种模式转向另一种模式时,我们可以看到一种趋势。

loss, accuracy = rnn_model.evaluate(X_test, Y_test, verbose = 1)
print(“Loss: {0},\nAccuracy: {1}”.format(loss, accuracy))


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/8b4b434ee16472bc0c18d517c9cf545b.png)

loss, accuracy = lstm_model.evaluate(X_test, Y_test, verbose = 1)
print(“Loss: {0},\nAccuracy: {1}”.format(loss, accuracy))


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/11f35998a5bea6a62e9915785e2a19d6.png)

loss, accuracy = gru_model.evaluate(X_test, Y_test, verbose = 1)
print(“Loss: {0},\nAccuracy: {1}”.format(loss, accuracy))


![](https://gitee.com/OpenDocCN/towardsdatascience-blog-zh-2020/raw/master/docs/img/107e253537e9d7df6cbea15abd6a5f27.png)

loss, accuracy = bidirect_model.evaluate(X_test, Y_test, verbose = 1)
print(“Loss: {0},\nAccuracy: {1}”.format(loss, accuracy))


![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgitee.com%2FOpenDocCN%2Ftowardsdatascience-blog-zh-2020%2Fraw%2Fmaster%2Fdocs%2Fimg%2F912c4af9e87604667b3090f6d7f4ac64.png&pos_id=img-YEwQQzGb-1727889434769)

如果你有任何问题、建议或批评,可以通过 LinkedIn 或评论区联系我。

# 合成媒体的正面使用案例(又名 Deepfakes)

> 原文:<https://towardsdatascience.com/positive-use-cases-of-deepfakes-49f510056387?source=collection_archive---------5----------------------->

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgitee.com%2FOpenDocCN%2Ftowardsdatascience-blog-zh-2020%2Fraw%2Fmaster%2Fdocs%2Fimg%2F5cd2e84735efe98ed231ea461bff4fd7.png&pos_id=img-08SsxQKQ-1727889434770)

从 [diego cervo](https://stock.adobe.com/contributor/38908/diego-cervo?load_type=author&prev_url=detail) 处获得许可——Adobe Stock

## Deepfakes 可以为所有人创造无数的可能性和机会,无论他们是谁,如何与周围的世界互动。

技术是一个很好的使能因素,可以赋予人很大的力量。由于数据科学和人工智能的进步,赋权的新想法和能力已经出现。人工智能可以为所有人创造可能性和机会,无论他们是谁,如何听、说或交流。

> [这本书现已在亚马逊上架——https://www . Amazon . com/deep fakes-aka-Synthetic-Media-Humanity-ebook/DP/b0b 846 ycnj/](https://www.amazon.com/Deepfakes-aka-Synthetic-Media-Humanity-ebook/dp/B0B846YCNJ/)

人工智能生成的合成媒体,也称为 deepfakes,有许多积极的用例。[人工智能生成的合成媒体,又名 Deepfakes](/ai-generated-synthetic-media-aka-deepfakes-7c021dea40e1) ,在某些领域取得了明显的进步,如可访问性、教育、电影制作、刑事取证和艺术表达。

在本文中,我将探索 deepfakes 的一些积极用例。我坚信,随着技术的发展和社会对 deepfake 现象的裁决,deepfakes 的大多数用例将会改善人们的生活,并赋予社区和机构权力。

> 科技可以给人们声音、目标和快速产生大规模影响的能力。

## 易接近

人工智能可以建立工具来听、看,并且很快用人工一般智能(AGI),推理越来越准确。人工智能生成的合成媒体可以帮助使辅助工具更加智能,在某些情况下,甚至可以负担得起和个性化,这可以帮助人们扩大他们的代理并获得独立性。技术,特别是基于人工智能的工具,可以为所有人带来无障碍的解决方案。

> **Deepfake 可以加速可访问性探索,从而提高公平性。**

微软的[seening . AI](https://www.microsoft.com/en-us/ai/seeing-ai)和谷歌的 [Lookout](https://www.blog.google/topics/accessibility/lookout-app-help-blind-and-visually-impaired-people-learn-about-their-surroundings/) 利用人工智能进行识别和合成语音来讲述物体、人和世界。人工智能生成的合成媒体可以为步行旅行的个性化辅助导航应用提供动力。

触觉手杖控制器 cane controller 可以通过模拟和手杖互动帮助视力障碍者在虚拟现实世界中导航。它可以使有视觉障碍的人通过将他们的手杖技能转移到虚拟世界中来导航虚拟环境。这项技术有助于实现平等和赋权。

对于[肌萎缩侧索硬化症](https://medlineplus.gov/amyotrophiclateralsclerosis.html) (ALS)患者来说,合成声音非常有力量,因为这种可怕的疾病影响了说话、交流和运动技能的能力。想象一下,即使失去了说话的能力,也能和你爱的人用自己的声音说话。[为 ALS 患者提供技术、设备和服务的 Gleason 团队](http://www.teamgleason.org/),正在与科技公司合作,为 ALS(卢·格里克病)患者实现和开发人工智能生成的合成媒体场景。

还有其他合成语音的使用案例。 [VOCALiD](https://vocalid.ai/) 利用 voicebank 和专有的语音混合技术为任何设备创建独特的人声角色,为有语言和听力障碍的人将文本转换为语音。合成声音也是使这些病人能够独立的必要条件。低沉的假声音也有助于天生的语言障碍。

## 教育

Deepfake 技术促进了教育领域的许多可能性。学校和老师在课堂上使用媒体、音频、视频已经有一段时间了。Deepfakes 可以帮助教育工作者提供比传统视觉和媒体形式更具吸引力的创新课程。

人工智能生成的合成媒体可以将历史人物带回生活,以实现更具吸引力和互动性的课堂。一个合成的重演视频或历史人物的声音和视频可能会更有影响力,更有吸引力,并且会是一个更好的学习工具。例如,JFK 结束冷战的决议是演讲,但从未发表过,是[重新创作的](https://www.cereproc.com/en/jfkunsilenced)使用合成声音,他的声音和演讲风格显然会让学生以一种创造性的方式学习这个问题。

合成人体解剖学、复杂的工业机械和复杂的工业项目可以在混合现实世界中建模和模拟,以便使用微软 [Hololens](https://www.microsoft.com/en-us/education/mixed-reality) 教授学生并进行合作。

> **创造性地使用合成语音和视频可以在规模和有限成本的情况下提高整体成功和学习成果。**

## 艺术

几十年来,好莱坞一直使用高端 CGI、VFX 和 SFX 技术来创造人工但可信的世界,以引人入胜地讲述故事。在 1994 年的电影《阿甘正传》中,主角遇到了 JFK 和其他历史人物。场景和效果的[创作](https://snippetofhistory.wordpress.com/portfolio/forrest-gump-with-president-john-f-kennedy-1994-movie/)是使用 CGI 和不同的技术完成的,耗资数百万美元。如今,复杂的 CGI 和 VFX 技术在电影中被用来生成合成媒体,以讲述一个迷人的故事。

> **Deepfakes 可以将昂贵的 VFX 技术大众化,成为独立故事讲述者的强大工具,而成本只是其一小部分。**

Deepfakes 是一个很好的工具,可以真实地实现喜剧或戏仿中真实事件的反映、延伸、扭曲和挪用。人工智能生成的合成媒体可以在娱乐业务中带来前所未有的机会,我们看到独立创作者或 YouTube 实现了很多机会。使用 GANS 的电影 deepfake 的一些很好的例子是 YouTube 的创作者,如 [ctrl shift face](https://www.youtube.com/channel/UCKpH0CKltc73e4wh0_pgL3g/videos) 和 [shamook](https://www.youtube.com/channel/UCZXbWcv7fSZFTAZV4beckyw/videos) 。

文化和娱乐企业可以出于艺术目的使用 deepfakes。佛罗里达州圣彼得堡的达利博物馆举办了一场名为[达利生活](https://www.theverge.com/2019/5/10/18540953/salvador-dali-lives-deepfake-museum)的展览,利用 deepfakes 让参观者与超现实主义画家萨瓦尔多·达利互动并自拍,让他重获新生。同样,三星在莫斯科的人工智能实验室通过使用 Deepfake 技术使[蒙娜丽莎](https://www.bbc.com/news/technology-48395521)栩栩如生。

在视频游戏行业,人工智能生成的图形和图像可以加快游戏创作的速度。Nvidia 演示了由 deepfakes 创建的混合游戏环境,并正在努力将其推向市场。

音频讲故事和书籍旁白是合成语音的另一个很好的用例。作者的合成声音字体可用于创建作者的书的音频格式。企业可以使用不同语言的同一演员的合成画外音来扩大其内容的覆盖范围。实现上述场景的创造性语音技术必须以道德和负责任的方式使用[ [1](https://medium.com/microsoft-design/responsible-innovation-the-next-wave-of-design-thinking-86bc9e9a8ae8) ],并有一个健全的同意框架,因为它对语音艺术家的生计和代理有直接影响。

## 自主与表达

合成媒体可以帮助人权活动家和记者在独裁和压迫政权中保持匿名。对于公民记者和活动人士来说,利用技术在传统或社交媒体上报道暴行是非常有力量的。Deepfake 可以用来匿名语音和面部,以保护他们的隐私。

Deepfakes 可用于为在线个人创建化身体验以进行自我表达。个人数字化身给予了自主权,可以帮助个人扩展他们的目的、想法和信念,并使自我表达成为可能,否则这对于一些人来说可能是困难的。患有某些身体或精神残疾的个人可以使用自己的合成化身进行在线自我表达。

> **Deepfakes 可以给个人在网络世界中自我表达和融入的新工具。**

联合国儿童基金会和麻省理工学院的项目“深度同理心”利用深度学习来了解受冲突影响的叙利亚社区的特征。然后,它模拟了世界各地的城市在类似的冲突中会是什么样子。该项目创建了波士顿、伦敦和世界其他主要城市的合成战争图像,以帮助增加对灾区受害者的同情。

有一些语音技术初创公司将创造合成语音作为一种新的丧亲疗法,或帮助人们记住死者并与他们联系。

## 延伸和信息放大

去年 4 月,一家健康慈善机构与大卫·贝克汉姆合作,制作了一个视频和语音宣传活动,以帮助终结疟疾。在“消灭疟疾”活动中,贝克汉姆无缝地讲了九种语言,以响应公众的呼吁。这场社会运动是一个很好的例子,它利用 deepfakes 来扩大公共信息的范围。[小贝视频背后的公司 Synthesia](https://www.synthesia.io/) 和语音初创公司 [VOCALiD](https://vocalid.ai/) 开发工具,将视频和音频内容本地化,用于学习工具、品牌营销、观众参与、客户服务和公共信息,以扩大信息的覆盖范围和传播范围。

文本到语音模型可以通过 podcaster 的声音字体帮助创建播客,以更少的错误和更快的速度从文本创建合成音频。

影响者可以利用 Deepfakes 来扩大他们的影响范围,增加他们的受众。使用 deepfakes,一个品牌可以通过高度针对性和个性化的信息接触到许多客户。Zalando 与 Cara Delevigne 一起执行了一项活动,该活动可以通过有影响力的视频镜头和声音字体变得更加个性化。19 岁的 CG“玉米卷卡车专家”和社交媒体名人 Lil Miquela 拥有 240 万粉丝。数字模型、人工智能生成的深度假货正在成为时尚和品牌营销的新趋势。

[人工智能基金会](https://aifoundation.com/)正在为有影响力的人和名人创建个人人工智能,征得他们的同意,以吸引和扩大他们与观众的接触,与粉丝建立更深层次的互动,并大规模提供个人体验。艾基金会最近推出了狄巴克·乔布拉的个人数字头像。

> **Deepfakes 将影响者营销带到了另一个高度。**

在德里选举的前几天,印度的一名政客创造了一个深度骗局来吸引不同语言的选民。这是第一次有记载的政党出于竞选目的使用深度造假。

## 公共安全与数字重建

重建犯罪现场是一门法庭科学和艺术,使用归纳和演绎推理和证据。人工智能生成的合成媒体可以帮助重建具有空间和时间人工制品相互关系的场景。2018 年,一组民事调查人员使用手机视频、尸检报告和监控录像重建了虚拟犯罪现场。

## 创新ˌ革新

数据和人工智能正在帮助许多行业的数字化转型和自动化。Deepfake 或人工智能生成的合成媒体正在成为吸引客户和提供个性化价值的基础。路透社展示了一个完全由人工智能生成的 deepfake [主持人领导的](https://www.synthesia.io/post/reuters)体育新闻摘要系统,以帮助大规模个性化新闻。在时尚零售行业,deepfakes 可以通过虚拟试用最新的服装和配饰来帮助客户成为模特。

一个令人兴奋的应用程序将捕捉顾客的面部、身体,甚至微小的习惯,以生成一个深度假货,并尝试最新的时尚趋势。[日本人工智能公司 Data Grid](https://datagrid.co.jp/) 创造了一个人工智能引擎,可以自动生成广告和时尚的虚拟模型。deepfake 的方法使品牌能够拥有一个虚拟的试衣间,让用户在购买之前体验产品。零售品牌也可以通过创建一个人工智能生成的混合现实世界来让顾客在家里尝试、布置和装饰他们的空间。

[微软 Hololens](https://dynamics.microsoft.com/en-us/mixed-reality/overview/) 开启企业和工业混合现实创新场景,提供价值。[产品可视化](https://dynamics.microsoft.com/en-us/mixed-reality/product-visualize/)让客户直观地探索工业产品。团队和技术人员可以通过混合现实协作工具[远程协助](https://dynamics.microsoft.com/en-us/mixed-reality/remote-assist/)在工业产品中一起工作。

人工智能技术也可以用来增强和提高低分辨率图像的分辨率。这些增强技术对于旧媒体或由低分辨率镜头创建的媒体非常有用。谷歌发表了一篇论文,利用潜在的对抗性生成器[创建](https://arxiv.org/pdf/2003.02365v1.pdf)高分辨率图像。微软研究院发表了一篇文章,使用三重域翻译网络来增强和[修复退化照片的缺陷](https://www.microsoft.com/en-us/research/publication/bringing-old-photos-back-to-life/)。

合成数据可以让医学研究人员在没有实际患者数据的情况下开发治疗疾病的新方法。他们可以将人工智能生成的合成数据用于训练模型,以产生类似的结果。英伟达、MGH & BWH 临床数据科学中心和梅奥诊所展示了他们如何使用 GANs——通过相互竞争来迭代和改进的算法——来创建带有肿瘤的合成大脑 MRI 图像。通过在合成医学图像上训练算法,并将它们与 10%的真实图像相结合,他们变得与只在真实图像上训练的算法一样擅长识别肿瘤。

> Deepfakes 还可以减轻一些患者的隐私担忧。

深度学习算法需要大量的训练数据来创建有效的模型,甚至开发 deepfake 检测模型。由于现实生活中的 deepfakes 不多,像脸书这样的公司不得不为脸书 Deepfake 检测挑战赛创造合成媒体和 deepfakes

## 结论

Deepfakes 提供了一个对我们的生活产生积极影响的绝佳机会。人工智能生成的合成媒体可以非常强大,是一个伟大的推动者。Deepfakes 可以给人们一个声音、目的和影响规模和速度的能力。从艺术、表达、公共安全到无障碍和商业,各行各业都出现了新的赋权理念和能力。Deepfakes 可以通过扩大他们的影响力为所有人创造可能性,而不管他们的局限性

然而,随着合成媒体技术的普及,被利用的风险也在增加。Deepfakes 可以用来损害名誉、伪造证据、欺骗公众和破坏对民主制度的信任。

[在下一篇帖子中,我将讨论 deepfakes 的一些恶意用例]。

*喜欢?* [*随便给我买本书*](https://www.buymeacoffee.com/ashishjaiman)

## 参考

[【1】](#_ftnref1)[https://medium . com/Microsoft-design/responsible-innovation-the-next-wave-of-design-thinking-86 BC 9e 9 A8 AE 8](https://medium.com/microsoft-design/responsible-innovation-the-next-wave-of-design-thinking-86bc9e9a8ae8)

【https://scholarship.law.bu.edu/cgi/viewcontent.cgi?】[context =教员 _ 奖学金](#_ftnref2)

[【3】](#_ftnref3)[https://www . Forbes . com/sites/Katie baron/2019/07/29/digital-doubles-the-deep fake-tech-nutrition-new-wave-retail/](https://www.forbes.com/sites/katiebaron/2019/07/29/digital-doubles-the-deepfake-tech-nourishing-new-wave-retail/)

[【4】](#_ftnref4)[https://arxiv.org/abs/1807.10225](https://arxiv.org/abs/1807.10225)

[【5】](#_ftnref5)[https://arxiv.org/pdf/2006.07397.pdf](https://arxiv.org/pdf/2006.07397.pdf)

# 后负油:1 年曲率作为远期曲线演变的度量

> 原文:<https://towardsdatascience.com/post-negative-oil-the-1-year-curvature-as-a-measure-of-forward-curve-evolution-a1013dcd6b2b?source=collection_archive---------50----------------------->

## 用单一指标量化前向曲线动态

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgitee.com%2FOpenDocCN%2Ftowardsdatascience-blog-zh-2020%2Fraw%2Fmaster%2Fdocs%2Fimg%2F3bd044bb09033c759a077fb5f4bc9e16.png&pos_id=img-q8WjfnME-1727889434770)

WTI 期货市场历史上首次跌破 0 美元,5 月合约(CLK20)下跌 306%,4 月 20 日周一收于-37.63 美元/桶。交易量和持仓量一直在向 6 月合约(CLM20)转移,随着 5 月合约在 4 月 21 日(周二)到期,6 月合约成为了近月合约。6 月合约也下跌,因为它成为短期市场的代表,导致升水更大。

我很好奇期货溢价通常是如何计算的,因为我意识到有几篇文章使用了不同月份合约(9 月 20 日、12 月 20 日等)的价差。)来量化短期和长期市场动态之间的差异。我知道期货溢价通常是指远期曲线的向上形状,但我想找到一个单一的指标来代表曲率。我还想探索远期曲线如何随时间演变,而不必盯着[日期 x 合约]矩阵来寻找模式。

# 前向曲线的演变

现有的可视化要么只显示当前的实时前向曲线,要么在相同的轴上叠加大量不同日期的杂乱前向曲线。我知道每个人都讨厌 3D 绘图,除了艺术家自己,但我相信这个绘图实际上可以减轻对曲线形状演变的解释。

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgitee.com%2FOpenDocCN%2Ftowardsdatascience-blog-zh-2020%2Fraw%2Fmaster%2Fdocs%2Fimg%2F84fa91ea5f866918449016d0f0fb0686.png&pos_id=img-nx16L5gN-1727889434771)

x 轴(CLM20。NYM 到 CLK21。NYM)代表从 2020 年 6 月到 2021 年 5 月的合约。y 轴(04–23 到 03–31)表示从 2020 年 4 月开始的最新日期。z 轴代表每份合约每天的收盘价。底部的等高线图表示顶部曲面图的展平表示。

从图中可以清楚地看出,月初的升水“变软”,然后在接近展期时明显变陡。

# 1 年曲率作为远期曲线演变的衡量标准

我想到了几种计算曲率的方法:

1.  由于 x 轴(周期)是统一的,因为每一步代表一个合约,如果每个合约之间的不同收盘价代表梯度,我们可以将这些差异相加得到总曲率。这显然是错误的,因为它只是从第一个合同到最后一个合同的梯度
2.  利用我在多变量微积分课上学到的知识,我想找到密切圆,这是逼近曲线某一点的“最佳拟合圆”。然而,很难找到这样一个点,如果曲线上有几个拐点,这可能是危险的。另一种方法是将曲线参数化,并考虑沿曲线运动的质点的加速度大小。

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgitee.com%2FOpenDocCN%2Ftowardsdatascience-blog-zh-2020%2Fraw%2Fmaster%2Fdocs%2Fimg%2F8f3c8fb52ef5c5a679106515c8faa0d5.png&pos_id=img-3yy645mP-1727889434772)

3.一种更简单的方法是计算并求和每条曲线的有限差分,因为 x 轴已经是离散的。这个想法是在每个点上累积“近似梯度”。使用内部点中的二阶精确中心差和边界处的一阶或二阶精确单侧(向前或向后)差来计算梯度。

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgitee.com%2FOpenDocCN%2Ftowardsdatascience-blog-zh-2020%2Fraw%2Fmaster%2Fdocs%2Fimg%2Fdca47f78b21c1493dcd911de1c259a35.png&pos_id=img-LcKbnRev-1727889434773)

如果这些值是等间距的,则中心差是向前和向后差的平均值。通过使用过去和未来的值进行比较,中心差给出了导数的更精确的近似值。然后,二阶中心差表示点与点之间梯度变化的程度。

# 结果

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgitee.com%2FOpenDocCN%2Ftowardsdatascience-blog-zh-2020%2Fraw%2Fmaster%2Fdocs%2Fimg%2F5fba33e1fe070a65fe3111960e345aa8.png&pos_id=img-WRp7jEZu-1727889434773)

结果指标是 1 年曲率,它考虑了曲线上的波动,而不是简单的点对点测量。这个单一值能够捕捉到月初的期货溢价、“软化”阶段以及月末的最终陡峭化。这有望提供一个可以使用的更加一致和可量化的度量。

## 如果您想与 3D 绘图互动,并访问一个简短的 Jupyter 笔记本,其中包含供您自己使用的代码,请留下注释。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值