import pandas as pd
import numpy as np
from nltk.corpus import stopwords
from sklearn.metrics.pairwise import linear_kernel
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
import re
import random
import cufflinks
from plotly.offline import iplot
cufflinks.go_offline()
cufflinks是一个可视化工具,在离线模式下能工作的更好
首先导入酒店数据
df = pd.read_csv('C:\\Users\\91144\\Desktop\\项目数据\\酒店系统\\Seattle_Hotels.csv',encoding="latin-1")
df.head()
df.shape
(152, 3)
desc是酒店的描述
df['desc'][0]
看下酒店介绍中主要描述信息
vec =CountVectorizer().fit(df['desc']) #将文本转换为词频特征。
bag_of_words = vec.transform(df['desc']) #使用拟合后的 vec 对同一列 'desc' 中的文本数据进行转换。转换的结果是一个稀疏矩阵,其中的行对应原始文本数据中的文档,列对应词汇表中的词汇。矩阵中的每个元素是相应词汇在文档中出现的频次。
以下是 CountVectorizer
的一些关键特性:
文本分词:
CountVectorizer
可以自动将文本分割成单词或短语,这个过程称为分词(tokenization)。词频统计: 它计算每个单词或短语在文档中出现的次数,并将这些次数作为特征值。
停用词过滤: 可以配置
CountVectorizer
以排除常见的停用词(如“the”,“is”,“in”等),这些词在文本分析中通常不携带太多有用信息。词汇表构建:
CountVectorizer
构建一个词汇表(vocabulary),用于将单词映射到它们在向量中的索引。文本向量化: 将每篇文档转换为一个数值向量,向量的长度等于词汇表的大小,每个元素对应于词汇表中单词的词频。
参数配置: 允许用户配置多个参数,如
max_df
(最大文档频率)、min_df
(最小文档频率)、max_features
(最大特征数)等,以控制向量化的过程。适用性: 适用于各种文本数据,包括新闻文章、产品评论、社交媒体帖子等。
将文本数据转化为特征矩阵是自然语言处理(NLP)和机器学习中的一个关键步骤,原因如下:
机器学习算法要求数值输入:大多数机器学习算法都是设计来处理数值数据的。文本数据是定性的,包含单词、句子和段落,这些信息必须被转换成数值形式,以便算法能够理解和处理。
特征提取:特征矩阵提供了文本数据的一种数值表示,使得可以量化文本中的信息,例如单词的出现频率或重要性。
向量化:文本向量化是将文本转换为固定长度的向量的过程。这些向量可以捕捉文本的某些特征,比如词频或上下文信息。
处理高维数据:文本数据很容易变得非常高维,尤其是当词汇量很大时。特征矩阵可以通过技术如词袋模型(BoW)或TF-IDF来降低维度,同时保留重要信息。
统一数据格式:特征矩阵允许不同样本(例如,不同的文档或句子)以统一的格式表示,这对于训练机器学习模型是必要的。
便于计算:数值形式的数据可以更有效地进行数学运算,如距离计算、相似度度量等,这些在文本相似性分析或聚类中非常有用。
提高模型性能:适当的特征表示可以显著提高机器学习模型的性能,因为它可以帮助模型更好地捕捉数据中的模式和关系。
可扩展性:特征矩阵使得可以应用各种机器学习算法,从简单的线性模型到复杂的神经网络。
稀疏性:在很多情况下,文本数据可以表示为稀疏矩阵,其中大部分元素为零。这可以减少存储需求并提高计算效率。
预处理和清洗:在转换为特征矩阵的过程中,可以执行文本清洗、去除停用词等预处理步骤,以提高数据质量。
bag_of_words.toarray()
#toarray()方法可以将这个稀疏矩阵转换为一个常规的NumPy数组
bag_of_words.shape
(152, 3200)
sum_words = bag_of_words.sum(axis=0)#知道每个词出现的总次数
sum_words
matrix([[ 1, 11, 11, ..., 2, 6, 2]], dtype=int64)
words_freq = [(word,sum_words[0,idx]) for word,idx in vec.vocabulary_.items()]#当前词出现的总数,分别多少个
words_freq
#进行排序
words_freq = sorted(words_freq,key=lambda x:x[1],reverse = True)#从大到小排
words_freq
将功能写入到一个函数里面
def get_top_n_words(corpus,n = None):
vec =CountVectorizer().fit(corpus)
bag_of_words = vec.transform(corpus)
sum_words = bag_of_words.sum(axis=0)#知道每个词出现的总次数
words_freq = [(word,sum_words[0,idx]) for word,idx in vec.vocabulary_.items()]#当前词出现的总数,分别多少个
words_freq = sorted(words_freq,key=lambda x:x[1],reverse = True)#从大到小排
return words_freq[:n]
common_words = get_top_n_words(df['desc'],20)
common_words
df1 = pd.DataFrame(common_words,columns = ['desc','count'])
df1.head()
#转化为方便画图的形式
df1.groupby('desc').sum()['count'].sort_values().iplot(kind='barh',yTitle='Count',linecolor = 'black',title='top20 before remove stopwords')
def get_top_n_words(corpus,n = None):
vec =CountVectorizer(stop_words='english').fit(corpus) #过滤停用词,自动过滤英语中常用的停用词
bag_of_words = vec.transform(corpus)
#这是 transform 方法,它将 corpus 中的文本转换为特征矩阵。对于 CountVectorizer,结果是每个单词出现次数的稀疏矩阵;对于 TfidfVectorizer,结果是每个单词的 TF-IDF 值的稀疏矩阵。
sum_words = bag_of_words.sum(axis=0)#知道每个词出现的总次数
words_freq = [(word,sum_words[0,idx]) for word,idx in vec.vocabulary_.items()]#当前词出现的总数,分别多少个
words_freq = sorted(words_freq,key=lambda x:x[1],reverse = True)#从大到小排
return words_freq[:n]
common_words = get_top_n_words(df['desc'],20)
df2 = pd.DataFrame(common_words,columns = ['desc','count'])
df2.groupby('desc').sum()['count'].sort_values().iplot(kind='barh',yTitle='Count',linecolor = 'black',title='top20 after remove stopwords')
def get_top_n_words(corpus,n = None):
vec =CountVectorizer(stop_words='english',ngram_range=(2,2)).fit(corpus) #过滤停用词,自动过滤英语中常用的停用词
bag_of_words = vec.transform(corpus)
sum_words = bag_of_words.sum(axis=0)#知道每个词出现的总次数
words_freq = [(word,sum_words[0,idx]) for word,idx in vec.vocabulary_.items()]#当前词出现的总数,分别多少个
words_freq = sorted(words_freq,key=lambda x:x[1],reverse = True)#从大到小排
return words_freq[:n]
common_words = get_top_n_words(df['desc'],20)
df3 = pd.DataFrame(common_words,columns = ['desc','count'])
df3.groupby('desc').sum()['count'].sort_values().iplot(kind='barh',yTitle='Count',linecolor = 'black',title='top20 beforengram_range=(2,2)s')
当你设置 ngram_range=(2,2)
时,你告诉向量化器只考虑长度为 2 的 n-gram。n-gram 是文本中连续的 n 个项目(在这个例子中是单词)的序列。例如,给定句子 "I love machine learning",长度为 2 的 n-gram 将包括 "I love"、"love machine" 和 "machine learning"。
描述的一些统计信息
df['word_count'] = df['desc'].apply(lambda x:len(str(x).split()))
.apply(lambda x: ...)
: 这是apply
函数,它将一个函数应用于desc
列中的每个元素。lambda x
是一个匿名函数,它接收desc
列中的每个元素作为输入x
。
df.head()
df['word_count'].iplot(kind = 'hist',bins =50)
文本处理
sub_replace = re.compile('[^0-9a-z #+_]')#正则表达式
stopwords = set(stopwords.words('english'))#停用词
def clean_txt(text):
text.lower()
text = sub_replace.sub('',text) #使用正则表达式替换掉所有非指定字符。
' '.join(word for word in text.split() if word not in stopwords) #分割文本为单词列表,并过滤掉停用词。将清洗后的单词列表重新连接为一个字符串。
return text
df['desc_clean'] = df['desc'].apply(clean_txt)
from nltk.corpus import stopwords
print(stopwords.words('english'))
df['desc'][0]
df['desc_clean'][0]
相似度计算
df.set_index('name',inplace=True)#。当 inplace=True 时,操作会直接在原始对象上进行,不返回任何值(通常返回 None)。
tf = TfidfVectorizer(analyzer='word',ngram_range=(1,3),stop_words='english')
tfidf_matrix = tf.fit_transform(df['desc_clean'])
tfidf_matrix[0].toarray()
array([[0., 0., 0., ..., 0., 0., 0.]])
cosine_similarity = linear_kernel(tfidf_matrix,tfidf_matrix)
在机器学习和数学中,余弦相似度是一种衡量两个非零向量间的相似度的度量方式,它测量两个向量在方向上的相似性,而不是它们的幅度。在自然语言处理中,余弦相似度经常用于评估文本数据集中文档之间的相似度。
在你提供的代码片段中,linear_kernel 通常被称为线性核函数或内积核,它可以用来计算两个向量之间的余弦相似度。在 scikit-learn 库中,linear_kernel 是 sklearn.metrics.pairwise 模块提供的一个函数。
cosine_similarity[0] #相似度
#构造索引
indices = pd.Series(df.index)
indices[:5]
pd.Series(df.index)
: 这将df
的索引转换为一个 pandas Series 对象。Series 是 pandas 中的一种数据结构,类似于一维数组,可以包含任何数据类型。
创建 Series 对象后,你可以执行多种操作,例如:
- 访问特定的索引值。
- 对索引进行排序。
- 使用索引作为标签进行绘图。
def recommendations(name,cosine_similarity):
recommended_hotels = []
idx = indices[indices==name].index[0] #找到一个索引
score_series = pd.Series(cosine_similarity[idx]).sort_values(ascending = False)
top_10_indexes = list(score_series[1:11].index)
for i in top_10_indexes:
recommended_hotels.append(list(df.index)[i])
return recommended_hotels
recommendations('Hilton Garden Seattle Downtown',cosine_similarity)
找到了相似度推荐酒店