整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

150 万条语音的情感分析

150 万条语音的情感分析

们对150万条语音进行了情感分析 ~

原标题 | Sentiment Analysis of 1.5 Million Audible Reviews

作 者 | Toby Manders

翻 译 | 廖颖、had_in、Jonathan-huang、david95、黛娜?卡特琳

编 辑 | Pita

在这个项目的第一部分中,我们收集和研究了一个数据集,其中包括asin、评级数量和每个单独的有声英语课程的URL。

我们将通过使用这些字段来尽可能多地获取文本评论和附带的评级,从而找到我们离开的地方。然后我们将训练一些LSTM神经网络,将评论分类为正负两种。

查看遍历笔记:https://github.com/tobymanders/Data_Analysis/blob/master/audible_eda/audible_reviews_scraper.ipynb

查看数据预处理和情绪分析笔记:https://github.com/tobymanders/Data_Analysis/blob/master/audible_eda/audible_review_classifier.ipynb

下载所有评论的数据集,可访问:https://drive.google.com/file/d/1Wka-rYvEykaG4fGR71zDis5d1NOFZlLX/view?usp=sharing

1. 遍历150万条评论

我们以前研究过音频目录中的分级分布,注意到顶部选择的少数节目的分级的极端集中(标题等级日志和评论数量日志之间的大致线性关系)。

我们今天将利用这种偏斜的优势,以最大限度地提高每小时可获取的评论数量。假设每个标题的书面评论数量与每个标题的评级数量成比例,我们可以预计大约50%的网站评论集中在我们数据集中的前1%的程序中。

从HTML中删除这些评论有一个障碍。大多数最受欢迎的标题的评论都隐藏在“查看更多”按钮下面。

当点击那个显示答案的按钮时,我们要检查网络请求。我们发现一个指向我们刚刚评论过的文章url链接。通过在这个链接向后阅读到末尾,我们能够收集对于给出项目的所有评论。由于这里的页面下载非常快(也因为我们正在使用多线程工作),在一段合理的时间内,我们可以从项目的前6%(26,101)中搜刮到高达80%的评论。

在遍历期间,我们有机会去做少量的家务活。我们将会使用评论内容去训练一个把评论分类成有帮助的(4~5颗星)和无用的(1~3颗星)的机器学习模型。如果在我们先前阅读过的文章中有留下标题和作者,我们的模型很有可能会‘记住它’,也就是说,那个项目有很高的评分了。这意味着对泛化能力有不好的影响,所以我们希望把作者和标题从评论中移除。这样做我们就不需要为每篇评论都储存信息了。

统一都用<unk>,简称‘未知’来代替单词的步骤叫做‘unking’。除了从每篇评论中‘unking’作者和标题外,我们还会用“停止”这个词来代替句号,去掉所有其他标点符号,并将所有文章内容改为小写。这减少了我们数据集中的“单词”数量。

几个小时后,我们会有超过150万的评论。

2.数据的准备

当我们为每篇评论收集评分时,‘overall’、‘story’和‘表现performance’中,我们会以‘overall’列作为标签。另外两列我们将会保存下来用作未来的分析。

为了把数据和目标转换成我们训练模型所需要的形式,我们需要完成接下来的准备工作:

1. 在词汇类型做参数的假设函数中,我们要根据使用频率从高频词汇数据中创建一个词汇表。

2.‘Unk' ——即用‘unk’代替所有数据集存在但词汇表中缺失的词汇。

3. 填补或删减所有条目去统一长度、序列长度和假设函数中的参数。

4. Tokenize(也就是整合)数据集中所有的单词。

5. 从‘overall’列中创建二进制标签。

我们的目标是把数据中的X数组整合成(评论总数 * 序列长度)的形式 和 把矢量y整合成评论总数的长度。

这是前面的部分条目。已经把内容标准化,移除了作者和标题。

为了决定截断更长或更短,让我们看看下面的分类情况。

上面的长度-频率图看起来像是指数图像。96.4%的评论都小于250个单词。我们将把250个单词作为序列长度。

那评论长度下限是什么呢?左边的图表向我们展示了数据集中剩下的绝大多数评论(>98%)都是多于10个单词。我们用10作为评论长度的下限。

按照字符长度排序,我们可以看到超过10个“单词”的最短评论。

大于10个单词的最短的评论。请注意,“单词”是空格之间的所有内容。

我们的下一步工作是根据所有的评论构建一个词汇表。我们将构建一个字典用来统计数据集中每个单词出现的频率,然后我们将使用平率最高的10,000个单词来构建词汇表,并且用“unk”来编码我们的数据集——如用“unk”替换评论中我们词汇表中没有的单词。同时我们还将数据集编码为数字数组——如“tokens”——我们可以在同一个函数中完成这两项任务。

在一些示例文本上测试我们的功能如下:

sample=‘i really loved dfalkjf especially the introduction’...print(tokenize_text(sample))
Unk ID: 24[4, 56, 79, 24, 301, 1, 1190]

注意到,未识别的“dfalkjf”被替换为“unk”,编码为24。其余的单词编码为对应于词汇表中单词的索引。

经过填充、截断和编码之后,我们的数据如下:

array([[ 24, 0, 0, ..., 24, 24, 24], [ 24, 9, 11, ..., 24, 24, 24], [ 149, 149, 149, ..., 24, 24, 24], ..., [ 131, 32, 873, ..., 24, 24, 24], [ 5, 3312, 368, ..., 24, 24, 24], [ 172, 195, 1, ..., 24, 24, 24]])

注意到每一行末尾的24,这就是用'unk'进行填充得到的。

最后,我们根据“overall”评级创建了二进制标签,并发现大约79%的评论获得了4星或5星评级。这个数字很重要,因为它意味着即使是最简单的模型(总是预测1)也能获得79%的准确率,这是必须要超过的数字。

3.训练模型

现在预处理步骤已经完成,我们可以训练我们的模型了。利用TensorFlow和Keras层,我们可以尝试网络结构以及不同的参数。我们所有的模型均将嵌入层作为网络第一层,嵌入层每个单词转换成固定长度的向量,这个长度也是一个超参数。

我们所有的模型都将至少有一个RNN层(特别是长短期记忆单元或称为LSTM层)。这一层将用于向前和向后传播。在每种情况下,LSTM层都将输入一个具有relu激活函数的全连接层和输出一个具有sigmoid激活函数的输出层,后者将得到一个介于0和1之间的值,该值将被阈值化以进行类别预测。

对于其他层,我们加入Dropout层以减少过拟合,其中包括一种特殊类型的Dropout层,该Dropout层接在嵌入层之后,,随机丢弃一维特征图而不是单个单词,以及一个一维卷积层,该卷积层将学习一组滤波器,以提取相邻的词之间的关系特征,我们还将尝试堆叠两层LSTMs。

我们将使用二分类交叉熵损失函数,Adam优化器,并使用early stopping回调函数,当验证集损失开始增加时,该回调函数将停止训练。

我们的最佳模型之一的训练集和验证集的准确性。验证损失在第5个epoch达到最低点,训练提前停止。

4.结果

表现最好的模型确实是最复杂的——在一组未知的测试集上有93.8%的准确率,这个测试集包含大约155,000个评论。然而,值得注意的是,最简单的模型达到了93.1%的准确率。

我们最简单的模型只包含三个隐藏层:嵌入长度只有8的嵌入层、只有8个单元的LSTM层以及一个16个单元的全连接层。网络总共有81k的参数,训练耗时53分钟。

model=tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size, 8), tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(8)), tf.keras.layers.Dense(16, activation='relu'), tf.keras.layers.Dense(1, activation='sigmoid')])

我们最复杂的模型,也是最终的赢家,除了LSTM层,还有7个隐藏层,包括dropout层、卷积层和pooling层:

对于二分类,受试者工作特征 (ROC)曲线很好地反映了模型的区分能力。它反映了这样一个事实:当您降低最终概率输出的阈值时,您会获得更高的真正率 ,但也会导致更高的误报率 。一个完美的模型会将更高的概率分配给正的样本,而不是负的样本,因此降低阈值将得到更多的正样本而不是更多的负样本。这样,曲线就会紧靠左上角。AUC相当于测量ROC曲线下的面积(越接近1越好) 。这里我们的模型在测试数据上的AUC为0.975.

让我们使用一些例子来测试一下我们的模型。我们会给它四个句子。分数小于0.5代表着负样本(消极情绪),大于0.5代表着正样本(积极情绪)。

这本糟糕的书真让人讨厌,真的,它让真让人难受。

我们的模型正确的给它打了0.01分(尽可能接近0)

我爱这本书,它很杰出、幽默而且新奇。

这一句得到0.99分。如果有歧义的句子会怎么样呢:

这本书很不错,但是它让我觉得难过。

0.52分,我们的模型要被我们玩哭了。那如果积极的词和消极的词同时出现呢:

这个故事真的很棒,但是解说员有点可怕。

0.72,模型给了“真的很棒”更多的权重。可能如果我们重新训练模型,能得到不同的结果。

最终,让我们观察一下我们的模型学习到的词嵌入向量。学到的我们字典里每一个单词的向量代表着关于这个单词的信息,这些信息用于预测词是正向的还是负向的。为了更直观的表示他们的空间关系,有助于我们理解,我们需要将这些词向量降维。

主成分分析(PCA)是一个将含有丰富信息的多维数据(比如包含很多变量)转化为坐标轴对齐(比如数据的第一维)的方法。我们会使用PCA将我们的128维的嵌入向量转化为2维数据,然后我们就可以将单词关系可视化:

如图,一个2D图表,从我们学到的词嵌入向量中选取了两个最主要的维度。

使用主成分分析法将词语表中61个常见词语转化为两维数据生成了上图。主要分为褒义词,比如“迷人的”、“卓越的”,标为蓝色;贬义词像“糟糕的”和“无聊的”,标为红色;还有中性词,比如“行为”和“书本”,标为黑色。

词嵌入清楚地反映了这次词语的词性,甚至可以看出更细致的关系。比如,我们直觉地感知近义词的关系:“单调的”和“单调”、“更糟”和“最差”、“乏味”和“厌倦”、“声音”和“叙述者”、“音频”和“质量”等等。

通过对整个词语表重复这个过程,只看最主要的成分,可以找到最积极和最消极的词语。分数最高的词语是“充分利用”,而分数最低的词语呢,就是“Refund(退款)”。

最后,我们在整个训练集上进行预测,来找“最差”和“最好”的评论。

“最差”评论:

  • 浪费,浪费,浪费,买这本书就是浪费,省点钱吧。

  • 什么可以使<标题>更好呢?

  • 没有什么可以使这本书更好了。温馨提醒,这本书不像有些人说的那么有趣,谁会买一本有趣的吸血鬼的书呢?

  • 你认为下一个会听到什么呢?

  • 不确定,读者会对吸血鬼或天启发表评论,而不是对作者或书籍朗读者。

  • 你为什么不喜欢<朗读者>的的表现呢?

  • 因为她的音色,她读每一个角色感觉都是一样的。

  • 你不喜欢这本书,但它有没有什么优点呢?

  • 没有...甚至更糟糕,因为它是数字媒体而不是实体书,我都不能把它拷贝下来回顾。我之前读/听过比这本书好太多的产品。

  • 还有什么补充的吗?

  • 我是对任意题材吸血鬼和天启故事的真爱粉,这本书就不该写出来更别说...

“最好”评论:

  • 太棒了

  • 太棒了太棒了太棒了太棒了太棒了太棒了...(此处省略N个“太棒了”)太棒了太棒了太棒了太棒了太棒了太棒了太棒了

via https://towardsdatascience.com/scraping-and-sentiment-analysis-of-1-5-million-audible-reviews-3502fa6bc86c

封面图来源:https://pixabay.com/zh/photos/%E4%B8%8D%E5%BF%AB%E4%B9%90-%E7%94%B7%E5%AD%90-%E9%9D%A2%E5%85%B7-%E4%BC%A4%E5%BF%83-%E8%84%B8-389944/

、语义化标签含义

语义化的标签,旨在让标签有自己的含义。

二、语义化标签的优势

  1. 代码结构清晰,方便阅读,有利于团队合作开发。
  2. 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以语义的方式来渲染网页。
  3. 有利于搜索引擎优化(SEO)。

三、常见的语义化标签

<title>:页面主体内容。

<h>:h1~h6,分级标题,<h1> 与 <title> 协调有利于搜索引擎优化。

<ul>:无序列表。

<li>:有序列表。

<header>:页眉通常包括网站标志、主导航、全站链接以及搜索框。

<nav>:标记导航,仅对文档中重要的链接群使用。

<main>:页面主要内容,一个页面只能使用一次。如果是web应用,则包围其主要功能。

<article>:定义外部的内容,其中的内容独立于文档的其余部分。

<section>:定义文档中的节(section、区段)。比如章节、页眉、页脚或文档中的其他部分。

<aside>:定义其所处内容之外的内容。如侧栏、文章的一组链接、广告、友情链接、相关产品列表等。

<footer>:页脚,只有当父级是body时,才是整个页面的页脚。

<small>:呈现小号字体效果,指定细则,输入免责声明、注解、署名、版权。

<strong>:和 em 标签一样,用于强调文本,但它强调的程度更强一些。

<em>:将其中的文本表示为强调的内容,表现为斜体。

<mark>:使用黄色突出显示部分文本。

<figure>:规定独立的流内容(图像、图表、照片、代码等等)(默认有40px左右margin)。

<figcaption>:定义 figure 元素的标题,应该被置于 figure 元素的第一个或最后一个子元素的位置。

<cite>:表示所包含的文本对某个参考文献的引用,比如书籍或者杂志的标题。

<blockquoto>:长引用,块引用拥有它们自己的空间。

<q>:短引用(跨浏览器问题,尽量避免使用)。

<time>:datetime属性遵循特定格式,如果忽略此属性,文本内容必须是合法的日期或者时间格式。

<address>:作者、相关人士或组织的联系信息(电子邮件地址、指向联系信息页的链接)。

<del>:移除的内容。

<meter>:定义已知范围或分数值内的标量测量。(Internet Explorer 不支持 meter 标签)

四. 代码示例

    <!-- hgroup 标题用来为标题分组,可以将一组相关的标题同时放入到hgroup中 -->
    <hgroup>
         <h1>回乡偶书</h1>
         <h2>其二</h2>
    </hgroup>


    <!-- p标签    表示页面中一个段落 也是块元素 -->
    <p>在p标签的内容 表示为一个段落</p>


    <!-- 
    em标签 表示语调语气加重 
    行内元素 :不会独占一行的元素
    -->
    <p>今天天气<em>真</em>不错</p>


    <!-- strong 表示强调,重要内容 -->
    <p>你今天必须要<strong>完成作业</strong></p>


    鲁迅说
    <!-- blockquote 表示 引用长引用  块元素 -->
    <blockquote>
        我说过很多话 但我都不记得了
    </blockquote>


    <!-- q标签 表示短引用 为行内元素 -->
    子曰<q>温故而知新</q>


</body>


(部分标签)效果图


关联面试题:请简述下你对HTML语义化的理解?知道的可以在评论区留言![送心]

内容首发于工粽号:程序员大澈,每日分享一段优质代码片段,欢迎关注和投稿!

大家好,我是大澈!

本文约 1100+ 字,整篇阅读约需 2 分钟。

今天分享一段优质 CSS 代码片段,应用灰度效果,让页面变成黑白显示。

老规矩,先阅读代码片段并思考,再看代码解析再思考,最后评论区留下你的见解!


body {
  filter: grayscale(1); // 1相当于100%
}


分享原因

这段代码展示了如何使用 CSS 滤镜来将整个网页变为灰度效果。

在特殊的日子里,网页有整体变灰色的需求,可以使用这段代码,这个需求很有必要。

再就是做一些老照片或黑白电影的效果,也可以使用这段代码。

代码解析

1. 选择器 body

这一部分选择了 HTML 文档的 <body> 元素,即整个网页的主体。

CSS 的 filter 属性通常用于图像,但也可以应用到其他任何 HTML 元素上。

2. grayscale(1);

grayscale 滤镜将元素的颜色变成灰度效果。

参数 1 表示 100% 灰度,参数 0 表示无灰度效果。

3. filter 所有属性值 大盘点!

CSS 的 filter 属性提供了多种图形效果,且这些属性值可以组合用起来,且可以应用于任何元素。

以下是 filter 属性的所有值及其详细解释:

blur()

功能:应用模糊效果。

参数:接受一个长度值(如 px、em),默认值是 0。

示例:filter: blur(5px);

brightness()

功能:调整图像的亮度。

参数:接受一个数值,1 为原始亮度。值小于 1 会降低亮度,值大于 1 会增加亮度。

示例:filter: brightness(0.5);

contrast()

功能:调整图像的对比度。

参数:接受一个数值,1 为原始对比度。值小于 1 会降低对比度,值大于 1 会增加对比度。

示例:filter: contrast(200%);

drop-shadow()

功能:应用阴影效果。

参数:类似于 box-shadow,包括偏移量、模糊半径和颜色。

示例:filter: drop-shadow(10px 10px 10px #000);

grayscale()

功能:将图像变为灰度。

参数:接受一个 0 到 1 之间的数值,0 为无灰度,1 为完全灰度。

示例:filter: grayscale(1);

hue-rotate()

功能:旋转图像的色相。

参数:接受一个角度值,单位为度(deg)。

示例:filter: hue-rotate(90deg);

invert()

功能:反转图像的颜色。

参数:接受一个 0 到 1 之间的数值,0 为无效果,1 为完全反转。

示例:filter: invert(1);

opacity()

功能:调整图像的透明度。

参数:接受一个 0 到 1 之间的数值,0 为完全透明,1 为完全不透明。

示例:filter: opacity(0.5);

saturate()

功能:调整图像的饱和度。

参数:接受一个数值,1 为原始饱和度。值小于 1 会降低饱和度,值大于 1 会增加饱和度。

示例:filter: saturate(2);

sepia()

功能:将图像变为棕褐色。

参数:接受一个 0 到 1 之间的数值,0 为无效果,1 为完全棕褐色。

示例:filter: sepia(1);

url()

功能:引用 SVG 滤镜。

参数:接受一个 URL,指向一个包含 SVG 滤镜的文件。

示例:filter: url(#filter-id);


- end -