LoginSignup
30
28

More than 5 years have passed since last update.

kuromoji.jsを使って日本語クローズテスト

Last updated at Posted at 2015-08-10

クローズテストってものがあるらしい

オライリーから出ているインタフェースデザインの実践教室という本を読んでいたところ、文章のユーザビリティをチェックする為のクローズテストについて説明がありました。

簡単に説明すると一定間隔で穴が開いた状態のテキストを読んで、ユーザーが文章の意味をくみ取れるかをチェックする為のテストです。
ある程度の単語が隠れた状態でも伝わる文章を書けという事でしょうか。

詳しくはこちら
Testing Content · An A List Apart Article

実装してみよう

先に上げた本の中で訳者が、日本語でUI用途の利用例が見つかれないよーと書いてあったので早速実装してみました。
また、先日からJavaScriptで言語処理100本ノック2015というのに取り組んでいる最中でしたので、kuromoji.js というライブラリを使いJavaScriptでの実装を行いました。

kuromoji.jsについて

簡単に使える Pure JavaScript の形態素解析器
ブラウザで自然言語処理 - JavaScriptの形態素解析器kuromoji.jsを作った

という事です。凄いらしい。
早速つかってみます。

デモ

テストのデモページになります。
辞書ファイルが16MBぐらいあって読み込むまで多少の時間がかかります。

ソースはこんな感じ

main.js
/**
クローズテスト用 kuromojiを継承
* @class closeTest
* @method init 初期化 パラメータのセット
* @method setProblem 空白の問題文を生成
* @method check 正解率のチェック
* @property {has} data 文章データ kuromoji.jsで形態素解析済み
* @property {number} oneset oneset毎に文字を隠す
* @property {string} targetElement jqueryに渡すdomエレメント
* @property {string} DIC_URL 辞書ファイルのパス
*/
var closeTest = function(){
  this.data = {
    planText:"",
    tokenize:{}
  };
  this.oneset;
  this.targetElement;
  this.DIC_URL = "bower_components/kuromoji/dist/dict/";
  this.tokenizer;
  this.init = function(_planText,_oneset,_targetElement){
    this.data.planText = _planText;
    this.oneset = _oneset || 5;
    this.targetElement = $(_targetElement);
  }
  this.setProblem = function(){
    this.targetElement.html("");
    this.data.tokenize = this.tokenizer.tokenize(this.data.planText);
    var _wrap = $('<div>').addClass('problem');
    var k = 1;
    for (var j = 0; j < this.data.tokenize.length; j++) {
      if(k % this.oneset == 0 && this.data.tokenize[j].pos != "記号"){
        var _inputprop = {
          type:"text",
          "data-surface":this.data.tokenize[j].surface_form
        }
        _wrap.append($('<input>').attr(_inputprop).addClass('surface'));
        this.targetElement.append(_wrap);
        k++;
      }else{
        _wrap.append($('<span>').html(this.data.tokenize[j].surface_form));
        this.targetElement.append(_wrap);
        if(this.data.tokenize[j].pos != "記号"){
          k++;
        }
      }
    }
  }
  this.check = function(){
    var _problem = $('.problem input');
    var _score = 0;
    _problem.each(function(){
      if($(this).val() == $(this).attr("data-surface")){
        _score++;
      }
    });
    return Math.round(_score/$('.problem input').length*100);
  }
}
closeTest.prototype = kuromoji;


$(function(){
  var _text = $('.testWording textarea').val();
  var closetest = new closeTest();
  closetest.init(_text,6,'.closeTest');
  closetest
    .builder({dicPath:closetest.DIC_URL})
    .build(function (error, tokenizer) {
      closetest.tokenizer = tokenizer;
      closetest.setProblem();
    });

  //チェックボタンの挙動
  $('.btnWrap').on('click','.btn.active.set',function(){
    closetest.data.planText = $('.testWording textarea').val();
    closetest.setProblem();
  });
});

※分かり易くする為に元のソースからjqueryでのUI操作周りを削った状態です。

kuromoji.js の使い方としてはここら辺ですかね。
ここだけ見ると分かり辛いですが closetestkuromojiを継承したクラスです。

closetest
    .builder({dicPath:closetest.DIC_URL})
    .build(function (error, tokenizer) {
      closetest.tokenizer = tokenizer;
      closetest.setProblem();
    });

builder().build()で準備が整った後、コールバックで処理をしています。
kuromojiで解析した結果は、一単語に対してこんな感じのキー配列で帰ってきます。

{
  basic_form:"吾輩",
  conjugated_for:"*",
  conjugated_type:"*",
  pos:"名詞",
  pos_detail_1:"代名詞",
  pos_detail_2:"一般",
  pos_detail_3:"*",
  pronunciation:"ワガハイ",
  reading:"ワガハイ",
  surface_form:"吾輩",
  word_id:957200,
  word_position:1,
  word_type:"KNOWN"
}

少しも難しい事がなく実装できました。

まとめ

kuromoji.jsが凄い。

あと自分で書いた文章でも、流し込んでテストをしてみると結構理解出来ない状況になります。
分かり易い文章を書くために有用なテストだと思いました。

それから何単語毎に削るのかとか固有名詞の場合は空白にしないとか、もう少し考えるとテストの精度が上がりそうですね。
そのうち直してみます。

ソースはgithubにも置いて有ります。

30
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
28