2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

  • 文章を書く時に改行位置をどこで区切るかは難しい。画面右端に達したら折り返す仕組みは様々な言語でサポートされているが、中途半端な所で改行されると読みにくい
  • Googleから読みやすい改行を実現する、BudouXと呼ばれるモデルが開発された
  • 本ページでは、BudouXの概略とFlutterで使用してみた結果を残す

BudouX

BudouXとは

  • Google JPが開発した、読みやすい改行のためオープンソースの分かち書き器
  • 日本語、中国語、タイ語をJava, Python, JavaScriptでサポート
  • 特徴
    • スタンドアロンで動作
    • 20KB程度に収まる軽量モデル
    • 言語に依存しない(学習させることができる)

モデルの特徴

BudouXは、ブースティング(弱学習器の繰り返しによる学習)を使ったAdaboostでモデル構築されており、日本語モデルのJsonの一部を下記に示す

{
  "UW3": {
    "。": 6699,
    "、": 4784,
    "を": 5769,
    "っ": -1853
    ...
  },
  "UW1": {
    "お": 922,
    "ご": 890,
    "ふ": 1899,
    "甘": -1424
    ...
  },
  "BW1": {
    "のみ": 3058,
    "以上": 1223,
    "まま": 2830,
    "ちが": -2703
    ...
  },
  "BW3": {
    "うま": 4971,
    "もの": 3479,
    "あり": 1053,
    "おり": -2875,
    ...
  },
  "TW2": {
    "気に入": -4086,
    "ではな": -1086,
    "とがあ": -1130,
    "そもそ": -1441,
    "してい": -406
  },
  "TW1": {
    "という": 545,
    "ていく": 1686,
    "ような": 1298,
    "しかし": 2079,
    "持って": -1851
  }
  ...
}
  • UW3, BW1, ... といった各カテゴリに対して、キーバリューが定義
    • UW (Unigram Wieght):特定の位置にある文字の重み
    • BW (Bigram Weight):隣接する2つの文字の組み合わせの重み
    • TW (Trigram Weight):隣接する3つの文字の組み合わせの重み
  • つまり、「何の文字が来たら改行するだろう」と、文字の種類ごとに重要度を割り当てているシンプルなモデル

Flutterのサンプルサンプルコード

日本語で書かれた文字列を読み込み、表示するサンプルを以下に示す。
なお実装には、BudouXをFlutterに移植されていたbudoux_dartを利用した。

import 'package:budoux_dart/budoux.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  // BudouXモデルを非同期でロード
  Future<BudouX> loadBudouxModel() async {
    final modelJson = await rootBundle.loadString('assets/ja.json');
    return BudouX(modelJson);
  }

  // テキスト
  final simpleText = '今日は全国的に晴れです。洗濯物がすぐに乾きます。ですが、'
      '明日は1日中曇りになる見込みです。傘の準備をしておいた方が良いでしょう。'
      'さらに、明後日は雨です。';

  final complexText = 'Flutter(フラッター)は、Googleによって開発されたフリーかつ'
      'オープンソースのUIのSDKである。単一のコードベースから、Android、iOS、Linux、macOS、'
      'Windows、Google Fuchsia向けのクロスプラットフォームアプリケーションを'
      '開発するために利用される。'
      '2018年12月4日、ロンドンで開催されたFlutter Live 18にて、初の正式版となる'
      'Flutter 1.0のリリースが発表された。';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: FutureBuilder<BudouX>(
        future: loadBudouxModel(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return const Center(child: Text('Error loading model'));
            // コンテンツの表示
          } else {
            return buildContent(snapshot.data!);
          }
        },
      )),
    );
  }

  Widget buildContent(BudouX budouX) {
    final parsedSimpleText = parseText(budouX, simpleText);
    final parsedComplexText = parseText(budouX, complexText);

    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        // simpleTextの改行なし文章 & BudouX適用した文章
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const SizedBox(width: 20),
            buildContainer(Text(simpleText)),
            const SizedBox(width: 20),
            buildContainer(Wrap(children: parsedSimpleText)),
          ],
        ),
        // complexTextの改行なし文章 & BudouX適用した文章
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const SizedBox(width: 20),
            buildContainer(Text(complexText)),
            const SizedBox(width: 20),
            buildContainer(Wrap(children: parsedComplexText)),
          ],
        )
      ],
    );
  }

  Widget buildContainer(Widget child) {
    return Container(
      decoration: BoxDecoration(
        border: Border.all(),
      ),
      width: 200,
      child: child,
    );
  }

  // テキストを解析してウィジェットのリストを返すメソッド
  List<Widget> parseText(BudouX budouX, String text) {
    // BudouXでは、改行の単位でリストに格納されている
    return budouX.parse(text).map((rowText) => Text(rowText)).toList();
  }
}
...

dependencies:
  flutter:
    sdk: flutter
  budoux_dart: ^1.0.2

...

flutter:
  uses-material-design: true
  assets:
    - assets/ja.json

実行結果

  • 左側:原文、右側:BudouXで加工した文
  • 単純な平仮名・漢字で構成された文章は、読みやすく改行されている
  • 一方、英語が混じった文章はモデルに組み込まれていないため、読みやすいとまでは言えない(多分、カタカナも?)
    • 例えば、"Google Fuchsia"や、"開発するために"、"Flutter Live 18"とかは改行したせいで読みにくい印象
      image.png

まとめ

  • BudouXは、軽量なモデルで利用できる改行
  • シンプルな文章では、その強みが発揮されていそう
  • 一方で、英語やカタカナが混じる文章では、中途半端な位置で改行されていた
  • 安易にUIに組み込むよりも、使いどころが大事そう

参考文献

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?