From 8407b896f1ba9caec380aa777823a3f018c67d27 Mon Sep 17 00:00:00 2001 From: Kevin Brubeck Unhammer Date: Tue, 30 Sep 2008 11:48:19 +0200 Subject: [PATCH] added ccm.py --- report/report.pdf | Bin 170384 -> 170392 bytes report/report.tex | 44 ++++--- src/ccm.py | 346 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.py | 12 +- 4 files changed, 382 insertions(+), 20 deletions(-) create mode 100644 src/ccm.py diff --git a/report/report.pdf b/report/report.pdf index 5d071330ee43bc30b0d9c993ac2de1507a70012d..2ae254929f767fc20cb068c69ea778f66bb9f923 100644 GIT binary patch delta 10031 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⁢7Qe6rd3N~`s` zxNFV}Ud$B^bGM}YN(Y_`T+aI%cR+K86OU=o-W^Ta+^O+HiY86-o)0Sw?0#dJu3kL( zHvd@(ud0_qz)hn+=1e6I*YMA&6k8s9BxNGLH{IW{>Vv&S?6qyM4};u&*Pa6g+UoLG zmzl-NpDRkwL$A7)Xp?BHwLfD-MTKjMGRCvp2;utdcqs;YYl3Od@52hZ`bF$ zQ}0!KGwQm3kom9Kciyn)&f$faiK`aY6S)3mKl3>m^-B{wFU8L~NzVTue5W07n4-Bw zbAw*;K32I?x(6P6N168TVHnbr%}IE{{yzEWRi4p8b?%Gf!CowmAG-Q4v^h-&90&>> z*HUFznv>UMOAZVgWXXBXA9(04SM9gO(ma>X`OMOs-#Aiv??%bVz`>818bkf66be{_ z&70i4V!vYaKgT6_&#qzBnH#HL74Wpyy6pG?7=<8J5&&ZHAX$|NLRcaRr%IrZlUx*ql1?w45+thPNJK22 zgjXd~@K^!_s1k8WE+4Q-+)EzFA{j@(5^<0!kpyB1B$6sXN@{x`mUMPmIO)lf&HoAz z$*Leopcke zjSLc~4qIywy`dxuNQ9_Gf9|64-n0ibpLH2o&nRNMsQrqHV<^sf&-q>=U9-6^ViaA?iTnR=iOPAqs_9 zt#k$BjS)hHh792WYEd+1k0OY&1tQ_;9K(U+t+UpnF&IXef{GW2Sb@UGAWDu5qA}!- z;OUh?crwZW2uJ#BFEuz8bCi)n9f-xa!E}D%2qb{MVi61}AQVO>q4t6}kVuc=A^NgH zFcAE^45@W-7%U8dsFMI3y;B4d0Yq7Wr$F?M5|DV1QF|$P)OnOG`q}yf{}UwPQN~a} zR5S?`h`x3aj6$Kuh)9CyLqfz6|7{HXCkT+~EhHl0L}OcwN{0a?dOkofG699*@&92o z9*{$akVHZ&rck94F#_;^*aSeREFc{LKw|`YHb5{Ui9V}DL^~>Iq`zwh{uc-l=u?dx zN6&FMB8W#DgPezUgb2`QpNJ>?%Q^V3%}5geEr?uB9Dwo!1ab5jayjt;y&MGs>2C>< z0{(|1kUM|^DG)t--~dDtjX@~ykjswV3*f0P*DwMKL=>?ABs`AZc7R0qQyd298y0dB zx>x{!4AHv^02H)kBr*Xdhopzzd&B|!pK{Xw+6?@M?I5)=0kM-nMCpPkIC|0p5K2a4 z1Oh!qLg<0sZxT{8^aV^J5+K4B2LJ0o5{g9uh>R*$fCQ0IaugyNU4uj-S`MK6(_!ze zPb8$&>7%f96VaZKNdy!|!J#k!9W4@>LUoBm0*#ZDvw8O84ag-k@5grt_< z$E~J?HVODEG5-uWLKqa(W(YtffdqjlB_IJuKj|QH6cQ?q$Y}6SWBz0eWKcyl5hST7 z3L-%edOScX0&NT)Ixg+sM=3CU{fnca>2O{qjv>b>|6EbPhN0p2tp?WA8M<#$U zJ&4DltR~}$s1b%tKs-Q zDD-58Ji{TB4j9Cvsvi&H2>|Ntj|Whj!L9ELP#782`9VAd{ha{PC=m>%0|ENSDT0A0 z??3{XzWNaiqJI}47zLHit-kU9uHv@8LF5HNqJB@s=o}+JI6&6`Pr>Wy07RlLPG6UT wbUgxu+;rp?Q*<@4>i=I6C#=LKJv^S%M+k9%+;#{+mA=kDG5W(J)914JXyrvLx| delta 10090 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 Lm6Fmn(!u^8#iQMB diff --git a/report/report.tex b/report/report.tex index d630da1..328438b 100644 --- a/report/report.tex +++ b/report/report.tex @@ -127,7 +127,20 @@ A similar calculation shows that $$P_{\text{CONTEXT}}(\beta|\text{true},s)=\frac Now let us consider $P_{\text{SPAN}}(\alpha|\text{false},s)$. Again by Bayes' Theorem we have $$P_{\text{SPAN}}(\alpha|\text{false},s)=\frac{P_{\text{SPAN}}(\text{false}|\alpha,s)P_{\text{SPAN}}(\alpha|s)}{P_{\text{SPAN}}(\text{false}|s)}$$ $P_{\text{SPAN}}(\alpha|s)$ is as before. $P_{\text{SPAN}}(\text{false}|s)=1-P_{\text{SPAN}}(\text{true}|s)$. And $P_{\text{SPAN}}(\text{false}|\alpha,s)=1-P_{\text{SPAN}}(\text{true}|\alpha,s)$. Thus -$$P_{\text{SPAN}}(\alpha|\text{false},s)=\frac{(1-\frac{1}{\#_s(\alpha)}\displaystyle\sum_{\langle i,j\rangle=\alpha}P_{\text{BRACKET}}(i,j,s))\frac{2n_s-1}{N_s}}{1-\frac{2n_s-1}{N_s}}$$$$=\frac{\#(\alpha)-\Sigma_{=\alpha}P_{BRACKET}(i,j,s)}{N_s-2n_s+1}$$ +$$ +P_{\text{SPAN}}(\alpha|\text{false},s)=\frac +{(1-\frac + {1} + {\#_s(\alpha)} + \displaystyle\sum_{\langle i,j\rangle=\alpha} + P_{\text{BRACKET}}(i,j,s))\frac + {\#_s(\alpha)} + {N_s}} +{1-\frac{2n_s-1}{N_s}} +$$ +$$=\frac +{\#(\alpha)-\Sigma_{=\alpha}P_{BRACKET}(i,j,s)} +{N_s-2n_s+1}$$ Similarly, we have $$P_{CONTEXT}(\beta|false,s) = \frac{\#(\beta)-\Sigma_{>i,j<=\beta}P_{BRACKET}(i,j,s)}{N_s-2n_s+1}$$ @@ -549,22 +562,23 @@ possible\footnote{221 parses in the dependency parsed WSJ-10 had \begin{table*}[hb] \centering - \begin{tabular}{l|ccc} - Model & P & R & F1 \\ + \begin{tabular}{l|cc} + Model & \multicolumn{2}{c}{F1, directed} \\ \hline - LBRANCH/RHEAD & & & 33.6 \\ - RANDOM & & & 30.1 \\ - RBRANCH/LHEAD & & & 24.0 \\ - K\&M's DMV & & & 43.2 \\ - Our DMV: \\ - Uniform initial distribution & 21.0 (18.7) & 20.1 (18.1) & 20.5 (18.4) \\ - $C_A=0; C_S=1;C_N=0.1;C_M=1$ & 24.8 (24.5) & 23.7 (23.7) & 24.2 (24.1) \\ % local screen - $C_A=0; C_S=1;C_N=0.1;C_M=10$ & 26.7 (31.6) & 25.5 (30.5) & 26.1 (31.0) \\ % uib screen -% $C_A=10;C_S=1;C_N=0.1;C_M=10$ & 25.6 (30.6) & 24.5 (29.6) & 25.0 (30.1) \\ - $C_A=10;C_S=1;C_N=3 ;C_M=10$ & & & 26.3 (31.4) \\ - $C_A=15;C_S=3;C_N=1 ;C_M=20$ & & & 27.2 (32.2) \\ + LBRANCH/RHEAD & \multicolumn{2}{c}{33.6} \\ + RANDOM & \multicolumn{2}{c}{30.1} \\ + RBRANCH/LHEAD & \multicolumn{2}{c}{24.0} \\ + K\&M's DMV & \multicolumn{2}{c}{43.2} \\[3pt] + Our DMV: & no ROOT & ROOT added \\ + \hline + Uniform initial distribution & 24.9 & 22.1 \\ + $C_A=0; C_S=1;C_N=0.1;C_M=1$ & 25.2 & 24.9 \\ + $C_A=0; C_S=1;C_N=0.1;C_M=10$ & 26.9 & 31.9 \\ +% $C_A=10;C_S=1;C_N=0.1;C_M=10$ & 25.0 & 30.1 \\ + $C_A=10;C_S=1;C_N=3 ;C_M=10$ & 26.3 & 31.4 \\ + $C_A=15;C_S=3;C_N=1 ;C_M=20$ & 27.2 & 32.2 \\ \end{tabular} - \caption{DMV results on the WSJ-10 for various initialization values (numbers in parentheses are when counting added ROOT links)} + \caption{DMV results on the WSJ-10 for various initialization values (the right column is when we counted ROOT links added to the gold parses)} \label{tab:dmv-wsj} \end{table*} diff --git a/src/ccm.py b/src/ccm.py new file mode 100644 index 0000000..677ad02 --- /dev/null +++ b/src/ccm.py @@ -0,0 +1,346 @@ +# ccm.py -- algorithm for the CCM model, +# http://repo.or.cz/w/dmvccm.git +# +# Copyright (C) 2008 Emily Morgan + +testcorpus = [tuple(s.split()) for s in ['a b c', 'b c a']] + +########################################################## +#functions for dealing with sentences +#indices refer to spaced between words and are 0-indexed + +#beginning and end of sentence tokens, needed for contexts +BEGIN = "BEGIN" +END = "END" + + +def alpha(i, j, sen): + '''returns span from i to j''' + return sen[i:j] + +def beta(i,j,sen): + '''returns context [i-1,j+1]''' + if i==0: + first = BEGIN + else: + first = sen[i-1] + if j==len(sen): + second = END + else: + second = sen[j] + return (first, second) + +####################################### +#stuff that just needs to happen once + +#constants for smoothing +const=1 +dist=2 + +def spancontextlists(corpus): + '''returns sets of all spans and all contexts''' + spanslist = set([]) + contextslist = set([]) + for s in corpus: + for i in range(len(s)+1): + for j in range(len(s)-i+1): + spanslist.add(alpha(i,i+j,s)) + contextslist.add(beta(i,i+j,s)) + return [spanslist, contextslist] + +def p_split(i,j,s): + l=j-i + n=len(s) + if l==0 or l>n: + return 0.0 + elif l==1 or l==n: + return 1.0 + elif n==3: + return .5 + elif n==4: + return .4 + elif n==5: + if l==2 or l==4: + return 5.0/14 + else: + return 4.0/14 + else: + return -1 + +def initP_BRACKET(corpus): + #no smoothing used yet + p_bracket={} + for s in corpus: + for i in range(len(s)+1): + for j in range(len(s)-i+1): + p_bracket[i,i+j,s]=p_split(i,i+j,s) + return p_bracket + +def initP_SPANandCONTEXT(corpus,P_BRACKET): + [totalspans,totalconstits]=counts(corpus) + [spanlist,contextlist]=spancontextlists(corpus) + apbracketsums={} + bpbracketsums={} + acounts={} + bcounts={} + P_SPAN={} + P_CONTEXT={} + for s in corpus: + for i in range(len(s)+1): + for j in range(len(s)-i+1): + a=alpha(i,i+j,s) + b=beta(i,i+j,s) + try: + acounts[a]+=1 + apbracketsums[a]+=P_BRACKET[i,i+j,s] + except KeyError: + acounts[a]=1 + apbracketsums[a]=P_BRACKET[i,i+j,s] + try: + bcounts[b]+=1 + bpbracketsums[b]+=P_BRACKET[i,i+j,s] + except KeyError: + bcounts[b]=1 + bpbracketsums[b]=P_BRACKET[i,i+j,s] + for a in spanlist: + P_SPAN[a,1]=(apbracketsums[a]+const)/(totalconstits+const*len(spanlist)) + P_SPAN[a,0]=(acounts[a]-apbracketsums[a]+dist)/\ + (totalspans-totalconstits+dist*len(spanlist)) + for b in contextlist: + P_CONTEXT[b,1]=(bpbracketsums[b]+const)/\ + (totalconstits+const*len(contextlist)) + P_CONTEXT[b,0]=(bcounts[b]-bpbracketsums[b]+dist)/\ + (totalspans-totalconstits+dist*len(contextlist)) + return [P_SPAN,P_CONTEXT] + + +####################################### +#relative frequency estimates + +def counts(corpus): + '''returns total numbers of spans and constituents in the corpus''' + spans = 0 + constits = 0 + for s in corpus: + n = len(s) + spans += (n+1)*(n+2)/2 #counting empty spans + constits += 2*n-1 + return [spans, constits] + +def p_relfreqs(corpus): + '''returns dictionaries p_span and p_context + with relative frequencies for each span and context + (irrespective of length)''' + [totalspans, totalconstits]=counts(corpus) + [spanslist, contextslist]=spancontextlists(corpus) + span_counts={} + context_counts={} + p_span_relfreq={} + p_context_relfreq={} + for s in spanslist: + span_counts[s]=0.0 + for s in contextslist: + context_counts[s]=0.0 + for s in corpus: + for i in range(len(s)+1): + for j in range(len(s)-i+1): + span_counts[alpha(i,i+j,s)]+=1 + context_counts[beta(i,i+j,s)]+=1 + for a in spanslist: + p_span_relfreq[a]=span_counts[a]/totalspans + for b in contextslist: + p_context_relfreq[b]=context_counts[b]/totalspans + return [p_span_relfreq, p_context_relfreq] + +############### +#reestimation + +# def calculatephi(corpus, p_span, p_context): +# phi={} +# for s in corpus: +# for i in range(len(s)+1): +# for j in range(len(s)-i+1): +# a=alpha(i,i+j,s) +# b=beta(i,i+j,s) +# if j-i==1: +# phi[i,i+j,s]=p_span[a,1]*p_context[b,1]/ \ +# p_context[b,0] +# elif j-i==len(s): +# phi[i,i+j,s]=p_span[a,1]*p_context[b,1]/ \ +# p_span[a,0] +# else: +# try: +# phi[i,i+j,s]=p_span[a,1]*p_context[b,1]/ \ +# (p_span[a,0]*p_context[b,0]) +# except ZeroDivisionError: +# print \ +# '''Error! a=%s, b=%s, p_span[a,0]=%s, and p_context[b,0]=%s\n''' % (a,b,p_span[a,0],p_context[b,0]) +# phi[i,i+j,s]=p_span[a,1]*p_context[b,1] + +# return phi + +def calculatephi(corpus, p_span, p_context): + phi={} + for s in corpus: + for i in range(len(s)+1): + for j in range(len(s)-i+1): + a=alpha(i,i+j,s) + b=beta(i,i+j,s) + phi[i,i+j,s]=p_span[a,1]*p_context[b,1]/ \ + (p_span[a,0]*p_context[b,0]) + return phi + +def calculateI(corpus,phi): + I={} + for s in corpus: + for jcounter in range(len(s)+1): + for i in range(len(s)+1-jcounter): + j=i+jcounter + if j-i==0: + I[i,j,s]=0 + elif j-i==1: + I[i,j,s]=phi[i,j,s] + else: + sum = 0 + for kcounter in range(j-i-1): + k=i+1+kcounter + sum += I[i,k,s]*I[k,j,s] + I[i,j,s]=phi[i,j,s]*sum + return I + +def calculateO(corpus,phi,I): + O={} + for s in corpus: + O[0,len(s),s]=1 + for jcounter in [len(s)-1-x for x in range(len(s))]: + for i in range(len(s)+1-jcounter): + j=i+jcounter + sum = 0 + for k in range(i): + sum+=I[k,i,s]*phi[k,j,s]*O[k,j,s] + for k in [j+1+x for x in range(len(s)-j)]: + sum+=I[j,k,s]*phi[i,k,s]*O[i,k,s] + O[i,j,s]=sum + return O + +def calculateP_BRACKET(corpus,I,O): + P_BRACKET={} + for s in corpus: + for i in range(len(s)+1): + for j in range(len(s)+1-i): + P_BRACKET[i,i+j,s]=I[i,i+j,s]*O[i,i+j,s]/I[0,len(s),s] + return P_BRACKET + +def calculateP_SPANandCONTEXT(corpus,P_BRACKET): + P_SPAN={} + P_CONTEXT={} + for s in corpus: + N=(len(s)+1)*(len(s)+2)/2 + acounts={} + apbracketsums={} + bcounts={} + bpbracketsums={} + for i in range(len(s)+1): + for j in range(len(s)+1-i): + a=alpha(i,i+j,s) + b=beta(i,i+j,s) + try: + acounts[a]+=1 + apbracketsums[a]+=P_BRACKET[i,i+j,s] + except KeyError: + acounts[a]=1 + apbracketsums[a]=P_BRACKET[i,i+j,s] + try: + bcounts[b]+=1 + bpbracketsums[b]+=P_BRACKET[i,i+j,s] + except KeyError: + bcounts[b]=1 + bpbracketsums[b]=P_BRACKET[i,i+j,s] + for a in acounts.keys(): + if len(s)==1: + if a==s: + trueval=1 + else: + trueval=0 + else: + trueval=apbracketsums[a]/(2*len(s)-1) + falseval=(acounts[a]-apbracketsums[a])/(N-2*len(s)+1) + try: + P_SPAN[a,1]+=trueval + P_SPAN[a,0]+=falseval + except KeyError: + P_SPAN[a,1]=trueval + P_SPAN[a,0]=falseval + for b in bcounts.keys(): + if len(s)==1: + if b==(BEGIN, END): + trueval=1 + else: + trueval=0 + else: + trueval=bpbracketsums[b]/(2*len(s)-1) + falseval=(bcounts[b]-bpbracketsums[b])/(N-2*len(s)+1) + try: + P_CONTEXT[b,1]+=trueval + P_CONTEXT[b,0]+=falseval + except KeyError: + P_CONTEXT[b,1]=trueval + P_CONTEXT[b,0]=falseval + [totalspans,totalconstits]=counts(corpus) + mtrue, mfalse=.01,.02 + for k,v in P_SPAN.items(): + if k[1]==1: + P_SPAN[k]=(v+mtrue)/(len(corpus)*(1+mtrue*totalspans)) + else: + P_SPAN[k]=(v+mfalse)/(len(corpus)*(1+mfalse*totalspans)) + for k,v in P_CONTEXT.items(): + if k[1]==1: + P_CONTEXT[k]=(v+mtrue)/(len(corpus)*(1+mtrue*totalconstits)) + else: + P_CONTEXT[k]=(v+mfalse)/(len(corpus)*(1+mfalse*totalconstits)) + return [P_SPAN,P_CONTEXT] + +def reestimate(corpus,p_span,p_context): + phi=calculatephi(corpus,p_span,p_context) + I=calculateI(corpus,phi) + O=calculateO(corpus,phi,I) + P_BRACKET = calculateP_BRACKET(corpus,I,O) + [newP_SPAN,newP_CONTEXT]=calculateP_SPANandCONTEXT(corpus,P_BRACKET) + return [newP_SPAN,newP_CONTEXT] + + + +############# +#test stuff + +def initialp(corpus): + '''a stupid initialization that always gives phi=1''' + [p_span, p_context]=p_relfreqs(corpus) + for k,v in p_span.items(): + p_span[k,1]= v + p_span[k,0]= v + for k,v in p_context.items(): + p_context[k,1]= v + p_context[k,0]= v + return [p_span, p_context] + +if __name__ == "__main__": + p_bracket=initP_BRACKET(testcorpus) +# print "\n".join(["%s : %s" % (k,v) for k,v in p_bracket.items()]) + [P_SPAN,P_CONTEXT]=initP_SPANandCONTEXT(testcorpus,p_bracket) + for n in range(2): +# print "\n".join(["%s : %s" % (k,v) for k,v in P_CONTEXT.items()]) + [P_SPAN,P_CONTEXT]=reestimate(testcorpus,P_SPAN,P_CONTEXT) + print "\n".join(["%s : %s" % (k,v) for k,v in P_SPAN.items()]) + + + +# [p_span, p_context]=initialp(testcorpus) +# phi=calculatephi(testcorpus,p_span,p_context) +# I = calculateI(testcorpus,phi) +# O = calculateO(testcorpus,phi,I) +# P_BRACKET = calculateP_BRACKET(testcorpus,I,O) +# [P_SPAN,P_CONTEXT]=calculateP_SPANandCONTEXT(testcorpus,P_BRACKET) +# print "\n".join(["%s : %s" % (k,v) for k,v in P_SPAN.items()]) +# print counts(testcorpus) +# print p_relfreqs(testcorpus) diff --git a/src/main.py b/src/main.py index a4384ba..e6798fd 100644 --- a/src/main.py +++ b/src/main.py @@ -17,10 +17,10 @@ def initialize_loc_h(tagonlys): # loc_h_harmonic.FSTOP_MIN = 13.5744632704 # loc_h_harmonic.FNONSTOP_MIN = 34.8939452454 loc_h_harmonic.HARMONIC_C = 0.0 #120.0 * random.random() # 509.63 - loc_h_harmonic.STOP_C = 1.0 #3.0 * random.random() - loc_h_harmonic.NSTOP_C = 0.1 #5.0 * random.random() # 0.1 + loc_h_harmonic.STOP_C = 3.0 #3.0 * random.random() + loc_h_harmonic.NSTOP_C = 1.0 #5.0 * random.random() # 0.1 loc_h_harmonic.FSTOP_MIN = 10.0 #20.0 * random.random() # 13.08 -# $C_A=0; C_S=1;C_N=0.1;C_M=10$ + loc_h_harmonic.RIGHT_FIRST = 1.0 loc_h_harmonic.OLD_STOP_CALC = False print ''' @@ -146,8 +146,10 @@ class Evaluation(): R: %5d/%5d = %s | R_r: %5d/%5d = %s F1: %s | F1_r: %s (unrooted gold parses: %d, double-headed: %d)'''%str_vals - tex_str_vals = tuple([p * 100 for p in (self._precision,self._precision_r,self._recall,self._recall_r,self._F1,self._F1_r)]) - tex_str = "$C_A=; C_S=;C_N=;C_M=$ & %.1f (%.1f) & %.1f (%.1f) & %.1f (%.1f) \\"%tex_str_vals + if self._precision != self._recall: print regular_str # raise Exception todo + + tex_str_vals = tuple([p * 100 for p in (self._F1,self._F1_r)]) + tex_str = "$C_A=; C_S=;C_N=;C_M=$ & %.1f & %.1f \\"%tex_str_vals return tex_str # todo make variable -- 2.11.4.GIT