個人項目
這個作業屬於哪個課程 | 課程鏈接 |
---|---|
這個作業要求在哪里 | 作業要求 |
這個作業的目標 | 完成論文查重代碼上傳到github上,完成github項目編寫 |
github鏈接
PSP2.1 | Personal Software Process Stages | 預估耗時(分鍾) | 實際耗時(分鍾) |
---|---|---|---|
Planning | 計划 | ---- | ---- |
Estimate | 估計這個任務需要多少時間 | 410 | 390 |
Development | 開發 | ---- | ---- |
Analysis | 需求分析 (包括學習新技術) | 120 | 100 |
Design Spec | 生成設計文檔 | 30 | 30 |
Design Review | 設計復審 | 30 | 30 |
Coding Standard | 代碼規范 (為目前的開發制定合適的規范) | 40 | 40 |
Design | 具體設計 | 30 | 30 |
· Coding | 具體編碼 | 60 | 60 |
· Code Review | 代碼復審 | 30 | 30 |
Test | 測試(自我測試,修改代碼,提交修改) | 30 | 30 |
Reporting | 報告 | ---- | ---- |
Test Repor | 測試報告 | 20 | 20 |
Size Measurement | 計算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后總結, 並提出過程改進計划 | 10 | 10 |
---- | 合計 | 410 | 390 |
2.1計算模塊接口的設計與實現過程
我實現了兩種論文查重算法,一種是基於詞頻向量的余弦距離算法,一種是simhash算法
余弦距離算法
包含一個主函數,一個filter函數,以及一個calc_similarity函數
calc_similarity函數用於實現對兩個論文進行進行詞頻向量的轉換以及余弦距離的計算,我們使用gensim自帶的doc2bow進行轉換,然后使用自帶的similarity函數進行計算
filter函數我們使用了jieba分詞進行cut,然后用re.match將標點符號空格分段去掉
余弦距離算法流程:
simhash算法
包含一個主函數,一個simhash類
simhash先計算字符串的simhash值,再用hammingDis計算兩段hash值的距離
simhash程序流程:
2.2關鍵函數的分析與實現
simhash算法
在實現和學習算法的過程中,我參考研究了以下文章:
在simhash中處理一個文本的步驟如下:
第一步,分詞:
對文本進行分詞操作,同時需要我們同時返回當前詞組在文本內容中的權重。
第二步,計算hash:
對於每一個得到的詞組做hash,將詞語表示為到01表示的bit位,需要保證每個hash結果的位數相同,如圖中所示,使用的是8bit。
第三步,加權
根據每個詞組對應的權重,對hash值做加權計算(bit為1則取為1做乘積,bit為0則取為-1做乘積),如上圖中,
10011111與權重2加權得到[2 -2 -2 2 2 2 2 2];
01001011與權重1加權得到[-1 1 -1 -1 1 -1 1 1];
01001011與權重4加權后得到[-4 4 -4 -4 4 -4 4 4];
第三步,縱向相加:
將上述得到的加權向量結果,進行縱向相加實現降維,如上述所示,得到[-3 3 -7 -3 7 -3 7 7]。
第四步,歸一化:
將最終降維向量,對於每一位大於0則取為1,否則取為0,這樣就能得到最終的simhash的指紋簽名[0 1 0 0 1 0 1 1]
第五步,相似度比較:
通過上面的步驟,我們可以利用SimHash算法為每一個網頁生成一個向量指紋,在simhash中,判斷2篇文本的相似性使用的是漢明距離。在在經驗數據上,我們多認為兩個文本的漢明距離<=3的話則認定是相似的。
基於詞頻向量的余弦距離算法
假設有兩個句子A,B
句子A:我喜歡吃蘋果,不喜歡吃榴蓮
句子B:我不喜歡吃蘋果,也不喜歡吃榴蓮。
第一步,分詞。
句子A:我/喜歡/吃/蘋果,不/喜歡/吃/榴蓮。
句子B:我/不/喜歡/吃/蘋果,也/不/喜歡/吃/榴蓮
實現:通過python的jieba分詞實現,即通過查詢內置的詞典進行分詞
第二步,列出所有的詞。
我,喜歡,吃,蘋果,榴蓮,不,也。
第三步,計算詞頻。
句子A:我 1,喜歡 2,吃 2,蘋果 1,榴蓮 1,不 1,也 0。
句子B:我 1,喜歡 2,吃 2,蘋果 1,榴蓮 1,不 2,也 1。
第四步,寫出詞頻向量。
句子A:[1, 2, 2, 1, 1, 1, 0]
句子B:[1, 2, 2, 1, 1, 2, 1]
第五步,計算余弦距離
我們可以把它們想象成空間中的兩條線段,都是從原點([0, 0, ...])出發,指向不同的方向。兩條線段之間形成一個夾角,如果夾角為0度,意味着方向相同、線段重合;如果夾角為90度,意味着形成直角,方向完全不相似;如果夾角為180度,意味着方向正好相反。因此,我們可以通過夾角的大小,來判斷向量的相似程度。夾角越小,就代表越相似。
以上內容參考自:TF-IDF與余弦相似性的應用(二):找出相似文章
3. 計算模塊接口部分的性能改進
simhash
耗時:
基於詞頻向量的余弦距離算法
耗時:
4.計算模塊部分單元測試展示
simhash
punc = './ <>_ - - = ", 。,?!“”:‘’@#¥% … &×()——+【】{};;● &~| \s:'
real_txt=open(sys.argv[1],encoding='utf8')
string1=''
string2=''
copy_txt=open(sys.argv[2],encoding='utf8')
real_txt=real_txt.read()
copy_txt=copy_txt.read()
print(copy_txt)
real_txt = re.sub(r'[^\w]+', '',real_txt)
seg=jieba.cut(real_txt)
string1=string1.join(seg)
line1 = re.sub(r"[{}]+".format(punc), "", string1)
copy_txt = re.sub(r'[^\w]+', '',copy_txt)
seg=jieba.cut(copy_txt)
string2=string2.join(seg)
line2 = re.sub(r"[{}]+".format(punc), "", string2)
print(line2)
keyWord = jieba.analyse.extract_tags(
'|'.join(content), topK=10, withWeight=True, allowPOS=())
print(keyWord)
keyList = []
for feature, weight in keyWord:
weight = int(weight * 10)
feature = self.string_hash(feature)
temp = []
for i in feature:
if(i == '1'):
temp.append(weight)
else:
temp.append(-weight)
# print(temp)
keyList.append(temp)
list1 = np.sum(np.array(keyList), axis=0)
print(list1)
if(keyList==[]): #編碼讀不出來
return '00'
simhash = ''
for i in list1:
if(i > 0):
simhash = simhash + '1'
else:
simhash = simhash + '0'
return simhash
基於詞頻向量的余弦距離算法
real_txt=open(sys.argv[1],encoding='utf8')
copy_txt=open(sys.argv[2],encoding='utf8')
str1=real_txt.read()
str2=copy_txt.read()
print(str2)
text1 = filter(str1)
text2 = filter(str2)
print(text2)
sim=calc_similarity(text1,text2)
def calc_similarity(text1,text2):
texts=[text1,text2]
dictionary = gensim.corpora.Dictionary(texts)
print(dictionary)
corpus = [dictionary.doc2bow(text) for text in texts]
print(corpus)
similarity = gensim.similarities.Similarity('-Similarity-index', corpus, num_features=len(dictionary))
test_corpus_1 = dictionary.doc2bow(text1)
cosine_sim = similarity[test_corpus_1][1]
return cosine_sim
代碼覆蓋率截圖
5.模塊部分異常處理說明
assert len(sys.argv)==4,"輸入不符合規范,缺少文件目錄"
assert os.path.exists(sys.argv[1]),"原文文件不存在,請檢查文件目錄是否正確"
assert os.path.exists(sys.argv[1]),"抄襲文件不存在,請檢查文件目錄是否正確"
6.項目程序功能測試
基於詞頻向量的余弦距離算法
simhash