Skip to content

yuhsak/wakachigaki

Repository files navigation

wakachigaki

6.2Kbの軽量日本語分かち書きライブラリ

動作確認用のデモサイト

Python版はこちら

紹介

wakachigaki は辞書を使わない軽量の日本語分かち書き用ライブラリです。

ピュアなJavaScriptなのでNode.jsやDeno, ブラウザなど環境を問わず動作し、TypeScriptやES Module1にも対応しています。

予め分かち書きされた大量の日本語テキストから作成した機械学習モデルを内包することで辞書不要の分かち書きを実現しています。

学習にはWikipedia日本語版のダンプデータ全量を用いました。MeCab + mecab-ipadic-NEologd で得られる分かち書き結果を約90%の精度で再現することが出来ています。

単語境界の判定には文中に出現する文字の種類や並び順の情報のみを用いるようになっており、文字や単語単位で固有の情報を一切利用していないため未知語に非常に強いのが特徴です。

辞書を用いる kuromoji.js などと異なり品詞の推定機能はありませんが、その分インストールも実行も軽量で環境を問わず動作します。

使い方

インストール

npm install wakachigaki

分かち書きの実行

import { tokenize } from 'wakachigaki'

/** CommonJSの場合 */
// const { tokenize } = require('wakachigaki')

tokenize('非常に効果的な機械学習モデル')
// => [ '非常', 'に', '効果', '的', 'な', '機械学習', 'モデル' ]

境界確率の取得

分かち書きされた結果を直接取得するだけでなく、テキスト内の各文字についてその文字の直後に単語境界がある確率を0~1の範囲の数値で取得することが出来ます。

import { features, predictProba } from 'wakachigaki'

// 特徴量を取得
const feats = features('非常に効果的な機械学習モデル')

predictProba(feats)
/*
=> [
  0.0327992634970502,     // 非
  0.9901071412275622,     // 常
  0.9742190417471894,     // に
  0.04298367736033199,    // 効
  0.7249201317135311,     // 果
  0.9920294555733393,     // 的
  0.904908994982585,      // な
  0.10174356598870479,    // 機
  0.3827245071932094,     // 械
  0.11608892206899486,    // 学
  0.6410674063348171,     // 習
  0.0045548383234342614,  // モ
  0.00006214363582036111, // デ
  0.9720230891240956      // ル
]
*/

tokenize() 関数は内部でこの数値が予め定義された閾値を超えているかどうかを判定の基準にしていて、閾値もまた threshold という変数でexportされています。

import { features, predictProba, predict, threshold } from 'wakachigaki'

const feats = features('非常に効果的な機械学習モデル')

const probas = predictProba(feats)

// probas.map(p => p >= threshold) と同じ結果
predict(feats)
/*
=> [
  false, // 非
  true,  // 常
  true,  // に
  false, // 効
  true,  // 果
  true,  // 的
  true,  // な
  false, // 機
  false, // 械
  false, // 学
  true,  // 習
  false, // モ
  false, // デ
  true   // ル
]
*/

ユーティリティ

内部で文字種の判定に利用している正規表現と判定用の関数も利用可能です。

正規表現の内容は src/feature/regexp.ts を参照して下さい。

import {
  regexp,
  isHiragana,
  isKatakana,
  isKanji,
  isNumeralKanji,
  isAlphabet,
  isNumeral,
} from 'wakachigaki'

/**
 * 与えられた文字列が文字種判定用の正規表現を満たすかどうかチェックする関数。入力は複数文字でもOK
 * 以下は全てtrueになる例
 **/

// ひらがな
isHiragana('あ')

// カタカナ
isKatakana('カ')

// 漢字
isKanji('漢字')

// 漢数字
isNumeralKanji('一二三四五六七八九十百千万億兆')

// アルファベット (半角, 全角を無視)
isAlphabet('aa')

// 数字 (半角, 全角を無視)
isNumeral('99')

ブラウザ対応

wakachigaki 自体では特にブラウザ用にビルドしたコードを配布していませんが、元々他パッケージへの依存がなくES Module形式に対応しているため unpkg.com などのCDNを経由すればすぐに動作させることが出来ます。

下記のコードをhtmlに貼り付ければ多くのブラウザでそのまま動くはずです。

<script type="module">
  import { tokenize } from 'https://unpkg.com/[email protected]'
  console.log(tokenize('ブラウザで分かち書きのテスト'))
  // => [ 'ブラウザ', 'で', '分かち', '書き', 'の', 'テスト']
</script>

Deno対応

wakachigaki はNode.js固有のAPIを使用していないためDeno環境でも動作します。

ブラウザ同様にCDNとしてunpkgを利用することも出来ますが、TypeScriptの型定義の配布に対応した Skypack を利用するのがおすすめです。

import { tokenize } from 'https://cdn.skypack.dev/[email protected]?dts'

console.log(tokenize('Denoで分かち書きのテスト'))
// => ['Deno', 'で', '分かち', '書き', 'の', 'テスト']

精度の比較

下記の表はJS環境で利用可能な類似のライブラリと併せて精度の比較を行ったものです。

比較用のコーパスにはNHN Japan株式会社提供のlivedoor ニュースコーパスを利用しました。

各記事を行単位に分解し適宜URLのみのものを取り除くなど前処理をして得られた約10万の文章について、MeCab + mecab-ipadic-NEologdで行った分かち書き結果を正解として各数値を算出しました。

従来の手法と比べても遜色ない結果が得られていることがわかります。

ただしwakachigakiがそもそも学習にmecab-ipadic-NEologdを用いているために新語や複合語に強くなっており、同列の条件での比較にはなっていない点に注意して下さい。あくまで参考程度の結果です。

特に高く見える適合率については、他ライブラリと比べて判定した単語境界の数が少なく実際の単語境界の数に近い数字になっていることからもmecab-ipadic-NEologdから学習した複合語の判定傾向の影響が強く出ていると考えられます。

ライブラリ 単語境界の数 判定数 正答数 一致率 適合率 再現率 F2スコア
wakachigaki 4611683 4589286 4234587 0.919 0.923 0.918 0.920
TinySegmenter 4611683 5055596 4170853 0.824 0.825 0.904 0.863
kuromoji.js (デフォルト辞書) 4611683 5015672 4312946 0.872 0.860 0.935 0.896

項目の意味

項目名 説明
単語境界の数 コーパス全体に対してMeCabが出力した単語境界の総数
判定数 ライブラリが出力した単語境界の総数
正答数 ライブラリが出力した単語境界のうち正解だったものの数
一致率 非単語境界と判定したものも含む全体の一致率 (Accuracy)
適合率 正答数 ÷ 判定数 (Precision)
再現率 正答数 ÷ 単語境界の数 (Recall)
F2スコア 適合率と再現率の調和平均

開発の動機

JSでアプリケーションを開発していると検索やレコメンド機能の実装などで日本語の分かち書きを行いたい時があります。

そんな時に npm install したらサクっと使えてブラウザやDenoでも動いてESM, TypeScriptにも対応しているものがあれば嬉しいと思ったのが直接の動機です。

特に最近はサーバとブラウザどちらでも動く処理を書く機会が多かったりサーバレス系のインフラの出番が増えて取り回しの良い軽量なライブラリが求められます。

そこで wakachigaki動作に環境依存がないことバンドルサイズがごく軽量なことES Module, TypeScriptに対応していることを目指して開発されました。

モデルの学習方法

機械学習モデルを利用した分かち書きの学習方法を検討している際 TinySegmenter がほぼ同様の構成になっているのを発見し大いに参考にさせて頂きました。

データの加工と学習にはPythonを使い、Wikipedia日本語版のダンプデータを全量使ってモデルの学習を行っています。

教師データの分かち書きには MeCab + mecab-ipadic-NEologd を利用しました。

コーパス内の各文字に対して複数のパラメータでNgramを取得し、漢字、ひらがな、カタカナなど文字の種類と文字のハッシュ値から算出した文字グループを特徴量として抽出、その文字の直後が単語境界かどうかの二値分類を学習しています。

Tiny Segmenterでも解説されていますが、クライアントに配布することも考えると学習結果として取り出すモデルのパラメータは出来る限り軽量にしたかったのでモデルはL1ノルム正則化ロジスティック回帰を採用し、確率的勾配降下法によるミニバッチ学習を行いました。

結果、モデルを表現するパラメータのJSONファイルはgzip後でわずか3Kbという軽量サイズになっています。

(学習用のコードもGitHubで公開する予定です)

クレジット

機械学習モデルの構築にあたり非常に優秀な機械学習エンジニアの友人たちに多大な助力を頂きました。感謝します🙌

@mski-iksm (GitHub)

@Gashin_Learning (Twitter)

Footnotes

  1. ブラウザ用にES Module形式のコードを配布していますが、パッケージ自体が厳密にNode.jsのNative ESMに対応しているわけではありません。Node.jsでは従来通りCommonJS形式のパッケージとして読み込まれます。TypeScriptが正式にNative ESMに対応した段階でDual Package化する予定です。

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published