2016-02-18 18 views
10

Tôi đã theo giấy here và mã here (nó được thực hiện bằng cách sử dụng kld đối xứng và mô hình lùi được đề xuất trong bài trong liên kết 1) để tính toán KLD giữa hai tập dữ liệu văn bản. Tôi đã thay đổi cho vòng cuối cùng để trả lại phân bố xác suất của hai bộ dữ liệu để kiểm tra nếu cả hai tổng đến 1:Tính toán phân kỳ đối xứng Kullback-Leibler giữa hai tài liệu

import re, math, collections 

def tokenize(_str): 
    stopwords = ['and', 'for', 'if', 'the', 'then', 'be', 'is', \ 
       'are', 'will', 'in', 'it', 'to', 'that'] 
    tokens = collections.defaultdict(lambda: 0.) 
    for m in re.finditer(r"(\w+)", _str, re.UNICODE): 
     m = m.group(1).lower() 
     if len(m) < 2: continue 
     if m in stopwords: continue 
     tokens[m] += 1 

    return tokens 
#end of tokenize 

def kldiv(_s, _t): 
    if (len(_s) == 0): 
     return 1e33 

    if (len(_t) == 0): 
     return 1e33 

    ssum = 0. + sum(_s.values()) 
    slen = len(_s) 

    tsum = 0. + sum(_t.values()) 
    tlen = len(_t) 

    vocabdiff = set(_s.keys()).difference(set(_t.keys())) 
    lenvocabdiff = len(vocabdiff) 

    """ epsilon """ 
    epsilon = min(min(_s.values())/ssum, min(_t.values())/tsum) * 0.001 

    """ gamma """ 
    gamma = 1 - lenvocabdiff * epsilon 

    """ Check if distribution probabilities sum to 1""" 
    sc = sum([v/ssum for v in _s.itervalues()]) 
    st = sum([v/tsum for v in _t.itervalues()]) 

    ps=[] 
    pt = [] 
    for t, v in _s.iteritems(): 
     pts = v/ssum 
     ptt = epsilon 
     if t in _t: 
      ptt = gamma * (_t[t]/tsum) 
     ps.append(pts) 
     pt.append(ptt) 
    return ps, pt 

tôi đã thử nghiệm với

d1 = """Many research publications want you to use BibTeX, which better organizes the whole process. Suppose for concreteness your source file is x.tex. Basically, you create a file x.bib containing the bibliography, and run bibtex on that file.""" d2 = """In this case you must supply both a \left and a \right because the delimiter height are made to match whatever is contained between the two commands. But, the \left doesn't have to be an actual 'left delimiter', that is you can use '\left)' if there were some reason to do it."""

sum(ps) = 1 nhưng sum(pt) là cách nhỏ hơn 1 khi:

This should be the case.

là ther e cái gì đó là không chính xác trong mã hoặc người nào khác? Cảm ơn!

Cập nhật:

Để làm cho cả pt và ps sum tới 1, tôi đã phải thay đổi mã để:

vocab = Counter(_s)+Counter(_t) 
    ps=[] 
    pt = [] 
    for t, v in vocab.iteritems(): 
     if t in _s: 
      pts = gamma * (_s[t]/ssum) 
     else: 
      pts = epsilon 

     if t in _t: 
      ptt = gamma * (_t[t]/tsum) 
     else: 
      ptt = epsilon 

     ps.append(pts) 
     pt.append(ptt) 

    return ps, pt 
+0

Không liên quan đến câu hỏi của bạn, trong chuỗi thử nghiệm (d1 và d2), bạn nên sử dụng hai dấu gạch chéo ngược liên tiếp. Ký tự dấu gạch chéo ngược được sử dụng để thoát trong python. Ví dụ: 'x =" \\ left "' thay vì 'x =" \ left "'. –

Trả lời

2

Cả tổng (ps) và tổng (pt) là tổng xác suất khối lượng của _s và _t ort of s (bởi "hỗ trợ của s", tôi có nghĩa là tất cả các từ xuất hiện trong _s, bất kể các từ xuất hiện trong _t). Điều này có nghĩa là

  1. tổng (ps) == 1, vì tổng số tiền lặp trên tất cả các từ trong _s.
  2. tổng (pt) < = 1, nơi bình đẳng sẽ giữ nếu hỗ trợ của t là tập hợp con hỗ trợ của s (nghĩa là, nếu tất cả các từ trong _t xuất hiện trong _s). Ngoài ra, tổng (pt) có thể gần bằng 0 nếu chồng chéo giữa các từ trong _s và _t là nhỏ. Cụ thể, nếu giao điểm của _s và _t là tập rỗng, thì tổng (pt) == epsilon * len (_s).

Vì vậy, tôi không nghĩ rằng có vấn đề với mã.

Ngoài ra, trái với tiêu đề của câu hỏi, kldiv() không tính toán phân kỳ KL đối xứng, nhưng sự phân kỳ KL giữa _s và phiên bản trơn tru của _t.

+0

Cảm ơn Tomer! "Chúng là xác suất trên sự hỗ trợ của s" có ý nghĩa bây giờ. Mặc dù trong bài báo nó đã nói rằng đây là đối xứng KLD, bạn có nghĩ rằng việc thực hiện ở đây là một chút không? – Blue482

+0

Bạn có thể tham khảo phần còn lại của mã không? –

+0

Xin chào Tomer, tôi đã thực hiện một số thay đổi nhỏ từ [mã gốc] (https://gist.github.com/mrorii/961963) và có thể tìm thấy tại đây (https://gist.github.com)/bluemonk482/f3e2fd35a774a61dbedd). Mã được sửa đổi tính ps và pt dựa trên liên kết vocab của chúng, thay vì dựa vào sự hỗ trợ của s. Bạn có nghĩ rằng đây là một phiên bản tốt hơn của kld hơn so với việc thực hiện ban đầu, để đo khoảng cách giữa hai văn bản corpus? Cám ơn rất nhiều! – Blue482

0

Tổng số phân bố xác suất của bạn cho mỗi tài liệu được lưu trữ trong các biến số scst, chúng gần với 1.

Các vấn đề liên quan