基于 FastAI 文本迁移学习的情感分类(93%+Accuracy)

news2024/11/14 14:54:01

胶片情感分析

前言

系列专栏:【深度学习:算法项目实战】✨︎
涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对抗网络、门控循环单元、长短期记忆、自然语言处理、深度强化学习、大型语言模型和迁移学习。

情感分析是指利用自然语言处理、文本分析、计算语言学和生物统计学,系统地识别、提取、量化和研究情感状态和主观信息。

语言模型通过学习来预测单词序列的概率。但为什么我们需要学习单词的概率呢?让我们通过一个例子来理解。我相信你一定用过谷歌翻译。出于不同的原因,我们都会用它将一种语言翻译成另一种语言。这是一个流行的 NLP 应用的例子,叫做机器翻译。在 “机器翻译 ”中,你需要从一种语言中输入一堆单词,然后将这些单词转换成另一种语言。现在,系统可能会给出许多潜在的翻译,您需要计算每种翻译的概率,以了解哪种翻译最准确。

目录

  • 1. 根据预训练模型训练文本分类器
    • 1.1 使用高级应用程序接口
    • 1.2 使用数据块应用程序接口
  • 2. ULMFiT 方法
    • 2.1 微调 IMDb 上的语言模型
    • 2.2 训练文本分类器

我们将使用《学习词向量进行情感分析》一文中的 IMDb 数据集,该数据集包含数千条电影评论。

1. 根据预训练模型训练文本分类器

我们将尝试使用预训练模型来训练分类器,为了准备好数据,我们将首先使用高级 API:

1.1 使用高级应用程序接口

我们可以使用以下命令下载数据并解压:

from fastai.text.all import *
path = untar_data(URLs.IMDB)
path.ls()
(#5) [Path('/home/sgugger/.fastai/data/imdb/unsup'),Path('/home/sgugger/.fastai/data/imdb/models'),Path('/home/sgugger/.fastai/data/imdb/train'),Path('/home/sgugger/.fastai/data/imdb/test'),Path('/home/sgugger/.fastai/data/imdb/README')]
(path/'train').ls()
(#4) [Path('/home/sgugger/.fastai/data/imdb/train/pos'),Path('/home/sgugger/.fastai/data/imdb/train/unsupBow.feat'),Path('/home/sgugger/.fastai/data/imdb/train/labeledBow.feat'),Path('/home/sgugger/.fastai/data/imdb/train/neg')]

数据按照 ImageNet 风格组织,在 train 文件夹中,我们有两个子文件夹:pos 和 neg(分别用于正面评论和负面评论)。我们可以使用 TextDataLoaders.from_folder 方法收集数据。我们唯一需要指定的是验证文件夹的名称,即 “test”(而不是默认的 “valid”)。

dls = TextDataLoaders.from_folder(untar_data(URLs.IMDB), valid='test')

然后,我们可以使用 show_batch 方法查看数据:

dls.show_batch()

在这里插入图片描述
文本数据
我们可以看到,该程序库自动处理了所有文本,然后将其拆分成标记符,并添加了一些特殊标记符,如

  • xxbos 表示文本开始
  • xxmaj 表示下一个词被大写

这样,我们就可以在一行中定义一个适合文本分类的学习器:

learn = text_classifier_learner(dls, AWD_LSTM, drop_mult=0.5, metrics=accuracy)

我们使用 AWD LSTM 架构,drop_mult 是一个参数,用于控制该模型中所有 dropout 的大小,我们使用准确率来跟踪我们模型效果。然后,我们就可以对预训练模型进行微调:

learn.fine_tune(4, 1e-2)

学习

learn.fine_tune(4, 1e-2)

模型训练
还不错!我们可以使用 show_results 方法来查看模型的运行情况:

learn.show_results()

文本分类模型评估
我们可以很容易地预测新文本:

learn.predict("I really liked that movie!")
('pos', tensor(1), tensor([0.0092, 0.9908]))

在这里,我们可以看到模型认为该评论是正面的。结果的第二部分是 “pos ”在我们的数据词汇表中的索引,最后一部分是每个类别的概率(“pos ”为 99.1%,“neg ”为 0.9%)。

1.2 使用数据块应用程序接口

我们还可以使用数据块 API 在 DataLoaders 中获取数据。这部分比较高深,如果你还不习惯学习新的 API,可以跳过这部分。

数据库块是通过向 fastai 库提供大量信息而建立的:
通过一个名为 “块”(block)的参数来确定所使用的类型:这里我们有文本和类别,因此我们传递 TextBlock 和 CategoryBlock。为了通知库我们的文本是文件夹中的文件,我们使用了 from_folder 类方法。

  • 如何获取原始项目,这里使用函数 get_text_files
  • 如何标注这些项目,这里使用父文件夹。
  • 如何分割这些项目,此处使用祖文件夹。
imdb = DataBlock(blocks=(TextBlock.from_folder(path), CategoryBlock),
                 get_items=get_text_files,
                 get_y=parent_label,
                 splitter=GrandparentSplitter(valid_name='test'))

这只是提供了一个如何组合数据的蓝图。要实际创建数据,我们需要使用 dataloaders 方法:

dls = imdb.dataloaders(path)

2. ULMFiT 方法

我们在上一节中使用的预训练模型被称为语言模型。它是在维基百科上进行预训练的,任务是在阅读了前面所有单词后猜测下一个单词。我们将这个语言模型直接微调为电影评论分类器,取得了很好的效果,但只要多做一步,我们就能做得更好:维基百科的英语与 IMDb 的英语略有不同。因此,我们可以根据 IMDb 语料库微调预训练的语言模型,然后以此为基础建立分类器,而不是直接跳转到分类器。

当然,其中一个原因是,了解你正在使用的模型的基础是很有帮助的。但还有一个非常实用的原因,那就是如果在微调分类模型之前微调(基于序列的)语言模型,就能获得更好的结果。例如,在 IMDb 情感分析任务中,数据集包含了 50,000 条额外的电影评论,这些评论在 unsup 文件夹中没有附加任何正面或负面标签。我们可以使用所有这些影评来微调预训练的语言模型–这将产生一个特别擅长预测影评下一个单词的语言模型。相比之下,预训练模型只在维基百科文章中进行训练。

这幅图概括了整个过程:请添加图片描述

2.1 微调 IMDb 上的语言模型

我们可以很容易地将文本放入适合语言建模的 DataLoaders 中:

dls_lm = TextDataLoaders.from_folder(path, is_lm=True, valid_pct=0.1)

我们需要为 valid_pct 传递一些信息,否则该方法将尝试使用祖文件夹名称来分割数据。通过传递 valid_pct=0.1,我们可以告诉它随机获取其中 10%的评论作为验证集。

我们可以使用 show_batch 查看数据。这里的任务是猜测下一个单词,因此我们可以看到目标都向右移动了一个单词。

dls_lm.show_batch(max_n=5)

在这里插入图片描述
然后,我们有一个方便的方法,可以像以前一样使用 AWD_LSTM 架构直接从中抓取一个学习器。我们使用准确率和困惑度作为衡量指标(困惑度是损失的指数),并将默认权重衰减设为 0.1。

learn = language_model_learner(dls_lm, AWD_LSTM, metrics=[accuracy, Perplexity()], path=path, wd=0.1).to_fp16()

默认情况下,预训练的学习器处于冻结状态,这意味着只有模型的头部会进行训练,而主体则保持冻结。在这里,我们将向你展示 fine_tune 方法背后的内容,并使用 fit_one_cycle 方法来拟合模型:

learn.fit_one_cycle(1, 1e-2)

训练模型
这个模型的训练需要一段时间,所以这是一个很好的机会来讨论保存中间结果的问题。

您可以像这样轻松保存模型的状态:

learn.save('1epoch')

它会在 learn.path/models/ 中创建一个名为 “1epoch.pth ”的文件。如果您想在以同样方式创建学习器后在另一台机器上加载模型,或稍后继续训练,您可以通过以下方式加载该文件的内容:

learn = learn.load('1epoch')

我们可以在解冻后对模型进行微调:

learn.unfreeze()
learn.fit_one_cycle(10, 1e-3)

在这里插入图片描述
完成后,我们就可以保存模型的全部内容,但最后一层除外,该层将激活度转换为选取词汇表中每个标记的概率。不包括最后一层的模型称为编码器。我们可以用 save_encoder 保存它:

learn.save_encoder('finetuned')

术语:Encoder(编码器): 不包括特定任务最终层的模型。在应用于视觉 CNN 时,其含义与 body 大致相同,但更多用于 NLP 和生成模型。

在利用这一点对评论分类器进行微调之前,我们可以使用我们的模型来生成随机评论:因为它经过训练可以猜测句子的下一个单词是什么,所以我们可以用它来编写新的评论:

TEXT = "I liked this movie because"
N_WORDS = 40
N_SENTENCES = 2
preds = [learn.predict(TEXT, N_WORDS, temperature=0.75) 
         for _ in range(N_SENTENCES)]
print("\n".join(preds))
i liked this movie because of its story and characters . The story line was very strong , very good for a sci - fi film . The main character , Alucard , was very well developed and brought the whole story
i liked this movie because i like the idea of the premise of the movie , the ( very ) convenient virus ( which , when you have to kill a few people , the " evil " machine has to be used to protect

2.2 训练文本分类器

我们几乎可以像以前一样收集数据进行文本分类:

dls_clas = TextDataLoaders.from_folder(untar_data(URLs.IMDB), valid='test', text_vocab=dls_lm.vocab)

主要区别在于,我们必须使用与微调语言模型时完全相同的词汇,否则学习到的权重将毫无意义。我们用 text_vocab 传递这个词汇。

然后,我们就可以像之前一样定义文本分类器了:

learn = text_classifier_learner(dls_clas, AWD_LSTM, drop_mult=0.5, metrics=accuracy)

所不同的是,在训练之前,我们先加载之前的编码器:

learn = learn.load_encoder('finetuned')

最后一步是使用辨别学习率和渐进解冻进行训练。在计算机视觉中,我们通常会一次性解冻模型,但对于 NLP 分类器,我们发现每次解冻几层会带来真正的不同。

learn.fit_one_cycle(1, 2e-2)

在这里插入图片描述
只用了一个历元,我们就得到了与第一节中的训练相同的结果,不算太差!我们可以向 freeze_to 传递 -2 以冻结除最后两个参数组之外的所有参数:

learn.freeze_to(-2)
learn.fit_one_cycle(1, slice(1e-2/(2.6**4),1e-2))

训练
然后我们可以再解冻一些,继续训练:

learn.freeze_to(-3)
learn.fit_one_cycle(1, slice(5e-3/(2.6**4),5e-3))

训练
最后是整个模型!

learn.unfreeze()
learn.fit_one_cycle(2, slice(1e-3/(2.6**4),1e-3))

训练整个模型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1715101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

J.搬砖【蓝桥杯】/01背包+贪心

搬砖 01背包贪心 思路&#xff1a;要让重量更小的在更前面&#xff0c;价值更大的在更后面&#xff0c;vi−wj>vj−wi viwi>vjwj 第 i 个箱子放在第 j 个箱子下面就显然更优。所以进行排序再用01背包即可。 #include<iostream> #include<algorithm> #defi…

vs工程添加自定义宏

一、简介 用户可以添加自定义宏变量方便工程路径名称的修改和配置 例&#xff1a;$(SolutionDir) 为解决方案路径&#xff0c;$(PojectDir) 为工程所在路径 测试环境&#xff1a;vs2017&#xff0c;qt5.14.0 二、配置 1、打开属性窗口&#xff1a;视图-》其他窗口-》属性管…

Android笔记--应用安装

这一节了解一下普通应用安装app的方式&#xff0c;主要是唤起系统来安装&#xff0c;直接上代码: 申请权限 <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name"android.permission.WRITE_EXT…

HaloDB 的 Oracle 兼容模式

↑ 关注“少安事务所”公众号&#xff0c;欢迎⭐收藏&#xff0c;不错过精彩内容~ 前倾回顾 前面介绍了“光环”数据库的基本情况和安装办法。 哈喽&#xff0c;国产数据库&#xff01;Halo DB! 三步走&#xff0c;Halo DB 安装指引 ★ HaloDB是基于原生PG打造的新一代高性能安…

Python Selenium 详解:实现高效的UI自动化测试

落日余辉&#xff0c;深情不及久伴。大家好&#xff0c;在当今软件开发的世界中&#xff0c;自动化测试已经成为保障软件质量和快速迭代的重要环节。而在自动化测试的领域中&#xff0c;UI自动化测试是不可或缺的一部分&#xff0c;它可以帮助测试团队快速验证用户界面的正确性…

爬虫案例(读书网)

一.我们还是使用简单的bs4库和lxml&#xff0c;使用xpath&#xff1a; 导入下面的库&#xff1a; import requests from bs4 import BeautifulSoup from lxml import etree 我们可以看见它的div和每个书的div框架&#xff0c;这样会观察会快速提高我们的简单爬取能力。 二.实…

Nginx网页服务

nginx的配置: 1、全局块&#xff1a;全局配置&#xff0c;对全局生效&#xff1b; 2、events块&#xff1a;配置影响 Nginx 服务器与用户的网络连接&#xff1b; 3、http块&#xff1a;配置代理&#xff0c;缓存&#xff0c;日志定义等绝大多数功能和第三方模块的配置&#xf…

C语言---文件操作

【C语言详解】——文件操作&#xff08;建议收藏&#xff09;_c语言 写文件原理-CSDN博客 一、文件的读取 # define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<errno.h> #include<string.h>int main() {FILE * pffopen("C:\\Users\\zhw\\De…

Java中的ORM框架——myBatis

一、什么是ORM ORM 的全称是 Object Relational Mapping。Object代表应用程序中的对象&#xff0c;Relational表示的是关系型数据库&#xff0c;Mapping即是映射。结合起来就是在程序中的对象和关系型数据库之间建立映射关系&#xff0c;这样就可以用面向对象的方式&#xff0c…

Vue3使用Composition API实现响应式

title: Vue3使用Composition API实现响应式 date: 2024/5/29 下午8:10:24 updated: 2024/5/29 下午8:10:24 categories: 前端开发 tags: Vue3CompositionRefsReactiveWatchLifecycleDebugging 1. 介绍 Composition API是Vue.js 3中新增的一组API&#xff0c;用于在组件中组…

服装服饰商城小程序的作用是什么

要说服装商家&#xff0c;那数量是非常多&#xff0c;厂家/经销门店/小摊/无货源等&#xff0c;线上线下同行竞争激烈&#xff0c;虽然用户群体广涵盖每个人&#xff0c;但每个商家肯定都希望更多客户被自己转化&#xff0c;渠道运营方案营销环境等不可少。 以年轻人为主的消费…

30【Aseprite 作图】桌子——拆解

1 桌子只要画左上方&#xff0c;竖着5&#xff0c;斜着3个1&#xff0c;斜着两个2&#xff0c;斜着2个3&#xff0c;斜着一个5&#xff0c;斜着一个很长的 然后左右翻转 再上下翻转 在桌子腿部分&#xff0c;竖着三个直线&#xff0c;左右都是斜线&#xff1b;这是横着水平线不…

使用NuScenes数据集生成ROS Bag文件:深度学习与机器人操作的桥梁

在自动驾驶、机器人导航及环境感知的研究中&#xff0c;高质量的数据集是推动算法发展的关键。NuScenes数据集作为一项开源的多模态自动驾驶数据集&#xff0c;提供了丰富的雷达、激光雷达&#xff08;LiDAR&#xff09;、摄像头等多种传感器数据&#xff0c;是进行多传感器融合…

检索字符串

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中&#xff0c;字符串对象提供了很多应用于字符串查找的方法&#xff0c;这里主要介绍以下几种方法。 &#xff08;1&#xff09;count()方…

Visual Studio 的调试

目录 引言 一、调试的基本功能 设置断点 启动调试 检查变量 逐步执行代码 调用堆栈 使用即时窗口 二、调试技巧 条件断点 日志断点 数据断点 异常调试 三、调试高级功能 远程调试 多线程调试 内存调试 性能调试 诊断工具 四、调试策略与最佳实践 系统化的…

Docker-一文详解容器通信的基础网络模式及衍生的自定义网络模式

启动容器时&#xff0c;通过-p 宿主机端口:容器端口&#xff0c;就可以通过访问宿主机端口访问到容器&#xff0c;这种原理机制是啥&#xff0c;有没有其它方式可以让宿主机和容器通信&#xff0c;以及容器与容器之间如何通信。带着这几个问题开始学习Docker的网络知识。 文章…

浅谈路由器转发数据包

当路由器转发数据包时&#xff0c;它会经历一系列步骤&#xff0c;包括接收数据包、路由表查询、以及转发数据包。以下是详细的步骤描述&#xff1a; 1. 接收数据包 以太网帧到达端口&#xff1a;当一个以太网帧到达路由器的某个网络接口&#xff08;端口&#xff09;时&#…

STL库--stack

目录 stack的定义 stack容器内元素的访问 stack常用函数实例解析 stack的常见用途 stack的定义 其定义的写法和其他STL容器相同&#xff0c;typename可以任意基本类型或容器&#xff1a; stack<typename> name; stack容器内元素的访问 由于栈本身就是一种后进先出…

成都欣丰洪泰文化传媒有限公司助力品牌快速崛起

在当今数字化浪潮汹涌的时代&#xff0c;电商行业作为新经济的代表&#xff0c;正以其独特的魅力和无限的潜力&#xff0c;引领着商业模式的创新与变革。在这个充满机遇与挑战的领域里&#xff0c;成都欣丰洪泰文化传媒有限公司凭借其专业的电商服务能力和前瞻性的战略眼光&…

【Python】解决Python报错:TypeError: ‘int‘ object is not iterable

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…