Đầ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 } 1 2 w {T } w {T } axSim(w,T ) (w) axSim(w,T ) (w) 1 ( , ) 2 idf(w) idf(w) m idf m idf sim T T
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; }
}