1:
2:
3: Общие слова
4: ~~~~~~~~~~~
5:
6: Словоформой считается жадная последовательность русских букв, латинских букв
7: и цифр. Например, "Екатерина", "England", "1974", "H2O".
8: "H_2O", "Владивосток-2000" -- это пары словорм.
9:
10: Начальная форма словоформы, не состоящей целиком из
11: русских букв -- это сама словоформа.
12:
13: Регистр букв при поиске не учитывается.
14:
15: Поиск по части слова не поддерживается. Не поддерживаются и
16: регулярные выражения.
17:
18: Список новых файлов, которые планируется поставить под CVS.
19: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20:
21: Словари:
22:
23: dict.koi Словарь Александра Лебедева для ispell.
24: Образован слиянием всех словарей,
25: которые я смог найти.
26:
27: mydict.koi Самопальное дополнение словаря. Допускаются некоторые
28: вольности. Например, в Лебедевском словаре
29: существительные второго склонения, как правило,
30: помечены ключем "K" или, если они не имеют формы
31: множественного числа - ключём "J". В mydict.koi
32: все такие существительные попадают с ключём "K".
33:
34:
35: ndict.koi Автоматически сгенерированный дополнительный словарь.
36: Пример: в dict.koi нет слова "Эйдельман",
37: а в базе встречаются словоформы "Эйдельман"
38: и "Эйдельмана". Скрипт, обнаружив это,
39: понял, что это могут быть формы существительного
40: женского рода "Эйдельмана" ("Эйдельман" -- форма
41: родительного падежа множественного числа), и дополнил
42: ею словарь.
43:
44:
45: raff.koi Таблица аффиксов к словарю Лебедева.
46:
47: Скрипты:
48:
49: makecheck.pl По таблице аффиксов генерирует текст функции,
50: ищущей начальную форму словоформы.
51:
52: mkRS.pl Пересоздаёт поисковые таблицы и обнуляет поле
53: ProcessedBySeacrh у всех вопросов.
54:
55: updateRS.pl Ищет вопросы с нулевым ProcessedBySearch
56: и добавляет информацию о них в таблицы.
57: Работает очень медленно (около секунды на вопрос на
58: AMD-400), начинает обрабатывать следующий ий вопрос
59: только после того, как в базе появилась информация о
60: предыдущем. В результате может быть в любой момент прерван
61: без ущерба для таблиц.
62:
63: updateRS1.pl Делает тоже самое, что updateRS.pl, но обрабатывает вопросы
64: порциями, записывая информацию в память, скидывая
65: информацию в базу только после того, как порция
66: будет полностью обработана. Оптимальный размер порции
67: зависит от мощности машины.
68:
69: dumpRS.pl Скидывает в файл дамп таблицы word2question.
70:
71: dumpin2out.pl Скидывает в файл таблицу соответствий
72: идентификатор вопроса в базе -> внешнее имя
73: (Турнир.Тур.Номер).
74:
75: dump2dump.pl Преобразует дамп таблицы word2question
76: под другую заливку базы, используя таблицы
77: соответствий двух заливок. Суть в том, что
78: при перезаливке базы изменяются идентификаторы
79: вопросов. Использование этого скрипта позволяет избежать
80: запуска "долгих" скриптов updateRS.pl и updateRS1.pl
81: Кроме того, скрипт может использоваться при переносе таблиц,
82: например, с бильбо на кулички.
83:
84: delRS Удаляет из дампа таблицы word2question информацию о
85: вопросах, соответствующих указанным файлам.
86:
87: checkPBS.pl Проставляет поле ProcessedBySearch на основании
88: информации из таблицы word2question
89:
90:
91: Вспомогательные файлы:
92:
93: chgk.cnf Конфигурационный файл.
94:
95: chgkfiles.pm Модуль для работы c файлами
96:
97: dbchgk Модуль для работы с базой
98:
99:
100:
101:
102: Стандартные процедуры
103: ~~~~~~~~~~~~~~~~~~~~~
104:
105: Полная заливка
106:
107: Запустить mkRS.pl, затем updateRS.pl и подождать сутки или больше.
108: Вместо updateRS.pl можно использовать updateRS1.pl, тогда будет побыстрее,
109: но всё равно довольно долго.
110:
111:
112: Перенос таблиц на другую машину
113:
114: На первой машине:
115: dumpRS.pl dump1
116: dumpin2out.pl first
117:
118: Затем залить dump1 и first на вторую машину и уже там:
119: dumpin2out.pl second
120: dump2dump.pl dump1 dump2 first second
121: loaddump second
122:
123: Все созданные файлы можно удалить.
124:
125: Добавление в базу новых файлов
126:
127: Добавить файлы скриптом updatedb.pl и запустить updateRS.pl.
128: Этот скрипт генерирует список нераспознанных слов.
129: Их начальные формы можно добавить в словарь mydict.koi.
130:
131: В принципе, эту процедуру хорошо бы делать перед заливкой (проверив
132: текстовые файлы), но во-первых скрипта для проверки файлов пока нет
133: (потому как я только сейчас его придумал), а во-вторых утяжелит
134: процесс апдейта. Лучше или иногда (раз в несколько месяцев) делать полную
135: переиндексацию, или сохранив список новых файлов, раз в те же самые
136: несколько месяцев проделывать процедуру удалить-добавить.
137:
138:
139:
140: Исправление существующих файлов
141:
142: Перед удалением старой базы:
143: dumpRS.pl temp
144: delRS temp список удалённых или исправленных файлов
145:
146: После заливки таблиц Questions и Tournaments:
147: loaddump.pl temp
148: rm temp
149: updateRS.pl
150:
151:
152: Генерация дополнительного словаря
153: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
154: Автоматически сгенерированный автоматический словарь
155: нужен для обработки слов, которых нет в стандартном словаре,
156: но которые встречаются в базе, причём в разных формах.
157: В основном, это имена собственные. Работа это одноразовая,
158: она проделана, потому скрипты не выкладываю.
159:
160: 1. Сделали полный список русских словоформ, встречающихся в базе.
161:
162: 2. Проверили каждую словоформу, используя основные словари,
163: получили список неопознанных словоформ
164:
165: 3. Построили граф, вершины которого -- неопознанные словоформы (около 70000),
166: а рёбро есть в том и только том случае, когда одна словоформа
167: может являться нальной формой другой.
168:
169: 4. Разбили граф на компоненты связности, в каждой попытвлись
170: найти словоформу, которая может быть начальной формой всех остальных.
171: Если такая нашлась -- добавили её в дополнительный словарь.
172:
173: В результате работы этого алгоритма образовались допсловарь (около 7000
174: начальных форм) и список так и неопознанных словоформ (их осталось
175: около 40000). Большая часть этих слов -- орфографические ошибки. Очень
176: много из них получились из-за того, что в некоторых файлах в русских
177: словах встречаются латинские буквы, совпадающие по начертанию с русскими.
178:
179: Для всеобщей гармонии необходимо сделать следующее:
180:
181: 1. Исправить орфографические ошибки
182: 2. Проверить и исправить автоматически сгенерированные начальные формы.
183: 3. Добавить в словарь почём зря не опознанные словоформы.
184:
185: Вторым и третьим пунктами я иногда медленно и печально занимаюсь.
186:
187:
188: Структура таблиц для русского поиска
189: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
190:
191: Таблица nf. В этой таблице живут список начальные формы.
192:
193: Поля:
194:
195: id INT UNSIGNED - идентификатор начальной формы
196: word CHAR(30) - сама начальная форма, записанная
197: заглавными русскими буквами.
198: flag CHAR(5) - список флагов таблицы аффиксов
199: number - количество вхождений форм данной начальной
200: формы в вопросы
201:
202: Таблица nests. В этой таблице живут пары соответствий словоформа -
203: начальная форма. Одной словоформе могут соответствовать несколько
204: начальных форм.
205:
206: Поля:
207:
208: id INT UNSIGNED - идентификатор записи
209: w1 CHAR(30) - словоформа, записанная заглавными буквами
210: w2 INT UNSIGNED - идентификатор начальной формы.
211:
212:
213: Таблица word2question. Таблица соответствий начальная форма -
214: список вхождений в вопросы. Наверное, эту таблицу можно
215: было объединить с таблицей nf.
216:
217: Поля:
218:
219: word INT UNSIGNED - идентификатор начальной формы
220: questions MEDIUMBLOB - список вхождений. Каждому вхождению соответствует
221: 4 байта: один на номер поля, два на номер вопроса,
222: один на позицию в вопросе. С ужасом жду, когда
223: Олег добавит вопрос номер 65536 и придётся
224: увеличивать число байт, отведенных на вхождение
225: или возиться с битами :) Хранится только нижний байт
226: номера вхождения в поле. Погрешность, связанную
227: с этим, считаю пренебрежимо малой.
228:
229:
230: Поиск
231: ~~~~~
232: Русский поиск производится скриптом db.cgi при указании опции
233: "metod=rus". Вот алгоритм:
234:
235:
236: 1. Выделяем из поисковый строки максимальные последовательности
237: русских, латинских букв и цифр.
238:
239: 2. Ищем начальные формы полученных словоформ по таблице nests. Формы,
240: которых там нет, проверяем по словарю и таблице аффиксов. Формы, которые
241: всё ещё неопознаны, считаем ненайденными.
242:
243: 3. По таблице word2questions ищем списки вхождений слов в
244: затребованные поля, выделяем списки вопосов, в которые входят слова,
245: в зависимости от значения опции all берём их объединение или пересечение -
246: это список найденных вопросов. Сохраняем для каждого вопроса списки вхождений.
247:
248: 4. Считаем для каждого найденного вопроса релевантность поисковой фразы и
249: сортируем по ней.
250:
251: 5. При выводе выделяем жирным шрифтом вхождения искомых слов.
252: Шаблон, по которому выделяются слова, формируется по таблице
253: nests.
254:
255:
256: В db.cgi добавлена также опция debug, при установке которой
257: выводится отладочная информация.
258:
259: В db.cgi поддерживаются также поиск по Simple Query и Advanced
260: Query (как их понимает altavista), но оказалось, что
261: поиск по регулярному выражению на пятидесяти тысячах вопросов работает
262: чересчур долго, потому эти возможности не используются.
263: Но, вообще-то, для них есть опции "metod=simple" и "metod=advancde".
264:
265: Формула релевантности
266: ~~~~~~~~~~~~~~~~~~~~~
267: Честно говоря, я взял первую пришедшую на ум формулу, вроде худо-бедно
268: работает.
269:
270: Пусть поисковая фраза состоит из слов s1,s2,...sn.
271: Каждое найденное слово добавляет к релевантности следующее значение:
272: количество_вхождений_в_вопрос+1000+1000/количество_вхождений_в_базу.
273:
274: Каждая пара (si, sj) добавляет к релевантности следующее значение:
275: 10 * (10- (min ( distance(i,j) , 10)).
276:
277: distance(i,j)=min(|i-j-pi+pj|)
278: (pi и pj -- позиции слов i и j в вопросе, минимум
279: считается по всем pi и pj)
280:
281:
282:
283: Суть в том, что максимальная релевантность будет у вопросов, в которых
284: встречается максимальное количество искомых слов (это имеет значение,
285: если all=no), затем учитывается распространённость каждого слова и
286: близость их в вопросе друг к другу. Максимальная релевантность,
287: как правило, будет у вопросов, в которых поисковые слова встречаются подряд,
288: в том же порядке, что и в запросе.
289:
290:
291:
292: Какие формы признаются одинаковыми
293: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
294: Те, которые попадают в одно гнездо, согласно таблице аффиксов словаря Лебедева
295: для ispell.
296:
297: Описывать, какие словоизменения учитываются, а какие -- нет,
298: непросто. Поскольку словарь создан не для определения начальной формы,
299: а для проверки орфографии, очень много словоизменений он не учитывает.
300: Например, в словаре можно встретить и слово агнец, и слово агнцев --
301: добавить формы в словарь, видимо, оказалось проще, чем править
302: таблицу аффиксов. По-хорошему над таблицей аффиксов и словарём надо очень
303: серьёзно работать. В идеале, надо использовать не словарь Лебедева, а
304: словарь Зализняка, но его таблиц в удобном для обработки электронном виде
305: я не нашёл.
306:
307:
308: Роман Семизаров
309: roma7@zaba.ru
310:
311:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>