Blog

2020.08.19

Engineering

Optunaコントリビュータ求む!

Hideaki Imamura

目次

  • はじめに
  • Optunaとは
  • Optunaへのプルリクエストの送り方
    • どんなコード変更を行うか考える
    • 実際に変更を加えてテストする
    • プルリクエストを送る
  • おわりに

はじめに

 皆さん、こんにちは。Optuna開発メンバーの今村 (@mamurai1208)です。皆さんはオープンソースソフトウェア (OSS)のタイポやバグを見つけたことはありませんか?そしてそれを手元で直しても、GitHubへの反映の仕方が分からず諦めてしまったことはありませんか?初めてOSS開発に参加される方は、以下のような疑問をお持ちのことでしょう。「プロジェクトのビルドってどうすればいいの?テスト環境ってどう作ればいいの?そもそもテストは手元でやらなきゃダメ?これらが書かれたガイドラインはどこにあるの?」

 それぞれのプロジェクトには独自の文化やルールがあるため、一つのベストプラクティスがあるわけではありません。このブログでは、Optuna開発メンバーの一人である山崎 (@hvy)によるブログを日本語に訳し、より初心者向けに加筆修正しました。Optunaへのコントリビューションの仕方、特に実際にコードの変更を伴うプルリクエストの送り方のヒントを提供できればと思います。

 一般に、GitHubにおけるプルリクエスト (プルリク)とは、そのプロジェクトのコードベースに変更を依頼することです。全てのプルリクに対して開発メンバーはレビューを行い、コードの正当性やスタイルをチェックします。この記事を読んでいただければ、プルリクに関する手続きを理解し、バグの報告や機能の要望といったGitHub上のコミュニケーションに自信が持てるようになると思います。

要約

We are proud of this project and have been trying to make this project great since day one. We believe you will love it, however, we do know that this is not a perfect project at all. 

コントリビューションガイドラインより抜粋

Optunaとは

 Optunaとはハイパーパラメータ最適化フレームワークです。Optunaが何なのか知りたい方は、我々の以前のブログを読んでみてください。ソースコードは全てPythonで書かれており、Python 3.5から3.8までをサポートしています。Python3.5のサポートはまもなく終了する予定で、それに伴って多くのソースコードのリファクタリングが必要です。 (既にプルリクの送り方が分かっている方は、ぜひお送りください!)

Optunaへのプルリクエストの送り方

 Optunaの開発メンバーは、最高のプロダクトを皆さんにお届けするため日々開発を進めています。しかし、開発メンバーだけでは全てのバグフィックスや新機能の追加を行うことはできません。もし、Optunaユーザの皆さんやOSS開発に興味のある皆さんに、プルリクを送ってもらえれば、Optunaの開発は大きく加速するでしょう。ここでは、そうした皆さんのためにヒントをまとめてみました。

 コントリビューションガイドラインには、Optunaにおけるプルリクの作成方法が書かれています。しかし、初めてプルリクを送る人にとっては、十分な情報ではないかもしれません。このブログは、初心者の方に向けてコントリビューションガイドラインを補完することを目的としています。

 ざっくり言うと、プルリクを出すまでの流れは、

  • コードの変更内容を考える
  • Optunaをインストールして変更を加え、テストする
  • リポジトリに変更内容を反映し、プルリクを作成する

となるでしょう。以下では、これらの手続きについて順を追って説明していきます。

どんなコード変更を行うか考える

取り組むタスクが決まっていないとき

 GitHubのissueにはバグ報告や新機能の提案、使い方の質問などが集まります。Optuna開発に興味のある方は、まずcontribution-welcomeとラベル付けされたissueの一覧を見てください。これらのissueはどなたでも取り組んでいただけます。もしissue内の説明が十分でない場合は、遠慮せず詳細を尋ねてください。

 初心者用のタスクには、さらにgood first issueのラベルが付けられています。これらはコードの局所的な変更や、ドキュメントの軽微な修正が多いでしょう。そのため、初めてOptunaの開発に加わる方は、ここからスタートすることをおすすめします。これらのタスクを見ても、ピンとくるものがなければ、個別にご相談いただいても大丈夫です。

`contribution-welcome`ラベルが付けられたissueの例。

contribution-welcomeラベルが付けられたissueの例。

取り組むべきタスクが決まっているとき

 自分でOptunaの問題を見つけたり、何か変更を行いたい点があったり、新機能を追加したいと思うこともあるでしょう。その場合は、最初に実装の詳細をissueを作って話し合うとよいかもしれません。もちろん、issueを作らずに直接プルリクを作成して頂いても全く構いません。

実際に変更を加えてテストする

 ここでは実際にOptunaをインストールし、変更を加えてテストする手続きを、順を追って説明します。

手元でOptunaをインストールし、変更を加える

 まずはOptunaを自分のGitHub上にforkしましょう。OptunaのGitHubページを開いて右上にあるforkボタンを押してください。続けて、forkしたリポジトリを自分の手元のPCにcloneしましょう。作業用ディレクトリに移動して環境を構築します。

$ cd WORKING_DIRECTORY
$ git clone git@github.com:${YOUR_GITHUB_NAME}/optuna.git
$ cd ./optuna

$ git remote add upstream git@github.com:optuna/optuna.git

forkしたリポジトリには”origin”という名前が自動的につきます。また、Optunaの元のリポジトリに”upstream”という名前を付けました。それではcloneしたOptunaを開発環境にインストールします。

$ pip install -e .

 このように編集可能モード (`-e`) でインストールしておけば、Optunaがインストール済みでも変更はすぐに反映されます。なお、開発に推奨される Python のバージョンは 3.6 か 3.7 です。Optunaがサポートしているサードパーティライブラリには、Python 3.5や3.8をサポートしていないものがあり、次のセクションで述べるテストが完全には動作しません。Optuna が最も確実に動作するPythonのバージョンは3.6と3.7です。

 それではインストールが成功したら、実際にコードに変更を加えてみましょう。まずは作業用のブランチを切ってください。ブランチの名前の付け方は、Optuna開発メンバーの付け方を参考にしてみてください。

$ git checkout -b WORKING_BRANCH_NAME

このブランチの上で作業することにしましょう。お好きなエディタ・IDEで変更したいファイルを開いて変更を加えてみてください。命名規則、型ヒント、フォーマットなどのOptunaのコーディングスタイルは、ガイドラインでカバーされています。慣れないうちは、テストを実行するたびにフォーマットのエラーが出ますが、変更の本質的な部分ではなく、容易に修正することができます。例えば、フォーマットのエラーに関してはエディタやIDEに `black` というプラグインをインストールすればファイル保存のたびに自動で修正してくれます。

手元でテストを実行する

 全てのユニットテスト用のコードは `tests/` の下にあり、そのサブディレクトリは `optuna/`のディレクトリ構成に対応しています。例えば、`tests/samplers_tests/test_grid.py` には `optuna/samplers/_grid.py` のユニットテストが含まれています。少なくとも自分が修正を加えた箇所と関連のあるテストは、手元で実行してみてください。もし関連するユニットテストがない場合は、新たにテストを追加するとよいでしょう。理想的には、既存のコードがどこも壊れていないことを確認するために、テストスイート全体を実行するべきです。しかし、Optunaでは必須ではありません。これは、Optuna は PyTorch, TensorFlow, Keras, LightGBM などのサードパーティライブラリをサポートしており、テストスイート全体を実行するためには多数のオプショナルな依存関係をインストールする必要があるためです。後になってテストの失敗が判明するかもしれませんが、それはプルリクを出した後に対処すれば良いでしょう。 (詳細は次の「プルリクエストを送る」を参照してください。)サードパーティライブラリに関するものを除いて、ほとんどのテストは `pytest` がインストールされていれば十分です。

$ pip install pytest
$ pytest tests/samplers_tests/test_grid.py

これだけで、`optuna/samplers/_grid.py`に加えた変更をテストできます!インストールしていないライブラリに関するテストを動かすと失敗するでしょう。その場合は適宜インストールを行ってください。

 もしテストスイート全体を実行したい場合は、pip install ".[testing]" を実行してオプショナルな依存関係をすべてインストールします。また、CircleCI のローカルCLIでコンテナを利用することもできます。また、公式のDockerイメージもいくつかあるので、環境設定済みのコンテナを利用することもできます。

 オプショナルな依存関係を全てインストールして、テストスイート全体を実行する手続きは以下のとおりです。

$ pip install ".[testing]"
$ pytest tests

これで変更を加えた箇所だけでなく、全てのユニットテストが実行されます。この処理には数分程度の時間がかかります。

 また、CircleCIのローカルCLIを使う方法もあります。CircleCIとはCI/CDサービスの1つです。 (詳細は公式リファレンスを参照してください。)Optunaでは、プルリクを作成すると全てのユニットテストが自動的にCircleCI上で走ります。それらのテストは、プルリクを作成するまで行えないというわけではなく、CircleCIのローカルCLIを用いて手元でテストを行うことができます。

CircleCI CLIを用いて手元でテストを実行するためには、テスト用のDocker環境を用意する必要があります。そのために、まずはDockerをインストールしましょう。具体的なインストール手順はご自身の環境に応じて、公式リファレンスを参照してください。

 次にCircleCI CLIをインストールしましょう。こちらも具体的なインストール手順はご自身の環境に応じて、公式リファレンスを参照してください。例えばmacOSでHomebrewが使える環境ならば、以下のコマンドでインストールされるはずです。

$ brew install --ignore-dependencies circleci

 インストールしたCircleCI CLIを用いてテストを実行しましょう。全てのテストを手元で実行する必要はありませんが、型ヒント、フォーマットなどのスタイルに関する以下のテストを実行しておくことをお勧めします。

$ circleci build --job checks

このテストはblack, flake8, mypyの3つのチェックを順に行います。blackはコードのフォーマットに関するテストで、失敗した場合は以下を実行することで自動的に修正できます。

$ black . --line-length 99 --exclude="docs|tutorial"

flake8はコーディングスタイルに関するテスト、mypyは型ヒントに関するテストです。失敗した場合はエラーメッセージを読みながら修正してみてください。これらの修正は慣れれば自明なものばかりですが、初めは戸惑うことが多いと思います。エラーが取れなくて困ったら一人で悩まず、プルリクを作成して、開発メンバーに質問してみてください。我々Optuna開発メンバーは全力で皆さんをサポートします。

ドキュメントについて

 開発メンバーは、ソースコード自体の修正と同じぐらいドキュメントの修正も大切にしています。実際、Optunaのドキュメントにはまだまだ改善の余地があります。例えば、APIに関して説明が十分でなかったり、文法的な誤りや単純なタイポなどが数多く含まれています。ソースコードの変更に加えて、関連するドキュメントも同時に変更して頂けるのであれば、それは願ってもないことです。もちろん、ドキュメントのみの修正も大歓迎です。

プルリクエストを送る

 コードに変更を加えたなら、いつでもプルリクを送ることができます。変更を終えて手元のテストを通過してからプルリクを送ってもよいですし、テストをする前にプルリクのドラフトを送っても大丈夫です。どんなプルリクでも歓迎します。

 プルリクを作成するためには、まず手元の変更をGitHub上のforkしたリポジトリにpushする必要があります。以下の”EDITED_FILE”には変更を加えたファイルを指定してください。また、”COMMIT_MESSAGE”には変更内容を一文で端的に書きましょう。

$ git add EDITED_FILE
$ git commit -m “COMMIT_MESSAGE”
$ git push origin WORKING_BRANCH_NAME

変更をpushした後に、元のOptunaのGitHubページを開くと`Compare & pull request`というボタンが出現します。

変更をpushした直後のOptunaのGitHubページの例。

変更をpushした直後のOptunaのGitHubページの例。

このボタンを押してみましょう。プルリク作成開始です!

プルリクエスト作成画面の例。

プルリクエスト作成画面の例。

 プルリク作成時・作成直後に気をつけるべきこととしては以下のようなものがあります。

  • プルリクのタイトルは、加えた変更を端的に表すような一文にしましょう。文末にピリオドはつけません。
  • プルリクの内容を記述するところに、なぜそのような変更を行ったかを記載しましょう。issueに対応したならissueへのリンクを貼り、機能についてのリファレンスがある場合にはそのリンクを貼りましょう。
  • 変更内容の詳細を記述しましょう。「コードを読めばわかる」という考えも一理ありますが、変更内容の適切な要約があると、レビューがスムーズになります。
  • CIでエラーが出た場合には、レビューを待つことなく対処しましょう。CircleCIの結果は、プルリク作成後にページ下部から確認できます。
  • プルリクを出してからしばらく時間が空くと、自分が変更しようとしているファイルが、別のプルリクによって先に変更されてしまうことがあります。その場合は以下の手続きを実行してみてください。最新のOptunaが手元の環境にマージされるでしょう。もし他の誰かによってなされた変更が、自分の変更と衝突する場合、どちらを優先するか手作業による修正が必要となります。
    $ git checkout master
    $ git fetch upstream
    $ git merge --ff-only upstream/master
    $ get checkout WORKING_BRANCH_NAME
    $ git merge master

 プルリクを作成すると、CircleCIやGitHub Actions上のCIジョブが自動的に開始されます。これらのジョブはテストを実行し、コーディングスタイルと型ヒントをチェックし、変更が既存のコードベースを壊さないかどうか確認します。何が実行されるか正確に知りたい場合は、CircleCIGitHub Actionsの設定ファイルをご覧ください。前のセクションでも述べたように、CircleCIはローカルで変更を確認できるCLIを提供しています。CIジョブの完了には数分程度の時間がかかるので、開発をスムーズにするためには、このCLIを用いて手元で変更を確認しておくと良いです。特に、 `circleci build –job checks` を実行してコーディングスタイルをチェックしておくことをお勧めします。

GitHub上のプルリクエストのページから確認できる画面。CIが報告する典型的なエラーが示されています。`checks` にはコードのフォーマットや型ヒントのチェックが含まれており、通常は簡単に対処することができます。

GitHub上のプルリクエストのページから確認できる画面。CIが報告する典型的なエラーが示されています。`checks` にはコードのフォーマットや型ヒントのチェックが含まれており、通常は簡単に対処することができます。

 開発メンバーはすべてのプルリクに目を通すようにしています。レビューはすぐに終わる場合もあれば、数週間に渡る場合もあるでしょう。実装が複雑であったり議論が必要だったりすると、結論が出るまでに時間がかかります。レビューの際には、スピードとコードの品質のバランスを取るようにしていますが、運用は完璧ではありません。このプロセスを改善できるとお考えの方は、ぜひお力添えください。

おわりに

 Optuna は多くのOSSプロジェクトと同様に、コントリビューションガイドラインを設けています。このブログを読み終えた方は、ぜひこちらもチェックしてみてください。Optuna開発に対する自信がさらに高まるはずです。GitHub上で皆さんにお会いできることを楽しみにしています!

 もしOptunaの最新ニュースに興味があるなら、ぜひ公式Twitter @OptunaAutoML をフォローしてください。また、GitHubよりはカジュアルにコミュニケーションをとることができるチャットルームGitterも用意してあります。質問はStack Overflowでも受け付けているので、気軽に質問してみてくださいね。

  • Twitter
  • Facebook