向量空间模型(VSM)是信息检索领域中常用的一种模型,它将文本表示为高维向量,可以通过计算向量间的相似度来实现文本分类、聚类、检索等任务。本文将介绍如何用Python实现向量空间模型,包括文本预处理、特征提取、向量化和相似度计算。
一、文本预处理
文本预处理是将原始文本转换为可供计算机处理的形式,包括分词、去除停用词、词干提取等步骤。Python中有许多成熟的文本处理库,比如NLTK、spaCy等,可以方便地完成这些操作。
以NLTK为例,首先需要下载其语料库:
```
import nltk
nltk.download()
```
然后通过以下代码进行分词、去除停用词和词干提取:
```
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
def preprocess(text):
# 分词
tokens = word_tokenize(text.lower())
# 去除停用词
stop_words = set(stopwords.words('english'))
tokens = [token for token in tokens if token not in stop_words]
# 词干提取
stemmer = PorterStemmer()
tokens = [stemmer.stem(token) for token in tokens]
return tokens
```
二、特征提取
特征提取是将文本转换为向量的过程,常用的方法包括词袋模型、TF-IDF等。这里我们采用TF-IDF方法,它可以通过计算每个词在文档中出现的频率和在所有文档中出现的频率来衡量词的重要性。
使用sklearn库可以方便地实现TF-IDF特征提取:
```
from sklearn.feature_extraction.text import TfidfVectorizer
def feature_extraction(corpus):
vectorizer = TfidfVectorizer(tokenizer=preprocess)
X = vectorizer.fit_transform(corpus)
return X.toarray(), vectorizer.get_feature_names()
```
其中corpus为文本集合,X为特征矩阵,每行代表一个文档,每列代表一个词,值为该词在该文档中的TF-IDF权重。
三、向量化
将文本向量化是将文本表示为向量的过程,我们可以使用特征提取得到的特征矩阵作为文本向量,也可以使用其他方法,比如词嵌入(word embedding)。
这里我们使用特征提取得到的特征矩阵作为文本向量:
```
def vectorize(text, vectorizer):
tokens = preprocess(text)
X = vectorizer.transform([' '.join(tokens)])
return X.toarray()[0]
```
其中text为待向量化的文本,vectorizer为特征提取得到的向量化器。
四、相似度计算
使用向量空间模型可以计算文本之间的相似度,常用的方法包括余弦相似度、欧几里得距离等。这里我们使用余弦相似度作为相似度度量方法:
```
import numpy as np
def cosine_similarity(u, v):
return np.dot(u, v) / (np.linalg.norm(u) * np.linalg.norm(v))
def similarity(text1, text2, vectorizer):
u = vectorize(text1, vectorizer)
v = vectorize(text2, vectorizer)
return cosine_similarity(u, v)
```
其中u、v分别为文本1、文本2的向量表示。
完整代码如下:
```
import nltk
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
def preprocess(text):
# 分词
tokens = word_tokenize(text.lower())
# 去除停用词
stop_words = set(stopwords.words('english'))
tokens = [token for token in tokens if token not in stop_words]
# 词干提取
stemmer = PorterStemmer()
tokens = [stemmer.stem(token) for token in tokens]
return tokens
def feature_extraction(corpus):
vectorizer = TfidfVectorizer(tokenizer=preprocess)
X = vectorizer.fit_transform(corpus)
return X.toarray(), vectorizer.get_feature_names()
def vectorize(text, vectorizer):
tokens = preprocess(text)
X = vectorizer.transform([' '.join(tokens)])
return X.toarray()[0]
def cosine_similarity(u, v):
return np.dot(u, v) / (np.linalg.norm(u) * np.linalg.norm(v))
def similarity(text1, text2, vectorizer):
u = vectorize(text1, vectorizer)
v = vectorize(text2, vectorizer)
return cosine_similarity(u, v)
if __name__ == '__main__':
corpus = [
'Machine learning is fun',
'Python is my favorite programming language',
'I like deep learning'
]
X, feature_names = feature_extraction(corpus)
print(feature_names)
print(X)
print(vectorize('Machine learning is fun', vectorizer))
print(similarity('Machine learning is fun', 'I like deep learning', vectorizer))
```