はじめに
光学設計といえば、光学設計ソフトウエア「Ansys Zemax OpticStudio」や
「CODEV」を使ったレンズパラメータ最適化が一般的ですが、
近年では機械学習を活用した新しいアプローチが登場しています。
今回試してみたのは以下のオープンソースプロジェクトです。
本記事で扱う"DeepLens"は「AWS DeepLens」ではありません
ディープラーニングと光学設計を組み合わせて
光学系の設計・解析を効率化することを目的としたシステムのようです。
DeepLens とは
DeepLensは、光学系の設計における収差の補正や最適化を
ニューラルネットで学習させることを目指した研究プロジェクトで、
アブドラ王立科学技術大学(KAUST)の研究チームが発表したもののようです。
「従来の最適化アルゴリズムの代替」あるいは「設計補助」として活用が期待できそうです。
従来の光学設計との比較
- Zemax/CODEVなどの光線追跡ソフト : 厳密な光線追跡・最適化(物理ベース)
- DeepLens : データ駆動型、学習済みモデルを利用して推定や予測が高速
つまり、
- 「設計初期の探索・スクリーニング」には機械学習が有効
- 「最終的な精密設計」には従来のレイトレーシングが有効
という住み分けが考えられますね。
実際に触ってみる
アプリケーションとしていくつか用意されていますが、
いわゆる"自動光学設計"を行うには「AutoLens」を使用します。
プログラムファイルを見ると、どうやらConfigsファイル内のymlファイルに
目標仕様やレンズタイプ(球面or非球面)などを指定するようです。
今回は手近なマシンで性能の良いGPUがないので
Google Colab上でGitHubからCloneし、実行してみることにしました。
if __name__ == "__main__":
args = config()
result_dir = args["result_dir"]
device = args["device"]
# Bind function
GeoLens.curriculum_design = curriculum_design
# Create a lens
lens = create_lens(
foclen=args["foclen"],
fov=args["fov"],
fnum=args["fnum"],
flange=args["flange"],
thickness=args["thickness"],
lens_type=args["lens_type"],
save_dir=result_dir,
)
lens.set_target_fov_fnum(
hfov=args["fov"] / 2 / 57.3,
fnum=args["fnum"],
)
logging.info(
f"==> Design target: focal length {round(args['foclen'], 2)}, diagonal FoV {args['fov']}deg, F/{args['fnum']}"
)
# =====> 2. Curriculum learning with RMS errors
lens.curriculum_design(
lrs=[float(lr) for lr in args["lrs"]],
decay=float(args["decay"]),
iterations=5000,
test_per_iter=100,
optim_mat=True,
match_mat=False,
shape_control=True,
result_dir=args["result_dir"],
)
# Need to train more for the best optical performance
lens.optimize(
lrs=[float(lr) for lr in args["lrs"]],
decay=float(args["decay"]),
iterations=5000,
centroid=False,
importance_sampling=True,
optim_mat=True,
match_mat=False,
shape_control=True,
result_dir=args["result_dir"],
)
# =====> 3. Analyze final result
lens.prune_surf(expand_surf=0.02)
lens.post_computation()
logging.info(
f"Actual: diagonal FOV {lens.hfov}, r sensor {lens.r_sensor}, F/{lens.fnum}."
)
#lens.write_lens_json(f"{result_dir}/final_lens.json")
lens.write_lens_zmx(f"{result_dir}/final_lens.zmx")
lens.analysis(save_name=f"{result_dir}/final_lens", zmx_format=True)
# =====> 4. Create video
create_video_from_images(f"{result_dir}", f"{result_dir}/autolens.mp4", fps=10)
こちらがAutoLensのメイン実行部です。
レンズの生成 → カリキュラム学習 → 最適化 → 解析 → 結果出力 という一連のフローを担っています。
カリキュラム学習
カリキュラム学習という手法を利用しているみたいなのですが、
この部分は以下の理解で良いかと思います。
lens.curriculum_design(
lrs=[float(lr) for lr in args["lrs"]],
decay=float(args["decay"]),
iterations=5000,
test_per_iter=100,
optim_mat=True,
match_mat=False,
shape_control=True,
result_dir=args["result_dir"],
)
- lrs 学習率リスト
- decay 学習率減衰
- iterations=5000 → 学習回数
- optim_mat=True → 材料特性も最適化対象に含める
- shape_control=True → 形状制御あり
Zemax形式での出力
#lens.write_lens_json(f"{result_dir}/final_lens.json")
lens.write_lens_zmx(f"{result_dir}/final_lens.zmx")
lens.analysis(save_name=f"{result_dir}/final_lens", zmx_format=True)
Zemaxのレンズデータ(.zmx)での出力にも対応していそうです。
可視化 (動画生成)
create_video_from_images(f"{result_dir}", f"{result_dir}/autolens.mp4", fps=10)
結果フォルダの画像を連結し、学習の進化をタイムラプス風に可視化していますね。
実行結果
適当なスマホレンズっぽい仕様で最適化しました。
こちらが初期状態です。
完全なフラットな板からスタートします。
5000回分の最適化後です。
そこそこ時間はかかりましたが(Colabの課金GPUを選んだんですが)
それっぽい見た目になってきました。
完全なフラット面からスタートさせると
それなりに性能の良いレンズ系にたどり着くにはかなり遠いような気がしますが、
ある程度形状がある状態から最適化をスタートさせる方法も果たしてあるのか…?
ただ、Zemaxでローカル最適化し
小まめにメリットファンクションを調整したりする作業無しに
光学設計が完結できればそれは究極のゴールですよね。
実業務で使うにはまだまだこのプログラムへの理解と試行錯誤が必要そうです。
ということで、この記事はもう少し続くかもしれません。
※本記事は筆者個人の見解であり、所属組織の公式見解を示すものではありません。
問い合わせ
光学シミュレーションソフトの導入や技術相談、
設計解析委託をお考えの方はサイバネットシステムにお問合せください。