本文首發(fā)于微信公眾號:Python for Finance
鏈接:https://mp.weixin.qq.com/s/i74pct7a4NBRSN39kg2NXA
余弦相似度簡介
余弦相似度原理
余弦相似性通過計算兩個向量的余弦角來測量兩個向量之間的相似性。
文本分析應(yīng)用余弦相似度
D1 = ‘the best data science course’
D2 = ‘data science is popular’
基于詞袋法構(gòu)造文本向量:
D1:[1,1,1,1,1,0,0]
D2:[0,0,1,1,0,1,1]
第一步,計算點積
第二步,計算模長
第三步,計算余弦相似度
余弦相似度的計算
numpy
向量與向量
import numpy as np
from numpy.linalg import norm
A = np.array([2,1,2])
B = np.array([3,4,2])
cosine = np.dot(A,B)/(norm(A)*norm(B))
print("余弦相似度:", cosine)
結(jié)果為:
余弦相似度: 0.8665782448262421
向量與矩陣
import numpy as np
from numpy.linalg import norm
A = np.array([[1,2,2],
[3,2,2],
[-2,1,-3]])
B = np.array([3,4,2])
cosine = np.dot(A,B)/(norm(A, axis=1)*norm(B))
print("余弦相似度:\n", cosine)
結(jié)果為:
余弦相似度:
[ 0.92847669 0.94579243 -0.39703333]
注意,A有三個向量,B是一個向量。我們得到了余弦相似度數(shù)組中的三個元素。第一元素對應(yīng)于A的第一個向量(第一行)和向量B之間的余弦相似性。第二個元素對應(yīng)于A的第二個向量(第二行)和向量B之間的余弦相似性。第三個元素也是如此。
矩陣與矩陣
import numpy as np
from numpy.linalg import norm
A = np.array([[1,2,2],
[3,2,2],
[-2,1,-3]])
B = np.array([[4,2,4],
[2,-2,5],
[3,4,-4]])
cosine = np.sum(A*B, axis=1)/(norm(A, axis=1)*norm(B, axis=1))
print("余弦相似度:\n", cosine)
結(jié)果為:
余弦相似度:
[0.88888889 0.5066404 0.41739194]
最后得到的相似度數(shù)組的意義:
- 第一個元素代表的是
A
中的第一行和B
中的第一行的余弦相似度 - 第二個元素代表的是
A
中的第二行和B
中第二行的余弦相似度 - 第三個元素代表的是
A
中的第二行和B
中第二行的余弦相似度
如何獲得A和B的任意兩行之間的余弦相似性呢?
import numpy as np
from numpy.linalg import norm
A = np.array([[1,2,2],
[3,2,2],
[-2,1,-3]])
B = np.array([[4,2,4],
[2,-2,5],
[3,4,-4],
[2,5,9]])
norm1 = norm(A,axis=-1,keepdims=True)
norm2 = norm(B,axis=-1,keepdims=True)
arr1_norm = A / norm1
arr2_norm = B / norm2
cos = np.dot(arr1_norm,arr2_norm.T)
print(cos)
結(jié)果為:
[[ 0.88888889 0.46420708 0.15617376 0.95346259]
[ 0.9701425 0.5066404 0.34089931 0.78624539]
[-0.80178373 -0.97700842 0.41739194 -0.66254135]]
最后得到的相似度矩陣的意義:
- 因為
A
是 3 行,B
是 4 行,因此最終的輸出矩陣維度是3 行 4 列
- 第一行代表的是
A
中的第一行和B
中的每一行的余弦相似度 - 第二行代表的是
A
中的第二行和B
中每一行的余弦相似度
scipy
向量與向量
from scipy import spatial
A = np.array([2,1,2])
B = np.array([3,4,2])
cos_sim = 1 - spatial.distance.cosine(A, B)
print(cos_sim)
sklearn
向量與向量
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# 向量表示為二維數(shù)組的形式,推薦使用
A = np.array([[1,2,2]])
B = np.array([[3,2,2]])
cos_sim = cosine_similarity(A, B)
print(cos_sim)
# 向量表示為一維數(shù)組的形式
A = np.array([1,2,2])
B = np.array([3,2,2])
cos_sim = cosine_similarity([A, B])
print(cos_sim)
結(jié)果為:
[[0.88929729]]
[[1. 0.88929729]
[0.88929729 1. ]]
向量與矩陣
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
A = np.array([[1,2,2],
[3,2,2],
[-2,1,-3]])
B = np.array([[4,2,4]])
cosine = cosine_similarity(A,B)
print("余弦相似度:\n", cosine)
結(jié)果為:
余弦相似度:
[[ 0.88888889]
[ 0.9701425 ]
[-0.80178373]]
矩陣與矩陣
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
A = np.array([[1,2,2],
[3,2,2],
[-2,1,-3]])
B = np.array([[4,2,4],
[2,-2,5],
[3,4,-4],
[2,5,9]])
cosine = cosine_similarity(A) # A中的行向量之間的兩兩余弦相似度,等價于cosine = cosine_similarity(A,A)
print("余弦相似度:\n", cosine)
cosine = cosine_similarity(A,B) # 第一行代表的是A中的第一行和B中的每一行的余弦相似度;第二行代表的是A中的第二行和B中每一行的余弦相似度
print("余弦相似度:\n", cosine)
使用cosine_similarity,傳入一個變量a時,返回數(shù)組的第i行第j列表示a[i]與a[j]的余弦相似度;傳入兩個變量a,b時,返回的數(shù)組的第i行第j列表示a[i]與b[j]的余弦相似度。
結(jié)果為:
余弦相似度:
[[ 1. 0.88929729 -0.53452248]
[ 0.88929729 1. -0.64820372]
[-0.53452248 -0.64820372 1. ]]
余弦相似度:
[[ 0.88888889 0.46420708 0.15617376 0.95346259]
[ 0.9701425 0.5066404 0.34089931 0.78624539]
[-0.80178373 -0.97700842 0.41739194 -0.66254135]]
英文文本計算余弦相似度
第一步,定義文檔
# 定義文檔
doc1 = 'The sun is the largest celestial body in the solar system'
doc2 = 'The solar system consists of the sun and eight revolving planets'
doc3 = 'Ra was the Egyptian Sun God'
documents = [doc1, doc2, doc3]
第二步,文本向量化
本例采用詞袋模型進行文本向量化,也可采用TF-IDF模型。
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
# 詞袋模型:文本向量化
count_vectorizer = CountVectorizer(stop_words='english')
sparse_matrix = count_vectorizer.fit_transform(documents)
# 文本向量化的可視化表格
doc_term_matrix = sparse_matrix.todense()
df = pd.DataFrame(doc_term_matrix,
columns=count_vectorizer.get_feature_names(),
index=['doc1', 'doc2', 'doc3'])
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ngPpthcD-1675524259020)(https://python-for-finance.oss-cn-hangzhou.aliyuncs.com/202302042219303.png)]
計算余弦相似度
from sklearn.metrics.pairwise import cosine_similarity
print(cosine_similarity(df))
結(jié)果為:
[[1. 0.4 0.2236068]
[0.4 1. 0.2236068]
[0.2236068 0.2236068 1. ]]
中文文本計算余弦相似度——以MD&A文本為例
我們來看一下中文情境下余弦相似度如何計算,主要多了一個分詞的步驟。在這里,我們使用到了 CNRDS 數(shù)據(jù)庫中關(guān)于 MDA 的 10 個樣本數(shù)據(jù),如需完整的 MDA 數(shù)據(jù)請到 CNRDS 數(shù)據(jù)庫中下載。
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import jieba
import re
# 調(diào)用數(shù)據(jù)
data = pd.read_excel(r"C:\Users\chenwei\Downloads\管理層討論與分析\管理層討論與分析.xlsx")
stopwords = pd.read_csv(r"C:\Users\chenwei\Downloads\stopwords-master\stopwords-master\cn_stopwords.txt", names=["stopwords"])
# 定義分詞函數(shù)
def cut_words(text):
words_list = []
# 只保留中文內(nèi)容
text = ''.join(re.findall('[\u4e00-\u9fa5]+', text))
words = jieba.lcut(text)
for word in words:
if word not in list(stopwords["stopwords"]):
words_list.append(word)
return " ".join(words_list)
# 對文本分詞
data["經(jīng)營討論與分析內(nèi)容"] = data["經(jīng)營討論與分析內(nèi)容"].apply(cut_words)
data
在這里,我們需要注意的是要設(shè)置token_pattern,這個參數(shù)接受正則表達式。默認情況下會忽略1個字符(但是在中文的情況下就不能忽略一個字符)
- token_pattern(默認參數(shù)) : r"(?u)\b\w\w+\b"
- token_pattern(修改之后) : r"(?u)\b\w+\b"
計算兩兩之間的文本相似度
# 基于詞集法構(gòu)造文本向量計算余弦相似度
# 實例化詞集法vectorizer
vectorizer = CountVectorizer(token_pattern=r"(?u)\b\w+\b",binary=True)
# 將語料集轉(zhuǎn)化為詞集向量
vec = vectorizer.fit_transform(data["經(jīng)營討論與分析內(nèi)容"])
# 計算余弦相似度
CS_SoW = cosine_similarity(vec)
# 基于詞袋法構(gòu)造文本向量計算余弦相似度
# 實例化詞袋法vectorizer
vectorizer = CountVectorizer(token_pattern=r"(?u)\b\w+\b")
# 將語料集轉(zhuǎn)化為詞袋向量
vec = vectorizer.fit_transform(data["經(jīng)營討論與分析內(nèi)容"])
# 計算余弦相似度
CS_BoW = cosine_similarity(vec)
# 基于TF-IDF方法構(gòu)造文本向量計算余弦相似度
# 實例化TF-IDF法vectorizer
vectorizer = TfidfVectorizer(token_pattern=r"(?u)\b\w+\b")
# 將語料集轉(zhuǎn)化為TF-IDF向量
vec = vectorizer.fit_transform(data["經(jīng)營討論與分析內(nèi)容"])
# 計算余弦相似度
CS_TFIDF = cosine_similarity(vec)
實證論文
潘欣,余鵬翼,蘇茹,王琳.并購重組業(yè)績承諾與企業(yè)融資約束——基于文本分析的經(jīng)驗證據(jù)[J].管理評論,2022,34(03):268-277.
第三,利用余弦相似度計算樣本與對應(yīng)年份融資約束集的相似度。首先將每一年的 MD&A 樣本和對應(yīng) 年份的融資約束文本集進行整合,利用 python 中的 jieba 庫對整合后的樣本進行分詞,由于分詞效果對下文 TF-IDF 算法結(jié)果具有重要影響,本文采用 github① 上提供的哈工大停用詞、四川大學(xué)機器智能實驗室停用詞、 百度停用詞、中文停用詞以及最全中文停用詞表整合后的 2462 個新中文停用詞列表,優(yōu)化分詞效果。然后根 據(jù)分詞后的詞頻提取特征,也即建立詞頻向量??紤]分詞后詞頻矩陣變大,詞頻向量會變得非常稀疏,本文采 用 TF-IDF 算法,也即詞頻-逆文檔頻率,先計算出關(guān)鍵詞的 TF-IDF 值,然后使用 TF-IDF 矩陣進行余弦相似度 計算,最終得到每年單個樣本與對應(yīng)年度融資約束文本集的相似度 ConstrainedSimilarity
①https://github.com/goto456/stopwords。
第四,考慮到不同的 MD&A 文本中會因章節(jié)標(biāo)題、固定格式、行業(yè)專有名詞和術(shù)語等存在共性內(nèi)容,為了 剔除行業(yè)和上市公司所在板塊要求信息披露方式的影響,本文先將每年的 MD&A 文本按照 2012 年證監(jiān)會行 業(yè)分類代碼進行劃分,對應(yīng)年度的融資約束文本集也按照行業(yè)進行劃分,然后按照上述方法同理計算每年單 個樣本 MD&A 文本與當(dāng)年對應(yīng)行業(yè)融資約束文本集的相似度,最終獲得 IndSimilarity 值,該值即為 MD&A 文 本與對應(yīng)年度融資約束文本集因行業(yè)共性內(nèi)容導(dǎo)致的相似度。同理得到因板塊信息披露方式相同而導(dǎo)致的 相似度 BoardSimilarity 值。
張勇,殷健.會計師事務(wù)所聯(lián)結(jié)與企業(yè)會計政策相似性——基于TF-IDF的文本相似度分析[J].審計研究,2022(01):94-105.
1.會計政策相似性的度量
參考 Brown和 Tucker(2011)的方法,本文采用余弦相似度和歐氏距離來衡量兩公司間會計政策文本的 相似度。計算步驟如下 :
(1)利用 Python中 jieba分詞工具,對每家公司的會計政策文本進行分詞,并將分詞后的會計政策文本制作成詞袋,然后利用該詞袋將處于同年度同行業(yè)所有公司的會計政策文本制作成語料庫。
(2)計算得到詞頻 TF。
(3)利用“逆文檔頻率”(IDF)對 TF進 行加權(quán)。如果含有特定詞 i的文本數(shù)量較多,那么特定詞 i的 IDF值較低,即權(quán)重較低。
(4)將“詞頻”(TF)和“逆文 檔頻率”(IDF)相乘,得到特定詞 i的 TF-IDF值。如果某個特定詞的 TF-IDF值越大,則表示其對文本的重 要性越高,越能有效衡量特定詞對單個文本內(nèi)容的信息含量,以及特定詞在語料庫中對不同文本內(nèi)容信息 的區(qū)分程度。
(5)將公司 i的會計政策文本與同年度同行業(yè)其他公司 {j}的會計政策文本進行配對,分別計 算出配對文本的余弦相似度和歐氏距離作為配對公司會計政策文本的相似度。其中余弦相似度以 TiCos來 表示,歐氏距離以 TiEud來表示,需要說明的是,本文通過取相反數(shù)對歐式距離進行了 趨同化處理。趨同化處理后的歐式距離越大,表示文本相似度越高。
[1]李成剛,賈鴻業(yè),趙光輝,付紅.基于信息披露文本的上市公司信用風(fēng)險預(yù)警——來自中文年報管理層討論與分析的經(jīng)驗證據(jù)[J/OL].中國管理科學(xué):1-14[2023-02-03].https://doi.org/10.16381/j.cnki.issn1003-207x.2020.2263.
3.3.1 文本相似度計算文章來源:http://www.zghlxwxcb.cn/news/detail-410608.html
文本相似度是衡量文本內(nèi)容與上一年份 披露信息的相似程度。本文借鑒Dyer等(2017) [19]的方法,采用粘性(Stickiness)指標(biāo)表示 衡量文本相似度。粘性(Stickiness)是指本 年度文本內(nèi)容中與上一年度相重復(fù)的詞匯或 短語。重復(fù)詞匯越多,相似度越高。本文采 用空間向量模型(VSM)的 TF-IDF 方法,計 算 MD&A 前后兩年粘性(Stickiness)詞匯數(shù) 量,用文本相似度(Sim)進行表示。具體計 算過程如下:首先,計算分詞后的文本詞項 的 TF-IDF 值;然后,將 MD&A 中的文本通 過向量的形式表示出來,向量元素為句子中 經(jīng)過分詞后的詞語出現(xiàn)的頻率,若前后兩年都出現(xiàn)了該詞匯即為粘性 (Stickiness)詞匯;最后,通過計算向量間 的余弦角比較前后兩年 MD&A 的相似程度。文章來源地址http://www.zghlxwxcb.cn/news/detail-410608.html
到了這里,關(guān)于Python文本分析 | 余弦相似度的計算的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!