before trying new pchoose reestimation
[dmvccm.git] / DMVCCM.org
blob1465f36ff9e4cff0b1ec9bec82274e53fb3574d1
1 # -*- coding: mule-utf-8-unix -*-
3 #+STARTUP: overview
4 #+TAGS: OPTIMIZE PRETTIER
5 #+STARTUP: hidestars
6 #+TITLE: DMV/CCM -- todo-list / progress
7 #+AUTHOR: Kevin Brubeck Unhammer
8 #+EMAIL: K.BrubeckUnhammer at student uva nl 
9 #+OPTIONS: ^:{} 
10 #+LANGUAGE: en
11 #+SEQ_TODO: TOGROK TODO DONE
14 * dmvccm report and project
15   DEADLINE: <2008-06-30 Mon>
16 - [[file:src/dmv.py][dmv.py]]
17 - [[file:src/io.py][io.py]]
18 - [[file:src/harmonic.py::harmonic%20py%20initialization%20for%20dmv][harmonic.py]]
20 (But absolute, extended, really-quite-dead-now deadline: August 31...)
22 [[http://www.student.uib.no/~kun041/dmvccm/DMVCCM_archive.html][Archived entries]] from this file.
23 * P_STOP and P_CHOOSE for IO/EM (reestimation)
24 [[file:src/dmv.py::DMV%20probabilities][dmv-P_STOP]]
25 Remember: The P_{STOP} formula is upside-down (left-to-right also).
26 (In the article..not the [[http://www.eecs.berkeley.edu/~klein/papers/klein_thesis.pdf][thesis]])
28 ** TOGROK L&Y formula (20) or c()-formula?
29 At first glance, I've been doing \\
30 c(s,r,_a_) / [ c(r+1,t, h_) * c(s,t, h_) ] \\
31 <=>
32 | 1/P_sent * e(s,r,_a_) * f(s,r,_a_)                                           |
33 | /                                                                            |
34 | [ 1/P_sent * e(r+1,t,h_) * f(r+t,t,h_) * 1/P_sent * e(s,t, h_) * f(s,t,h_) ] |
36 while L&Y uses
37 | w_sent = 1/P_sent * prob(h_->_a_ h_) * e(s,r,_a_) * e(r+1,t, h_) * f(s,t,h_) |
38 | /                                                                            |
39 | v_sent = 1/P_sent * e(s,t,h_) * f(s,t,h_) = c(s,t,h_)                        |
41 Just for completion: \\
42 PSTOP =eg. c(s,t,_h_) / c(s,t,h_) for certain s,t \\
43 <=>
44 | 1/P_sent * e(s,t,_h_) * f(s,t,_h_) |
45 | /                                  |
46 | 1/P_sent * e(s,t, h_) * f(s,t, h_) |
48 vs what seems to be the direct L&Y translation:
50 | 1/P_sent * prob(_ h_ -> STOP h_) * e(s,t,h_) * f(s,t,_h_) |
51 | /                                                         |
52 | 1/P_sent * e(s,t,_h_) * f(s,t,_h_)                        |
54 ...but if we used that, e(s,t,h_) would cancel out and we'd just be
55 dividing the outer scores * rule-probability.. hmm.. Also, there's the
56 problem of what 'rule-probability' means here, since there's on the
57 one hand the CNF-rule probability, and on the other hand PSTOP and
58 PCHOOSE -- in stop rules, PSTOP is the rule-probability, while for
59 attachment rules, it's PCHOOSE*(1-PSTOP). 
60 ** TODO [#A] P_CHOOSE formula:
61    - Note taken on [2008-06-16 Mon 12:33] \\
62      Implemented as assumed below, but this does not give 1-summing
63      probabilities, why? Are we checking the right configurations? Eg,
64      is it enough to just check c(s,t,h_), c(s,r,_a_) and
65      c(r+1,t,h_) for left attachments??
67 So far assuming this:
69 | P_{CHOOSE}(a : h,R) = | \sum_{corpus} \sum_{s=loc(h)} \sum_{t > loc(h)} \sum_{loc(h) < r <= t} c(r,t,_a_)               |
70 |                       | \sum_{corpus} \sum_{s=loc(h)} \sum_{t > loc(h)} \sum_{loc(h) < r <= t} c(s,t,h) * c(s, r-1, h_) |
71 |                       |                                                                                                 |
72 | P_{CHOOSE}(a : h,L) = | \sum_{corpus} \sum_{s<loc(h)} \sum_{t>=loc(h)} \sum_{r<loc(h)} c(s,r,_a_)                       |
73 |                       | \sum_{corpus} \sum_{s<loc(h)} \sum_{t>=loc(h)} \sum_{r<loc(h)} c(s,t,h_) * c(r+1, t, h_)        |
74 t >= loc(h) since there are many possibilites for right-attachments
75 below, and each of them alone gives a lower probability (through
76 multiplication) to the upper tree (so add them all)
78 The reason we have to check /both/ children of the attachments is that we
79 have to make sure they are contiguous (otherwise we would have no way
80 of ruling out eg. h_->_b_,_b_->b_->_a_, where h_ covers *s* and *t*,_b_ is
81 from *s* to *x<r* and _ a_ is from *s* to *r*).
82 *** TOGROK Problem with this formula:
83 On calculating P_{CHOOSE}(det | vbd, L) from the 1-sentence corpus
84 "det nn vbd", there are two ways in which 'det' could be left
85 attached; one is where it is attached non-adjacently (after 'vbd' has
86 attached 'nn'):
87 :>>> c_L = c(0,0,(SEAL,g.tagnum('det')),0,g,'det nn vbd'.split(),{},{})
88 :>>> c_L
89 :0.62669683257918563 # so far so good
91 :>>> c_R = c(1,2,(RGO_L,g.tagnum('vbd')),2,g,'det nn vbd'.split(),{},{})
92 :>>> c_R
93 :0.11312217194570134 # still seeems an OK probability
95 :>>> c_M = c(0,2,(RGO_L,g.tagnum('vbd')),2,g,'det nn vbd'.split(),{},{})
96 :>>> c_M
97 :0.31674208144796384 # and this seems good
99 :>>> c_L / (c_R * c_M)
100 :17.490571428571432  # but this is Way off...
102 ** DONE P_STOP formulas for various dir and adj:
103    CLOSED: [2008-06-15 Sun 23:40]
104 Assuming this:
106 | P_{STOP}(STOP : h,L,non_adj) = | \sum_{corpus} \sum_{s<loc(h)} \sum_{t>=loc(h)} c(s,t,_h_) |
107 |                                | \sum_{corpus} \sum_{s<loc(h)} \sum_{t>=loc(h)} c(s,t,h_)  |
108 |                                |                                                           |
109 | P_{STOP}(STOP : h,L,adj) =     | \sum_{corpus} \sum_{s=loc(h)} \sum_{t>=loc(h)} c(s,t,_h_) |
110 |                                | \sum_{corpus} \sum_{s=loc(h)} \sum_{t>=loc(h)} c(s,t,h_)  |
111 |                                |                                                           |
112 | P_{STOP}(STOP : h,R,non_adj) = | \sum_{corpus} \sum_{s=loc(h)} \sum_{t>loc(h)} c(s,t,h_)   |
113 |                                | \sum_{corpus} \sum_{s=loc(h)} \sum_{t>loc(h)} c(s,t,h)    |
114 |                                |                                                           |
115 | P_{STOP}(STOP : h,R,adj) =     | \sum_{corpus} \sum_{s=loc(h)} \sum_{t=loc(h)} c(s,t,h_)   |
116 |                                | \sum_{corpus} \sum_{s=loc(h)} \sum_{t=loc(h)} c(s,t,h)    |
118 (And P_{STOP}(-STOP|...) = 1 - P_{STOP}(STOP|...) )
119 * DONE outer probabilities
120   CLOSED: [2008-06-12 Thu 11:11]
121 # <<outer>>
122 There are 6 different configurations here, based on what the above
123 (mother) node is, and what the Node for which we're computing is.
124 Here *r* is not between *s* and *t* as in inner(), but an /outer/ index. *loc_N*
125 is the location of the Node head in the sentence, *loc_m* for the head
126 of the mother of Node.
128 + mother is a RIGHT-stop:
129   - outer(*s, t*, mom.LHS, *loc_N*), no inner-call
130   - adjacent iff *t* == *loc_m*
131 + mother is a  LEFT-stop:
132   - outer(*s, t*, mom.LHS, *loc_N*), no inner-call
133   - adjacent iff *s* == *loc_m*
135 + Node is on the LEFT branch (mom.L == Node)
136   * and mother is a LEFT attachment:
137     - *loc_N* will be in the LEFT branch, can be anything here.
138     - In the RIGHT, non-attached, branch we find inner(*t+1, r*, mom.R,
139       *loc_m*) for all possible *loc_m* in the right part of the sentence.
140     - outer(*s, r*, mom.LHS, *loc_m*).
141     - adjacent iff *t+1* == *loc_m*
142   * and mother is a RIGHT attachment:
143     - *loc_m* = *loc_N*. 
144     - In the RIGHT, attached, branch we find inner(*t+1, r*, mom.R, *loc_R*) for
145       all possible *loc_R* in the right part of the sentence.
146     - outer(*s, r*, mom.LHS, *loc_N*).
147     - adjacent iff *t* == *loc_m*
149 + Node is on the RIGHT branch (mom.R == Node)
150   * and mother is a LEFT attachment:
151     - *loc_m* = *loc_N*. 
152     - In the LEFT, attached, branch we find inner(*r, s-1*, mom.L, *loc_L*) for
153       all possible *loc_L* in the left part of the sentence.
154     - outer(*r, t*, mom.LHS, *loc_m*).
155     - adjacent iff *s* == *loc_m*
156   * and mother is a RIGHT attachment:
157     - *loc_N* will be in the RIGHT branch, can be anything here.
158     - In the LEFT, non-attached, branch we find inner(*r, s-1*, mom.L, *loc_m*) for
159       all possible *loc_m* in the left part of the sentence.
160     - outer(*r, t*, mom.LHS, *loc_N*).
161     - adjacent iff *s-1* == *loc_m*
163 [[file:outer_attachments.jpg]]
165 : in notes:   in code (constants):    in Klein thesis:
166 :-------------------------------------------------------------------
167 : _h_         SEAL                    bar over h
168 :  h_         RGO_L                   right-under-left-arrow over h
169 :  h          GO_R                    right-arrow over h
171 :             LGO_R                   left-under-right-arrow over h
172 :             GO_L                    left-arrow over h
174 Also, unlike in [[http://bibsonomy.org/bibtex/2b9f6798bb092697da7042ca3f5dee795][Lari & Young]], non-ROOT ('S') symbols may cover the
175 whole sentence, but ROOT may /only/ appear if it covers the whole
176 sentence.
177 ** COMMENT qtrees, tex
178 \usepackage{qtree}
179 \usepackage{amssymb}
181 \newcommand{\GOR}[1]{\overrightarrow{#1}}
182 \newcommand{\RGOL}[1]{\overleftarrow{\overrightarrow{#1}}}
184 \newcommand{\SEAL}[1]{\overline{#1}}
186 \newcommand{\LGOR}[1]{\overrightarrow{\overleftarrow{#1}}}
187 \newcommand{\GOL}[1]{\overleftarrow{#1}}
189 \Tree [.{$\RGOL{h}$} [.{$_s \SEAL{a} _t$\\
190   Node} ] {$_{t+1} \RGOL{h} _r$\\
191   R} ]
192 \Tree [.{$\GOR{h}$} {$_{s} \GOR{h} _{t}$\\
193   Node} [.{$_{t+1} \SEAL{a} _r$\\
194   R} ] ]
195 \Tree [.{$\RGOL{h}$} [.{$_r \SEAL{a} _{s-1}$\\
196   L} ] {$_{s} \RGOL{h} _t$\\
197   Node} ]
198 \Tree [.{$\GOR{h}$} {$_{r} \GOR{h} _{s-1}$\\
199   L} [.{$_{s} \SEAL{a} _t$\\
200   Node} ] ]
203 \Tree [.{$h\urcorner$} [.{$_s \ulcorner a\urcorner _t$\\
204   Node} ] {$_{t+1} h\urcorner _r$\\
205   R} ]
206 \Tree [.{$h$} {$_{s} h _{t}$\\
207   Node} [.{$_{t+1} \ulcorner a\urcorner _r$\\
208   R} ] ]
209 \Tree [.{$h\urcorner$} [.{$_r \ulcorner a\urcorner _{s-1}$\\
210   L} ] {$_{s} h\urcorner _t$\\
211   Node} ]
212 \Tree [.{$h$} {$_{r} h _{s-1}$\\
213   L} [.{$_{s} \ulcorner a\urcorner _t$\\
214   Node} ] ]
216 * TOGROK Find Most Probable Parse of given test sentence
217 We could probably do it pretty easily from the chart:
218 - for all loc_h, select the (0,len(sent),ROOT,loc_h) that has the highest p
219 - for stops, just keep going
220 - for rewrites, for loc_dep select the one that has the highest p
221 * TOGROK Combine CCM with DMV
222 Page 108 (pdf: 124) of [[http://www.eecs.berkeley.edu/~klein/papers/klein_thesis.pdf][Klein's thesis]] gives info about this.
223 ** TODO Make inner() and outer() also allow left-first attachment
224 Using P_{ORDER}(/left-first/ | w) etc.
225 * TODO Get a dependency parsed version of WSJ to test with
226 * Initialization   
227 [[file:~/Documents/Skole/V08/Probability/dmvccm/src/dmv.py::Initialization%20todo][dmv-inits]]
229 We go through the corpus, since the probabilities are based on how far
230 away in the sentence arguments are from their heads.
231 ** TOGROK CCM Initialization    
232 P_{SPLIT} used here... how, again?
233 ** DONE Separate initialization to another file?                      :PRETTIER:
234    CLOSED: [2008-06-08 Sun 12:51]
235 [[file:src/harmonic.py::harmonic%20py%20initialization%20for%20dmv][harmonic.py]]
236 ** DONE DMV Initialization probabilities
237 (from initialization frequency)
238 ** DONE DMV Initialization frequencies    
239    CLOSED: [2008-05-27 Tue 20:04]
240 *** P_STOP    
241 P_{STOP} is not well defined by K&M. One possible interpretation given
242 the sentence [det nn vb nn] is
243 : f_{STOP}( STOP|det, L, adj) +1
244 : f_{STOP}(-STOP|det, L, adj) +0  
245 : f_{STOP}( STOP|det, L, non_adj) +1
246 : f_{STOP}(-STOP|det, L, non_adj) +0
247 : f_{STOP}( STOP|det, R, adj) +0
248 : f_{STOP}(-STOP|det, R, adj) +1
250 : f_{STOP}( STOP|nn, L, adj) +0
251 : f_{STOP}(-STOP|nn, L, adj) +1
252 : f_{STOP}( STOP|nn, L, non_adj) +1  # since there's at least one to the left
253 : f_{STOP}(-STOP|nn, L, non_adj) +0
254 **** TODO tweak
255 # <<pstoptweak>>
256 :            f[head,  'STOP', 'LN'] += (i_h <= 1)     # first two words
257 :            f[head, '-STOP', 'LN'] += (not i_h <= 1)     
258 :            f[head,  'STOP', 'LA'] += (i_h == 0)     # very first word
259 :            f[head, '-STOP', 'LA'] += (not i_h == 0)     
260 :            f[head,  'STOP', 'RN'] += (i_h >= n - 2) # last two words
261 :            f[head, '-STOP', 'RN'] += (not i_h >= n - 2) 
262 :            f[head,  'STOP', 'RA'] += (i_h == n - 1) # very last word
263 :            f[head, '-STOP', 'RA'] += (not i_h == n - 1) 
265 :            # this one requires some additional rewriting since it
266 :            # introduces divisions by zero
267 :            f[head,  'STOP', 'LN'] += (i_h == 1)     # second word
268 :            f[head, '-STOP', 'LN'] += (not i_h <= 1) # not first two
269 :            f[head,  'STOP', 'LA'] += (i_h == 0)     # first word
270 :            f[head, '-STOP', 'LA'] += (not i_h == 0) # not first
271 :            f[head,  'STOP', 'RN'] += (i_h == n - 2)     # second-to-last
272 :            f[head, '-STOP', 'RN'] += (not i_h >= n - 2) # not last two
273 :            f[head,  'STOP', 'RA'] += (i_h == n - 1)     # last word
274 :            f[head, '-STOP', 'RA'] += (not i_h == n - 1) # not last
276 :            f[head,  'STOP', 'LN'] += (i_h == 1)     # second word
277 :            f[head, '-STOP', 'LN'] += (not i_h == 1) # not second
278 :            f[head,  'STOP', 'LA'] += (i_h == 0)     # first word
279 :            f[head, '-STOP', 'LA'] += (not i_h == 0) # not first
280 :            f[head,  'STOP', 'RN'] += (i_h == n - 2)     # second-to-last
281 :            f[head, '-STOP', 'RN'] += (not i_h == n - 2) # not second-to-last
282 :            f[head,  'STOP', 'RA'] += (i_h == n - 1)     # last word
283 :            f[head, '-STOP', 'RA'] += (not i_h == n - 1) # not last
284 vs 
285 "all words take the same number of arguments" interpreted as
286 :for all heads:
287 :    p_STOP(head, 'STOP', 'LN') = 0.3
288 :    p_STOP(head, 'STOP', 'LA') = 0.5
289 :    p_STOP(head, 'STOP', 'RN') = 0.4
290 :    p_STOP(head, 'STOP', 'RA') = 0.7
291 (which we easily may tweak in init_zeros())
292 *** P_CHOOSE
293 Go through the corpus, counting distances between heads and
294 arguments. In [det nn vb nn], we give 
295 - f_{CHOOSE}(nn|det, R) +1/1 + C
296 - f_{CHOOSE}(vb|det, R) +1/2 + C
297 - f_{CHOOSE}(nn|det, R) +1/3 + C
298   - If this were the full corpus, P_{CHOOSE}(nn|det, R) would have
299     (1+1/3+2C) / sum_a f_{CHOOSE}(a|det, R)
301 The ROOT gets "each argument with equal probability", so in a sentence
302 of three words, 1/3 for each (in [nn vb nn], 'nn' gets 2/3). Basically
303 just a frequency count of the corpus...
305 In a sense there are no terminal probabilities, since an /h/ can only
306 rewrite to an 'h' anyway (it's just a check for whether, at this
307 location in the sentence, we have the right POS-tag).
308 * [#C] Deferred
309 http://wiki.python.org/moin/PythonSpeed/PerformanceTips Eg., use
310 map/reduce/filter/[i for i in [i's]]/(i for i in [i's]) instead of
311 for-loops; use local variables for globals (global variables or or
312 functions), etc.
314 ** TODO when reestimating P_STOP etc, remove rules with p < epsilon   :OPTIMIZE:
315 ** TODO inner_dmv, short ranges and impossible attachment             :OPTIMIZE:
316 If s-t <= 2, there can be only one attachment below, so don't recurse
317 with both Lattach=True and Rattach=True.
319 If s-t <= 1, there can be no attachment below, so only recurse with
320 Lattach=False, Rattach=False.
322 Put this in the loop under rewrite rules (could also do it in the STOP
323 section, but that would only have an effect on very short sentences).
324 ** TODO clean up the module files                                     :PRETTIER:
325 Is there better way to divide dmv and harmonic? There's a two-way
326 dependency between the modules. Guess there could be a third file that
327 imports both the initialization and the actual EM stuff, while a file
328 containing constants and classes could be imported by all others:
329 : dmv.py imports dmv_EM.py imports dmv_classes.py
330 : dmv.py imports dmv_inits.py imports dmv_classes.py
332 ** TOGROK Some (tagged) sentences are bound to come twice             :OPTIMIZE:
333 Eg, first sort and count, so that the corpus
334 [['nn','vbd','det','nn'],
335  ['vbd','nn','det','nn'],
336  ['nn','vbd','det','nn']]
337 becomes
338 [(['nn','vbd','det','nn'],2),
339  (['vbd','nn','det','nn'],1)]
340 and then in each loop through sentences, make sure we handle the
341 frequency correctly.
342           
343 Is there much to gain here?
345 ** TOGROK tags as numbers or tags as strings?                         :OPTIMIZE:
346 Need to clean up the representation.
348 Stick with tag-strings in initialization then switch to numbers for
349 IO-algorithm perhaps? Can probably afford more string-matching in
350 initialization..
351 * Adjacency and combining it with the inside-outside algorithm
352 Each DMV_Rule has both a probN and a probA, for adjacencies. inner()
353 and outer() needs the correct one in each case.
355 In each inner() call, loc_h is the location of the head of this
356 dependency structure. In each outer() call, it's the head of the /Node/,
357 the structure we're looking outside of.
359 We call inner() for each location of a head, and on each terminal,
360 loc_h must equal s (and t). In the recursive attachment calls, we use
361 the locations (sentence indices) of words to the left or right of the
362 head in calls to inner(). /loc_h lets us check whether we need probN or
363 probA/.
364 ** Possible alternate type of adjacency
365 K&M's adjacency is just whether or not an argument has been generated
366 in the current direction yet. One could also make a stronger type of
367 adjacency, where h and a are not adjacent if b is in between, eg. with
368 the sentence "a b h" and the structure ((h->a), (a->b)), h is
369 K&M-adjacent to a, but not next to a, since b is in between. It's easy
370 to check this type of adjacency in inner(), but it needs new rules for
371 P_STOP reestimation.
372 * Expectation Maximation in IO/DMV-terms
373 outer(s,t,Node) and inner(s,t,Node) calculates the expected number of
374 trees (CNF-)headed by Node from *s* to *t* (sentence positions). This uses
375 the P_STOP and P_CHOOSE values, which have been conveniently
376 distributed into CNF rules as probN and probA (non-adjacent and
377 adjacent probabilites).
379 When re-estimating, we use the expected values from outer() and
380 inner() to get new values for P_STOP and P_CHOOSE. When we've
381 re-estimated for the entire corpus, we distribute P_STOP and P_CHOOSE
382 into the CNF rules again, so that in the next round we use new probN
383 and probA to find outer- and inner-probabilites.
385 The distribution of P_STOP and P_CHOOSE into CNF rules also happens in
386 init_normalize() (here along with the creation of P_STOP and
387 P_CHOOSE); P_STOP is used to create CNF rules where one branch of the
388 rule is STOP, P_CHOOSE is used to create rules of the form 
389 : h  -> h  _a_
390 : h_ -> h_ _a_
392 Since "adjacency" is not captured in regular CNF rules, we need two
393 probabilites for each rule, and outer() and inner() have to know when
394 to use which.
397 * Python-stuff
398 # <<python>>
399 Make those debug statements steal a bit less attention in emacs:
400 :(font-lock-add-keywords
401 : 'python-mode                   ; not really regexp, a bit slow
402 : '(("^\\( *\\)\\(\\if +'.+' +in +io.DEBUG. *\\(
403 :\\1    .+$\\)+\\)" 2 font-lock-preprocessor-face t)))
404 :(font-lock-add-keywords
405 : 'python-mode
406 : '(("\\<\\(\\(io\\.\\)?debug(.+)\\)" 1 font-lock-preprocessor-face t)))
408 - [[file:src/pseudo.py][pseudo.py]]
409 - http://nltk.org/doc/en/structured-programming.html recursive dynamic
410 - http://nltk.org/doc/en/advanced-parsing.html 
411 - http://jaynes.colorado.edu/PythonIdioms.html
415 * Git
416 Repository web page: http://repo.or.cz/w/dmvccm.git
418 Setting up a new project:
419 : git init
420 : git add .
421 : git commit -m "first release"
423 Later on: (=-a= does =git rm= and =git add= automatically)
424 : git init
425 : git commit -a -m "some subsequent release"
427 Then push stuff up to the remote server:
428 : git push git+ssh://username@repo.or.cz/srv/git/dmvccm.git master
430 (=eval `ssh-agent`= and =ssh-add= to avoid having to type in keyphrase all
431 the time)
433 Make a copy of the (remote) master branch:
434 : git clone git://repo.or.cz/dmvccm.git 
436 Make and name a new branch in this folder
437 : git checkout -b mybranch
439 To save changes in =mybranch=:
440 : git commit -a 
442 Go back to the master branch (uncommitted changes from =mybranch= are
443 carried over):
444 : git checkout master
446 Try out:
447 : git add --interactive
449 Good tutorial:
450 http://www-cs-students.stanford.edu/~blynn//gitmagic/