作者 | Viet Hoang Tran Duong
来源 | DeepHub IMBA
头图 | CSDN付费下载于视觉中国
数据是新的石油,文本是我们需要更深入钻探的油井。文本数据无处不在,在实际使用之前,我们必须对其进行预处理,以使其适合我们的需求。对于数据也是如此,我们必须清理和预处理数据以符合我们的目的。这篇文章将包括一些简单的方法来清洗和预处理文本数据以进行文本分析任务。
我们将在Covid-19 Twitter数据集上对该方法进行建模。这种方法有3个主要组成部分:
首先,我们要清理和过滤所有非英语的推文/文本,因为我们希望数据保持一致。
其次,我们为复杂的文本数据创建一个简化的版本。
最后,我们将文本向量化并保存其嵌入以供将来分析。
清理和过滤文本
首先,为了简化文本,我们要将文本标准化为仅为英文字符。此函数将删除所有非英语字符。
def clean_non_english(txt):
txt = re.sub(r'\W+', ' ', txt)
txt = txt.lower()
txt = txt.replace("[^a-zA-Z]", " ")
word_tokens = word_tokenize(txt)
filtered_word = [w for w in word_tokens if all(ord(c) < 128 for c in w)]
filtered_word = [w + " " for w in filtered_word]
return "".join(filtered_word)
我们甚至可以通过删除停止词来做得更好。停词是出现在英语句子中对意思没有多大帮助的常见词。我们将使用nltk包来过滤stopwords。由于我们的主要任务是使用word cloud将tweet的主题可视化,所以这一步需要避免使用“the,”“a,”等常见单词。但是,如果你的任务需要完整的句子结构,比如下一个单词预测或语法检查,你可以跳过这一步。
import nltk
nltk.download('punkt') # one time execution
nltk.download('stopwords')
from nltk.corpus import stopwords
stop_words = set(stopwords.words('english'))def clean_text(english_txt):
try:
word_tokens = word_tokenize(english_txt)
filtered_word = [w for w in word_tokens if not w in stop_words]
filtered_word = [w + " " for w in filtered_word]
return "".join(filtered_word)
except:
return np.nan
对于tweets,在清理之前我们需要考虑一个特殊的特性:提及@。您的数据可能具有这样的特殊特性(也可能没有),这是具体情况,而不是普遍要求。因此,在盲目地清理和预处理数据之前,要充分了解您的数据!
def get_mention(txt):
mention = []
for i in txt.split(" "):
if len(i) > 0 and i[0] == "@":
mention.append(i)
return "".join([mention[i] + ", " if i != len(mention) - 1 else mention[i] for i in range(len(mention))]
以前,我们清理非英文字符。现在,我们删除非英语文本(语义上)。Langdetect是一个python包,它允许检查文本的语言。它是谷歌的语言检测库从Java到Python的直接端移植。
from langdetect import detect
def detect_lang(txt):
try:
return detect(txt)
except:
return np.nan
然后我们过滤掉所有不是“en”语言的列。
简化复杂的数据
对于数值数据,良好的处理方法是缩放,标准化和规范化。此资源有助于理解并将这些方法应用于您的数据。在本文的讨论范围内,由于其他资源在此方面做得很好,因此我将不做进一步讨论。
对于分类数据,有许多方法。两种名义上的方法是标签编码器(为每个标签分配一个不同的编号)和一种热编码(以0和1的向量表示)。有关这些分类值的方法的更多详细信息,请参见此处。与我提到的这两种资源相比,此资源非常丰富,具有更多类型的编码。
这篇文章将介绍一些减少数据特别是位置数据复杂性的方法。在我的数据集中,有一列位置,带有作者的地址。但是,由于这些原始数据过于混乱和复杂(具有城市,县,州,国家/地区),因此我无法对其进行太多分析。因此,我们可以将文本标准化,并将其缩小到“国家”级别。处理位置数据的程序包是geopy。它可以识别正确的地址并将这些位置重新格式化为标准格式。然后,您可以选择保留所需的任何信息。对我来说,国家,国家足够体面。
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="twitter")def get_nation(txt):
try:
location = geolocator.geocode(txt)
x = location.address.split(",")[-1]
return x
except:
return np.nan
向量化和嵌入
文本向量化将文本转换为值的向量以表示其含义。早些时候,我们有一种热编码方法,其向量的大小与我们的词汇量相同,在出现文本的任何地方都为1,在其他地方为0。如今,我们拥有更高级的方法,例如spacy,GloVe甚至bert嵌入。对于本项目的范围,我将向您介绍python和Jupiter笔记本中的GloVe。
首先,我们下载嵌入向量。您可以在此处手动下载或直接在笔记本中进行下载。
!wget http://nlp.stanford.edu/data/glove.6B.zip
!unzip glove*.zip
然后,我们创建一个向量矢量化每个数据点的函数。句子是每个单词的平均表示。对于空句子,我们将其默认为零向量。
def vectorize(value, word_embeddings, dim = 100):
sentences = value.to_list()
sentence_vectors = []
for i in sentences:
if len(i) != 0:
v = sum([word_embeddings.get(w, np.zeros((dim,))) for w in i.split()])/(len(i.split())+0.001)
else:
v = np.zeros((dim,))
sentence_vectors.append(v)
sentence_vectors = np.array(sentence_vectors)
return sentence_vectors
最后,我们对整个数据集进行矢量化处理,并将矢量化的numpy数组另存为文件,因此我们不必在每次运行代码时都再次进行此过程。矢量化版本将以.npy文件的形式保存为numpy数组。Numpy包方便存储和处理海量数组数据。
作为我的个人标准做法,我尝试将每个部分之后的所有数据保存为单独的文件,以评估数据并更灵活地更改代码。
def vectorize_data(data = data, value = 'english_text', dim = 100):
# Extract word vectors
word_embeddings = {}
f = open('glove.6B.{}d.txt'.format(str(dim)), encoding='utf-8')
for line in f:
values = line.split()
word = values[0]
coefs = np.asarray(values[1:], dtype='float32')
word_embeddings[word] = coefs
f.close() text_vec = vectorize(data[value], word_embeddings, dim)
np.save("vectorized_{}.npy".format(str(dim)), text_vec)
print("Done. Data:", text_vec.shape)
return True
总结
数据预处理,特别是文本预处理,可能是一个非常麻烦的过程。机器学习工程师工作流程的很大一部分将用于这些清理和格式化数据(如果您的数据已经完全清理好了,那么,幸运的是,对于所有实现这一目标的工程师来说,他们都感到很荣幸)。
这篇文章中的所有代码都是非常抽象的,可以应用于许多数据项目(您只需更改列名,所有代码都可以正常工作)。在笔记本中,我还添加了异常功能来处理故障情况,以确保您的代码不会在中途崩溃。我希望它对您的项目有帮助,就像对我的帮助一样。
最后,所有的代码可以在这里找到:
https://github.com/viethoangtranduong/covid19-tweets
更多精彩推荐