当前位置: 首页 > news >正文

深度学习:基于长短时记忆网络LSTM实现情感分析

目录

1 LSTM网络介绍

1.1 LSTM概述

1.2 LSTM网络结构

1.3 LSTM门机制

1.4 双向LSTM

2 Pytorch LSTM输入输出

2.1 LSTM参数

2.2 LSTM输入

 2.3 LSTM输出

2.4 隐藏层状态初始化

3 基于LSTM实现情感分析

3.1 情感分析介绍

3.2 数据集介绍

3.3 基于pytorch的代码实现

3.3.1 数据集加载

3.3.2 模型构建

3.3.3 模型训练

3.3.4 模型验证

3.3.5 模型预测

3.4 运行结果

3.5 完整代码

4 总结


1 LSTM网络介绍

1.1 LSTM概述

长短时记忆网络(Long Short Term Memory Network, 简称LSTM),是一种特殊的RNN,LSTM为解决RNN网络存在的长序列数据处理中的梯度消失和梯度爆炸问题而提出。它最早由Hochreiter&Schmidhuber于1997年提出,后经众多专家学者提炼和推广,现在因性能出色已经被广泛使用。

LSTM许多领域都有广泛的应用,典型的应用场景如下所示:

  • 自然语言处理(NLP)。在NLP领域,LSTM可以用于文本分类、情感分析、机器翻译等任务。通过对文本序列进行建模,LSTM能够捕捉到文本中的长期依赖关系,从而提高模型的准确率。
  • 语音识别(Speech Recognition)。在语音识别中,LSTM网络模型可以用于声学模型和语言模型的建模。通过对语音信号和语言模型进行联合建模,LSTM能够提高语音识别的准确率。
  • 股票走势预测。LSTM可以应用于股票市场的预测,通过分析历史数据,可以帮助投资者预测未来的股票走势。

1.2 LSTM网络结构

LSTM主要依靠引入“门”机制来控制信息的传播。与循环神经网络RNN相比,LSTM的网络结构要复杂的多。在LSTM网络中,通过引入三个门来控制信息的传递,这三个门分别为遗忘门(forget gate),输入门(input gate)和输出门(output gate)。门机制是LSTM中重要的概念,那么什么是“门”以及门机制在LSTM中是如何解决长距离依赖的问题的。

RNN是一个包含大量重复神经网络模块的链式形式,在标准RNN里,这些重复的神经网络结构往往也非常简单,比如只包含单个tanh层:

标准RNN中只包含单个tanh层的重复模块,LSTM也有与之相似的链式结构,但不同的是它的重复模块结构不同,是4个以特殊方式进行交互的神经网络。LSTM示意图如下:

图中的符号含义如下:

在示意图中,从某个节点的输出到其他节点的输入,每条线都传递一个完整的向量。粉色圆圈表示pointwise操作,如节点求和,而黄色框则表示用于学习的神经网络层。合并的两条线表示连接,分开的两条线表示信息被复制成两个副本,并将传递到不同的位置。

LSTM的内部结构图如下:

图中ca2e01a80a0220069168f9b012ff4216.png代表遗忘门,cf5bcb9803a46fb739b2800951c1c319.png代表输入门,3091516090d9993be68608a46fdd16f3.png代表输出门。C是memroy cell,存储记忆信息。681ac60ef0697ba97c40ebbbff9872d3.png代表上一时刻的记忆信息,3802974735f2ec4406ecb0f40bb75db7.png代表当前时刻的记忆信息,h是LSTM单元的输出,5a90fed5f45bb9b10a9202b28941df7a.png是前一刻的输出。

原始RNN的隐藏层只有一个状态,即h,它对于短期的输入非常敏感。那么,假如我们再增加一个状态,即c,让它来保存长期的状态,如下图所示:

新增加的状态c,称为单元状态(cell state)。把上面的图按照时间维度展开:

在每个时刻t,LSTM的输入有三个:当前的输入值x(t),前一时刻LSTM的输出值h(t-1),前一时刻的单元状态c(t-1)。LSTM的输出有两个,当前时刻LSTM的输出值h(t),当前时刻的单元状态c(t)。

LSTM的关键,就是怎样控制长期状态c。在这里,LSTM的思路是使用三个控制开关。

  • 第一个开关,负责控制继续保存长期状态c;
  • 第二个开关,负责控制把即时状态输入到长期状态c;
  • 第三个开关,负责控制是否把长期状态c作为当前的LSTM的输出。

三个开关的作用如下图所示:

1.3 LSTM门机制

现实中的“门”通常解释为出入口,在LSTM网络的门也是一种出入口,但是是控制信息的出入口。门的状态通常有三种状态,分别为全开(信息通过概率为1),全闭(信息通过概率为0)以及半开(信息通过概率介于0和1之间)。在这里,我们发现对于全开,全闭以及半开三种状态下的信息通过可以通过概率来表示,在神经网络中,sigmoid函数也是一个介于0和1之间的表示,可以应用到LSTM中门的计算中。

开关在算法中用门来实现,门实际上就是一层全连接层,它的输入是一个向量,输出是一个0到1之间的实数向量。假设W是门的权重向量,b是偏置项,那么门可以表示为:

门的使用,就是用门的输出向量按元素乘以我们需要控制的那个向量。因为门的输出是0到1之间的实数向量,那么,当门输出为0时,任何向量与之相乘都会得到0向量,这就相当于啥都不能通过;输出为1时,任何向量与之相乘都不会有任何改变,这就相当于啥都可以通过。因为σ(也就是sigmoid函数)的值域是(0,1),所以门的状态都是半开半闭的。

LSTM一共有三个门,LSTM用两个门来控制单元状态c的内容:

  • 遗忘门(forget gate):它决定了上一时刻的单元状态c(t-1)有多少保留到当前时刻c(t);
  • 输入门(input gate):它决定了当前时刻网络的输入x(t)有多少保存到单元状态c(t)。
  • 输出门(output gate):它来控制单元状态c(t)有多少输出到LSTM的当前输出值h(t)。

遗忘门:控制上一时刻的单元状态

遗忘门的主要作用是用来决定当前的状态需要丢弃之前的那些信息。遗忘门是由前一个时刻的输出h和这个时刻的输入x决定的,遗忘门的计算传播如下图:

输入门:控制当前时刻的输入门

 输入门也是由上一时刻的输出h和这个时刻的输入t决定的,计算传播如下图:

除了遗忘门、输入门,还有当前时刻的单元状态c(这只是一个临时值,描述当前输入,由输入门控制)也是由前一时刻的输出h和这个时刻的输入x决定的,计算公式如下:

计算传播如下:

最终的要传到下一层的当前时刻的单元状态c,由遗忘门、输入门、描述输入的单元状态临时值、前一个时刻的最终单元状态共同决定。

圆圈表示按元素乘,计算规则如下图:

作用于一个向量和一个矩阵时广播。

前一个时刻的最终单元状态由遗忘门决定,当前单元状态的临时值由输入门决定,通过遗忘门和输入门将当前的记忆和长期的记忆组合在一起,形成最终的当前时刻的单元状态。

由于遗忘门的控制,它可以保存很久很久之前的信息,由于输入门的控制,它又可以避免当前无关紧要的内容进入记忆。

输出门:控制当前时刻的单元状态

当前时刻LSTM的输出由输出门控制,输出门控制了长期记忆对当前输出的影响,与当前时刻的输入x和前一时刻的输出h有关,计算公式如下:

输出门的计算传播如下:

最终输出的计算由当前时刻的最终单元状态c和输出门共同决定,最终单元状态不仅包括此时的记忆,还包括之前的记忆。计算公式如下:

LSTM的最终计算如下图:

1.4 双向LSTM

双向LSTM,由两个普通LSTM组成,能够同时利用过去和未来时刻的信息,推导当前时刻的信息。双向LSTM可以在序列中处理上下文上的信息,从而更好地进行处理。双向LSTM可以通过查看序列中的前后文本来预测每个时间步长的输出。

以自然语言处理为例,双向LSTM模型能比单向LSTM模型获得更好的语言模型。在NLP中,人们常常使用双向LSTM来捕捉词汇上下文信息和句子结构信息,提高语言模型的性能。具体网络结构如下:

多层LSTM结构如下 :

2 Pytorch LSTM输入输出

2.1 LSTM参数

torch.nn.LSTM(*args, **kwargs)

Parameters:

  • input_size – The number of expected features in the input x

  • hidden_size – The number of features in the hidden state h

  • num_layers – Number of recurrent layers. E.g., setting num_layers=2 would mean stacking two LSTMs together to form a stacked LSTM, with the second LSTM taking in outputs of the first LSTM and computing the final results. Default: 1

  • bias – If False, then the layer does not use bias weights b_ih and b_hh. Default: True

  • batch_first – If True, then the input and output tensors are provided as (batch, seq, feature) instead of (seq, batch, feature). Note that this does not apply to hidden or cell states. See the Inputs/Outputs sections below for details. Default: False

  • dropout – If non-zero, introduces a Dropout layer on the outputs of each LSTM layer except the last layer, with dropout probability equal to dropout. Default: 0

  • bidirectional – If True, becomes a bidirectional LSTM. Default: False

  • proj_size – If > 0, will use LSTM with projections of corresponding size. Default: 0

LSTM总共有七个参数,其中只有前三个是必须的。由于大家普遍使用PyTorch的DataLoader来形成批量数据,因此batch_first也比较重要。LSTM的两个常见的应用场景为文本处理和时序预测:

  • input_size:输入特征维度

(1)文本处理:在文本处理中,由于一个单词没法参与运算,因此我们得通过Word2Vec来对单词进行嵌入表示,将每一个单词表示成一个向量,此时input_size=embedding_size。比如每个句子中有五个单词,每个单词用一个100维向量来表示,那么这里input_size=100;

(2)时序数据处理:在时间序列预测中,比如需要预测负荷,每一个负荷都是一个单独的值,都可以直接参与运算,因此并不需要将每一个负荷表示成一个向量,此时input_size=1。 但如果我们使用多变量进行预测,比如我们利用前24小时每一时刻的[负荷、风速、温度、压强、湿度、天气、节假日信息]来预测下一时刻的负荷,那么此时input_size=7。

  • hidden_size:隐藏层节点个数。可以根据实际情况设置。
  • num_layers:层数。nn.LSTMCell与nn.LSTM相比,num_layers默认为1。
  • batch_first:默认为False。

LSTM默认batch_first=False,即默认batch_size这个维度是在数据维度的中间的那个维度,即喂入的数据为【seq_len, batch_size, hidden_size】这样的格式。此时:

lstm_out:【seq_len, batch_size, hidden_size * num_directions】
lstm_hn:【num_directions * num_layers, batch_size, hidden_size】

当设置batch_first=True时,喂入的数据就为【batch_size, seq_len, hidden_size】这样的格式。此时:

lstm_out:【 batch_size, seq_len, hidden_size * num_directions】
lstm_hn:【num_directions * num_layers, batch_size, hidden_size】

2.2 LSTM输入

 可以看到,输入由两部分组成:input、(初始的隐状态h_0,初始的单元状态c_0) ​ 其中input:

input(seq_len, batch_size, input_size)

当设置batch_first=True时:

input(batch_size, seq_len, input_size)
  • seq_len:在文本处理中,如果一个句子有7个单词,则seq_len=7;在时间序列预测中,假设我们用前24个小时的负荷来预测下一时刻负荷,则seq_len=24。
  • batch_size:一次性输入LSTM中的样本个数。在文本处理中,可以一次性输入很多个句子;在时间序列预测中,也可以一次性输入很多条数据。
  • input_size:输入特征维度。

(h_0, c_0):

h_0(num_directions * num_layers, batch_size, hidden_size)
c_0(num_directions * num_layers, batch_size, hidden_size)

h_0和c_0的shape一致。

  • num_directions:如果是双向LSTM,则num_directions=2;否则num_directions=1。
  • num_layers:层数。
  • batch_size:一次性输入LSTM中的样本个数。
  • hidden_size:隐藏层节点个数。

总结如下:

输入数据包括input,(h_0,c_0):

  • input就是shape==(seq_length,batch_size,input_size)的张量,batch_first默认为False
  • h_0的shape==(num_layers×num_directions,batch,hidden_size)的张量,它包含了在当前这个batch_size中每个句子的初始隐藏状态,num_layers就是LSTM的层数,如果
  • bidirectional=True,num_directions=2,否则就是1,表示只有一个方向,
  • c_0和h_0的形状相同,它包含的是在当前这个batch_size中的每个句子的初始细胞状态。
  • h_0,c_0如果不提供,那么默认是0
  • batch_first=True, 就是让batch在输入和输出放在最前面的维度

 2.3 LSTM输出

输出也由两部分组成:output、(隐状态h_n,单元状态c_n),其中output的shape为:

output(seq_len, batch_size, num_directions * hidden_size)

当设置batch_first=True时: 

output(batch_size, seq_len, num_directions * hidden_size)

h_n和c_n的shape保持不变

总结如下:

输出数据包括output,(h_n,c_n):`

  • output的shape==(seq_length,batch_size,num_directions×hidden_size),它包含的LSTM的最后一层的输出特征(h_t),t是batch_size中每个句子的长度。batch_first默认为False。
  • h_n是包含了所有层的信息。shape==(num_directions × num_layers,batch,hidden_size)
  • c_n.shape==h_n.shape
  • h_n包含的是句子的最后一个单词的隐藏状态,c_n包含的是句子的最后一个单词的细胞状态,所以它们都与句子的长度seq_length无关。
  • output[-1]与h_n是相等的,因为output[-1]包含的正是batch_size个句子中每一个句子的最后一个单词的隐藏状态,注意LSTM中的隐藏状态其实就是输出,cell state细胞状态才是LSTM中一直隐藏的,记录着信息。

2.4 隐藏层状态初始化

在LSTM网络训练过程中,每个batch都会将隐藏层重新初始化。

    for epoch in range(epochs):for index, (x_train, y_train) in enumerate(train_loader):cur_batch = len(x_train)h = model.init_hidden(cur_batch)  # 初始化第一个Hidden_statex_train, y_train = x_train.to(device), y_train.to(device)step += 1  # 训练次数+1

h与c是状态,不是参数,每个batch中都需要初始化为0,LSTM 中的参数是W,b。而LSTM网络中训练的是参数,不是状态。

每个batch训练,都要重新开始进行传播,不考虑两个batch之间的关系,所以都要进行隐藏状态的初始化。

3 基于LSTM实现情感分析

3.1 情感分析介绍

文本情感分析(Sentiment Analysis)是自然语言处理(NLP)方法中常见的应用,也是一个有趣的基本任务,尤其是以提炼文本情绪内容为目的的分类。它是对带有情感色彩的主观性文本进行分析、处理、归纳和推理的过程。
本文将介绍情感分析中的情感极性(倾向)分析。所谓情感极性分析,指的是对文本进行褒义、贬义、中性的判断。在大多应用场景下,只分为两类。例如对于“喜爱”和“厌恶”这两个词,就属于不同的情感倾向。
本文将详细介绍如何使用深度学习模型中的LSTM模型来实现文本的情感分析。

3.2 数据集介绍

以某电商网站中某个商品的评论作为语料(corpus.csv),该数据集一共有4310条评论数据,文本的情感分为两类:“正面”和“反面”,其中正面数据1908条,负面数据2375条。

evaluation,label
用了一段时间,感觉还不错,可以,正面
电视非常好,已经是家里的第二台了。第一天下单,第二天就到本地了,可是物流的人说车坏了,一直催,客服也帮着催,到第三天下午5点才送过来。父母年纪大了,买个大电视画面清晰,趁着耳朵还好使,享受几年。,正面
电视比想象中的大好多,画面也很清晰,系统很智能,更多功能还在摸索中,正面
不错,正面
用了这么多天了,感觉还不错。夏普的牌子还是比较可靠。希望以后比较耐用,现在是考量质量的时候。,正面
物流速度很快,非常棒,今天就看了电视,非常清晰,非常流畅,一次非常完美的购物体验,正面
非常好,客服还特意打电话做回访,正面
物流小哥不错,辛苦了,东西还没用,正面
......
价格给力,买的时候有点贵了,现在便宜了。,负面
价格欺诈,先把价格抬很好,然后降价,刚买了没几天,电视还没怎么体验呢,又降了200。有点心塞。询问客服,客服都不搭理的。物流师傅倒是不错,只是物流公司不按约定时间送货,随意更改。,负面
留意微鲸好久了,一直等待活动入手。可惜越等越贵,今年电视全部都涨价了,6月果断入手。用着还不错,一到跟儿子一起打开,他很开心,可以看巧虎,挂架是找了楼下装空调的师傅打了墙孔,有钻头我就自己搞定了,负面
买的第三台微鲸电视了,效果很好,送货快,推荐哦(????????)哦,就是今年涨价了,去年618 55寸只要2600而且还是lg的屏,今年换成京东方了,负面
买完就降价两百,负面
去nmd京东,说好30天价保。5月24号下单买的3198,6月1日直接给我降到2698!当时安装师傅都说买贵了,我还没在意,现在给我来这一出。去nmlgb的京东,当别人都是傻子吗?!,负面
去年1299元购买一台微鲸W43F,觉得不错。打算再买一台,谁知涨价了。经反复比较觉得还是微鲸性价比高,最后决定升级55寸4K大屏。内存2G+16G,还有语音遥控。悲催的是遥控器可能是坏的,正在申请售后。希望不要出什么麻烦。,负面
去年双十一的时候买了微鲸55寸的电视,使用感觉还可以,后来电视一直涨价,好在这次京东618的价格还算可以,虽然还是相比去年的价格还是上涨了不少,但这个也没办法,显示屏,内存,闪存的那些上游厂家都涨价了,可惜的就是43寸的电视在使用中感觉性能上略有不足,不过普通家庭看电视也可以了,负面
速度快,价格一般速度快,价格一般,负面
微鲸的性价比和操作性一直是比较好的,从去年到现在,给自己和亲戚买了五六个了,虽然液晶面板涨价,但总体来说还是划算的。和市面上大多的智能电视相比,软件安装不受限是个最大的优点,而且蓝牙遥控也很好用,比红外好操作。界面也很友好。,负面
微鲸电视不是第一个人,已经是买第二台了,一直觉得不错。嗯,但是价格比之前买的贵了,希望,又不过趁着618还是很划算的。,负面
微鲸电视超棒(⊙o⊙)哦,就是比去年贵不少,负面

数据集的下载地址:corpus.csv

3.3 基于pytorch的代码实现

3.3.1 数据集加载

data_path = 'data/corpus.csv'df = pd.read_csv(data_path)x = df['evaluation']y = df['label']texts_cut = [jieba.lcut(one_text) for one_text in x]label_set = set()for label in y:label_set.add(label)label_set = np.array(list(label_set))labels_one_hot = []for label in y:label_zero = np.zeros(len(label_set))label_zero[np.in1d(label_set, label)] = 1labels_one_hot.append(label_zero)labels = np.array(labels_one_hot)num_words = 3000tokenizer = Tokenizer(num_words=num_words)tokenizer.fit_on_texts(texts=texts_cut)num_words = min(num_words, len(tokenizer.word_index) + 1)sentence_len = 64texts_seq = tokenizer.texts_to_sequences(texts=texts_cut)texts_pad_seq = pad_sequences(texts_seq, maxlen=sentence_len, padding='post', truncating='post')# 拆分训练集和测试集x_train, x_test, y_train, y_test = train_test_split(texts_pad_seq, labels, test_size=0.2, random_state=1)train_dataset = TensorDataset(torch.from_numpy(x_train), torch.from_numpy(y_train))test_dataset = TensorDataset(torch.from_numpy(x_test), torch.from_numpy(y_test))batch_size = 32train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=True)

3.3.2 模型构建

import torch.nn as nn
import torchclass SentimentNet(nn.Module):device = torch.device('cuda') if torch.cuda.is_available() else torch.device("cpu")def __init__(self, vocab_size, input_dim, hid_dim, layers, output_dim):super(SentimentNet, self).__init__()self.n_layers = layersself.hidden_dim = hid_dimself.embeding_dim = input_dimself.output_dim = output_dimdrop_prob = 0.5self.lstm = nn.LSTM(self.embeding_dim, self.hidden_dim, self.n_layers,dropout=drop_prob, batch_first=True)self.fc = nn.Linear(in_features=self.hidden_dim, out_features=self.output_dim)self.sigmoid = nn.Sigmoid()self.dropout = nn.Dropout(drop_prob)self.embedding = nn.Embedding(vocab_size, self.embeding_dim)def forward(self, x, hidden):x = x.long()embeds = self.embedding(x)lstm_out, hidden = self.lstm(embeds, hidden)out = self.dropout(lstm_out)out = self.fc(out)out = self.sigmoid(out)out = out[:, -1, :]out = out.squeeze()out = out.contiguous().view(-1)return out, hiddendef init_hidden(self, batch_size):hidden = (torch.zeros(self.n_layers, batch_size, self.hidden_dim).to(self.device),torch.zeros(self.n_layers, batch_size, self.hidden_dim).to(self.device))return hidden

3.3.3 模型训练

    model = SentimentNet(num_words, 256, 128, 8, 2)lr = 0.0001optimizer = torch.optim.Adam(model.parameters(), lr=lr)criterion = nn.BCELoss()device = torch.device('cuda') if torch.cuda.is_available() else torch.device("cpu")epochs = 32step = 0model.train()  # 开启训练模式for epoch in range(epochs):for index, (x_train, y_train) in enumerate(train_loader):cur_batch = len(x_train)h = model.init_hidden(cur_batch)  # 初始化第一个Hidden_statex_train, y_train = x_train.to(device), y_train.to(device)step += 1  # 训练次数+1x_input = x_train.to(device)model.zero_grad()output, h = model(x_input, h)# 计算损失loss = criterion(output, y_train.float().view(-1))loss.backward()nn.utils.clip_grad_norm_(model.parameters(), max_norm=5)optimizer.step()if step % 32 == 0:print("Epoch: {}/{}...".format(epoch + 1, epochs),"Step: {}...".format(step),"Loss: {:.6f}...".format(loss.item()))epoch_loss.append(loss)

3.3.4 模型验证

    model.eval()loss = 0for data in tqdm(train_loader):x_train, y_train = datax_train, y_train = x_train.to(device), y_train.to(device)cur_batch = len(x_train)h = model.init_hidden(cur_batch)  # 初始化第一个Hidden_statex_input = x_train.long()x_input = x_input.to(device)output, h = model(x_input, h)loss += criterion(output, y_train.float().view(-1))print("test Loss: {:.6f}...".format(loss))

3.3.5 模型预测

    test_text_cut = [jieba.lcut("商品质量相当不错,点赞"),jieba.lcut("什么破东西,简直没法使用")]test_seq = tokenizer.texts_to_sequences(texts=test_text_cut)test_pad_seq = pad_sequences(test_seq, maxlen=sentence_len, padding='post', truncating='post')h = model.init_hidden(len(test_pad_seq))output, h = model(torch.tensor(test_pad_seq), h)print(output.view(-1, 2))

3.4 运行结果

Epoch: 1/32... Step: 108... Loss: 73.786831...
Epoch: 2/32... Step: 216... Loss: 64.638946...
Epoch: 3/32... Step: 324... Loss: 62.405033...
Epoch: 4/32... Step: 432... Loss: 55.636972...
Epoch: 5/32... Step: 540... Loss: 47.018067...
Epoch: 6/32... Step: 648... Loss: 42.855574...
Epoch: 7/32... Step: 756... Loss: 38.990385...
Epoch: 8/32... Step: 864... Loss: 36.197353...
Epoch: 9/32... Step: 972... Loss: 38.080607...
Epoch: 10/32... Step: 1080... Loss: 35.610960...
Epoch: 11/32... Step: 1188... Loss: 33.048675...
Epoch: 12/32... Step: 1296... Loss: 31.463715...
Epoch: 13/32... Step: 1404... Loss: 31.872352...
Epoch: 14/32... Step: 1512... Loss: 32.763812...
Epoch: 15/32... Step: 1620... Loss: 28.785963...
Epoch: 16/32... Step: 1728... Loss: 29.832949...
Epoch: 17/32... Step: 1836... Loss: 27.506568...
Epoch: 18/32... Step: 1944... Loss: 25.992162...
Epoch: 19/32... Step: 2052... Loss: 23.530551...
Epoch: 20/32... Step: 2160... Loss: 25.915338...
Epoch: 21/32... Step: 2268... Loss: 24.821649...
Epoch: 22/32... Step: 2376... Loss: 21.365095...
Epoch: 23/32... Step: 2484... Loss: 21.001188...
Epoch: 24/32... Step: 2592... Loss: 19.786633...
Epoch: 25/32... Step: 2700... Loss: 18.771839...
Epoch: 26/32... Step: 2808... Loss: 18.928787...
Epoch: 27/32... Step: 2916... Loss: 18.087029...
Epoch: 28/32... Step: 3024... Loss: 17.189056...
Epoch: 29/32... Step: 3132... Loss: 16.458333...
Epoch: 30/32... Step: 3240... Loss: 15.939349...
Epoch: 31/32... Step: 3348... Loss: 15.498337...
Epoch: 32/32... Step: 3456... Loss: 15.064007...
100%|██████████| 27/27 [00:01<00:00, 21.16it/s]
test Loss: 9.794393...
tensor([[0.9946, 0.0059],[0.0509, 0.9495]], grad_fn=<ViewBackward0>)

loss值变化曲线:

    x = [epoch + 1 for epoch in range(epochs)]plt.plot(x, epoch_loss_list)plt.xlim(0, 32)plt.ylim(0, 100)plt.show()

3.5 完整代码

代码:https://gitcode.net/ai-medical/lstm_sentiment_analyse

4 总结

LSTM通过其内部的门控机制,能够有效地处理长序列数据并捕捉序列中的长期依赖关系,因此在各种序列数据建模任务中具有广泛的应用前景。

相关文章:

深度学习:基于长短时记忆网络LSTM实现情感分析

目录 1 LSTM网络介绍 1.1 LSTM概述 1.2 LSTM网络结构 1.3 LSTM门机制 1.4 双向LSTM 2 Pytorch LSTM输入输出 2.1 LSTM参数 2.2 LSTM输入 2.3 LSTM输出 2.4 隐藏层状态初始化 3 基于LSTM实现情感分析 3.1 情感分析介绍 3.2 数据集介绍 3.3 基于pytorch的代码实现 3…...

selenium使用已经获取的cookies登录网站报错unable to set cookie的处理方式

用selenium半手动登录github获取其登录cookies后&#xff0c;保存到一个文件gtb_cookies.txt中。 然后用selenium使用这个cookies文件&#xff0c;免登录上github。但是报错如下&#xff1a;selenium.common.exceptions.UnableToSetCookieException: Message: unable to set co…...

初阶数据结构(四)带头双向链表

&#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;数据结构 &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &#x1f339;&#x1f339;&#x1f339;关注我带你学习编程知识 带头双向链表 链表的相关介绍初始化链表销毁链…...

2022年9月及10月

9月 1.Halcon12的HObject和Hobject halcon12 可以用HObject&#xff0c;也可以用Hobject&#xff0c;用法都一样 包括HalconCpp.h 如果附加目录中&#xff1a; C:\Program Files\MVTec\HALCON-12.0\include\halconcpp\ 在前面&#xff0c;则用 HalconCpp::HObject 如果附加目录…...

Vmware安装

title: “Vmware安装” createTime: 2021-11-22T09:53:2908:00 updateTime: 2021-11-22T09:53:2908:00 draft: false author: “name” tags: [“VMware”,“安装”,“linux”] categories: [“install”] description: “测试的” linux安装VMware Workstation16 1.安装包 …...

RSA算法

算法简介 RSA是一种非对称加密方式。发送者把明文通过公钥加密后发送出去&#xff0c;接受者把密文通过私钥解密得到明文。 算法过程 生成公钥和私钥 选取两个质数p和q&#xff0c;np*q。n的长度就是密钥长度。φ(n)(p-1)*(q-1)φ(n)为n的欧拉函数。找到1-φ(n)间与φ(n)互质的…...

计算机竞赛 深度学习手势识别 - yolo python opencv cnn 机器视觉

文章目录 0 前言1 课题背景2 卷积神经网络2.1卷积层2.2 池化层2.3 激活函数2.4 全连接层2.5 使用tensorflow中keras模块实现卷积神经网络 3 YOLOV53.1 网络架构图3.2 输入端3.3 基准网络3.4 Neck网络3.5 Head输出层 4 数据集准备4.1 数据标注简介4.2 数据保存 5 模型训练5.1 修…...

Spring的Ordered

Ordered Java中的Ordered接口是Spring框架中的一个接口&#xff0c;用于表示对象的顺序。它定义了一个方法getOrder()&#xff0c;用于获取对象的顺序值&#xff0c;值越小的对象越先被处理。 Ordered接口是Spring框架中的一个接口&#xff0c;用于定义组件的加载顺序。当一个…...

前端两年半,CSDN创作一周年

文章目录 一、机缘巧合1.1、起因1.2、万事开头难1.3、 何以坚持&#xff1f; 二、收获三、日常四、憧憬 五、总结 一、机缘巧合 1.1、起因 最开始接触CSDN&#xff0c;还是因为同专业的同学&#xff0c;将计算机实验课的实验题&#xff0c;记录总结并发在了专业群里。后来正式…...

定时任务管理平台青龙 QingLong

一、关于 QingLong 1.1 QingLong 介绍 青龙面板是支持 Python3、JavaScript、Shell、Typescript 多语言的定时任务管理平台&#xff0c;支持在线管理脚本和日志等。其功能丰富&#xff0c;能够满足大部分需求场景&#xff0c;值得一试。 主要功能 支持多种脚本语言&#xf…...

java多线程相关介绍

1. 线程的创建和启动 在 Java 中创建线程有两种方式。一种是继承 Thread 类并重写其中的 run() 方法&#xff0c;另一种是实现 Runnable 接口并重写其中的 run() 方法。创建完线程对象后&#xff0c;调用 start() 方法可以启动线程。 2. 线程的状态 Java 的线程在不同阶段会处于…...

css复合选择器

交集选择器 紧紧挨着 <template><div><p class"btn">Click me</p><button class"btn" ref"myButton" click"handleClick">Click me</button></div> </template> <style> but…...

USART串口协议

通信接口 •通信的目的&#xff1a;将一个设备的数据传送到另一个设备&#xff0c;扩展硬件系统 • 通信协议&#xff1a;制定通信的规则&#xff0c;通信双方按照协议规则进行数据收发 全双工&#xff1a;指通信双方能够同时进行双向通信&#xff0c;一般来说&#xff0c;全双…...

picoctf_2018_shellcode

picoctf_2018_shellcode Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments32位&#xff0c;啥都没开 这个看着挺大的&#xff0c;直接来个ROPchain&#xff0c;…...

Apache Derby的使用

Apache Derby是关系型数据库&#xff0c;可以嵌入式方式运行&#xff0c;也可以独立运行&#xff0c;当使用嵌入式方式运行时常用于单元测试&#xff0c;本篇我们就使用单元测试来探索Apache Derby的使用 一、使用IDEA创建Maven项目 打开IDEA创建Maven项目&#xff0c;这里我…...

leetcode 图相关的题

图 图相关知识有leetcode207课程表1(有环判断)以及210 课程表2(拓扑排序). 链表遍历 def dfs(n):print(n)dfs(n)二叉树遍历 def dfs(n):print(n)dfs(n.left)dfs(n.right)多叉树遍历 dfs(root) def dfs(n):for node in n.nodes:dfs(node)图遍历 visited [False] * n_node…...

程序员们,我们能工作到65岁吗?

软件开发人员的职业生涯可以持续多久&#xff1f;这是大多数认真考虑成为专业程序员的人不禁想知道的事情。 在谈论这样一个要求很高的职业时&#xff0c;这是一个非常自然的问题。没有人愿意花费数年时间学习一项技能&#xff0c;这些技能将在几年内不再相关&#xff0c;或者当…...

【洛谷 P1996】约瑟夫问题 题解(队列+模拟+循环)

约瑟夫问题 题目描述 n n n 个人围成一圈&#xff0c;从第一个人开始报数,数到 m m m 的人出列&#xff0c;再由下一个人重新从 1 1 1 开始报数&#xff0c;数到 m m m 的人再出圈&#xff0c;依次类推&#xff0c;直到所有的人都出圈&#xff0c;请输出依次出圈人的编号。…...

字符串函数与内存函数讲解

文章目录 前言一、字符串函数1.求字符串长度strlen 2.长度不受限制的字符串函数(1)strcpy(2)strcat(3)strcmp 3.长度受限制的字符串函数(1)strncpy(2)strncat(3)strncmp 4.字符串查找(1)strstr(2)strtok 5.错误信息报告(1)strerror(2)perror 二、内存函数1.memcpy2.memmove3.me…...

c语言系统编程之多进程

程序与进程的区别&#xff1f; 程序是静态的未运行的二进制文件&#xff0c;存储在磁盘中 进程是已经运行的二进制文件&#xff0c;存储在内存中 进程的内存划分图有哪几部分&#xff1f; 堆&#xff08;存储malloc和calloc出来的空间&#xff09;、栈&#xff08;局部变量…...

前端还是后端:探讨Web开发的两大街区

前端还是后端&#xff1a;探讨Web开发的两大街区 一、引言二、两者的对比分析技能要求和专业知识职责和工作内容项目类型和应用领域就业前景和市场需求 三、技能转换和跨领域工作四、全栈开发结语 一、引言 Web开发领域涉及到前端开发和后端开发这两个不同而又互为补充的领域。…...

JavaScript中如何确定this的值?如何指定this的值?

&#x1f380;JavaScript中的this 在绝大多数情况下&#xff0c;函数的调用方法决定了this的值&#xff08;运行时绑定&#xff09;。this不能在执行期间被赋值&#xff0c;并且在每次函数呗调用时this的值也可能会不同。 &#x1f37f;如何确定this的值&#xff1a; 在非严格…...

ubuntu下源码编译方式安装opencv

基础条件 ubuntu 20.04 opencv 3.4.3 opencv 源码编译的安装步骤 第一步&#xff0c; 首先clone源码 git clone https://github.com/opencv/opencv.git第二步&#xff0c;依赖包&#xff0c;执行下面的命令 sudo apt-get install build-essential sudo apt-get install cmak…...

spring boot整合常用redis客户端(Jedis、Lettuce、RedisTemplate、Redisson)常见场景解决方案

Java操作redis有三种客户端供选择&#xff1a;Jedis、Lettuce、Redisson。 在实际项目中运用最多的客户端还是Redisson、RedisTemplate&#xff1b;其中RedisTemplate并非是一个新的redis客户端实现&#xff0c;RedisTemplate是Spring Data Redis中提供的封装好的redis操作模板…...

HarmonyOS之运行Hello World

目录 下载与安装DevEco Studio 配置环境 创建项目 认识DevEco Studio界面 运行Hello World 了解基本工程目录 工程级目录 模块级目录...

postgresql数据库|wal日志的开启以及如何管理

一&#xff0c; wal的基本概念 WAL即Write Ahead Log预写式日志,简称wal日志,相当于oracle中的redo日志。只是oracle中redo是固定几个redo日志文件,然后轮着切换去写入。pg中wal日志是动态切换,单个wal日志写满继续写下一个wal日志&#xff0c;连续不断生成wal日志。&#xf…...

小波变换学习笔记【1】

【声明】本博客为学习B站视频小波分解与重构所做笔记&#xff0c;供自己和大家查阅学习&#xff0c;想查看 up 原视频请移步 B 站&#xff0c;侵删。 1.1 小波变换的由来 傅里叶变换基本思想&#xff1a;将信号分解成一系列不同频率的连续正弦波的叠加。 其缺点是&#xff0c;…...

雷柏mv20鼠标使用体验

用了1年多&#xff0c;第一次用竖着的鼠标&#xff0c;现在已经很习惯了&#xff0c;感觉还不错。说说使用感受&#xff1a; 1、 仍然是长时间使用鼠标&#xff0c;但是很少出现手腕痛的情况&#xff0c;确实是有一定效果的。 2、使用场景是有限制的&#xff0c;我是配合笔记…...

【分布式云储存】Springboot微服务接入MinIO实现文件服务

文章目录 前言技术回顾准备工作申请accessKey\secretKey创建数据存储桶公共资源直接访问测试 接入springboot实现文件服务依赖引入配置文件MinIO配置MinIO工具类 OkHttpSSLSocketClient兼容ssl静态资源预览解决方案资源上传预览测试测试结果 前言 上篇博客我们介绍了分布式云存…...

机器人中的数值优化|【四】L-BFGS理论推导与延伸

机器人中的数值优化|【四】L-BFGS理论推导与延伸 往期内容回顾 机器人中的数值优化|【一】数值优化基础 机器人中的数值优化|【二】最速下降法&#xff0c;可行牛顿法的python实现&#xff0c;以Rosenbrock function为例 机器人中的数值优化|【三】无约束优化&#xff0c;拟牛…...

常见网站安全漏洞/杭州明开seo

转载请注明&#xff1a;http://blog.csdn.net/xinzhangyanxiang/article/details/9774135 本篇笔记针对ML公开课的第七个视频&#xff0c;主要内容包括最优间隔分类器&#xff08;Optimal Margin Classifier&#xff09;、原始/对偶问题&#xff08;Primal/Dual Problem&#x…...

扬中做网站/怎么做自媒体

相信大家开始玩gitlabjenkins的时候对着两个工具有肯定有一定了解&#xff0c;我就不做详细解释了&#xff0c;下面就跟大家简单的说下gitlab&#xff0c;jenkins之间工作关系&#xff1a; GitLab是一个代码仓库&#xff0c;用来管理代码。Jenkins是一个自动化服务器&#xff0…...

网站未备案做seo会被k吗/个人网站推广

Syn攻击是最常见又最容易被利用的一种攻击手法&#xff0c;利用TCP协议的缺陷&#xff0c;发送大量伪造TCP连接请求&#xff0c;常用假冒的IP发来海量的SYN包&#xff0c;被攻击的服务器回应SYNACK&#xff0c;因为对方是假冒的IP&#xff0c;永远收不到包并且不会回应&#xf…...

网站开发技术 难点/活动策划公司

2021年湖北高考成绩查询时间&#xff0c;随着高考的结束&#xff0c;高考成绩的发布时间就成为了广大考生和家长所关注的问题&#xff0c;以下是小编整理的湖北高考成绩查询方式相关信息&#xff0c;希望对大家有所帮助&#xff01;下面就和小编一起来看看吧。 www.Tz365.cn202…...

知乎 做网站的公司 中企动力/照片查询百度图片搜索

表一 转载于:https://www.cnblogs.com/sallon/archive/2012/05/24/2516276.html...

做网站软件frontpage/广州白云区疫情实时动态

1.使用QT自带的布局类能去掉控件的间隙吗&#xff1f; 下面是QT的设计师界面&#xff0c;我在一个QWidget上面放了4个按钮&#xff0c;并且把这4个按钮放到了一个水平布局内&#xff0c;大家看右下角的参数&#xff0c;我已经全部设置为0&#xff0c;但是从界面上依然能直观低…...