Skip to main content
naive_bayes (NAIVE_BAYES) Dictionary は、多項 Naive Bayes モデルを使ってテキストを分類します。これはテキスト向けの標準的なイベントモデルで、入力内のN-gramが各クラスにどれだけ出現するかに基づいて、各クラスをスコアリングします。クラスごとのn-gram の出現回数のテーブルを与えると、読み込み時に一度だけそれをコンパイルしてモデルを作成し、その後は渡された任意のテキストの分類に使用します。 感情分析、トピックやスパムのラベル付け、言語や文字体系の判定といった、高速で軽量なテキスト分類に適しています。 Dictionary は、次の3つの関数のいずれかでクエリできます。 通常の dictGet でも分類できます (注意を参照) 。もう1つの関数 naiveBayesNgrams は分類を行いません。代わりに、Dictionary と同じ方法でテキストをN-gramに分割するため、生テキストから学習データを作成できます (生テキストから学習データを構築する を参照) 。

クイックスタート

ここでは、感情分析用の token-mode のユニグラム (n = 1) モデルを構築します。 1. クラスごとの n-gram の出現回数を格納したソーステーブルを作成します。
2. 学習データを挿入 — 単語 (ユニグラム) と、各単語が正例 (1) および負例 (0) クラスで出現する頻度:
3. NAIVE_BAYES レイアウトの Dictionary を作成します:
PRIMARY KEY ngramngram カラムをキーにしますが、NAIVE_BAYES Dictionary では、この「キー」は分類対象として渡すテキストを指し、参照のために保存されている値ではありません (Dictionary structure を参照) 。LAYOUT はモデルを設定します。class_attribute 'class_id'class_id をクラスラベルとして指定し (つまり、もう一方の attribute である count はクラスごとの出現回数です) 、n 1 はユニグラムを使用し、mode 'token' はテキストを空白区切りの単語に分割します (Layout parameters を参照) 。 4. 分類naiveBayesClassifier はクラス ID を返します:
ステップ2で挿入したトレーニングデータに基づくと、1 は正のクラスに対応します。
同様に、0 は負のクラスに対応します。 dictGet でも同じ結果が得られます。
予測結果の確率、または各クラスの確率を取得します:
予測は、確率 0.64 でクラス 0 (負) です。
naiveBayesClassifierWithAllProbs は、可能性が最も高いクラスから最も低いクラスまで、確率の合計が 1.0 になる形ですべてのクラスを返します。ここでは、負のクラスが 0.64、正のクラスが 0.36 です。

仕組み

学習 (ロード時) 。 各行は (n-gram, class, count) という観測値です。Dictionary がロードされると、これらの行はモデルに一度だけ取り込まれます。重複する (n-gram, class) の行は合算され、count = 0 の行は無視されます。 分類 (クエリ時) 。 文字列を分類する際、モデルは次のように動作します。
  1. moden に従って文字列を n-gram に分割します (トークン化モードを参照) 。
  2. クラス事前確率と、そのクラスで入力中の n-gram がどれだけ出現していたかを組み合わせて、各クラスのスコアを計算します。
  3. スコアに基づいてクラスを順位付けします。最も高いスコアのクラスが naiveBayesClassifier の予測結果として返されます。naiveBayesClassifierWithProbnaiveBayesClassifierWithAllProbs は、そのクラス、またはすべてのクラスについての確率も返します。
各クラスのスコアに影響する要素は 2 つあります。1 つ目は平滑化に使われる alpha です。平滑化は、学習時にある 1 つの n-gram がそのクラスに現れなかったというだけで、モデルがそのクラスに 0 のスコアを与えてしまうのを防ぎます。alpha が小さいほど、モデルは学習データにより強く依存するため、あるクラスが他より大幅に高いスコアを得ることがありますが、学習データが少ない場合や偏っている場合には、モデルが敏感になりすぎることもあります。alpha が大きいほど、n-gram の出現回数の影響は小さくなり、クラス間のスコアはより近くなります。alpha が非常に大きい場合、n-gram の情報はほとんど効かなくなり、スコアは主にクラス事前確率 (次に説明します) によって決まります。 2 つ目はクラス事前確率です。これは、モデルがテキストを見る前に、各クラスがどれくらい起こりやすいとみなすかを表します。どの n-gram も考慮される前に各クラスに与えられる初期スコアとして機能するため、事前確率が高いクラスほど予測されやすくなります。これをどう設定するかは priors_mode に依存します。デフォルトでは (proportional)、学習データ内の n-gram 総数が多いクラスほど高い初期スコアを持ちます。uniform ではすべてのクラスが同じ条件で始まるため、n-gram だけが判定を左右します。explicit では、各クラスの初期値を自分で設定します。事前確率モードを参照してください。 学習データ内のどこにも一度も現れなかった n-gram は無視されます。これはモデルの語彙に含まれていないため、どのクラスにも有利にも不利にもなりません。 このアルゴリズムは、テキスト分類のための多項ナイーブベイズモデルに従います。詳しくは Manning, Raghavan & Schütze, Introduction to Information Retrieval, ch. 13 (Text Classification and Naive Bayes) を参照してください。

Dictionary の構造

NAIVE_BAYES Dictionary は固定の構造を持ちます。
  • PRIMARY KEY は単一の String カラム、つまり n-gram です。クエリ時、この”key”は保存済みのルックアップキーではなく、分類対象として渡すテキストそのものを指します。
  • これに加えて、符号なし整数の属性をちょうど 2 つ 宣言します。クラスラベルと出現回数です。クラス ID は内部的に常に UInt32 を使用するため、属性を UInt64 として宣言していても、クラスラベルは UInt32 (最大 4294967295) に収まっている必要があります。これより大きい値は、Dictionary の作成時ではなくロード時に拒否されます。同じことは宣言した型にも当てはまります。元データのクラス ID または回数が宣言した属性型に収まらない場合、暗黙に切り捨てられるのではなく、ロードに失敗します。
  • class_attribute レイアウトパラメータは、どの属性がクラスラベルかを指定します。もう一方は自動的に回数として扱われます。2 つの属性は、どちらの順序で宣言してもかまいません。
ソーステーブルには 事前に集計された 回数が格納されます。各 (n-gram, class) につき 1 行で、そのクラスにその n-gram が何回出現したかを表します。これらの回数は、コーパスをトークン化して結果をグループ化することで生成します。独自の学習パイプラインで行うことも、ClickHouse で生テキストから学習データを構築することもできます (生のテキストから学習データを構築する を参照) 。Dictionary はそれらを取り込むだけです。 モデルの更新。 モデルはテーブルをバックエンドに持つ Dictionary であるため、再学習はテーブルを更新して再ロードすることで行います。

レイアウトパラメータ

Dictionary は、CREATE DICTIONARY DDL (上記のクイックスタートと同様) または XML 設定ファイルで定義できます。そのファイルの配置場所については、Dictionary layoutsを参照してください。以下の例では、すべてのレイアウトオプションを設定して全体を確認できるようにしています。必須なのは class_attributenmode のみで、その他のデフォルト値は上の表に示しています。設定ファイルでは、事前確率は prior 要素を繰り返して記述します (以下の例のとおり、クラスごとに 1 つ) 。また、bytecodepoint のパディングトークンは数値で記述します (config では raw bytes を保持できません) 。さらに、token リテラルは必要に応じて XML エスケープされるため、<s>&lt;s&gt; になります。

トークン化モード

mode は「トークン」を何とみなすかを決めるため、N-gram の形もそれによって決まります。元の N-gram は、同じ moden で生成されている必要があります。
  • byte — 各トークンは 1 バイトです。UTF-8 は前提としません。n = 2 の場合、'abc' からはバイト bi-gram の 'ab''bc' が生成されます。適している用途 は、任意のバイト列に対する言語やエンコーディングの検出、および文字より細かい単位の特徴が重要なあらゆるデータです。通常は n >= 2 と組み合わせて使います。
  • codepoint — 各トークンは 1 つの Unicode コードポイントです。入力は UTF-8 として解釈されます。n = 1 の場合、'café' からはコードポイント 'c''a''f''é' が生成されます。適している用途 は、文字体系や言語の検出、および空白による単語境界が当てにならない短いテキストや CJK テキストです。 (元の N-gram は有効な UTF-8 である必要があります。クエリ入力は寛容にデコードされます。詳しくは Notes を参照してください。)
  • token — 各トークンは、ASCII whitespace (space、tab、newline、carriage return、form feed、vertical tab。連続する場合は 1 つの separator として扱われます) で区切られた単語です。U+00A0 (no-break space) や U+2003 (em space) などの非 ASCII の Unicode whitespace は separator ではなく、トークン内にそのまま残ります。分割するのは whitespace だけで、小文字化や記号の除去は行われません。したがって、'Hello, World!''Hello,''World!' というトークンになり (カンマ、!、大文字はすべて保持されます) 、n = 2 の場合は 1 つの bi-gram 'Hello, World!' を形成します。適している用途 は、空白区切りの言語における単語レベルの分類 — 感情、topic、スパム、文の言語などです。

事前確率モード

事前確率とは、モデルがテキストを見るに、各クラスに対してどの程度あり得ると見なしているかを表すものです。priors_mode は、その設定方法を選びます。
  • proportional (デフォルト) — 各クラスの事前確率は、学習データ内でのそのクラスの合計 N-gram 数に比例します。つまり、そのクラスの count カラムの合計であり、行数や学習文書数ではありません。そのため、より多く出現したクラスほど、初期状態で起こりやすいと見なされます。学習時のクラス比率 (合計 N-gram 数ベース) が、クエリ時に想定される出現頻度と一致している場合は、これを選択してください指定するものはありません — 元のカウントから導出されます。
  • uniform — 最初はすべてのクラスが同じ確率になるため、どのクラスも有利にならず、予測は完全に入力の N-gram に基づいて決まります。クラスが均等である場合や、学習時の頻度がクエリ時に各クラスが現れる頻度を反映していない場合は、これを選択してください指定するものはありません。
  • explicitpriors [(0, 0.6), (1, 0.4)] を使って事前確率を指定します。クラスごとに 1 つの (class, probability) ペアを与え、各確率は 0 より大きく 1 以下で、合計は 1.0 でなければなりません。実際のベース率が分かっていて、それが学習データと異なる場合は、これを選択してください。たとえば、学習セットは均等でも、本番トラフィックのうちスパムは 1% しかない、といった場合です。各クラスの実際に想定される比率から、これらを計算してください

境界トークン (パディング)

パディングはデフォルトで無効です。n > 1 の場合にのみ意味を持ち、テキストの先頭と末尾でモデルがシグナルを利用できるようになるため、精度の向上に役立ちます。 有効な理由。 n > 1 の場合、テキスト中央のN-gramは左右両方のコンテキストを完全に持ちますが、最初と最後のトークンはそうではありません。境界トークンを追加すると、「テキストの開始」と「テキストの終了」を示すN-gramが生成され、モデルは位置に関連したパターンを学習できます。たとえば、メッセージの先頭に現れるときに特徴的な単語や、単語の末尾に典型的な文字などです。 必要な対応:
  1. 各側を個別に決定する。 start_tokenend_token は独立しています。一方のみ、両方、またはどちらも設定しないことが可能です。空の値はその側がパディングされないことを意味します。
  2. 実際のデータと衝突しないレアな値を選択する。 たとえば、byte には 0x01 / 0xFFcodepoint には U+10FFFE / U+10FFFFtoken には <s> / </s> などを使用します。
  3. 同じパディングでトレーニング用N-gramを生成する。 Dictionaryはクエリ入力にパディングを適用しますが、ソースには適用しないため、境界トークンはロードするN-gramにあらかじめ組み込まれている必要があります。一致を保証する最も簡単な方法は、naiveBayesNgrams を使用してソースを構築し、layoutに指定するのと同じ start_tokenend_token (および nmode) を渡すことです。これにより、Dictionaryがクエリ時に生成するパディング済みN-gramと完全に一致するN-gramが出力されます。
パディングトークンのフォーマットはモードによって異なります:
  • byte — バイト値を表す数値で、10進数または 0x 16進数で指定します ('1''0x01' は同じです) :
  • codepoint — UTF-8コードポイントを表す数値で、10進数または 0x 16進数で指定します ('1114110''0x10FFFE' は同じです) :
  • token — リテラルのトークン文字列:

生テキストから学習データを作成する

事前に集計済みのカウントではなく、ラベル付きの生テキストから始める場合は、naiveBayesNgrams 関数を使って N-gram に分割します。レイアウトと同じ nmodestart_tokenend_token を指定すると、Dictionary が想定するものとまったく同じ N-gram が生成されるため、学習データはクエリ時にモデルが参照するデータと一致します。 (class_id, text) の行からなるテーブルがある場合、1 つの GROUP BY(ngram, class_id, count) の元データを作成します:
training_data は、NAIVE_BAYES Dictionary の有効なソースになりました (ここでは token ユニグラム を使用しています。レイアウトに合わせて nmode の引数を変更してください) 。この Dictionary はクエリ入力を与えられたとおりにそのままトークン化するため、学習テキストが小文字化されていてもクエリテキストがそうでない場合、両者の N-gram は一致せず、モデルの精度が低下します。
事前確率と文書数proportional の事前確率 (デフォルト) は、各クラスの総 N-gram 数に基づいて重み付けされ、文書数には基づきません。古典的な文書頻度ベースの事前確率 (documents_in_class / total_documents) を使いたい場合は、生の docs テーブルから計算し、priors_mode 'explicit' を指定して渡してください。
次に、上で計算した明示的な事前確率を指定して training_data から Dictionary を作成し、新しいレビューを分類します:
クラス 1 はポジティブ、0 はネガティブなので、どちらのレビューも正しく分類されています。

その他の例

バイトモード — バイトのバイグラム (n = 2, mode 'byte'; class 0 = 文字 ad からなる文字列、class 1 = 文字 xz) :
コードポイントモード — 文字ごとのスクリプト判定 (n = 1mode 'codepoint'、class 0 = ラテン文字、1 = キリル文字) :
store_source を使って学習データを読み出します:
生テキストからの言語検出 — 境界パディングを付けた短い単語の例です (n = 2mode 'codepoint'、class 0 = 英語、1 = スペイン語) 。学習用の N-gram は naiveBayesNgrams を使って生の単語から構築され、関数とレイアウトの両方に渡される境界トークンによって、モデルは各単語の先頭と末尾の文字を利用できます:

注記

  • 計算型 Dictionary のセマンティクス。 これは 計算型 の Dictionary です。dictGet(dict, '<class_attribute>', text)text を分類します (キーは保存済みのキーではなく、分類対象の入力です) 。count 属性にはクエリできず、dictHas は常に 1 を返します。
  • ロード時のソース検証。 すべてのソース N-gram は、設定された nmode に一致している必要があります (codepoint mode では、有効な UTF-8 であることも必要です) 。一致しない場合、ロードは失敗します。count が 0 の行は無視されるため (仕組み を参照) 、空のソース、または count が 0 の行しかないソースは学習対象がなく、ロードに失敗します。
  • クエリ時のトークン化は寛容です。 ソース検証とは異なり、クエリ入力が拒否されることはありません。codepoint mode では、有効な UTF-8 でないバイト列は、クエリを失敗させるのではなく、可能な限りデコードされます。token mode では、単語の区切りとして扱われるのは ASCII whitespace のみです (U+00A0 のような Unicode whitespace は token 内に残ります) 。不正な入力でも分類は行われますが、通常は事前確率に基づく分類になります。これは、その N-gram が学習済みのものと一致しないためです。
最終更新日 2026年7月23日