## python 文檔相似度驗證
```python
# coding=UTF-8
import time
import os
import sys
import re
import json
import hashlib
from Db import *
import jieba
from gensim import corpora,models,similarities
reload(sys)
sys.setdefaultencoding('utf-8')
# 1. 名詞與概念:
# 文檔: 字符串
# 詞: 一個詞語
# 集(合): 集合中的每個元素都是唯一的
# 分詞列表: 結巴分詞庫返回的詞列表(非集合,而是可能會有重復的詞,這點很重要!!!)
# 詞袋: 可以看做是分詞的集合 (不重復)
# 語料庫: 一個向量, 表示了詞袋中的每個詞 在 某個分詞列表 中出現的頻率(頻率為0, 即沒在分詞列表中出現的詞不計入向量)
# 向量: [(a, b), ...] a:詞, b:頻率 (純數學的概念是一組坐標值,這里是一個列表,每一項為一個元組,元組里面兩個元素)
# tip: 測試語料庫 用來匹配的, 語料庫 用來被匹配的, 相當于 搜索詞 和 搜索源數據庫 (d0 ~ d7 相當于表中的記錄)
# 要解決的問題: 得到 一個字符串 與 其它多條字符串 之間的相關性值
# 解決方式: 一個 分詞列表 與 其它 多個分詞列表 之間的相關性值(中間有計算 文檔中每個詞的TF-IDF值 等過程), 即最終得到與每個目標文檔的相似度
# 分詞列表 = jieba.cut(待分詞的字符串 即文檔)
# 詞袋 = corpora.Dictionary(分詞列表的列表)
# 語料庫 = 詞袋.doc2bow(分詞列表)
# -----
# 2. 參考:
# 用Python進行簡單的文本相似度分析_xiexf189的博客-CSDN博客_python 文本相似度
# https://blog.csdn.net/xiexf189/article/details/79092629
# 結巴分詞
# https://github.com/fxsjy/jieba
# 一文看懂 TF-IDF (概念圖解+4大變種+發展歷史)
# https://easyai.tech/ai-definition/tf-idf/
# TF (Term Frequency)—— “單詞頻率”
# IDF(Inverse Document Frequency)—— “逆文檔頻率”
# ----
# 3. 流程總結:
# 1. 對 d0 ~ d7 文檔進行分詞,得到 分詞列表, 再組合成 "分詞列表的列表" [['', ...], ...]
# 2. 使用 "分詞列表的列表" 生成 詞袋, 即 詞集合(每個詞唯一了)
# 3. 用 詞袋 依次 和 每個 分詞列表 來生成一個個 語料庫 ,d0語料庫, ...
# 4. 將 生成的8個 語料庫 組成一個 語料庫列表
# 5. 對 語料庫列表進行建模 tfidf模型 = model(語料庫列表)
# 6. ____^_^____第一階段到這里可以告一段落,可以先休息一下,我們一會再繼續
# 7.
# 8. 對 t_doc 文檔進行分詞,得到 分詞列表
# 9. 使用上面的 詞袋 和 t_doc 的 分詞列表 生成一個 t_doc語料庫 (重點: 基于同一 詞袋 生成的 語料庫 之間才能進行相似性分析)
# 10. 獲取測試文檔中,每個詞的TF-IDF值, t_doc 的 TF-IDF值 = tfidf模型[t_doc語料庫] (一個向量,表示了每個詞的 TF-IDF值)
# 11. 同理: d0 的 TF-IDF值 = tfidf模型[d0語料庫]
# 12. 語料庫轉化對象 = tfidf模型[語料庫列表] (<gensim.interfaces.TransformedCorpus object at 0x0000000016715F60>)
# 13. ____^_^____再休息一會,消化一下上面的東西
# 14.
# 15. 回顧一下,現在我們有了: 詞袋, 語料庫列表[d0語料庫, ...], tfidf模型 和 t_doc語料庫, 每個文檔 的 TF-IDF值, 語料庫轉化對象
# 16. 下面我們將利用這些已得到的東西, 來實現我們一開始的目標: 分析 t_doc 文檔 與 每個目標文檔 d0 ~ d7 之間的相似度
# 17. 得到 相似性對象 = similarities.SparseMatrixSimilarity(語料庫轉化對象, 詞袋長度) (<gensim.similarities.docsim.SparseMatrixSimilarity object at 0x0000000016787FD0>)
# 18. 答案 = 相似性對象[t_doc 的 TF-IDF值] <type 'numpy.ndarray'> 矩陣: (t_doc 與 d0 的相似度, ..., t_doc 與 d7 的相似度)
# 19. 對 numpy.ndarray 結果進行排序: [(a, b), ...] a: 第幾個文檔, b: 相似度
# 20. 同理, d0 與 d0 ~ d7 的相似度 = 相似性對象[d0 的 TF-IDF值]
# 21. 相似性對象[語料庫轉化對象] 得到 d0 與 d0 ~ d7, ..., d7 與 d0 ~ d7 的 相似度列表 [[...],...]
# 22. 完, 建議多看幾遍
# ==========================================================
# 待進行分詞的文檔
doc0 = "我不喜歡上海"
doc1 = "上海是一個好地方"
doc2 = "北京是一個好地方"
doc3 = "上海好吃的在哪里"
doc4 = "上海好玩的在哪里"
doc5 = "上海是好地方"
doc6 = "上海路和上海人上海上海上海"
doc7 = "喜歡小吃"
# 將 d1 改成 '我喜歡上海,不喜歡吃' d0 和 d1 的相關性就達到了 0.65295446 (原來 0.011466),
# 但其實二者表達的是完全相反的意思,所以這個相似性,僅僅只是文本的詞頻率比較, 而沒有任何的語義解析處理
# 測試文檔(判斷這個文檔與其它文檔的相關性)
# 用少文檔 去匹配 多文檔合成的分詞庫
doc_test = "我喜歡上海的小吃" # [(7, 0.70477605), (0, 0.54680777), (3, 0.17724207), (4, 0.17724207), (6, 0.030088982), (5, 0.013545224), (1, 0.010553493), (2, 0.0)]
# doc_test = "可以看做是集合" # [(5, 0.5692461), (1, 0.4435168), (2, 0.32457215), (0, 0.0), (3, 0.0), (4, 0.0), (6, 0.0), (7, 0.0)]
# doc_test = "可以看做集合" # [(0, 0.0), (1, 0.0), (2, 0.0), (3, 0.0), (4, 0.0), (5, 0.0), (6, 0.0), (7, 0.0)]
all_doc = []
all_doc.append(doc0)
all_doc.append(doc1)
all_doc.append(doc2)
all_doc.append(doc3)
all_doc.append(doc4)
all_doc.append(doc5)
all_doc.append(doc6)
all_doc.append(doc7)
# 全部分詞列表的列表
all_doc_list = []
for doc in all_doc:
# 對每一個文檔進行分詞
# 默認使用了,精確分詞模式
# 精確模式: 試圖將句子最精確地切開,適合文本分析
# 只是將詞切開,并不做詞集合,這點很重要
doc_list = [word for word in jieba.cut(doc)]
all_doc_list.append(doc_list)
print all_doc_list
# exit()
# 制作語料庫
# 使用全部分詞列表的列表 制作詞袋,每個詞都是唯一的
dictionary = corpora.Dictionary(all_doc_list)
for i,item in dictionary.items():
print i, item
# exit()
# print dictionary.keys()
print dictionary.token2id
# 使用 上一步生成的詞袋 和 全部分詞列表的列表 制作語料庫列表(唯一的詞袋 再與 文檔的分詞列表 生成語料庫,即一組向量 )
# 語料庫是一個向量,向量中的每個元素是一個二元組(編號、頻次數),對應分詞后的文檔中的每一個詞
# 語料庫列表
corpus = [dictionary.doc2bow(doc) for doc in all_doc_list]
# 向量列表
print corpus
# exit()
# tip: 將這些向量列表合并(詞頻累加),就能得出 之前的 分詞文檔列表集 中的詞頻
# 同理,現在也對 測試文檔進行處理
# 現在對測試文檔也進行分詞
doc_test_list = [word for word in jieba.cut(doc_test)]
print doc_test_list
# 用 上面生成的詞袋 和 測試文檔分詞列表 制作一個語料庫
# 這里的關鍵是,制作語料庫 使用的是 上面的詞袋(搜索詞集),這為后面計算相關性埋下伏筆
doc_test_vec = dictionary.doc2bow(doc_test_list)
print doc_test_vec
# doc_test_vec = dictionary.doc2bow(['上海1', '上海1', '湖北'])
# print doc_test_vec
# 相當于現在得到了 測試的分詞列表 與 搜索詞集 的 向量,即詞頻
# 但 也只是知道了 詞頻關系,還是無法得知 測試的分詞列表 究竟與 哪個 文檔 相關性最高
# exit()
# 下面開始計算相關性
# 使用TF-IDF模型對語料庫建模 (使用語料庫列表進行建模)
tfidf = models.TfidfModel(corpus)
# 語料庫模型 = models.TfidfModel(語料庫列表)
# TfidfModel(num_docs=8, num_nnz=34) <class 'gensim.models.tfidfmodel.TfidfModel'>
print tfidf, type(tfidf)
# 上面埋下的伏筆開始顯現作用了:只有使用了相同的詞袋生成的語料庫之間才能夠計算相似性
# 獲取測試文檔中,每個詞的TF-IDF值 (使用測試語料庫)
# 值是一個向量: [(a, b), ...] a:詞, b: TF-IDF值
doc_test_tfidf = tfidf[doc_test_vec]
print doc_test_tfidf
# 第一個文檔中,每個詞的TF-IDF值 (使用第一個文檔的語料庫)
print tfidf[corpus[0]]
# <gensim.interfaces.TransformedCorpus object at 0x0000000016715F60>
print tfidf[corpus]
# 對每個目標文檔,分析測試文檔的相似度
index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=len(dictionary.keys()))
# <gensim.similarities.docsim.SparseMatrixSimilarity object at 0x0000000016787FD0>
print index
# 測試語料庫 與 每個 語料庫 的相似度
sim = index[doc_test_tfidf]
# <type 'numpy.ndarray'>
print 'sim', sim, type(sim)
# 第一個語料庫 與 每個 語料庫的相似度
print index[tfidf[corpus[0]]]
# 全部語料庫 與 語料庫列表本身 的相似度列表
# 相當于 d0 與 d0 ~ d7, ..., d7 與 d0 ~ d7 的 相似度列表 [[...],...]
print index[tfidf[corpus]]
# 根據相似度排序
print sorted(enumerate(sim), key=lambda item: -item[1])
```
last update: 2020-11-20 21:32:02
- 開始
- 公益
- 更好的使用看云
- 推薦書單
- 優秀資源整理
- 技術文章寫作規范
- SublimeText - 編碼利器
- PSR-0/PSR-4命名標準
- php的多進程實驗分析
- 高級PHP
- 進程
- 信號
- 事件
- IO模型
- 同步、異步
- socket
- Swoole
- PHP擴展
- Composer
- easyswoole
- php多線程
- 守護程序
- 文件鎖
- s-socket
- aphp
- 隊列&并發
- 隊列
- 講個故事
- 如何最大效率的問題
- 訪問式的web服務(一)
- 訪問式的web服務(二)
- 請求
- 瀏覽器訪問阻塞問題
- Swoole
- 你必須理解的計算機核心概念 - 碼農翻身
- CPU阿甘 - 碼農翻身
- 異步通知,那我要怎么通知你啊?
- 實時操作系統
- 深入實時 Linux
- Redis 實現隊列
- redis與隊列
- 定時-時鐘-阻塞
- 計算機的生命
- 多進程/多線程
- 進程通信
- 拜占庭將軍問題深入探討
- JAVA CAS原理深度分析
- 隊列的思考
- 走進并發的世界
- 鎖
- 事務筆記
- 并發問題帶來的后果
- 為什么說樂觀鎖是安全的
- 內存鎖與內存事務 - 劉小兵2014
- 加鎖還是不加鎖,這是一個問題 - 碼農翻身
- 編程世界的那把鎖 - 碼農翻身
- 如何保證萬無一失
- 傳統事務與柔性事務
- 大白話搞懂什么是同步/異步/阻塞/非阻塞
- redis實現鎖
- 淺談mysql事務
- PHP異常
- php錯誤
- 文件加載
- 路由與偽靜態
- URL模式之分析
- 字符串處理
- 正則表達式
- 數組合并與+
- 文件上傳
- 常用驗證與過濾
- 記錄
- 趣圖
- foreach需要注意的問題
- Discuz!筆記
- 程序設計思維
- 抽象與具體
- 配置
- 關于如何學習的思考
- 編程思維
- 談編程
- 如何安全的修改對象
- 臨時
- 臨時筆記
- 透過問題看本質
- 程序后門
- 邊界檢查
- session
- 安全
- 王垠
- 第三方數據接口
- 驗證碼問題
- 還是少不了虛擬機
- 程序員如何談戀愛
- 程序員為什么要一直改BUG,為什么不能一次性把代碼寫好?
- 碎碎念
- 算法
- 實用代碼
- 相對私密與絕對私密
- 學習目標
- 隨記
- 編程小知識
- foo
- 落盤
- URL編碼的思考
- 字符編碼
- Elasticsearch
- TCP-IP協議
- 碎碎念2
- Grafana
- EFK、ELK
- RPC
- 依賴注入
- 科目一
- 開發筆記
- 經緯度格式轉換
- php時區問題
- 解決本地開發時調用遠程AIP跨域問題
- 后期靜態綁定
- 談tp的跳轉提示頁面
- 無限分類問題
- 生成微縮圖
- MVC名詞
- MVC架構
- 也許模塊不是唯一的答案
- 哈希算法
- 開發后臺
- 軟件設計架構
- mysql表字段設計
- 上傳表如何設計
- 二開心得
- awesomes-tables
- 安全的代碼部署
- 微信開發筆記
- 賬戶授權相關
- 小程序獲取是否關注其公眾號
- 支付相關
- 提交訂單
- 微信支付筆記
- 支付接口筆記
- 支付中心開發
- 下單與支付
- 支付流程設計
- 訂單與支付設計
- 敏感操作驗證
- 排序設計
- 代碼的運行環境
- 搜索關鍵字的顯示處理
- 接口異步更新ip信息
- 圖片處理
- 項目搭建
- 閱讀文檔的新方式
- mysql_insert_id并發問題思考
- 行鎖注意事項
- 細節注意
- 如何處理用戶的輸入
- 不可見的字符
- 抽獎
- 時間處理
- 應用開發實戰
- python 學習記錄
- Scrapy 教程
- Playwright 教程
- stealth.min.js
- Selenium 教程
- requests 教程
- pyautogui 教程
- Flask 教程
- PyInstaller 教程
- 蜘蛛
- python 文檔相似度驗證
- thinkphp5.0數據庫與模型的研究
- workerman進程管理
- workerman網絡分析
- java學習記錄
- docker
- 筆記
- kubernetes
- Kubernetes
- PaddlePaddle
- composer
- oneinstack
- 人工智能 AI
- 京東
- pc_detailpage_wareBusiness
- doc
- 電商網站設計
- iwebshop
- 商品規格分析
- 商品屬性分析
- tpshop
- 商品規格分析
- 商品屬性分析
- 電商表設計
- 設計記錄
- 優惠券
- 生成唯一訂單號
- 購物車技術
- 分類與類型
- 微信登錄與綁定
- 京東到家庫存系統架構設計
- crmeb
- 命名規范
- Nginx https配置
- 關于人工智能
- 從人的思考方式到二叉樹
- 架構
- 今日有感
- 文章保存
- 安全背后: 瀏覽器是如何校驗證書的
- 避不開的分布式事務
- devops自動化運維、部署、測試的最后一公里 —— ApiFox 云時代的接口管理工具
- 找到自己今生要做的事
- 自動化生活
- 開源與漿果
- Apifox: API 接口自動化測試指南