首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用python探知一个故事的大意(上)

使用python探知一个故事的大意(上)

作者头像
哒呵呵
发布2018-08-06 17:25:06
3910
发布2018-08-06 17:25:06
举报
文章被收录于专栏:鸿的学习笔记鸿的学习笔记

Dan Kuster - July 10, 2015

CONTENTS

1. Background

2. Define the problem (outcomes, technicalrequirements)

3. Simple experiment to learn what makes thisproblem hard

4. Add functionality to satisfy requirements

· Identifya good use case (+data) for testing against human interpretation

· Hack: sliding window to sample context

· Smoothing methods

· Hack: Dynamic time warping to compareplotlines across stories

5. Compare many stories to find similarplotlines

The Disney movie plot formula (or, “How would Vonnegut drawthe shapes of Disney stories?”)

Background

如果你还没有看过Vonnegut的视频,“听和学”总会是好的第一步。Vonnegut给了我们一个方法来描绘故事的大概,即故事的开始到结束都用来叙述主角的当前性格(好与坏)。他的方法需要一个人去阅读每个故事,并给出理解,有着他们自己的个人背景和一般的故事的理解。我们将使用python和机器学习模型自动化评分方法,去进行情绪分析。为了自动化解决方案,我们需要清晰,具体,可解决的技术要求。然后,我们将编写代码来实现满足每个需求的功能。

2. Define the problem

解决问题的第一步是根据所需的结果和技术要求清楚地定义问题。 让我们开始下一步。

要绘制故事的大意,我们需要一个自动化的方法,即在从头到尾扫描文本时就给出分数。分数代表叙述者的积极性。

我们需要的技术有:

  1. 精度。 任何(人类)读者应该能够通过简单地检查和解释文本来验证他们所阅读的故事的准确性; 当好事发生时,分数应该变高(〜1.0),当坏事发生时给出低分(〜0.0),否则为中性(〜0.5)。
  2. 对快速(真实)的财富(fortune)变化敏感。有趣的故事往往会突然改变财富,这应该反映在情节线上。“灵敏度”在这里是一般工程意义上的,而不是在机器学习定义中的查准率(即,真阳性率)
  3. 可解释性。简单是使得Vonnegut的绘制线如此引人注目的原因。我们不一定需要这样简单的大意,但我们必须能够对故事中发生的事情做出有意义的结论。
  4. 可视化,使得能够快速评估和比较Vonnegut“故事的大意”。
  5. 自动化。不需要人为判断,只需输入文本。
  6. 易于使用各种文本。

我们可以定义一些额外“好用的”特征:

· 不等长度可比较,因为两个感兴趣的文本很少具有完全相同的长度。

  • 可实验,所以人们可以尝试在自己的文本构建新的可视化等。

3. Start with a simple experiment (MVP)

我们从一个非常简单的实验开始。然后,我们将评估我们的技术要求,并确定如何扩展和添加功能的优先级。有(至少)三个好的理由开始一个简单的实验:

它强迫我们连接一切并使其工作。实施甚至是最简单的工作版本的过程都将揭示我们在此工程中的真正关键点 - 我们将了解什么是困难的和未解决的部分。测试通常会冲击假设,并针对过早优化分析对冲。它也产生了一种其他人可以使用的产品。来自多个来源的反馈不太可能遭受任何给定个体的偏见。

Import modules.

import sys

import os

import pandas as pd # dataframes to store text samples + scores

# Plotting

import matplotlib.pyplot as plt

%matplotlib inline

import seaborn # for more appealing plots

seaborn.set_style("darkgrid")

# Pretty printing

import pprint

pp = pprint.PrettyPrinter(indent=4)

# indico API

import indicoio #https://pypi.python.org/pypi/IndicoIo; install using `pip install -U indicoio`

# Is an indico API key defined?

if not indicoio.config.api_key:

sys.exit("Unable to find an indico API key, please add one to yourpython environment. Aborting.")

Note: If this is your first time using an indico API, register for a freeAPI key at indico.io. There are several ways to define your key for python; a good option isto add an environment variable to define your personal API key. On Linux orOSX, you can simply add a line to ~/.bash_profile to define your personal APIkey. For example: export INDICO_API_KEY=<your api key>

Simple example input.

Link tofull transcription of The Lion King movie, transcribed by fans

# Sample text from the beginning of `The Lion King`fan-transcribed script

input_text = """Rafiki puts the juice andsand he collects on

Simba's brow---a ceremonial crown. He then picks

Simba up and ascends to the point of Pride Rock.

Mufasa and Sarabi follow. With a crescendo in the

music and a restatement of the refrain, Rafiki

holds Simba up for the crowd to view."""

通过对输入文本评分来自我测试(作为人类情感解释者)。

我可以说,input_text是保留积极的,它发生在狮子王电影的开始,当其他积极的事情发生在电影(一般)中。 作为一个英语母语者,我不会在这个短语中看到任何矛盾或特别极端。短语“crescendo in the music”是一个重要的(积极的)提示,生活经验表明一个新的王子的介绍是一个积极的事情。 Polite, modest smiles all around。 如果情绪分数0.0是完全否定的,1.0是非常积极的,0.5是中性的,我期望输入文本的情感分数为:0.6 <分数<0.9。

你应该自己估计......现在就做,在你看到预测之前!

score = indicoio.batch_sentiment([input_text]) # make an API call to get sentiment score forthe input text

print(score)

[0.7735788628299651]

验证结果

Is the score reasonable? Yes, everything agrees with my self-test.

好吧,那很容易! 现在我们有一个情感模型的好玩的例子,是时候尝试一些更实际的东西了。

我们只进行了一次测试(n = 1),所以我们不能区分可重复的方法和快乐的偶然。 让我们通过这个简单的实验应用我们学到的技术:

How the indico sentiment analysis API works:

情绪分析API将机器学习过程抽象为API调用,因此您可以对任何输入文本使用预训练模型。 发送字符串列表,获取分数列表。 因此它被优化成更快速,稳健和“足够准确”(IMDB上的90%准确度)的东西,所以我们希望在一个故事中对许多样本进行评分。

在屏幕的后面是使用标记的文本数据的巨大语料库来训练多项式逻辑回归模型以区分标记为正的文本与标记为负的文本。 当您向API发送字符串列表时,每个字符串被标记为n元语法以计算TF-IDF(术语频率 - 逆文档频率)特征。 然后,模型使用预训练的特征来预测输入文本的积极性,并返回分数。这些模型部署在强大的负载平衡的分布式架构上,因此多个用户可以发送多个请求并可靠地获取结果。

Why use an API instead of implementing from scratch(using scikit-learn, etc)?

因为它抽象了整个数据收集,清洁,特征工程,预训练,正则化,验证,部署和性能/扩展的一整套流程。使用上述API,您可以使用一行代码来获得情感分数。 对于需要调整某些事情以获得最佳准确性的情况,或者需要针对特定目的或领域的特定数据进行训练,您应该可以构建自己的自定义模型。但即使如此,预训练的模型也可以很好地运行来探索你的数据,并快速发现是否值得使用自定义模型。

4. Add functionality: auto-sampling

要扩展这个程序功能以可以跨文本扫描并给出一系列分数,我们需要升级我们的代码以使用可以包含序列(而不仅仅是单个值)的数据结构。我们还需要一个从一组输入文本生成样本的策略。不动脑筋的策略是以有规律间隔对输入文本进行切片。 虽然它似乎是很有吸引力的简单性,但切片在故事的上下文中引入了不连续,这将导致情绪分析出问题。 换句话说,我们应该如何选择我们减少的地方,以便我们不会在块与块之间的破坏信息?这时情绪分析可能很棘手,我们想确保我们保留所有可能的信息。

消除切片边界的一个有用的解决方案是从滑动上下文的窗口采样。 这需要我们评估更多的样本,但情绪分析模型很快,所以不用担心!

Hack 1: sliding window to sample context

def sample_window(seq, window_size = 10, stride =1):

"""

Generatorslides a window across the input sequence

and returnssamples; window size and stride define

the contextwindow

"""

for pos inxrange(0, len(seq), stride):

yieldseq[pos : pos + window_size]

def merge(seq, stride = 4):

"""

Generatorstrides across the input sequence,

combining theelements between each stride.

"""

for pos inxrange(0, len(seq), stride):

yieldseq[pos : pos + stride]

Core logic/script.

d = {} #dictionary to store results (regardless of story lengths)

# Parse text

delim = " "

words = [s for s in input_text.split()] # simplest tokenization method

# Merge words into chunks

### Note: this defines the granularity of context forsentiment analysis,

### might be worthexperimenting with other sampling strategies!

merged_words = [" ".join(w) for w inmerge(words, 5)]

# Sample a sliding window of context

delim = " "

samples = [delim.join(s) for s insample_window(merged_words, 3, 1)]

pp.pprint(samples) # comment this line out for big input!

d['samples'] = samples

# Score sentiment using indico API

print("\n Submitting %i samples..." % (len(samples)))

scores = indicoio.batch_sentiment(samples)

d['scores'] = scores

print(" ...done!")

[ "Rafikiputs the juice and sand he collects on Simba's brow---a ceremonial crown. Hethen",

"sand hecollects on Simba's brow---a ceremonial crown. He then picks Simba up and ascends",

'brow---aceremonial crown. He then picks Simba up and ascends to the point of Pride',

'picks Simba upand ascends to the point of Pride Rock. Mufasa and Sarabi follow.',

'to the pointof Pride Rock. Mufasa and Sarabi follow. With a crescendo in the',

'Rock. Mufasaand Sarabi follow. With a crescendo in the music and a restatement of',

'With acrescendo in the music and a restatement of the refrain, Rafiki holds Simba',

'music and arestatement of the refrain, Rafiki holds Simba up for the crowd to',

'the refrain,Rafiki holds Simba up for the crowd to view.',

'up for thecrowd to view.',

'view.']

Submitting 11samples...

...done!

Visualize the results.

# Load the dict into a dataframe; overkill for now but usefulbelow
df = pd.DataFrame()
for k,v in d.iteritems(): 
    df[k] =pd.Series(v)  # keys -> columns,values -> rows
df.plot(figsize = (16,8))
df  # display thetable of values

Out[8]:

samples

scores

0

Rafiki puts the juice and sand he collects on …

0.716651

1

sand he collects on Simba’s brow—a ceremonia…

0.451806

2

brow—a ceremonial crown. He then picks Simba…

0.211606

3

picks Simba up and ascends to the point of Pri…

0.156922

4

to the point of Pride Rock. Mufasa and Sarabi …

0.317079

5

Rock. Mufasa and Sarabi follow. With a crescen…

0.561463

6

With a crescendo in the music and a restatemen…

0.913848

7

music and a restatement of the refrain, Rafiki…

0.949742

8

the refrain, Rafiki holds Simba up for the cro…

0.934285

9

up for the crowd to view.

0.770297

10

view.

0.289271

未完待续

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-12-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档