(4) 相似文章推薦

開發(fā)環(huán)境

系統(tǒng): macOS Sierra; 開發(fā)軟件: PyChram CE; 運行環(huán)境: Python3.6

需求分析

在用戶閱讀某篇文章的時候,為用戶推薦更多與在讀文章內(nèi)容相似的文章

概念

<b>相似推薦</b>:當(dāng)用戶表現(xiàn)出對某人或某物感興趣時,為他/她推薦相似的人或物,核心思想:人以類聚,物以群分;
<b>協(xié)同過濾推薦</b>:指利用用戶過去的行為或意見,預(yù)測當(dāng)前用戶最喜歡哪些東西或?qū)δ男〇|西感興趣

采用余弦相似度原理來實現(xiàn)相似文章推薦

<b>原理:</b>
將每篇文章的詞頻統(tǒng)計結(jié)果當(dāng)作一個向量,如果兩篇文章向量的夾角越小即余弦值越接近1,那么我們說這兩篇文章越相似


原理.png

假如有如下兩篇文章
文章A - '放假我喜歡彈吉他,看書'
文章B - '放假我不喜歡看書,喜歡打球'
這兩篇文章的詞頻統(tǒng)計結(jié)果如下:

      放假 我 喜歡 彈 吉他 看書 不 打球
文章A   1  1  1   1  1   1   0   0
文章B   1  1  2   0  0   1   1   1

則根據(jù)余弦計算公式,文章A和文章B兩個向量間的余弦值計算如下:


math.png

若余弦值越接近1, 則說明文章A和B越相似


  • 導(dǎo)入需要用到的包

import os
import codecs
import re
import jieba
import pandas
import numpy
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics import pairwise_distances
  • 創(chuàng)建語料庫

# 創(chuàng)建語料庫
filePaths = []
fileContents = []
for root, dirs, files in os.walk(
    'data/SogouC.mini/Sample'
):
    for name in files:
        filePath = os.path.join(root, name)
        f = codecs.open(filePath, 'r', 'utf-8')
        fileContent = f.read()
        f.close()
        filePaths.append(filePath)
        fileContents.append(fileContent)

corpus = pandas.DataFrame({
    'filePath': filePaths,
    'fileContent': fileContents
})

語料庫中的文章是從搜狗實驗室下載的,內(nèi)容如下:

目錄結(jié)構(gòu).png

創(chuàng)建的語料庫如下:

語料庫.png
  • 對文章進行分詞

# 匹配中文分詞
zhPattern = re.compile(u'[\u4e00-\u9fa5]+')

# 對每篇文章進行分詞處理
for index, row in corpus.iterrows():
    fileContent = row['fileContent']
    segments = []
    segs = jieba.cut(fileContent)  # 分詞默認以','分隔
    for seg in segs:
        if zhPattern.search(seg):
            segments.append(seg)
    row['fileContent'] = ' '.join(segments)  # 將分詞以空格分隔

分詞后結(jié)果如下:


分詞.png
  • 統(tǒng)計詞頻,將詞頻向量化

# 讀取停用詞文件
stopWords = pandas.read_csv(
    'data/StopwordsCN.txt',
    encoding='utf-8',
    index_col=False,
    quoting=3,
    sep='\t'
)

# 詞頻統(tǒng)計 & 文檔向量化
countVectorizer = CountVectorizer(
    stop_words=list(stopWords['stopword'].values),
    min_df=0,
    token_pattern=r"\b\w+\b"
)
textVector = countVectorizer.fit_transform(corpus['fileContent'])

詞頻矩陣如下:


vector.png
  • 統(tǒng)計詞頻矩陣的余弦相似度計算

# 統(tǒng)計詞頻矩陣的余弦相似度計算
distance_matrix = pairwise_distances(
    textVector,
    metric='cosine'
)

運行結(jié)果如下:


cosine.png

上面的矩陣代表的意思是兩個文章(即兩個向量)之間的夾角值,這里我用x代替上面矩陣中的數(shù)值。 為什么斜對角的數(shù)值都為0呢?因為文章跟本身是完全相同的,所以兩個向量相同,夾角值為0

     文章1  文章2  文章3  ...  文章n
文章1  0     x     x     ...   x 
文章2  x     0     x     ...   x
文章3  x     x     0     ...   x
...   ...   ...   ...   ...   ...
文章n  x     x     x     ...   0
  • 獲取與該文章最相似的3篇文章(即矩陣中值最小的前三個)

# 獲取與本篇文章相似度最高的三篇文章
sort_matrix = numpy.argsort(distance_matrix, axis=1)[:, 1:4]  # argsort為升序排列,取第1列到第3列的值,第0列為自己本身
similarity = pandas.Index(filePaths)[sort_matrix].values

similarityDF = pandas.DataFrame({
    'filePath': filePaths,
    's1': similarity[:, 0],
    's2': similarity[:, 1],
    's3': similarity[:, 2],
})

最后結(jié)果如下:


result.png
  • 參考

小蚊子數(shù)據(jù)分析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容