Тридцатого июля мы чистили базу знаний Ти3 от мусора. Система уверенно считала, что Рим — это пригород, и подобного там хватало: связей набралось больше ста шестидесяти тысяч, и часть из них была откровенным враньём.
Вопрос стоял так: какую долю связей резать. Десять процентов худших? Пять? Я перебрал три собственные версии, и замер отверг все три. Помню раздражение: очевидно же, что мусор надо резать по качеству, а числа говорят — не работает.
Корень оказался не в доле, а в позиции. Мусор сидел не равномерно, а на узлах-концентраторах — тех немногих понятиях, куда сходятся тысячи связей. Двести неверных связей на пятнадцати таких узлах отравляли пятьдесят три тысячи сущностей. Меньше процента записей портили треть базы.
Лечение вышло смешное по объёму: семьдесят удалённых записей на живой базе. Семьдесят, а не десять тысяч. Проверку я придумал заранее: до чистки цепочка «Рим — город — пригород», после «Рим — город». Прошла и на копии, и на живом.
А дальше две ошибки, и обе мои.
Первая: контрольный замер, которым я доказывал, что удаляю именно мусор, оказался негодным. Он брал пятнадцать первых узлов по номеру в базе и ловил половину того же самого мусора. То есть не доказывал ничего, а выглядел убедительно. Переделал на узлы с похожей связностью — тогда разница стала настоящей.
Вторая дороже. Константу, обозначающую тип связи «является», я угадал. Взял тройку. Тройка означала «находится в». Декодер честно нашёл ноль нужных связей среди ста шестидесяти девяти тысяч, и собственная проверка остановила прогон до того, как что-нибудь удалилось. То есть систему от меня спасла система. Записал в правила буквально: константу, которая решает, что именно удаляется, угадывать нельзя.
Главное, что я вынес из того дня, применимо далеко за пределами баз знаний: когда что-то портит систему, смотри где сидит порча, а не сколько её. Распределение почти никогда не ровное. Виноват обычно очень маленький кусок в очень важном месте — и ищут его в последнюю очередь, потому что по объёму он не выглядит проблемой.
Андрей Рощупкин