
Cosmos 3のReasonerで、画像から不良品を判定できるか試してみた
はじめに
前回まで、Cosmos 3で欠陥画像を生成できるかを見てきました。今回はCosmos 3の理解する側を使ってみます。Cosmos 3は生成モデルであると同時に、画像を読んで言葉で答えるVLM(Vision-Language Model)=Reasonerを内蔵しています。これが良品と不良を見分ける目的で使えるかを試しました。
先に結論から。
- 明白な欠陥(傷・割れ・錆)はゼロショットで種類・位置ともにほぼ当てます。
- ただし微妙な欠陥(凹み等)は見逃したり、視覚的に似た種別(欠け、汚れ)を混同したり、正常品を過検出したりします。
- つまりReasonerは素の状態でも使えるが実運用には届かず、自社データでのファインチューニングが要る、という結論でした。NVIDIA公式の事例(前世代の Cosmos Reason 1-7B をウェハーマップの分類にFTした例)も、ゼロショット14.37%→96.8%まで伸びています(モデルもタスクも本検証とは別なので、直接比較ではなく"ドメインFTで大きく伸びる"傾向の参考として)。
Reasonerとは(Cosmos 3の"理解"のTower)
Cosmos 3は、Reasoner(画像を理解するVLM) と Generator(画像・動画を生成) の2つのtowerでできています。これまでの検証記事では、Cosmos 3を"生成"でしか使っていませんでした(画像を読んで答えさせる"理解"の使い方は今回が初めて)。Reasonerは画像+質問→テキストで答える側で、キャプション・VQA・欠陥の種類や位置の言語化ができます。ベースはQwen3-VL-32Bです。
動かし方(vLLMサーバ経路)
ここでハマりどころが1つ。生成で使うcosmos-frameworkのCLIでmodel_mode:reasonerを指定すると、この構成ではテキスト専用で起動して画像を受け付けてくれません(LLMTokenizerProcessorでエラーになります)。で、いろいろ試した結果、画像を読ませるVQAはvLLMサーバ経路が正解でした。
vllm serve /mnt/weights/Cosmos3-Super \
--hf-overrides '{"architectures": ["Cosmos3ForConditionalGeneration"]}' \
--tensor-parallel-size 4 --mm-encoder-tp-mode data --async-scheduling \
--allowed-local-media-path / --served-model-name cosmos3-super --port 8001
--hf-overridesでReasonerのアーキテクチャを明示指定するのが肝で、これで画像の入り口が開きます(アーキ名はvLLMの版で違っていて、このbuildではCosmos3ForConditionalGenerationでした)。あとはOpenAI互換APIに画像を投げるだけです。
curl -s http://localhost:8001/v1/chat/completions -H "Content-Type: application/json" -d '{
"model":"cosmos3-super",
"messages":[{"role":"user","content":[
{"type":"text","text":"Is there any defect? What type? Where?"},
{"type":"image_url","image_url":{"url":"file:///path/to/part.jpg"}}
]}]
}'
検証: 自作の欠陥画像で判定させる
手頃な欠陥画像がなかったので、自分たちがCosmosで生成した欠陥画像(種類と位置を指定して作ったもの)を読ませてみました。
金属部品にscratch/crack/dent/rust/chipを1つずつ配置した6枚(c1〜c6)を、選択肢を固定して分類させた結果がこちらです。
| 画像 | 目視で写っている欠陥 | Reasonerの判定 | 正誤 |
|---|---|---|---|
| c1 | 割れ状の線(+擦り傷) | crack / 中央 | ○ |
| c2 | 擦り傷(左上) | scratch / 左上 | ○ |
| c3 | 割れ(右エッジ) | crack / 右上 | ○ |
| c4 | 明確な凹み(中央) | none(欠陥なし) | × 見逃し |
| c5 | 錆(右下) | rust / 右下 | ○ |
| c6 | エッジの欠け | chip / 左下 | ○ |
6枚中5枚を正しく判定しました。ゼロショットでここまで当てるのは正直ちょっと驚きです。唯一の失敗はc4の凹み(dent)の見逃しでした。凹みは低コントラストの3D変形なので、平面的な傷や色の異常より読み取りにくい、という弱点が出た感じですね。
面白かったのが自由記述との差です。自由記述で聞くと、c6の「欠け(chip)」を「汚れ(contamination)」と誤答しました。ところが「none / scratch / crack / dent / chip / rust / stain から1つ選べ」と選択肢を固定するとchipと正解しました。実運用では自由記述より固定クラスの分類にしたほうが、視覚的に似た種別の混同が減る可能性が高い、という学びでした。
実写ではどうか
手持ちの実写の金属・樹脂部品(いずれも良品)でも試しました。6枚中3枚は正しく「欠陥なし」と判定しましたが、残り3枚は良品なのに「欠陥あり」と誤検出しました。
「汚れ」「表面の傷・変色」「加工痕」といった、正常な表面の質感を"欠陥"と拾ってしまいました。
今回は実写の不良サンプルが無いので見逃し側は測れていません。実写での本格的な定量評価は、不良も含むラベル付きの標準データで行います。
結論: ゼロショットは"入口"、実運用はファインチューニング
- 明白な欠陥の検出は素でも強い。でも微妙な欠陥の見逃し・似た種別の混同・正常品の過検出があって、そのまま検査ラインには乗せられません。
- これはNVIDIA自身のデータとも整合します。公式のウェハーマップ分類の例では、前世代のCosmos Reason 1-7Bをゼロショット14.37%→100枚/クラスのファインチューニングで96.8%まで上げています。"自社ドメインのラベル付きデータでファインチューニングが実用の鍵、というわけです。
次回以降
実写画像でラベル付きの標準ベンチを使って、ReasonerをLoRAでファインチューニングして判定精度が実際にどこまで上がるかを、同じ画像セットで測ってみます。
Built on NVIDIA Cosmos. nvidia/Cosmos3-Super(OpenMDW-1.1)を使用しています。









