![見出し画像](https://assets.st-note.com/production/uploads/images/160160677/rectangle_large_type_2_ef8e72c63e9c4d928e09beac165c7a72.jpeg?width=1200)
プロダクトを意識したAI開発 - LayerXサマーインターン体験記
2024年8月、僕はLayerXの機械学習エンジニアサマーインターンに参加しました。そこで、学生の立場ではなかなか経験できない「プロダクトにAIをどう活かすか」を考える貴重な機会を得たので、その振り返り記事を書きます。
このインターンでは、AIの精度向上に向けた実験から、ユーザー体験を支えるUI開発に至るまで、一連のプロセスを一貫して経験しました。プロジェクトにどのように取り組んだかを技術的な内容も交えて具体的にご紹介します。AIを活用したプロダクト開発に関心がある方や、インターンに興味を持っている学生の皆さんにとって、何かしら参考になる点があれば嬉しいです。
1. 自己紹介
僕は機械学習を活用したサービス作りを趣味にしている大学生です。カリフォルニア州のUCSCという大学に通っており、夏休みに日本に帰国し、複数の企業でインターンに参加しました。Twitterでは@masaishi2001、GitHubではmasaishiとして活動中です。最近は、画像生成の推論コードをシンプルに書いたライブラリである「PareDiffusers」を開発しました。
2. LayerXサマーインターンとは
LayerXは、「すべての経済活動を、デジタル化する。」というミッションを掲げ、業務効率化クラウドサービス「バクラク」などのSaaSを提供する企業です。今年初めて開催されたサマーインターンは、ソフトウェアエンジニアと機械学習エンジニアの2職種で実施され、僕は機械学習エンジニアインターンに参加しました。
機械学習チームのインターンでは、バクラクが抱える課題の中から、事前の面談を通じてそれぞれのインターン生に最適なプロジェクトを用意していただき、チームのサポートを受けながら取り組む形式でした。このような充実したサポートのもと、現場の課題解決に向けた貴重な経験を積むことができました。
サマーインターンのプログラムについてさらに詳しく知りたい方は、ぜひ下記の記事をご覧ください。
3. インターンの流れ
LayerXインターン中に行われた朝会や夕会といった1日のスケジュールや、チームとのコミュニケーション、フィードバックを通じて得た学びについて紹介します。
3.1 朝会
LayerXの機械学習チームでは、スクラム形式で毎日朝会が行われていました。僕は独立したプロジェクトに取り組んでいたため、直接の連携はなかったものの、チームの一員としてこの流れを体験できたことは非常に貴重でした。
朝会では、各自の進捗を報告し、必要に応じてアドバイスをもらうことができます。今まで個人での開発が中心で、チーム開発の経験が少なかった僕にとって、実際にスプリント運用を体験しながら学べたのは大きな収穫でした。スクラムの運用方法やNotionを活用したタスク管理の詳細については、下記の記事に分かりやすくまとめられているので、興味のある方はぜひ参考にしてみてください。
3.2 昼ご飯
オフィスが銀座にあるため、ランチは多くの選択肢があり、充実した食事を楽しむことができました。インターン期間中、機械学習チームのメンバーだけでなく、他部署の方々ともランチに行く機会が多く、さまざまな視点からお話を伺える良い機会でした。特に、「新しいロジックや施策をAI-OCRに組み込む際に、評価する上で注意すべきこと」や「外部API設計の難しさ」について伺えたことは、僕にとって非常に興味深く、学びが多かったです。
![](https://assets.st-note.com/img/1730451573-rdfePhKugBoUk6OViv73m08l.jpg?width=1200)
3.3 夕会
夕会では、Notionのテンプレート機能を活用し、「現状」「仮説」「アクション」の3項目をもとに進捗を記録・共有しました。この形式により、なぜその実験を行うのか、どのような仮説に基づいているのかを整理しやすく、モデル学習の実行にも明確な目的を持って臨む習慣が身につきました。
さらに、毎日の夕会では、実験結果をチームに共有し、メンターや他の機械学習チームの方々からフィードバックや助言をもらえる環境が整っていました。これによって、実験内容を深く掘り下げ、視野を広げることができ、深い学びを得ることができました。
僕にとって夕会は、インターンの中で最も成長を実感できる貴重な場となりました。
4. プロジェクト
僕は、前任のインターン生が取り組んでいた「バクラク経費精算における領収書自動分割プロジェクト」を引き継ぎました。このセクションで、プロジェクトの背景や目的を紹介します。
このプロジェクトは、バクラク経費精算に密接に関わるもので、ここで概要を説明したいと思います。経費精算の際には、領収書から日付や金額などの情報を入力する必要があります。これを補助するために、バクラクではAI-OCR機能が導入されており、領収書をアップロードするだけで取引先名や金額などの経費精算に必要な項目が自動で入力される仕組みになっています。
しかし、このAI-OCR機能に対して、「複数の領収書を一度に処理できるようにしてほしい」という要望が複数寄せられていました。特に、経費精算業務で複数の領収書を台紙にまとめて貼り付け、スキャンして管理しているお客様もおり、そうしたデータをアップロードするだけで一括処理できる機能が求められていました。
この課題を解決するために、以下のようなニーズに応えることが必要とされました。
![](https://assets.st-note.com/img/1730277009-mV03gZQJ8covKHtDP2kauRw6.png?width=1200)
1. 経費精算の手間削減: 複数の領収書を一度に写真に収めて一括処理を可能にすることで、社員の負担を軽減する。
2. サービスからの一括出力: サービス提供元から複数領収書がまとめてPDFで出力される場合、各項目を別々の領収書として処理可能にする。
3. 複数領収書の一括管理: スキャンされた台紙に貼り付けられた複数の領収書を自動的に識別し、個別に処理できるようにする。
このような要件に応えるため、「領収書自動分割プロジェクト」では、AIを活用して複数の領収書が含まれる画像から個々の領収書を検出し、個別のデータとして処理できるようにすることを目指しました。
僕はTerm 2のサマーインターンとしてこのプロジェクトに参加しましたが、引き継いだ時点でTerm 1のインターン生がデータ収集やモデルの学習、精度向上のためのいくつかの実験を行っていました。インターン期間中の目標は、このモデルの精度をさらに向上させ、デプロイしてバクラクのAI-OCRに統合することでした。
5. モデル
このセクションでは、領収書自動分割に使用したモデルについて紹介します。
領収書自動分割とは要するに、入力画像から領収書と認識できる物体を複数検出するタスクです。このような物体検出タスクには、各オブジェクトを個別に区別できるInstance Segmentationが適していると考えられたため、前任者はRTMDetというモデルを採用していました。
RTMDetは、物体検出やセグメンテーションにおいて、YOLOモデルを高速化し、斜めに配置された物体も検出できる「Rotated Object Detection」や、画像内の各オブジェクトを個別に分離する「Instance Segmentation」に対応したモデルです。Instance Segmentationとは、画像内に存在する同一カテゴリの複数のオブジェクトを、重なりなども考慮しながら個別に検出・分離する技術です。
メンターからは、モデルの精度を向上させるためにはまずモデルの仕組みを深く理解し、そのアーキテクチャに基づいて実験の仮説を立てることが重要であるとアドバイスを受けました。そこで、RTMDetの論文を読み理解を深めた上で、毎週行われる機械学習チームの「LayerX Machine Learning勉強会」にて、その内容を発表をしました。この勉強会は僕がLayerXを知るきっかけとなった場であり、そこで発表する機会を得られ大変嬉しかったです。
6. AI-UX
今回のインターンでは、モデルの学習からウェブアプリの開発まで、常に「AI-UX」を意識して取り組みました。
LayerXの掲げる「AI-UX」とは、単にAI技術を組み込むだけでなく、「AIを前提とした理想のUX」を実現するために、AIに限らずあらゆる手段を駆使して最高の体験を提供しようとするアプローチです。
AI-UXについて詳しく知りたい方は、以下の記事をご覧ください:
Kaggleなどでモデルを学習させていた際は、スコア向上のみを目標にしており、それを用いたアプリケーションのUI/UXまで考慮することはありませんでした。しかし、今回のプロジェクトでは、次のセクション「7. 精度向上のために行った実験」で紹介する各実験を進める際にも、AI-UXを意識し、ユーザーが実際にどう使うかを念頭に置いていました。
まず、モデル学習を回す前に、バクラクのAI-OCRに領収書自動分割機能を組み込む際のことを考えました。そして、複数の領収書が写った画像をアップロードしたとき、それぞれの領収書が自動的に枠で囲まれるUIを追加し、ユーザーが修正した後、個別でAI-OCRにかけようと考えました。
そのため、誤検知(False Positive)が多少増えたとしても、検出すべき領収書が見逃される未検出(False Negative)が少ないモデルを目指しました。
なぜなら、未検出があるとユーザーが手動で領収書を選択する手間が増えてしまいますが、誤検知がある場合は不要な枠を削除するだけで済み、手間が比較的少ないからです。このように、ユーザーの操作負担を最小限にするために、未検出を抑えることを優先目標としてモデルの精度向上に取り組みました。
7. 精度向上のために行った実験
モデルの精度を向上させるために、以下の実験を行いました。
1枚の領収書から、背景除去を用いた擬似ラベルの作成
1枚の領収書を複数配置したデータセット作成
Albumentationsを用いたData Augmentation
1枚の領収書擬似ラベルのデータクレンジング
複数領収書から、背景除去を用いた擬似ラベルの作成
1枚の領収書を並べるアルゴリズムの変更
この中から「背景除去による擬似ラベル作成」と「1枚の領収書を複数配置したデータセット作成」の2つの実験結果について詳しく説明します。
7.1 背景除去による擬似ラベル作成
現状
Instance Segmentationモデルは物体検出モデルのため、テストデータの画像上にbboxなどの検出結果を描画できます。この結果を確認したところ、False Positive(領収書でない物体の誤検出)は少なく、検出すべき領収書が検出されない未検出(False Negative)が多いという問題があることがわかりました。例えば、テストデータAにはPDF内に3枚の領収書が写っていましたが、現状のモデルでは2枚しか検出できていませんでした。
また、学習データとして用意した複数の領収書が含まれるデータは約150枚と少なく、データ総数が少ないという状況でした。
仮説
そこで、1枚のみが写っている領収書画像も学習データに加えることでデータの多様性が増え、精度向上が期待できるのではないかと考えました。
実際のアプリケーションでは、複数の領収書が含まれる画像データを想定していますが、1枚の領収書だけが写っている画像を増やすことで、領収書の種類や背景のバリエーションを広げることができ、検出精度が改善されると考えました。
アクション
1枚の領収書が写っているデータを集めるため、OCR結果に「領収書」という単語が1つだけ含まれる画像を抽出し、そこに背景除去を適用して擬似ラベルを作成しました。
まず、背景除去のライブラリであるrmbegを使用し、その後、OpenCV(cv2)を用いて残ったオブジェクトの領域と輪郭を検出しました。しかし、背景除去だけでは不十分で、写真内のキーボードやボールペンなど、領収書以外の不要なオブジェクトがノイズとして残るケースが多く見られました。
そこで、ノイズをさらに除去するため、次の2つのフィルタリング条件を追加しました。
1つ目の条件は、領域の面積が画像全体の10%以上であることです。実際にデータを確認したところ、1枚の領収書が写っている場合、領収書が画像全体の中で比較的大きな面積を占める傾向が見られたため、この条件を採用しました。
2つ目の条件は、輪郭が6角形以下であることです。基本的には領収書は4角形として検出されますが、折れ曲がっている場合もあるため、少し余裕を持たせた形です。
このフィルタリング条件を適用した結果、約1500枚のデータが残り、それらの画像を確認して精査しました。最終的に、領収書のみを正確に検出できている1000枚を選別し、学習データとして追加しました。
結果
しかし、1枚の領収書データを過剰に増やした結果、複数の領収書が写っている画像で1枚しか検出されないケースが増え、精度が下がってしまいました。
具体的には、テストデータAで従来は3枚中2枚を検出できていたのが、このアプローチでは1枚しか検出されない結果となりました。
この実験から、1枚の領収書データを増やしすぎると、モデルがそのパターンに偏ってしまい、検出結果が1枚に限られてしまうリスクが高まることがわかりました。
7.2 1枚の領収書を複数配置したデータセット作成
現状
領収書データにさらなるバリエーションが必要でしたが、1枚の領収書データを増やしすぎると、検出が再び1枚に偏りやすくなり、過学習のリスクが高くなることが懸念されました。
また、学習データを詳しく見直したところ、お客様が複数の領収書を撮影する際は、比較的整然と並べて撮影する傾向があることがわかりました。
また別の観点として、テストデータの検証から、白以外の背景で撮影された画像でmAPスコアが特に低くなることが判明しました。
仮説
この課題に対して、複数の領収書が写っている擬似データを作成すれば、1枚に過学習するリスクを抑え、複数の領収書が配置されたシーンにも対応できるのではないかと考えました。具体的には、1枚の領収書を複数並べたデータセットを用意することで、実際にお客様が撮影する状況に近い画像が再現できるのではないかと仮説を立てました。
また、背景には白背景とBG-20kを採用しました。BG-20kは、前任のインターン生がデータ拡張に活用し、精度向上に効果を示した背景データセットです。このデータセットを利用することで、さまざまな環境下で撮影された領収書画像にも対応できる柔軟なモデルが期待できると考えました。
アクション
まず、白背景に1枚の領収書画像を横に2〜4枚並べるコードを作成し、データ数を増やしました。また、BG-20kの背景に背景除去した領収書画像を配置し、複数の領収書が写っているデータセットを作成しました。
さらに、並べる際のアルゴリズムを工夫し、配置にランダム性を持たせつつ、自然な並び方で領収書が配置されるようにしました。
結果
こうして作成した白背景に複数の領収書を並べたデータを学習に使用した結果、特にPDF形式のデータに対する精度が向上しました。
テストデータAでも、従来は3枚のうち1枚しか検出できなかったものが、この方法を適用することで3枚すべてを正確に検出できるようになりました。
残念ながら、写真データのmAPスコアの向上には至りませんでしたが、アプリケーションに組み込む際に発生しないほうが良いと考えていた、未検出を減らすことができたため、良い結果が得られたと感じています。
8. ウェブアプリの開発
プロジェクトの最終目標は、実際にデプロイしてAI-OCRに組み込むことでしたが、時間の都合でそこまで到達することはできませんでした。そのため、領収書自動分割を組み込む際の参考になるよう、デモ用のウェブアプリを開発しました。
まず、モデルをONNX形式に変換して高速化し、FastAPIを使って推論サーバーを構築しました。LayerX機械学習チームで使われているテンプレートを使用していたため、そのサーバーをそのままSageMakerのエンドポイントでデプロイすることも簡単でした。今回は時間の都合で、FastAPIサーバーをローカル環境に立ち上げデモを作成しました。
ウェブアプリ自体はNext.jsで構築しました。ウェブ上でバウンディングボックス(bbox)を操作できるようにするため、HTMLのcanvas機能を拡張するライブラリであるfabric.jsを採用しました。そして、画像をアップロードすると、領収書を検出し修正可能なbboxを描画するアプリを開発しました。
以下にデモ動画を配置しました。この動画では、社員の方から提供していただいたGOの複数領収書データをアップロードし、検出された領収書部分を編集する手順を確認できます。誤検出された領域を選んで簡単に削除できるようになっており、AIの検出が不完全でも手軽に修正が可能です。各機能を紹介する前に、この動画でアプリ全体の流れと使用感をイメージしていただければと思います。
![](https://assets.st-note.com/production/uploads/images/161699408/picture_pc_20f56a3c24455bfe1adb9b4089c28f4c.gif?width=1200)
8.1. ウェブUIの機能
デモ用ウェブアプリの開発するにあたり、AI-UXの考え方を意識しつつ以下のUI機能を実装しました。
• 誤検出bboxの削除: 誤って検出されたbboxを選択し、Deleteキーで簡単に削除できるようにしました。
• bboxの追加: 「bboxを追加」ボタンを設け、スコアがしきい値未満の候補から、次にスコアが高いbboxを新たに追加できるようにしました。
• bboxの手動調整: ユーザーがbboxの位置やサイズをドラッグ&ドロップで調整できるようにしました。
こうした機能を実装する中で、AI-UXの「100%正しいAIモデルは存在しない」という前提を意識しつつ、モデルの精度向上とUI設計がどのように協調できるかを探りながら進めました。精度を高めることだけでなく、検出漏れや誤検出が発生した場合のユーザーの操作性も考慮して、UIの使いやすさを確保しています。
bboxの追加では、単に中央にbboxを配置するのではなく、未検出領域をカバーするためにスコアが次に高い領域から候補を追加する仕様にし、ユーザーの操作とAIの補完作業が自然と繋がるようにしました。
8.2 推論サーバーの機能
推論サーバーでは、RTMDetを動かすだけではなく以下の機能も実装しました。
• 自動回転で正しい向きに調整:TesseractのOCRスコアを活用し、領収書を正しい向きに自動で回転させるようにしました。
• 斜め撮影の画像を水平化:傾きのある領収書画像を水平に補正できるようにしました。この水平化処理により、後段のAI-OCRによる項目抽出においても、正しく文字認識される効果が期待できます。
TesseractのOCRスコアをもとに、領収書が正しい向きであるかをサーバー側で自動的に判断し、必要に応じて回転させる機能を実装しました。この仕組みによって、ユーザーがどの向きで領収書を撮影しても、サーバー側で正しい向きに自動回転されるようにしました。
9. 感想
今回のインターンでは、バクラクのAI-OCRに直接組み込むという目標を達成するには至りませんでしたが、単にウェブアプリでAIを使うだけでなく、モデルの学習段階から「プロダクトにどう取り込むか」を考慮しながら学習を進めることができたことは、非常に実践的で貴重な経験でした。LayerXのインターンは、精度向上を追求するだけでなく、実際のプロダクトに適したAI開発を学ぶ場として、他にはない貴重な学びが得られる機会でした。
特に自分にとって成長につながったのは、モデルの精度を高めるための仮説構築と、それに基づく実験を毎日の夕会でエンジニアの方々と議論し、フィードバックを得ながら進めたプロセスでした。仮説を立て、その検証を重ねることの重要性を改めて感じました。仮説構築の大切さについては、インターン運営側の振り返り記事で詳しく書かれているので、興味がある方はぜひ読んでみてください。
また、LayerXが掲げる「AI-UX」の考え方を意識して開発に取り組めたことも大きな収穫でした。「100%正しいAIモデルは存在しない」という前提のもと、ユーザーが後から訂正や補完を行えるUX設計を行い、AIの精度向上だけでなく、モデルの出力が不完全でもユーザーが補正しやすいように工夫したデモ用ウェブアプリを開発することができました。このような視点での学びは、僕のような学生にとって得がたい実践的な経験であり、大きな価値があったと思います。
最後に、サマーインターン期間中、サポートしてくださった機械学習チームやLayerXの皆さんに心から感謝を伝えたいです。
![](https://assets.st-note.com/img/1731248925-pNG3vg4nl26dAxSImouTXzKJ.jpg?width=1200)