MOB-LOG

モブおじの記録 (Programming, 統計・機械学習)

ハンドドリップコーヒーの抽出パラメータをOptunaで最適化したい

TL; DR

『Optunaによるブラックボックス最適化』を読んでたらコーヒー抽出のパラメータを最適化する話が出てきた(フレンチプレス)。おれ、ハンドドリップに親しい。せやハンドドリップのパラメータ最適化しよう。Optunaで温度とか注ぎ量とかタイミングを最適化するシステムを用意した。

参考はこの方 @shu65(Shuji Suzuki) のブログのポスト:

モチベーション

ざっと考えて動機とメリットはこんな感じ。

  1. 改善と手軽さの両立

    日常的にハンドドリップでコーヒーを作って飲んでいるが、忙しいので抽出方法の改善を満足にできていないし(井崎式で無難に入れている状態)、無難な淹れ方さえわかれば、高い豆を買った方が味は良くなるので、そこまで深掘りして淹れ方の工夫はしていない(淹れ方を工夫するより金を払った方が楽)。

    そこで「脳死で旨いコーヒーが探索できるツールが必要」に至る。

  2. マンネリの解消

    正直長年コーヒーを淹れて飲んでいるとやり方が固定されてきてあまり工夫しようと思わなくなった(まずくなければいい)。刺激が欲しい。

  3. いろんな豆の最高な淹れ方を探求したい

    いろいろな豆を買って試すけれど、豆の本質的な良い・悪いを評価しているのではなく、「今の自分の淹れ方に合った豆を探している」状態な感じ。つまり、コーヒーがおいしくないのは豆のおいしさを引き出せてないお前が悪い、を否定できない。

  4. インターネッツの豆知識の検証

    インターネッツ上のコーヒー知識人の抽出方法、細かいテクニックとその理由は大変参考になるが、ときに知識と直感(味を確かめた結果)とが異なることあり自分で試してみないと納得できない。

    データで語りたい。

  5. 浅煎りの豆の克服

    焦げ焦げ深煎りのダークローストのコーヒーならおいしく入れるのは簡単だが、浅煎りのフルーティーな豆はおいしく入れるのが非常に難しい(冷めたら雑味が最悪とか)。特に浅煎りの豆に対して3の「豆のおいしさを引き出せていない」を感じる。

Materials and Methods

器具

  • コーヒースケール。

    時間と重みを測れるもの。 (Amazon.deで買ったよくわからんメーカーのやつ。多分中華製) (日本ではHarioかTIMEMOREのやつを好んで使っていた)

  • 電気ケトル

    温度調整ができるものがいいが(山善←安い、Hario Buono ←高い、など。山善の注ぎ感がよかった)、Finlandではまだ用意できていないのでケトルと注ぎポッド間でお湯を入れ替えて冷ましている。

  • コーヒーケトル(注ぎ用)。電気ケトルがコーヒードリップ用なら不要。(写真はHario Buono)

  • ドリッパー Hario V60, ペーパー

    無難。メタルドリッパーを使っている。

  • コーヒーミル

    TIMEMOREのC3。結構の精度でかつ素早く豆を粉砕できる。(ミルっことかほしい)

V60ドリップセット

ハンドドリップの手続き

抽出方法は固定する必要がある。今回設定した方法は井崎式ベースで、3回に分けてお湯を注ぐ。

手順 パラメータ 備考
1 出来上がり量を決定。 出来上がり量: W_\text{total}
固定
固定豆に吸われる量も含む。豆/水 でNormalizeしているが、1杯分より2杯分の方が濃くなるので。
濃い方がうまいし、一度に入れる量によって濃さが決まるので、試行間で統一する。
(コーヒー豆はキャニスターに入れ冷凍庫で保存しておく) コーヒー豆(種類、ロースト具合)。 今回は固定。 取り出す際は常温で放置せず、空気への露出を避ける(容易に結露する)。 ロースターほしい(LISON)。
2 豆の量を測る。 B [g] 豆:水 比: =  R_{ \frac{\text{beans}}{\text{water}}} = \frac{B}{W_\text{total}}, により決定される豆の量:
 B = R_{ \frac{\text{beans}}{\text{water}} } \times W_\text{total}
豆の量は出来上がり量に依存する。
井崎式では大体 100gの水に対して6—8gが使用される様子だが、ロースト具合によって豆の重みが変わるので(水含有量が変わるはず)、広く取りたい。
3 豆を挽く。 ミルのクリック数(器具に依存):  C_\text{fineness}
4 お湯を沸かし、湯温を調節する。 注ぐ直前のお湯温度:  T_\text{water}
 [80\text{--}96^\circ\text{C}]。(調節できる電気ポットの場合)
繰り返し回数(電気ポット → 注ぎポット、注ぎポット→電気ポットの回数):  T(調節可能でない場合)
温度調節できるやつが欲しかったが、フィンランドで購入するとamazon.de, amazon.co.uk で最低でも60 EUR, amazon.co.jp山善のポットを 6,000 JPY で買っても10,000JPYになってしまう(最近見たら9,000JPYに値上げしてたので14,000JPY掛かる)。いつか買う。
調節できないので、電気ポット⇔注ぎポットで入れ替えてジャバジャバして冷ます。
5 ドリッパー上でペーパーをリンスする。ドリッパー上でペーパーをリンスする。 リンスするかどうか: {r} [boolean] 器具を温めるとかいう意味合いの方が大きいらしい。
6 1投目。
注ぎ量  W_\text{P1} [g] を注ぎ時間  T_\text{P1} [sec]で注ぐ。(タイマースタート)
注ぎ割合: R_\text{P1} = \frac{W_\text{P1}}{W_\text{total}}
注ぎ時間: T_\text{P1} [sec]
注ぎ時間の調整がむずいので、15 secとかでいいかも。
7 スピニング(1回目)。
ドリッパーをスピンさせて湯を行き渡らせる。
スピニングするかどうか: {s_1} [boolean] 意味があるのかを確かめたい。ねるねるねるね、イケア効果の可能性(自己満足かも)。意味があるのかを確かめたい。ねるねるねるね、イケア効果の可能性(自己満足かも)。
8 蒸らし。1投目の注ぎ始めから  T_\text{steep} [sec]蒸らす。  T_\text{steep}:蒸らし時間。1投目直前(開始時間)—2投目の時間。
9 2投目。
注ぎ量  W_\text{P2} [g] を注ぎ時間  T_\text{P2} [sec]で注ぐ ( t_\text{P2} = T_\text{steep} [sec] のタイミングで注ぎ始め)。
注ぎタイミング: t_\text{P2} = T_\text{steep}
注ぎ割合: R_\text{P2} = \frac{W_\text{P2}}{W_\text{total}}
注ぎ時間: T_\text{P2} [sec]
注ぎ量  W_\text{P2} [g] を注ぎ時間  T_\text{P2} [sec]で注ぐ。
10 3投目。
注ぎ量  W_\text{P3} [g] を注ぎ時間  T_\text{P3} [sec]で注ぐ ( t_\text{P3} [sec] のタイミングで注ぎ始め)。
注ぎタイミング: t_\text{P3}
注ぎ割合: R_\text{P3} = \frac{W_\text{P2}}{W_\text{total}}
注ぎ時間: T_\text{P3} [sec]
注ぎ量  W_\text{P3} [g] を注ぎ時間  T_\text{P3} [sec]で注ぐ。
中心に注ぐか、全体に注いでコーヒーベッドを壊すのかは考慮せず。
11 スピニング(2回目)。
ドリッパーをスピンさせてコーヒーベッドを崩す。
スピニングするかどうか: {s_2} [boolean] 最後はめちゃくちゃのぐちゃぐちゃにするのが楽しい。(でも楽しいだけかも)
12 残りの湯をドリッパーを介さず注ぐ。 抽出後に注ぐ量: W_{\text{rest}} = {W_\text{total}} -(W_\text{P1}+W_\text{P2}+W_\text{P3}) で決定。(自動で決まるため最適化なし)

システム (コーヒー抽出パラメータ最適化)

Human in the Coffee Loop v0.1

構成要素

  • PC(GPUは要らない):計算リソースおよびインターフェース
  • Optuna君:最適化パッケージ。(Ask-and-Tell Interface を使用)
  • Google Spreadsheet:データベースとして
  • ヒト:実験動物兼、労働員。Optuna君の言う通りにコーヒーを淹れ、飲んで評価する。

手順

  1. ヒトがPC上でスクリプト起動
    1. Google Spreadsheet上のレシピ×評価 (Score) を参照しOptunaのStudyに反映させる。
    2. Optunaがレシピを生成。
    3. Google Spreadsheet上にレシピを保存し、ヒトへ提示。
  2. ヒトがレシピに従ってコーヒーを淹れる。
  3. 飲んで評価。1—7の7点評価をしてGoogle Formで回答する。

Results

いままで3回淹れたが、ランダムのためおいしくない(えぐみが強いが飲めはする)。今後、データがたまり次第まとめる予定。

所感

コードは今のところ @shu65(Shuji Suzuki) さんの方法のパラメータを変更しただけ。独立サンプリングではなく同時サンプリングになっているかを確認はした(元々そうなっている)。

運用してみていろいろ変更したら公開したい。

→ とりあえずここに: Human_in_the_Coffee_Loop.ipynb