Я хочу использовать наивный байес, чтобы классифицировать документы по относительно большому количеству классов. Я хочу подтвердить, действительно ли упоминание имени сущности в статье действительно является этой сущностью, исходя из того, похожа ли эта статья на статьи, в которых эта сущность была правильно проверена.
Скажем, мы находим текст "Дженерал Моторс" в статье. У нас есть набор данных, который содержит статьи и правильные объекты, упомянутые в In. Итак, если мы нашли «General Motors», упомянутый в новой статье, он должен попасть в этот класс статей в предыдущих данных, которые содержали известные подлинные упомянуть "Дженерал Моторс" против класса статей, в которых не упоминается эта организация?
(Я не создаю класс для каждой сущности и не пытаюсь классифицировать каждую новую статью для каждого возможного класса. У меня уже есть эвристический метод для поиска правдоподобных упоминаний имен сущностей, и я просто хочу проверить правдоподобие ограниченное количество упоминаний имени объекта в статье, которое метод уже обнаруживает.)
Учитывая, что число потенциальных классов и статей было довольно большим, а наивный байесов относительно прост, я хотел сделать все это в SQL, но у меня возникли проблемы с запросом скоринга ...
Вот что у меня есть:
CREATE TABLE `each_entity_word` (
`word` varchar(20) NOT NULL,
`entity_id` int(10) unsigned NOT NULL,
`word_count` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`word`, `entity_id`)
);
CREATE TABLE `each_entity_sum` (
`entity_id` int(10) unsigned NOT NULL DEFAULT '0',
`word_count_sum` int(10) unsigned DEFAULT NULL,
`doc_count` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`entity_id`)
);
CREATE TABLE `total_entity_word` (
`word` varchar(20) NOT NULL,
`word_count` int(10) unsigned NOT NULL,
PRIMARY KEY (`word`)
);
CREATE TABLE `total_entity_sum` (
`word_count_sum` bigint(20) unsigned NOT NULL,
`doc_count` int(10) unsigned NOT NULL,
`pkey` enum('singleton') NOT NULL DEFAULT 'singleton',
PRIMARY KEY (`pkey`)
);
Каждая статья в отмеченных данных разбивается на отдельные слова, и для каждой статьи для каждого объекта каждое слово добавляется к each_entity_word
и / или его word_count
увеличивается, а doc_count
увеличивается на entity_word_sum
, оба по отношению к entity_id
. Это повторяется для каждой сущности, о которой известно, что она упоминается в этой статье.
Для каждой статьи независимо от сущностей, содержащихся в каждом слове, total_entity_word
total_entity_word_sum
аналогично увеличиваются.
- P (слово | любой документ) должно равняться
word_count
в total_entity_word
для этого слова более
doc_count
в total_entity_sum
- P (слово | документ упоминает сущность x )
должен равняться
word_count
в
each_entity_word
для этого слова для entity_id
x более doc_count
в
each_entity_sum
для entity_id
x
- P (слово | документ содержит не упомянутое лицо x ) должно равняться (
word_count
в total_entity_word
минус его word_count
в each_entity_word
для этого слова для этой сущности) сверх (doc_count
в total_entity_sum
минус doc_count
для этой сущности в each_entity_sum
)
- P (документ упоминает сущность x ) должно равняться
doc_count
в each_entity_sum
для этого идентификатора сущности более doc_count
в total_entity_word
- P (в документе не упоминается сущность x ) должно равняться 1 минус (
doc_count
в each_entity_sum
для x идентификатора сущности над doc_count
в total_entity_word
).
Для новой статьи, которая выходит, разбейте ее на слова и просто выберите, где слово в ('I', 'want', 'to', 'use' ...) против each_entity_word
или total_entity_word
, На платформе db, с которой я работаю (mysql) предложения IN относительно хорошо оптимизированы.
Также в sql нет агрегатной функции product (), поэтому, конечно, вы можете просто сделать sum (log (x)) или exp (sum (log (x))), чтобы получить эквивалент product (x).
Итак, если я получу новую статью, разделю ее на отдельные слова и вставлю эти слова в большое предложение IN () и потенциальный идентификатор объекта для проверки, как я могу получить наивную байесовскую вероятность того, что статья упадет? в класс этой сущности в sql?
EDIT:
Попробуйте # 1:
set @entity_id = 1;
select @entity_doc_count = doc_count from each_entity_sum where entity_id=@entity_id;
select @total_doc_count = doc_count from total_entity_sum;
select
exp(
log(@entity_doc_count / @total_doc_count) +
(
sum(log((ifnull(ew.word_count,0) + 1) / @entity_doc_count)) /
sum(log(((aew.word_count + 1) - ifnull(ew.word_count, 0)) / (@total_doc_count - @entity_doc_count)))
)
) as likelihood,
from total_entity_word aew
left outer join each_entity_word ew on ew.word=aew.word and ew.entity_id=@entity_id
where aew.word in ('I', 'want', 'to', 'use'...);