Logo
Section 1 / 6

数据预处理

学习如何在使用LSTM模型之前,使用NLTK对数据进行清洗和预处理。

导入

数据预处理

学习如何在使用LSTM模型之前,使用NLTK对数据进行清洗和预处理。

我需要回顾一下

加载数据集

我们将使用世界杯推文数据集。通过 pandas 加载该数据集,并展示部分推文样本。

从 CSV 文件读取数据到 pandas DataFrame 中

1import pandas as pd 2 3df = pd.read_csv("/usr/local/notebooks/worldcup-tweets.csv") 4print(df.head())

在上述代码中:

  • 第1行:我们导入 pandas 库并简写为 pd,用于读取 CSV 文件。

  • 第2–3行:调用 pandas 的 read_csv() 方法来加载世界杯推文数据集。最后调用 DataFrame 的 head() 方法打印出文件的前几行。

使用 NLTK 进行数据处理

该数据集中包含了一些对判断推文情感(正面或负面)无用的字符,例如标点符号和特殊字符。因此我们需要将这些内容从推文中移除。
同时,还需要将 sentiment 列转换为数值形式表示,这可以通过 scikit-learn 提供的 LabelEncoder 实现。

此外,推文中还包含一些不利于情感分析的词语,比如英语中的常见词:the、at、and 等,这类词被称为停用词(stopwords)。我们将借助 nltk 库来去除这些停用词。首先定义一个函数以移除所有英文停用词,并将其应用于推文列。

移除停用词

1import nltk 2from nltk.corpus import stopwords 3nltk.download('stopwords', quiet=True) 4 5def remove_stop_words(tweets): 6 tweets_minus_sw = [] 7 stop_words = stopwords.words('english') 8 tweets = tweets.split() 9 cleaned_tweets = [tweets_minus_sw.append(word) for word in tweets if word.lower() not in stop_words] 10 cleaned_tweets = ' '.join(tweets_minus_sw) 11 return cleaned_tweets 12 13df['tweets'] = df['tweets'].apply(remove_stop_words) 14print(df)

在上述代码中:

  • 第1–2行:导入 nltk 库以及来自 nltk.corpus 的 stopwords 模块。

  • 第3行:调用 nltk.download() 方法下载 stopwords 数据集,设置 quiet=True 以关闭下载日志输出。

  • 第5–11行:定义 remove_stop_words() 函数,用于移除输入文本中的停用词并返回清理后的结果。函数内部:

    • 第6行:创建空列表 tweets_minus_sw,用于存储去除停用词后的单词。

    • 第7行:从 stopwords 模块获取英文停用词列表。

    • 第8行:调用 split() 方法将输入字符串拆分为单词列表。

    • 第9行:使用 for 循环遍历每个单词,若其小写形式不在停用词列表中,则添加至 tweets_minus_sw。

    • 第10–11行:使用 ' '.join() 将列表合并成字符串并返回。

  • 第13–14行:将 remove_stop_words 函数应用到 DataFrame df 的 tweets 列上以清除停用词,最后打印处理后的 DataFrame。

接下来,我们也把情感列转换为数值表示。

对正面与负面情感进行编码

1from sklearn.preprocessing import LabelEncoder 2 3labelencoder = LabelEncoder() 4df = df.assign(sentiment = labelencoder.fit_transform(df["sentiment"])) 5print(df)

在上述代码中:

  • 第1行:从 sklearn.preprocessing 模块导入 LabelEncoder。

  • 第3行:创建一个 LabelEncoder 类的实例。

  • 第4行:使用 LabelEncoder 的 fit_transform() 方法将 sentiment 列的值转换为数值形式。

  • 第5行:打印 DataFrame df,此时可以看到 sentiment 列已变为数值。

我们对比一下原始推文与去除停用词后的推文。

观察部分推文可以发现,像 this、was、a 这样的词已被删除,但仍然能看到一些特殊字符存在。接下来我们解决这个问题。

移除标点符号和特殊字符

目前情感列已经完成数值化处理,但推文仍是文本格式,还需将其向量化。
我们首先从推文中移除标点符号和其他特殊字符。

使用正则表达式移除标点符号及其他特殊字符

1import re 2 3def re_sub(review_sentence): 4 review = re.sub('[^a-zA-Z]', ' ', review_sentence) 5 return review 6 7df['tweets'] = df['tweets'].map(re_sub) 8docs = df['tweets'] 9print(docs)

在上述代码中:

  • 第1行:导入 re 模块,用于支持正则表达式操作。

  • 第3–5行:定义 re_sub() 函数以移除非字母字符。函数内部使用 re.sub() 方法将所有非字母字符替换为空格,并将结果存入变量 review,最后返回该变量。

  • 第7行:将 re_sub 函数映射到数据集的 tweets 列,并更新其值。

  • 第8–9行:将 tweets 列的数据赋值给变量 docs 并打印输出。

去除重复项

我们先从数据集中删除重复的记录。

从数据集中删除重复项

1print("去重前总行数:", len(df)) 2 3df = df.drop_duplicates() 4 5print("去重后总行数:", len(df))

在上述代码中:

  • 第1行:打印 DataFrame df 的行数,初始为 1040 行。

  • 第3行:调用 DataFrame 的 drop_duplicates() 方法,移除世界杯推文数据集中的重复行。

  • 第5行:再次打印 DataFrame 的行数,显示重复项已被移除,总行数由 1040 减少至 1035。

文本向量化

我们将使用 scikit-learn 的 TfidfVectorizer 函数将文本数据转换为数值表示。该函数需要指定最大特征数量。

1from jax import numpy as jnp 2from sklearn.feature_extraction.text import TfidfVectorizer 3from sklearn.model_selection import train_test_split 4 5vectorizer = TfidfVectorizer(max_features=10000) 6X = vectorizer.fit_transform(docs).toarray() 7X_train, X_test , y_train, y_test = train_test_split(docs, labels , test_size = 0.20, random_state=0) 8 9print("X_train\n", X_train) 10print("\nX_test\n", X_test)

我们使用 Keras 的 TextVectorization 层将文本转换为整数形式。该函数可自动过滤标点符号并将文本转为小写。我们传入参数 max_features 设为 5000,表示词汇表大小限制为 5000。你可以调整此数值,观察模型性能的变化。

定义好向量化层后,需将其应用于训练数据,通过调用 adapt 方法实现。该方法会根据提供的数据集构建词汇表,并在指定了 max_tokens 时进行截断。可通过调用 get_vocabulary 方法查看生成的词汇表。

1import tensorflow as tf 2 3max_features = 5000 # 最大词汇量 4batch_size = 128 5max_len = 25 # 输出序列的固定长度(用于填充) 6 7vectorize_layer = tf.keras.layers.TextVectorization(standardize='lower_and_strip_punctuation', max_tokens=max_features, output_mode='int', output_sequence_length=max_len) 8vectorize_layer.adapt(X_train) 9 10print(vectorize_layer.get_vocabulary())

我们可以使用训练好的向量化层将训练集和测试集转换为数值形式。

1X_train_padded = vectorize_layer(X_train) 2X_test_padded = vectorize_layer(X_test) 3 4print(X_train_padded) 5print(X_test_padded)

创建 tf.data 数据集

为了更高效地将数据加载到 LSTM 模型中,我们生成并预取训练集和测试集的小批量数据。首先创建一个 tf.data.Dataset。

1training_data = tf.data.Dataset.from_tensor_slices((X_train_padded, y_train)) 2validation_data = tf.data.Dataset.from_tensor_slices((X_test_padded, y_test)) 3 4training_data = training_data.batch(batch_size) 5validation_data = validation_data.batch(batch_size)

接着预取一个批次的数据,打乱顺序,并以 NumPy 数组形式返回。其中 tfds.dataset_as_numpy 可将 tf.data.Dataset 转换为 NumPy 数组的可迭代对象。

1import tensorflow_datasets as tfds 2 3def get_train_batches(): 4 ds = training_data.prefetch(1) 5 ds = ds.shuffle(3, reshuffle_each_iteration=True) 6 return tfds.as_numpy(ds)

TensorBoard 与状态管理

LSTM模型