Đầu vào: Hai văn bản đã tách từ. Đầu ra: Độ tƣơng tự giữa hai văn bản.
Độ tƣơng tự giữa hai văn bản đƣợc tính theo công thức:
Bƣớc 1: Tính toán giá trị idf của một từ
Idf của một từ đƣợc tính bằng tổng số toàn bộ tài liệu trong tập corpus chia cho tổng số tài liệu chứa từ đó.
Bƣớc 2: Tính độ tƣơng tự lớn nhất của một từ so với một văn bản
Để dễ tính toán, ta biểu diễn văn bản dƣới dạng mảng các từ (từ ghép + danh từ riêng) riêng lẻ. Sau đó, ta xét các trƣờng hợp nhƣ sau:
Nếu có 2 từ giống hệt nhau thì trả lại giá trị 1.
Nếu có 2 từ giống nhau nhƣng khác nhau ở chữ hoa chữ thƣờng thì trả lại giá trị 0.98.
Nếu có 2 từ khác nhau nhƣng là từ đồng nghĩa thì trả lại giá trị 0.98. Nếu không có từ nào khớp thì trả lại giá trị 0.
1 2 1 2 2 1 w{T} w{T} 12 w{T} w{T} axSim(w,T) (w) axSim(w,T) (w) 1 (,) 2 idf(w) idf(w) m idf m idf simTT
Bƣớc 3: Tính toán độ tƣơng tự giữa hai văn bản: dựa vào các tính toán từ bƣớc 2 và theo công thức đã nêu ở trên.
Mã nguồn của module này nhƣ sau: public class Processor {
/*
* Tính toán IDF của 1 từ
* Giá trị mặc định là 1 (khi là từ mới - chƣa xuất hiện trong tài liệu nào) */
public static double getIDF(String word) {
int total_doc = FileProcessor.VProcessedFiles.size(); String sValue = WordDict.HashDict.get(word);
if (total_doc == 0 || sValue == null || sValue.length() == 0) return 1; int total_appear = sValue.split(";").length;
if (total_appear == 0) return 1;
double result = total_doc / total_appear; return result;
} /*
* Tính độ tƣơng tự lớn nhất của 1 từ so với 1 văn bản (dƣới dạng mảng các từ) * word: từ dùng để so khớp.
* sWordArr: nội dung văn bản đã tách ra thành mảng các String riêng lẻ */
public static double getMaxSim(String word, String[] sWordArr) { double maxValue = 0;
word = word.trim(); //loại bỏ các ký tự thừa ở đầu và cuối if (word.length() == 0) return 0;
Integer value1 = WordDict.CompoundDict.get(word); for (String currWord: sWordArr) {
if (currWord.length() <= 0) continue; if (currWord.equals(word)) { maxValue = 1; break; } else if (currWord.equalsIgnoreCase(word)) { if (maxValue < 0.98) maxValue = 0.98; } else {
Integer value2 = WordDict.CompoundDict.get(currWord);
if (value1!= null && value2!=null && value1.intValue() == value2.intValue()) { if (maxValue < 0.98) { maxValue = 0.98; } } } } return maxValue; } /*
* Tính toán độ tƣơng tự giữa 2 văn bản * Đầu vào: 2 văn bản s1 + s2
*/
public static double getSim(String s1, String s2) { String sArr1[] = s1.split(" ");
String sArr2[] = s2.split(" "); double total_maxsim1 = 0; double total_idf1 = 0;
for (int i = 0; i < sArr1.length; i++) { String word = sArr1[i];
double word_idf = getIDF(word); total_idf1 += word_idf;
total_maxsim1 += getMaxSim(word, sArr2) * word_idf; }
double sim1 = 0; if (total_idf1 != 0) {
sim1 = total_maxsim1 / total_idf1; }
double total_maxsim2 = 0; double total_idf2 = 0;
for (int i = 0; i < sArr2.length; i++) { String word = sArr2[i];
double word_idf = getIDF(word); total_idf2 += word_idf;
total_maxsim2 += getMaxSim(word, sArr1) * word_idf; }
double sim2 = 0; if (total_idf2 != 0) {
sim2 = total_maxsim2 / total_idf2; }
return (sim1 + sim2)/2; }
}