単純ベイズを使用して、ドキュメントを比較的多数のクラスに分類したいと考えています。私は、エンティティが正しく検証された記事とその記事が類似しているかどうかに基づいて、記事内のエンティティ名の言及が本当にそのエンティティであるかどうかを確認しようとしています。
たとえば、ある記事で「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|any document) は、その単語
の
word_count
inに等しい必要があり ますtotal_entity_word
doc_count
total_entity_sum
- P(単語|ドキュメントは
エンティティxに言及
word_count
し ています)each_entity_word
entity_id
doc_count
each_entity_sum
entity_id
- P(単語|ドキュメントはエンティティxについて言及していません) は、(そのエンティティのinからその単語のinを引いたもの) 以上 ( inのそのエンティティの inを引いたもの)に等しくなければなりません
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
そのエンティティ ID に対して等しい必要がありますdoc_count
。total_entity_word
- P(ドキュメントはエンティティxについて言及していません) は 1 マイナス ( xのエンティティ ID に対してin )
doc_count
に等しい必要があります。each_entity_sum
doc_count
total_entity_word
入ってくる新しい記事の場合、それを単語に分割し、または のいずれeach_entity_word
かに対して ('I'、'want'、'to'、'use'...) の単語を選択するだけtotal_entity_word
です。私が(mysql)で作業しているdbプラットフォームでは、IN句は比較的適切に最適化されています。
また、SQLにはproduct()集計関数がないため、もちろん、sum(log(x))またはexp(sum(log(x)))を実行して、product(x)と同等のものを取得できます。
したがって、新しい記事を取得し、それを個別の単語に分割し、それらの単語を大きな IN() 句とテストする潜在的なエンティティ ID に入れる場合、記事がそのエンティティに該当する単純なベイジアン確率を取得するにはどうすればよいですか? SQLのidのクラス?
編集:
#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'...);