返回介绍

6.3 探索传播性的特征

发布于 2024-01-26 22:17:32 字数 8197 浏览 0 评论 0 收藏 0

我们在这里收集的故事代表了在过去一年中,大约500个传播度最高的作品。我们将尝试解构这些文章来寻找使它们广为流传的共同特征。先从图像数据开始。

6.3.1 探索图像数据

让我们来看看每个故事中包含的图片数量。我们运行一个数值统计,然后绘制图表。

dfc['img_count'].value_counts().to_frame('count')

上述代码生成图6-13的输出。

图6-13

现在,让我们绘制这些信息。

fig, ax = plt.subplots(figsize=(8,6)) 
y = dfc['img_count'].value_counts().sort_index() 
x = y.sort_index().index 
plt.bar(x, y, color='k', align='center') 
plt.title('Image Count Frequency', fontsize=16, y=1.01) 
ax.set_xlim(-.5,5.5) 
ax.set_ylabel('Count') 
ax.set_xlabel('Number of Images')

上述代码生成图6-14的输出。

图6-14中的数字已经令人惊讶了。绝大多数的故事里都有五张图片,而只有一张甚至没有图片的故事是相当罕见的。

因此,我们发现人们倾向于分享包含大量图片的内容。下面来看看这些图像中最常见的颜色。

mci = dfc['main_hex'].value_counts().to_frame('count') 
mci

上述代码生成图6-15的输出。

图6-14

图6-15

图6-15看上去不是很有帮助,因为我们并不理解HEX值代表什么颜色。不过,这里可以使用pandas中的一个新功能,称为conditional formatting,它可以帮助我们。

mci['color'] = ' ' 
def color_cells(x): 
     return 'background-color: ' + x.index 
mci.style.apply(color_cells, subset=['color'], axis=0) 
mci

上述代码生成图6-16的输出。

这当然很有帮助。我们可以看到一些颜色,例如淡蓝色、黑色和绿色(这里是以灰度渲染的),但颜色的粒度是如此之细,总共有超过450 个唯一的值。让我们使用一点聚类的技术将其转化成更容易管理的范围。由于这里有每个颜色的RBG值,我们可以创建一个三维空间,并使用K-means算法来聚集它们。我不会在这里讨论算法的细节,不过它是一个相当简单的迭代算法,它通过测量每个数据点到到中心点的距离来生成聚类,并迭代式地重复该过程。算法需要我们选择k的值,或者说是期望的聚类数量。由于RGB值的范围是从0到256,我们将使用256的平方根,也就是16。如此一来,我们可获得一个可管理的数量,同时保留调色板的特点。

我们首先将RGB值拆分成单独的列,如下所示。

def get_csplit(x): 
     try: 
         return x[0], x[1], x[2] 
     except: 
          return None, None, None
dfc['reds'], dfc['greens'], dfc['blues'] = 
zip(*dfc['main_rgb'].map (get_csplit)) 

接下来,我们将使用它来运行我们的K-means模型并获取中心值。

from sklearn.cluster import KMeans 
clf = KMeans(n_clusters=16) 
clf.fit(dfc[['reds', 'greens', 'blues']].dropna()) 
clusters = pd.DataFrame(clf.cluster_centers_, columns=['r', 'g', 'b']) 
clusters 

上述代码生成图6-17的输出。

图6-16

图6-17

现在,从每页的首张图片中,我们获得了16个最受欢迎的主流颜色。接下来使用pandas 的DataFrame.style()方法以及我们刚刚创建的为单元格填色的函数,来看看这些主流颜色长什么样子。这里需要将索引设置为等于三列中十六进制值那列,以使用我们的color_cells函数,具体如下。

def hexify(x): 
     rgb = [round(x['r']), round(x['g']), round(x['b'])] 
     hxc = mpc.rgb2hex([(x/255) for x in rgb]) 
     return hxc 
clusters.index = clusters.apply(hexify, axis=1) 
clusters['color'] = ' ' 
clusters.style.apply(color_cells, subset=['color'], axis=0)

上述代码生成图6-18的输出。

图6-18

那么,你看到了。这些是广为流传的内容中最常见的颜色(至少在第一张图像中)。比预期更单调一点:虽然有一些蓝色和红色,但多数还是棕色这种灰蒙蒙的色调。

现在让我们继续检视故事的标题。

6.3.2 探索标题

我们将从创建一个函数开始,使用它来检查最常见的元组。将其设置好之后,将来在正文上也可以使用它。

from nltk.util import ngrams 
from nltk.corpus import stopwords 
import re 
def get_word_stats(txt_series, n, rem_stops=False): 
     txt_words = [] 
     txt_len = [] 
     for w in txt_series: 
          if w is not None: 
             if rem_stops == False: 
                word_list = [x for x in ngrams(re.findall('[a-z0- 
                9']+', w.lower()), n)] 
             else: 
                  word_list = [y for y in ngrams([x for x in
                  re.findall('[a-z0-9']+', w.lower())\ 
                  if x not in stopwords.words('english')], n)] 
                  word_list_len = len(list(word_list)) 
                  txt_words.extend(word_list) 
                  txt_len.append(word_list_len) 
     return pd.Series(txt_words).value_counts().to_frame('count'), 
     pd.DataFrame (txt_len, columns=['count'])

这里有很多要解释,所以让我们逐步分析。我们创建了一个函数并接收Series、一个整数和一个布尔值作为输入。整数决定了我们将用于n元语法解析的n, 而布尔值决定我们是否排除停用词。函数返回每行[4]的元组[5]数目和每个元组的频率。

下面让我们在标题上运行这个函数,暂时保持停用词。先从一元语法开始。

hw,hl = get_word_stats(dfc['title'], 1, 0) 
hl

上述代码生成图6-19的输出。

现在,每个标题的字数都有了,让我们来看看其统计信息。

hl.describe()

上述代码生成图6-20的输出。

图6-19

图6-20

我们可以看到传播广泛的故事其标题长度的中位数恰好在11个字。让我们来看看最常用的那些单词,如图6-21所示。

这种信息不是很有价值,但它符合我们的期望。让我们来看看二元语法的同类信息。

hw,hl = get_word_stats(dfc['title'], 2, 0) 
hw

上述代码生成图6-22的输出。

图6-21

图6-22

这肯定是更有趣。从中可以看到标题中的某些部分反复出现。最突出的两个是(donald, trump[6])和(die,at)。Trump是有道理的,因为他做了一些抓眼球的声明,但令人惊讶的是看到关于死亡的标题。快速浏览过去一年的头条新闻,发现一些知名人物最近去世了,所以这也有一定的意义。

现在让我们去掉停用词,再次运行代码。

hw,hl = get_word_stats(dfc['title'], 2, 1) 
hw

上述代码生成图6-23的输出。

再次,我们看到了许多期待的东西。看起来如果我们改变数字的解析方式(用单个标识符,例如[number],来替换每一个数字),可能会看到更多这样的元组排名靠前。如果你愿意尝试,我会把这个练习留给你。

让我们再来看看三元语法。

hw,hl = get_word_stats(dfc['title'], 3, 0)

上述代码生成图6-24的输出。

图6-23

图6-24

看来,元组包括的词语越多,标题越来越像经典的BuzzFeed风格。让我们看看事实是否如此。我们还没看过哪个网站产生的病毒式传播故事最多,这里通过图表来看看BuzzFeed是否领先。

dfc['site'].value_counts().to_frame()

上述代码生成图6-25的输出。

图6-25

我们可以清楚地看到,BuzzFeed在名单中占主导地位,和第二位Huffington Post拉开了明显的距离,而这个网站也有Jonah Peretti的参与。看起来研究病毒式传播的科学可以产生巨大的收益。

到目前为止,我们已经检视了图像和标题,接下来继续观察故事的正文。

6.3.3 探索故事的内容

在上一节中,我们创建了一个函数来发现故事标题中常见的n元语法,现在应用这个函数来探索故事的完整内容。

我们将这样开始:去除停用词,使用二元组。因为与故事主体相比,标题是非常短小的,所以包含停止词是有一定意义的,但在故事正文中,通常去除它们是更合理的做法。

hw,hl = get_word_stats(dfc['text'], 2, 1) 
hw 

上述代码生成图6-26的输出。

有趣的是,我们在标题中看到的轻松愉快的元组在这里完全消失了。正文充满了关于恐怖主义、政治和种族关系的讨论。

标题的内容是轻松愉快的,而正文的内容却是黑暗而富有争议的,这怎么可能?我的猜测是“13 Puppies Who Look Like Elvis”比“The History of US Race Relations”这类文章的字数要少的多[7]

让我们再来看看一个实验。这次将评估故事正文的三元组。

hw,hl = get_word_stats(dfc['text'], 3, 1) 
hw 

上述代码生成图6-27的输出。

我们似乎突然进入了广告和社交活动的领域。有了这些,让我们继续构建内容评分的预测模型。

图6-26

图6-27

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文