ICT-STARTのホームページ

パソコンなどの話題を書いていきます。


N-gramについて|自然言語処理・全文検索

N-gramとは文章を指定文字数ごとに切り出し文字の出現する一を検索用のインデックスとして使う方法です。

例えば2文字ごとに切り出すバイグラム方式は、以下PHPでこのような実行結果になります。

<?php

$NGRAM = 2;

$sentence = "私は今、日本に住んでいます。";

 

$result = array();

for($i = 0;$i <= (mb_strlen($sentence) - $NGRAM);$i++) {

    $parts = mb_substr($sentence, $i, $NGRAM);

    $parts = strtolower($parts);

    $result[$i] = $parts;

}

print_r($result);

 

?>

実行結果

Array
(
    [0] => 私は
    [1] => は今
    [2] => 今、
    [3] => 、日
    [4] => 日本
    [5] => 本に
    [6] => に住
    [7] => 住ん
    [8] => んで
    [9] => でい
    [10] => いま
    [11] => ます
    [12] => す。
)

このように14文字からなる文章から13個のNgramを抽出しました。添字はそのNgramの出現位置を表します。

次にこの文章から句読点を省きます。
 

<?php

$NGRAM = 2;

$EXCLUDES = array("、""。");

$sentence = "私は今、日本に住んでいます。";

 

$result = array();

for($i = 0;$i <= (mb_strlen($sentence) - $NGRAM);$i++) {

    $parts = mb_substr($sentence, $i, $NGRAM);

    $parts = strtolower($parts);

 

    $exists_exclude = false;

    foreach($EXCLUDES as $exclude) {

        $pos = mb_strpos($parts, $exclude);

        if($pos === 0) {

            $exists_exclude = true;

        } else if($pos !== false) {

            $parts = str_replace($exclude, " ", $parts);

        }

    }

    if(!$exists_exclude) {

        $result[$i] = $parts;

    }

}

print_r($result);

 

?>

実行結果

Array
(
    [0] => 私は
    [1] => は今
    [2] => 今
    [4] => 日本
    [5] => 本に
    [6] => に住
    [7] => 住ん
    [8] => んで
    [9] => でい
    [10] => いま
    [11] => ます
    [12] => す
)
 

上記では"、", "。"の二文字が除外され項2,12では句読点の場所にスペースが入っています。除外しただけのため添字は先のプログラムと一緒になっています。

次に同じワードでまとめ出現位置の配列にします。

<?php

$NGRAM = 2;

$EXCLUDES = array("、""。");

$sentence = "あかぱじゃま、あおぱじゃま、きぱじゃま";

 

$result = array();

for($i = 0;$i <= (mb_strlen($sentence) - $NGRAM);$i++) {

    $parts = mb_substr($sentence, $i, $NGRAM);

    $parts = strtolower($parts);

 

    $exists_exclude = false;

    foreach($EXCLUDES as $exclude) {

        $pos = mb_strpos($parts, $exclude);

        if($pos === 0) {

            $exists_exclude = true;

        } else if($pos !== false) {

            $parts = str_replace($exclude, " ", $parts);

        }

    }

    if(!$exists_exclude) {

        $result[$i] = $parts;

    }

}

$counted_list = array();

foreach($result as $num => $word) {

    if(array_key_exists($word, $counted_list)) {

        $counted_list[$word][] = $num;

    } else {

        $counted_list[$word] = array($num);

    }

}

print_r($counted_list);

 

?>

実行結果

Array
(
    [あか] => Array
        (
            [0] => 0
        )

    [かぱ] => Array
        (
            [0] => 1
        )

    [ぱじ] => Array
        (
            [0] => 2
            [1] => 9
            [2] => 15
        )

    [じゃ] => Array
        (
            [0] => 3
            [1] => 10
            [2] => 16
        )

    [ゃま] => Array
        (
            [0] => 4
            [1] => 11
            [2] => 17
        )

    [ま ] => Array
        (
            [0] => 5
            [1] => 12
        )

    [あお] => Array
        (
            [0] => 7
        )

    [おぱ] => Array
        (
            [0] => 8
        )

    [きぱ] => Array
        (
            [0] => 14
        )

)
 

上記の解析結果をMySQLに格納します。そのために2グラム用のテーブルを作成します。

CREATE TABLE ngrams_2
(
    document_id int(11)  not null,
    grams varchar(2) not null,
    words_in_document varchar(256)
) type=InnoDB;
ALTER TABLE ngrams_2 ADD PRIMARY KEY (document_id, grams);

上記テーブル作成後以下を実行します。

<?php

$NGRAM = 2;

$EXCLUDES = array("、""。");

$sentence = "あかぱじゃま、あおぱじゃま、きぱじゃま";

 

$result = array();

for($i = 0;$i <= (mb_strlen($sentence) - $NGRAM);$i++) {

    $parts = mb_substr($sentence, $i, $NGRAM);

    $parts = strtolower($parts);

 

    $exists_exclude = false;

    foreach($EXCLUDES as $exclude) {

        $pos = mb_strpos($parts, $exclude);

        if($pos === 0) {

            $exists_exclude = true;

        } else if($pos !== false) {

            $parts = str_replace($exclude, " ", $parts);

        }

    }

    if(!$exists_exclude) {

        $result[$i] = $parts;

    }

}

$counted_list = array();

foreach($result as $num => $word) {

    if(array_key_exists($word, $counted_list)) {

        $counted_list[$word][] = $num;

    } else {

        $counted_list[$word] = array($num);

    }

}

 

$conn = mysql_connect("localhost:3306""user""pass");

if(!$conn) {

    echo mysql_error();

    exit();

}

$res = mysql_select_db("mydatabase", $conn);

if(!$res) {

    echo mysql_error();

    exit();

}

echo "mysql connected.n";

 

$document_id = '0';

foreach($counted_list as $key => $indexes) {

    $words = implode(",", $indexes);

    $sql = "insert into ngrams_2 (document_id, grams, words_in_document)

             values ('$document_id''$key''$words')";

    echo $key." at ".$words."n";

    mysql_query($sql, $conn);

}

mysql_close($conn);

 

?>

実行結果

mysql connected.
あか at 0
かぱ at 1
ぱじ at 2,9,15
じゃ at 3,10,16
ゃま at 4,11,17
ま  at 5,12
あお at 7
おぱ at 8
きぱ at 14

テーブルデータを確認します。

mysql> select * from ngrams_2;
+-------------+--------+-------------------+
| document_id | grams  | words_in_document |
+-------------+--------+-------------------+
|           0 | あお   | 7                 |
|           0 | あか   | 0                 |
|           0 | おぱ   | 8                 |
|           0 | かぱ   | 1                 |
|           0 | きぱ   | 14                |
|           0 | じゃ   | 3,10,16           |
|           0 | ぱじ   | 2,9,15            |
|           0 | ま     | 5,12              |
|           0 | ゃま   | 4,11,17           |
+-------------+--------+-------------------+
 

トップへ

ブログへ

製作物

Java系

簡易Webサーバー

自然言語処理・全文検索

トップ

Rust Language

Kotlin

 

Androidアプリ

HandyReader : C/C++,Java等のソースコードに色付けをしてくれるアプリです。