import pandas as pd
import ndl
%matplotlib inline
%precision 3
pd.set_option('display.precision', 3)
First we'll try a strictly agglutinative morphemic alignment, with a one-to-one mapping between forms and meanings:
morphemes = pd.DataFrame()
morphemes['Cues'] = [('stem','a','c'),('stem','a','d'),('stem','b','c'),('stem','b','d')]
morphemes['Outcomes'] = [('nom','sg'),('nom','pl'),('acc','sg'),('acc','pl')]
morphemes['Frequency'] = [1,1,1,1]
morphemes
Cues | Outcomes | Frequency | |
---|---|---|---|
0 | (stem, a, c) | (nom, sg) | 1 |
1 | (stem, a, d) | (nom, pl) | 1 |
2 | (stem, b, c) | (acc, sg) | 1 |
3 | (stem, b, d) | (acc, pl) | 1 |
After 1,000 learning iterations, we check the associations between the cues and the outcomes:
W1 = ndl.rw(morphemes,M=1000)
W1
acc | nom | pl | sg | |
---|---|---|---|---|
a | -0.37 | 0.62 | 0.13 | 0.12 |
b | 0.62 | -0.37 | 0.12 | 0.13 |
c | 0.13 | 0.12 | -0.37 | 0.62 |
d | 0.12 | 0.13 | 0.62 | -0.37 |
stem | 0.25 | 0.25 | 0.25 | 0.25 |
And, the complete forms get the right interpretation:
pd.DataFrame([ndl.activation(c,W1) for c in morphemes.Cues],index=morphemes.Cues)
acc | nom | pl | sg | |
---|---|---|---|---|
Cues | ||||
(stem, a, c) | 0 | 1 | 0 | 1 |
(stem, a, d) | 0 | 1 | 1 | 0 |
(stem, b, c) | 1 | 0 | 0 | 1 |
(stem, b, d) | 1 | 0 | 1 | 0 |
Now we'll try a paradigm with the same cues and the same outcomes, but this time they're not arrange with a one-to-one correspondence:
gestalt = morphemes.copy()
gestalt['Cues'] = [('stem','a','c'),('stem','b','c'),('stem','b','d'),('stem','a','d')]
gestalt
Cues | Outcomes | Frequency | |
---|---|---|---|
0 | (stem, a, c) | (nom, sg) | 1 |
1 | (stem, b, c) | (nom, pl) | 1 |
2 | (stem, b, d) | (acc, sg) | 1 |
3 | (stem, a, d) | (acc, pl) | 1 |
W2 = ndl.rw(gestalt,M=1000)
This time, the number distincton doesn't get learned:
pd.DataFrame([ndl.activation(c,W2) for c in gestalt.Cues],index=gestalt.Cues)
acc | nom | pl | sg | |
---|---|---|---|---|
Cues | ||||
(stem, a, c) | 0.00 | 1 | 0.60 | 0.40 |
(stem, b, c) | 0.00 | 1 | 0.64 | 0.36 |
(stem, b, d) | 0.99 | 0 | 0.61 | 0.39 |
(stem, a, d) | 1.00 | 0 | 0.57 | 0.43 |
But, if we add compound cues, things work:
gestalt2 = gestalt.copy()
gestalt2['Cues'] = [('stem','a','c','a&c'),('stem','b','c','b&c'),('stem','b','d','b&d'),('stem','a','d','a&d')]
gestalt2
Cues | Outcomes | Frequency | |
---|---|---|---|
0 | (stem, a, c, a&c) | (nom, sg) | 1 |
1 | (stem, b, c, b&c) | (nom, pl) | 1 |
2 | (stem, b, d, b&d) | (acc, sg) | 1 |
3 | (stem, a, d, a&d) | (acc, pl) | 1 |
W3 = ndl.rw(gestalt2,M=1000)
pd.DataFrame([ndl.activation(c,W3) for c in gestalt2.Cues],index=gestalt2.Cues)
acc | nom | pl | sg | |
---|---|---|---|---|
Cues | ||||
(stem, a, c, a&c) | 8.14e-04 | 1.00e+00 | 0.04 | 0.96 |
(stem, b, c, b&c) | -4.13e-04 | 1.00e+00 | 0.95 | 0.05 |
(stem, b, d, b&d) | 1.00e+00 | 2.06e-04 | 0.04 | 0.96 |
(stem, a, d, a&d) | 9.99e-01 | 3.18e-04 | 0.96 | 0.04 |