Detailed Explanation of Douyin False Information Recognition Based on LSTM+Attention and RNN--From Data Acquisition to Model Building Training

From LSTM to LSTM-attention

LSTM source:

RNN problem: long-term dependence problem and gradient disappearance problem, so LSTM is proposed.

The RNN structure diagram is shown in the figure

 LSTM structure:

LSTM is a variant of RNN. LSTM introduces a set of memory units (Memory Units), allowing the network to learn when to forget historical information and when to update memory units with new information.

Core: memory (cell state) and gating mechanism

The state of the cell runs on the entire chain, and only some small linear operations are applied to it, and the information can easily flow through the entire chain unchanged.

A Gate is a way to optionally let information pass through. It consists of a sigmoid neural network layer and a point multiplication operation.

The Sigmoid neural network layer outputs a number between 0 and 1. This number describes how much information each component can pass through. 0 means no information is passed, and 1 means all pass.

 LSTM-Attention model

LSTM-Attention model is a model based on recurrent neural network (RNN) and attention mechanism (Attention). It performs well in the processing of long text or sequence data, and can be used in fields such as natural language processing (NLP), speech recognition, video classification, etc.

 The core of the LSTM-Attention model is to embed the attention mechanism into the LSTM network, so that the network can automatically learn and focus on the most important information in the input sequence. In a traditional LSTM network, the output at each time step is fixed, no matter which part of the input sequence has the most influence on the output at the current time step. The LSTM-Attention model can adaptively calculate the output of each time step according to the content of the input sequence, making the model more flexible and accurate.

The working principle of the LSTM-Attention model is as follows:

Each element of the input sequence is converted into a vector representation by an embedding layer.

The LSTM network processes the output of the embedding layer to generate an output sequence that includes all time steps.

For the output of each time step, a weight vector is calculated by the attention mechanism, which represents the importance of each element in the input sequence at the current time step.

The output of all time steps and the corresponding weight vector are weighted and summed to generate the final representation.

The final representation passes through a fully connected layer and outputs the prediction result of the model.

It should be noted that different LSTM-Attention models may have different implementations, such as different attention mechanisms or different network architectures. But in general, the LSTM-Attention model is based on the combination of RNN and Attention mechanism, an efficient model for processing sequence data.

Douyin comment crawling

Only the user name and comments are crawled here. The id and url can be replaced with the web pages you need, and the path behind userName and comment can be modified by yourself.

# 打开页面后,尽量直接拉到评论下面!!!!
import random
import pandas as pd
import time
from selenium import webdriver
from tqdm import tqdm, trange
from selenium.webdriver.common.by import By
from selenium.webdriver import ChromeOptions

# 实现规避检测
option = ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])


def getData(url):

    # chromedriver.exe,下载,这个看自己安装的Google的版本,下载解压后放到当前代码路径下。下载地址 http://chromedriver.storage.googleapis.com/index.html
    driver = webdriver.Chrome(options=option)
    driver.get(url)
    time.sleep(20) # 手动点下弹窗关闭登录,或者自己扫码登录!!!

    userNames = []  # 用户名
    comments = []   # 评论文本


    for i in trange(1, 1000):  # 自行设定爬取条数,不建议太多!!!

        try:
            # 去掉中途出现的登录页面
            driver.find_element(by=By.XPATH,
                                value='//*[@id="login-pannel"]/div[2]').click()
            print("1")
        except:
            try:
                # 用户名
                userName = driver.find_element(by=By.XPATH,
                                            value= f"//*[@id='douyin-right-container']/div[2]/div/div[1]/div[5]/div/div/div[3]/div[{i}]/div/div[2]/div/div[1]/div[1]/div/a/span/span/span/span/span/span").text
                print(userName)
                # 评论
                comment = driver.find_element(by= By.XPATH,
                                              value= f"//*[@id='douyin-right-container']/div[2]/div/div[1]/div[5]/div/div/div[3]/div[{i}]/div/div[2]/div[1]/p/span/span/span/span/span/span/span").text

                print(comment)
                userNames.append(userName)
                comments.append(comment)
                print(f"第{i}条下载完成!!!")
            except:
                continue
    return userNames, comments

if __name__ == "__main__":

    id = "7220016152687201593"  # 这串数字是视频ID
    url = f"https://www.douyin.com/video/{id}"
    userNames, comments = getData(url)
    print(userNames,comments)
    data = pd.DataFrame({"userName":userNames, "comments": comments})
    data.to_csv(f"./result_ID{id}.csv") # save path
    print("**********done***********")

crawl results

 Note: After crawling Douyin's comments, I found that there are no rumors in them. Many of them are happy comments from netizens. If you continue to achieve this effect, the effect will be very bad, so I just use this data to go through the process. The step of processing the data to whether it is a rumor or not is stopped. Here is my code for processing this data.

  1. The crawled data is stored in the csv file, which needs to be converted into json format first, and jieba is used for simple word segmentation in this process.
    import pandas as pd
    import jieba
    import json
    import os
    
    # 获取当前工作目录
    cwd = os.getcwd()
    
    # 将相对路径转换为绝对路径
    csv_path = os.path.abspath('./Douyin-main/DY.csv')
    
    # 使用绝对路径读取CSV文件
    df = pd.read_csv(csv_path, encoding='utf-8')
    
    
    # 对数据做中文分词去噪处理
    def clean_text(text):
        text = str(text)
        # 去掉换行符、制表符、多余空格
        text = text.replace('\n', '').replace('\t', '').strip()
        # 分词并去掉停用词
        stop_words = set(['的', '了', '是', '在', '我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这'])
        words = jieba.cut(text)
        words = [w for w in words if w not in stop_words]
        return ' '.join(words)
    
    data = []
    
    
    with open('./Douyin-main/DY.json', 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False)
        f.write('\n')
    
    with open('./Douyin-main/DY.json', 'w', encoding='utf-8') as f: 
        for index, row in df.iterrows(): 
            item = { 'id': row['id'], 'userName': row['userName'], 'comments': clean_text(row['comments']) } 
            json.dump(item, f, ensure_ascii=False) 
            f.write('\n')

    The resulting json is as follows:

  2. Divide each piece of data in the above json file into a json file
    import json
    import os
    
    # 创建all文件夹
    if not os.path.exists('./Douyin-main/all'):
        os.makedirs('./Douyin-main/all')
    
    # 打开包含多个JSON对象的文件
    with open('./Douyin-main/DY.json', 'r', encoding='utf-8') as f:
        json_data = f.read()
    
    # 将JSON字符串按照换行符分割成一个列表
    json_objects = json_data.strip().split('\n')
    
    # 遍历列表,将每个JSON对象存储到单独的文件中
    for i, json_str in enumerate(json_objects):
        # 将JSON字符串转换为Python对象
        json_obj = json.loads(json_str)
    
        # 将Python对象转换为JSON字符串,格式化输出到文件中
        with open(f'./Douyin-main/all/json_obj_{i}.json', 'w', encoding='utf-8') as out_file:
            out_file.write(json.dumps(json_obj, ensure_ascii=False, indent=4))

    Next, if you want to label the data yourself, you need to manually divide the rumors and non-rumors into two folders.

Realization principle

In this practice, a rumor detection model based on a recurrent neural network (RNN) is used to vectorize rumor events in the text, and the deep features of the text are mined through the learning and training of the recurrent neural network, which avoids the problem of feature construction and can discover Those features that are not easy to be found, thus producing better results.

Dataset introduction:

The data used in this practice is the Chinese rumor data captured from the false information reporting platform of Sina Weibo. The data set contains a total of 1538 rumors and 1849 non-rumors. Each piece of data is in json format, where the text field represents the text content of the original Weibo.

Dataset introduction reference https://github.com/thunlp/Chinese_Rumor_Dataset

environment settings

The missing package can be downloaded with the following command

The python environment required by the paddle package is 3.8 or below. I use 3.8 here, and other packages are easy to install.

pip install numpy==1.23.5 -i https://pypi.tuna.tsinghua.edu.cn/simple

data processing

The following data is the data used in the project, which is the marked rumor data downloaded from the Internet

(1) Decompress the data, read and parse the data, and generate all_data.txt

(2) Generate a data dictionary, namely dict.txt

(3) Generate a data list, and divide the training set and verification set, train_list.txt, eval_list.txt

(4) Define the training data set provider train_reader and the verification data set provider eval_reader

  • Generate all_data.txt
import zipfile
import os
import io
import random
import json
import matplotlib.pyplot as plt
import numpy as np
import paddle
import paddle.fluid as fluid
from paddle.fluid.dygraph.nn import Conv2D, Linear, Embedding
from paddle.fluid.dygraph.base import to_variable


target_path = "."

#谣言数据文件路径
rumor_class_dirs = os.listdir(target_path+"/CED_Dataset/rumor-repost/")

#非谣言数据文件路径
non_rumor_class_dirs = os.listdir(target_path+"/CED_Dataset/non-rumor-repost/")

original_microblog = target_path+"/CED_Dataset/original-microblog/"


#谣言标签为0,非谣言标签为1
rumor_label="0"
non_rumor_label="1"

#分别统计谣言数据与非谣言数据的总数
rumor_num = 0
non_rumor_num = 0
all_rumor_list = []
all_non_rumor_list = []

#解析谣言数据
for rumor_class_dir in rumor_class_dirs: 
    if(rumor_class_dir != '.DS_Store'):
        #遍历谣言数据,并解析
        try:
            with open(original_microblog + rumor_class_dir, 'r',encoding='utf-8') as f:
                rumor_content = f.read()
            rumor_dict = json.loads(rumor_content)
            all_rumor_list.append(rumor_label+"\t"+rumor_dict["text"]+"\n")
            rumor_num +=1
        except:
            print("无法读取文件:"+rumor_class_dir)
            continue
#解析非谣言数据
for non_rumor_class_dir in non_rumor_class_dirs: 
    if(non_rumor_class_dir != '.DS_Store'):
        try:
            with open(original_microblog + non_rumor_class_dir, 'r',encoding='utf-8') as f2:
                non_rumor_content = f2.read()
            non_rumor_dict = json.loads(non_rumor_content)
            all_non_rumor_list.append(non_rumor_label+"\t"+non_rumor_dict["text"]+"\n")
            non_rumor_num +=1
        except:
            print("无法读取文件:"+non_rumor_class_dir)
            continue
        
print("谣言数据总量为:"+str(rumor_num))
print("非谣言数据总量为:"+str(non_rumor_num))

#全部数据进行乱序后写入all_data.txt
data_list_path="./"
all_data_path=data_list_path + "all_data.txt"
all_data_list = all_rumor_list + all_non_rumor_list

random.shuffle(all_data_list)

#在生成all_data.txt之前,首先将其清空
with open(all_data_path, 'w') as f:
    f.seek(0)
    f.truncate() 
    
with open(all_data_path, 'a') as f:
    for data in all_data_list:
        f.write(data) 
print('all_data.txt已生成')

 Generate the following files:

 

  • generate data dictionary
# 生成数据字典
data_path = "./all_data.txt"
dict_path = "./dict_data.txt"

# 生成数据字典
def create_dict(data_path, dict_path):
    with open(dict_path, 'w') as f:
        f.seek(0)
        f.truncate() 

    dict_set = set()
    # 读取全部数据
    with open(data_path, 'r', encoding='utf-8') as f:
        lines = f.readlines()
    # 把数据生成一个元组
    for line in lines:
        content = line.split('\t')[-1].replace('\n', '')
        for s in content:
            dict_set.add(s)
    # 把元组转换成字典,一个字对应一个数字
    dict_list = []
    i = 0
    for s in dict_set:
        dict_list.append([s, i])
        i += 1
    # 添加未知字符
    dict_txt = dict(dict_list)
    end_dict = {"<unk>": i}
    dict_txt.update(end_dict)
    end_dict = {"<pad>": i+1}
    dict_txt.update(end_dict)
    # 把这些字典保存到本地中
    with open(dict_path, 'w', encoding='utf-8') as f:
        f.write(str(dict_txt))

    print("数据字典生成完成!")


create_dict(data_path, dict_path)

 Generate the following files:

  • generate data list
import os

data_list_path = './'

# 创建序列化表示的数据,并按照一定比例划分训练数据train_list.txt与验证数据eval_list.txt
def create_data_list(data_list_path):
    #在生成数据之前,首先将eval_list.txt和train_list.txt清空
    with open(os.path.join(data_list_path, 'eval_list.txt'), 'w', encoding='utf-8') as f_eval:
        f_eval.seek(0)
        f_eval.truncate()
        
    with open(os.path.join(data_list_path, 'train_list.txt'), 'w', encoding='utf-8') as f_train:
        f_train.seek(0)
        f_train.truncate() 
    
    with open(os.path.join(data_list_path, 'dict_data.txt'), 'r', encoding='utf-8') as f_data:
        dict_txt = eval(f_data.readlines()[0])

    with open(os.path.join(data_list_path, 'all_data.txt'), 'r', encoding='utf-8') as f_data:
        lines = f_data.readlines()

    i = 0
    maxlen = 0
    with open(os.path.join(data_list_path, 'eval_list.txt'), 'a', encoding='utf-8') as f_eval,open(os.path.join(data_list_path, 'train_list.txt'), 'a', encoding='utf-8') as f_train:
        for line in lines:
            words = line.split('\t')[-1].replace('\n', '')
            maxlen = max(maxlen, len(words))
            label = line.split('\t')[0]
            labs = ""
            # 每8个 抽取一个数据用于验证
            if i % 8 == 0:
                for s in words:
                    lab = str(dict_txt[s])
                    labs = labs + lab + ','
                labs = labs[:-1]
                labs = labs + '\t' + label + '\n'
                f_eval.write(labs)
            else:
                for s in words:
                    lab = str(dict_txt[s])
                    labs = labs + lab + ','
                labs = labs[:-1]
                labs = labs + '\t' + label + '\n'
                f_train.write(labs)
            i += 1
        
    print("数据列表生成完成!")
    print("样本最长长度:" + str(maxlen))


create_data_list(data_list_path)

Generate the following files:

  •  Define the training dataset provider
import os
import sys
import json
import torch.nn as nn
import torch
import matplotlib
import paddle
import io
import random
import numpy as np


# # 把生成的数据列表都放在自己的总类别文件夹中
data_root_path = "./"


def data_reader(file_path, phrase, shuffle=False):
    all_data = []
    with io.open(file_path, "r", encoding='utf8') as fin:
        for line in fin:
            cols = line.strip().split("\t")
            if len(cols) != 2:
                continue
            label = int(cols[1])
            
            wids = cols[0].split(",")
            all_data.append((wids, label))

    if shuffle:
        if phrase == "train":
            random.shuffle(all_data)

    def reader():
        for doc, label in all_data:
            yield doc, label
    return reader

class SentaProcessor(object):
    def __init__(self, data_dir,):
        self.data_dir = data_dir
        
    def get_train_data(self, data_dir, shuffle):
        return data_reader((self.data_dir + "train_list.txt"), 
                            "train", shuffle)

    def get_eval_data(self, data_dir, shuffle):
        return data_reader((self.data_dir + "eval_list.txt"), 
                            "eval", shuffle)

    def data_generator(self, batch_size, phase='train', shuffle=True):
        if phase == "train":
            return paddle.batch(
                self.get_train_data(self.data_dir, shuffle),
                batch_size,
                drop_last=True)
        elif phase == "eval":
            return paddle.batch(
                self.get_eval_data(self.data_dir, shuffle),
                batch_size,
                drop_last=True)
        else:
            raise ValueError(
                "Unknown phase, which should be in ['train', 'eval']")



def load_vocab(file_path):
    fr = open(file_path, 'r', encoding='utf8')
    vocab = eval(fr.read())   #读取的str转换为字典
    fr.close()

    return vocab


# 打印前2条训练数据
vocab = load_vocab(os.path.join(data_root_path, 'dict_data.txt'))
if "<pad>" not in vocab:
    vocab["<pad>"] = len(vocab)
    with open(os.path.join(data_root_path, 'dict_data.txt'), 'w', encoding='utf-8') as f:
        f.write(str(vocab))


# print(vocab.keys())

def ids_to_str(ids):
    words = []
    for k in ids:
        w = list(vocab.keys())[list(vocab.values()).index(int(k))]
        words.append(w if isinstance(w, str) else w.decode('ASCII'))
    return " ".join(words)


file_path = os.path.join(data_root_path, 'train_list.txt')
with io.open(file_path, "r", encoding='utf8') as fin:
    i = 0
    for line in fin:
        i += 1
        cols = line.strip().split("\t")
        if len(cols) != 2:
            sys.stderr.write("[NOTICE] Error Format Line!")
            continue
        label = int(cols[1])
        wids = cols[0].split(",")
        print(str(i) + ":")
        print('sentence list id is:', wids)
        print('sentence list is: ', ids_to_str(wids))
        print('sentence label id is:', label)
        print('---------------------------------')

        if i == 2: break

vocab = load_vocab(os.path.join(data_root_path, 'dict_data.txt'))


class RumorDataset(paddle.io.Dataset):
    def __init__(self, data_dir):
        self.data_dir = data_dir
        self.all_data = []

        with io.open(self.data_dir, "r", encoding='utf8') as fin:
            for line in fin:
                cols = line.strip().split("\t")
                if len(cols) != 2:
                    sys.stderr.write("[NOTICE] Error Format Line!")
                    continue
                label = []
                label.append(int(cols[1]))
                wids = cols[0].split(",")
                if len(wids) >= 150:
                    wids = np.array(wids[:150]).astype('int64')
                else:
                    wids = np.concatenate([wids, [vocab["<pad>"]] * (150 - len(wids))]).astype('int64')
                label = np.array(label).astype('int64')
                self.all_data.append((wids, label))

    def __getitem__(self, index):
        data, label = self.all_data[index]
        return data, label

    def __len__(self):
        return len(self.all_data)


batch_size = 8
train_dataset = RumorDataset(os.path.join(data_root_path, 'train_list.txt'))
test_dataset = RumorDataset(os.path.join(data_root_path, 'eval_list.txt'))

train_loader = paddle.io.DataLoader(train_dataset, places=paddle.CPUPlace(), return_list=True,
                                    shuffle=True, batch_size=batch_size, drop_last=True)
test_loader = paddle.io.DataLoader(test_dataset, places=paddle.CPUPlace(), return_list=True,
                                   shuffle=True, batch_size=batch_size, drop_last=True)
# check

print('=============train_dataset =============')
for data, label in train_dataset:
    print(data)
    print(np.array(data).shape)
    print(label)
    break

print('=============test_dataset =============')
for data, label in test_dataset:
    print(data)
    print(np.array(data).shape)
    print(label)
    break

model building

model.py


import paddle
from paddle.nn import Conv2D, Linear, Embedding
from paddle import to_tensor
import paddle.nn.functional as F
import data_reader



class RNN(paddle.nn.Layer):
    def __init__(self):
        super(RNN, self).__init__()
        self.dict_dim = data_reader.vocab["<pad>"]
        self.emb_dim = 128
        self.hid_dim = 128
        self.class_dim = 2
        self.embedding = Embedding(
            self.dict_dim + 1, self.emb_dim,
            sparse=False)
        self._fc1 = Linear(self.emb_dim, self.hid_dim)
        self.lstm = paddle.nn.LSTM(self.hid_dim, self.hid_dim)
        self.fc2 = Linear(19200, self.class_dim)

    def forward(self, inputs):
        # [32, 150]
        emb = self.embedding(inputs)
        # [32, 150, 128]
        fc_1 = self._fc1(emb)#第一层
        # [32, 150, 128]
        x = self.lstm(fc_1)
        x = paddle.reshape(x[0], [0, -1])
        x = self.fc2(x)
        x = paddle.nn.functional.softmax(x)
        return x

rnn = RNN()
paddle.summary(rnn,(32,150),"int64")



# class RNN(paddle.nn.Layer):
#     def __init__(self):
#         super(RNN, self).__init__()
#         self.dict_dim = data_reader.vocab["<pad>"]
#         self.emb_dim = 128
#         self.hid_dim = 128
#         self.class_dim = 2
#         self.embedding = Embedding(
#             self.dict_dim + 1, self.emb_dim, sparse=False)
#         self._fc1 = Linear(self.emb_dim, self.hid_dim)
#         self.lstm = paddle.nn.LSTM(self.hid_dim, self.hid_dim)
#         self.fc2 = Linear(19200, self.class_dim)
#         self.attention_layer = paddle.nn.Linear(self.hid_dim, 1)

#     def forward(self, inputs):
#         # [32, 150]
#         emb = self.embedding(inputs)
#         # [32, 150, 128]
#         fc_1 = self._fc1(emb)
#         # [32, 150, 128]
#         lstm_out, (h_n, c_n) = self.lstm(fc_1)
#         # [32, 150, 1]
#         attn_weights = self.attention_layer(lstm_out)
#         # [32, 150]
#         attn_weights = paddle.nn.functional.softmax(attn_weights, axis=1)
#         # [32, 128]
#         attn_output = paddle.sum(lstm_out * attn_weights, axis=1)
#         x = paddle.reshape(attn_output, [0, -1])
#         x = self.fc2(x)
#         x = F.softmax(x)
#         return x


# rnn = RNN()
# paddle.summary(RNN, (32, 150), "int64")

# print(rnn)

 In the above code, the front part is only the framework implemented by LSTM, and the commented out part is implemented by LSTM-Attention. The effect of LSTM-Attention is not very good. I don’t know why.

The architecture diagram after running is:

train.py

import os
import sys
import json
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import transforms, datasets
from tqdm import tqdm
import paddle.fluid as fluid
from model import RNN
import paddle
import data_reader
import matplotlib.pyplot as plt
from PIL import Image


def draw_process(title,color,iters,data,label):
    plt.title(title, fontsize=24)
    plt.xlabel("iter", fontsize=20)
    plt.ylabel(label, fontsize=20)
    plt.plot(iters, data,color=color,label=label)
    plt.legend()
    plt.grid()
    plt.show()



def train(model):
    model.train()
    opt = paddle.optimizer.Adam(learning_rate=0.002, parameters=model.parameters())

    steps = 0
    Iters, total_loss, total_acc = [], [], []

    for epoch in range(5):
        for batch_id, data in enumerate(data_reader.train_loader):
            steps += 1
            sent = data[0]
            label = data[1]

            logits = model(sent)
            loss = paddle.nn.functional.cross_entropy(logits, label)
            acc = paddle.metric.accuracy(logits, label)

            if batch_id % 50 == 0:
                Iters.append(steps)
                total_loss.append(loss.numpy()[0])
                total_acc.append(acc.numpy()[0])

                print("epoch: {}, batch_id: {}, loss is: {}".format(epoch, batch_id, loss.numpy()))

            loss.backward()
            opt.step()
            opt.clear_grad()

        # evaluate model after one epoch
        model.eval()
        accuracies = []
        losses = []

        for batch_id, data in enumerate(data_reader.test_loader):
            sent = data[0]
            label = data[1]

            logits = model(sent)
            loss = paddle.nn.functional.cross_entropy(logits, label)
            acc = paddle.metric.accuracy(logits, label)

            accuracies.append(acc.numpy())
            losses.append(loss.numpy())

        avg_acc, avg_loss = np.mean(accuracies), np.mean(losses)

        print("[validation] accuracy: {}, loss: {}".format(avg_acc, avg_loss))

        model.train()

    paddle.save(model.state_dict(), "model_final.pdparams")

    draw_process("trainning loss", "red", Iters, total_loss, "trainning loss")
    draw_process("trainning acc", "green", Iters, total_acc, "trainning acc")


model = RNN()
train(model)

The result of the operation is as follows

 

to_eval.py

import os
import sys
import json
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import transforms, datasets
from tqdm import tqdm
import paddle.fluid as fluid
from model import RNN
import paddle
import data_reader
import matplotlib.pyplot as plt
from PIL import Image

'''
模型评估
'''
model_state_dict = paddle.load('model_final.pdparams')
model = RNN()
model.set_state_dict(model_state_dict)
model.eval()
label_map = {0: "是", 1: "否"}
samples = []
predictions = []
accuracies = []
losses = []

for batch_id, data in enumerate(data_reader.test_loader):

    sent = data[0]
    label = data[1]

    logits = model(sent)

    for idx, probs in enumerate(logits):
        # 映射分类label
        label_idx = np.argmax(probs)
        labels = label_map[label_idx]
        predictions.append(labels)
        samples.append(sent[idx].numpy())

    loss = paddle.nn.functional.cross_entropy(logits, label)
    acc = paddle.metric.accuracy(logits, label)

    accuracies.append(acc.numpy())
    losses.append(loss.numpy())

avg_acc, avg_loss = np.mean(accuracies), np.mean(losses)
print("[validation] accuracy: {}, loss: {}".format(avg_acc, avg_loss))
print('数据: {} \n\n是否谣言: {}'.format(data_reader.ids_to_str(samples[0]), predictions[0]))

The result of the operation is as follows:

Each time a piece of data in the test set is randomly selected for judgment

Reference article:

Notes & Practice | Rumor Detection Based on LSTM | First Understanding of Long Short Memory Neural Network_Big Data World Olu's Blog-CSDN Blog

Graduation project realizes rumor detection based on CNN - python deep learning machine learning_ rumor detection code_DanCheng-studio's blog-CSDN blog

Guess you like

Origin blog.csdn.net/weixin_45897172/article/details/130352921