2021年9月14日火曜日

GitHub Actions Composite Action で uses が使えるようになった!

GitHub Actions: Reduce duplication with action composition | GitHub Changelog

GitHub Actions では Composite Action でワークフローの一部を1つのアクションとしてまとめ共有できることができます。
複合実行ステップ アクションの作成 - GitHub Docs

GitHub Actions は YAML のアンカー・エイリアスに対応しておらず、 Azure Pipelines のような Templates 機能もありませんが、この機能で Action に切り出すことで似たようなことができます。
Composite Action は Docker や Javascript Action と違い、通常のワークフローの記述と近いかたちで書くことができますので、よりアンカー・エイリアスや Templates と近い感覚で記述ができます。

**近い**としたのは Composite Action で書けることは通常のワークフローよりも制限がされているからです。
uses もその1つでした。
今回のアップデートで uses が使えるようになり、checkout アクションや python / node / ruby などの setup 系アクションを含んだ Composite Action を書けるようになったので、かなり便利になりました!

(個人的には shell を動的に解決したいとか conditional (if) を使いたいとかはありますが、uses が対応されたことで大分使い勝手が良くなったので嬉しい)


2021年9月8日水曜日

CEDEC でやってた表記ゆれ検出をお試し実装してみた

CEDEC2021: ゲーム制作効率化のためのAIによる画像認識・自然言語処理への取り組み
ゲーム制作効率化のためのAIによる画像認識・自然言語処理への取り組み - Speaker Deck

こちらの講演の中であった表記ゆれ検出の実装実験をしてみました。
ポイントとなるのは「形態素解析」と「編集距離」です。

形態素解析はこのブログでもたまに扱ってました。
ブログズミ: TreeTagger を使ってソースコード中の単語をリストアップしてみた
ブログズミ: ソースコード中の単語からの略語/スペルミス検出に挑戦

↑これらは TreeTagger 使ったものでした。

実は、前職でも同じような表記ゆれ検出はしたことがあって、そのときは MeCab で形態素解析し、単語の出現数をカウントしてソート出力するだけのものでした。
出現数の少ない単語から見ていくと、「あ、これは揺れてそう」ってのがわかったのでそれなりに有用でした。
なので、CEDEC の方法であった「出現数の差が大きいほどスコアが上がる」は良いと思いました。

で、今回は形態素解析には Jumanpp を編集距離はレーベンシュタイン距離を使いました。
実装はこちら。
講演の内容そのものの実装ではないです。スコア計算の部分はテスト対象の入力に合わせて書いたので万能ではないと思いますが、なるべく一般化したルールにしてるつもり。

https://github.com/srz-zumix/tails-of-words

PyPI でも公開してるので pip でインストールできます。
https://pypi.org/project/tails-of-words/0.1.2/
また Dockerhub にイメージもおいてるのでそれ使っても実行できます。
https://hub.docker.com/r/srzzumix/tails-of-words

実装メモ

実装上のポイントをメモしてます。

  • yomi がひらがなの場合とカタカナの場合がある
  • yomi に長音(ー)が追加される場合がある
  • 総当りで調べるのですべての単語差分を記録すると killed される
  • 半角スペース、"、@、# を含んでると pknp で例外出るので全角にする
  • 「えー!?」のように全角!・?があると、つながった状態で1単語になるので、分解するため半角にする

テスト

試しに拙著をチェックしてみました。

拙著の場合、未定義語(15)まで集計対象にするとアルファベットのみの単語の大文字・小文字違いがスコアが高くなり、ノイズだったので -i 6 で名詞のみに制限。
-t 1 で 1.0 以上のスコアのものを表示してます。

画像をご覧いただくと、「コンパイラー vs コンパイラ」の表記ゆれを検出してるのが見つかります。それ以外は表記ゆれではないと思いますが、書き損じの可能性はあるかもしれませんね。

最後に

実装自体は1日、スコア計算の部分とかの調整で1日。
あとは周辺機能の整理とかで1日くらいですかね。
(仕事じゃなくて夜中に書いてたやつなので工数じゃないよ)

とりあえず最低限のものを作るだけなら、めちゃくちゃ簡単にできます。
ただし、精度はいまいちだと思います。
リストアップされたものを人間がチェックする必要性がありますが、リストアップする部分まで人間がやるよりはかなりマシでしょう。

ここから検出精度を上げるのはとても大変だと思います。
トライアンドエラーで色々評価軸を追加したり、スコア計算の調整したりすることになると思いますが、コスパがどんどん悪くなっていくと思います。
(業務外だったら関係ないのかもしれないけど・・)
流行りの機械学習で精度アップできるかもしれないですが、どうなんでしょうね?
(この辺は詳しくないのでわかりません)

実はこの手の話をすると、似たようなこと昔やったことあるって人が結構います。
みんなサクッと実装できたといいますが、精度・コスパの話も同じような感想でした。

これは完全な余談なんですが、
Jumanpp の出力をいい感じに print したいなーと思って Power-Assert みたいな出力にしようと(すぐ道草をする悪い癖が出そうになったのを我慢)して、適当に作った print が割といい感じにできたのが良かった :D


対して難しいことはしてませんが、この実装が役に立てば幸いです。
では。

2021年9月3日金曜日

GitHub Actions でペアな値のマトリックスを組む

 CI でパラメタライズドなテストを実行するときに、マトリックスを組むことがあると思います。
GitHub Actions でも strategy.matrix でマトリックスを組めます。

例えば、上記公式ドキュメントのサンプルの

strategy:
  matrix:
    node: [10, 12, 14]
steps:
  # Configures the node version used on GitHub-hosted runners
  - uses: actions/setup-node@v2
    with:
      # The Node.js version to configure
      node-version: ${{ matrix.node }}

↑こちらは node-version が 10,12,14 のステップがそれぞれ実行されます。合計で 3 回です。

さらに、因子を追加して例えば

strategy:
  matrix:
    node: [10, 12, 14]
    expect: [ "dubnium",  "erbium", "fermium" ] 

とすると、以下のような組み合わせになります。

101214
dubnium10,dubnium12,dubnium14,dubnium
erbium10,erbium12,erbium14,erbium
fermium10,fermium12,fermium14,fermium

node と expect の因子の直行になります。合計は 3x3 の 9 回です。
ただ、このような組み合わせではなく、ペアな因子1つを作りたい場合もあります。
上の例では [10, dubnium], [12, erbium], [14, fermium] という組み合わせにしたいです。
その場合は、以下のように include を使って書くとスマートそうです。

strategy:
  matrix:
    include:
      - node: 10
        expect: dubnium
      - node: 12
        expect: erbium
      - node: 14
        expect: fermium      
strategy:
  matrix:
    node: [10]
    expect: ["dubnium"] 
    include:
      - node: 12
        expect: erbium
      - node: 14
        expect: fermium
 

前者は include のみで記述、後者は matrix に include で組み合わせを追加しています。
この例では前者のほうがきれいに見えますが、一部の組み合わせだけ値が異なる場合は後者の方法で書いたほうがきれい書けける場合もあります。

実例

今まで1つの値に複数の値をもたせたりしてたのですが、とてもきれいに書き直せました。


こちらはサンプルの前者の方法と同じで、include で必要な組み合わせを書いています。


https://github.com/srz-zumix/ci-yaml/blob/e1e1d6d15bb75f9682bc05304e7ec61162de094b/.github/workflows/search.yml
こちらはサンプルの後者と同じ方法で、 path が "" の場合は matrix で、空白以外の場合は include で組み合わせを追加しています。


今回は以上です。では。