Недавно я очень заинтересовался связью записей и наткнулся на проект Duke, который предоставляет некоторые инструменты для решения этой проблемы. Я думал, что попробую.
Типичная проблема при связывании записей состоит в том, что у нас есть две записи из разных наборов данных, которые представляют одну и ту же сущность, но не имеют общего ключа, который мы можем использовать для их объединения. Поэтому нам нужно придумать эвристику, которая позволит нам это сделать.
У Герцога есть несколько примеров, демонстрирующих это в действии, и я решил пойти со связывающими странами . Здесь у нас есть страны из Dbpedia и базы данных Mondial, и мы хотим связать их вместе.
Первое, что нам нужно сделать, это построить проект:
|
1
2
|
export JAVA_HOME=`/usr/libexec/java_home`mvn clean package -DskipTests |
На момент написания этого документа будет помещен файл zip fail, содержащий все, что нам нужно, в duke-dist / target / . Давайте распакуем это:
|
1
|
unzip duke-dist/target/duke-dist-1.3-SNAPSHOT-bin.zip |
Далее нам нужно скачать файлы данных и файл конфигурации Duke:
|
1
2
3
4
|
wget https://raw.githubusercontent.com/larsga/Duke/master/doc/example-data/countries-dbpedia.csvwget https://raw.githubusercontent.com/larsga/Duke/master/doc/example-data/countries.xmlwget https://raw.githubusercontent.com/larsga/Duke/master/doc/example-data/countries-mondial.csvwget https://raw.githubusercontent.com/larsga/Duke/master/doc/example-data/countries-test.txt |
Теперь мы готовы попробовать:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
java -cp "duke-dist-1.3-SNAPSHOT/lib/*" no.priv.garshol.duke.Duke --testfile=countries-test.txt --testdebug --showmatches countries.xml ... NO MATCH FOR:ID: '7706', NAME: 'guatemala', AREA: '108890', CAPITAL: 'guatemala city', MATCH 0.9825124555160142ID: '10052', NAME: 'pitcairn islands', AREA: '47', CAPITAL: 'adamstown',ID: 'http://dbpedia.org/resource/Pitcairn_Islands', NAME: 'pitcairn islands', AREA: '47', CAPITAL: 'adamstown', Correct links found: 200 / 218 (91.7%)Wrong links found: 0 / 24 (0.0%)Unknown links found: 0Percent of links correct 100.0%, wrong 0.0%, unknown 0.0%Records with no link: 18Precision 100.0%, recall 91.74311926605505%, f-number 0.9569377990430622 |
Мы можем заглянуть в файл country.xml, чтобы увидеть, как вычисляется сходство между записями:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<schema> <threshold>0.7</threshold>... <property> <name>NAME</name> <comparator>no.priv.garshol.duke.comparators.Levenshtein</comparator> <low>0.09</low> <high>0.93</high> </property> <property> <name>AREA</name> <comparator>no.priv.garshol.duke.comparators.NumericComparator</comparator> <low>0.04</low> <high>0.73</high> </property> <property> <name>CAPITAL</name> <comparator>no.priv.garshol.duke.comparators.Levenshtein</comparator> <low>0.12</low> <high>0.61</high> </property> </schema> |
Таким образом, мы выясняем сходство столицы и страны, вычисляя расстояние Левенштейна, т.е. минимальное количество односимвольных правок, необходимых для преобразования одного слова в другое.
Это работает очень хорошо, если в одном из наборов данных есть опечатка или разница в написании. Однако мне было любопытно, что произойдет, если в стране будет два совершенно разных названия, например, Кот-д’Ивуар иногда называют Кот-д’Ивуар. Давайте попробуем изменить название страны в одном из файлов:
|
1
|
"19147","Cote dIvoire","Yamoussoukro","322460" |
|
1
2
3
4
|
java -cp "duke-dist-1.3-SNAPSHOT/lib/*" no.priv.garshol.duke.Duke --testfile=countries-test.txt --testdebug --showmatches countries.xml NO MATCH FOR:ID: '19147', NAME: 'ivory coast', AREA: '322460', CAPITAL: 'yamoussoukro', |
Я также попробовал это с отчетами о матчах BBC и ESPN в матче «Манчестер Юнайтед» против «Тоттенхэма» — BBC называет игроков по фамилии, а у ESPN есть их полные имена.
Когда я сравнивал полное имя с фамилией с помощью компаратора Левенштейна, совпадений, как и следовало ожидать, не было. Мне пришлось разделить имена ESPN на имя и фамилию, чтобы получить ссылку на работу.
Точно так же, когда я изменил название команды на «Манчестер Юнайтед», а не «Манчестер Юнайтед» и «Тоттенхэм», а не «Тоттенхэм Хотспур», это тоже не сработало.
Я думаю, что мне, вероятно, нужно написать специфичный для предметной области компаратор, но мне также любопытно, смогу ли я придумать кучу обучающих примеров, а затем обучить модель, чтобы определить, что делает две записи похожими. Это было бы менее детерминированным, но, возможно, более надежным.
| Ссылка: | Рекордная связь: игра с Дьюком от нашего партнера по JCG Марка Нидхэма в блоге Марка Нидхэма . |