質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

700閲覧

Fast APIで画像をアップロードすると"Object of type Tensor is not JSON serializable"というエラーが発生

RYO777

総合スコア1

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2023/12/16 05:23

編集2023/12/16 12:00

実現したいこと

  • Fast API上に画像をアップロードし、良品と不良品を判定するアプリを作成したいと考えています。

  • しかし、画像をアップロードすると "TypeError: Object of type Tensor is not JSON serializable" というエラーが発生します。

  • 解決方法のわかる方がおられましたらご教授いただけますと幸いです。情報不足でしたら、コメントいただければと思います。

前提

vscodeで、model2.pyとmain2.pyのファイルを作成しています。
modelは保存済みのVAEモデルをロードして使用しております。

発生している問題・エラーメッセージ

エラーメッセージ "TypeError: Object of type Tensor is not JSON serializable"

該当のソースコード(python)

main2.py

1from fastapi import FastAPI, File, UploadFile 2from fastapi.responses import JSONResponse 3from model2 import VAE, z_dim 4import torch 5import cv2 6import numpy as np 7 8app = FastAPI() 9 10# モデルのインスタンスを作成 11loaded_model = VAE(z_dim) 12# 学習したパラメータを読み込む 13loaded_model.load_state_dict(torch.load('vae_model_epoch20.pth', map_location=torch.device('cpu'))) 14 15# モデルを評価モードに切り替える(推論時に必要) 16loaded_model.eval() 17 18# Define anomaly score threshold (adjust as needed) 19anomaly_score_threshold = 35.0 20 21async def process_image(file: UploadFile): 22 contents = await file.read() 23 nparr = np.frombuffer(contents, np.uint8) 24 image = cv2.imdecode(nparr, cv2.IMREAD_COLOR) 25 image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 26 image = torch.tensor(image, dtype=torch.float32) / 255.0 27 image = image.permute(2, 0, 1).unsqueeze(0) 28 29 # Encode and reconstruct the image 30 with torch.no_grad(): 31 z, ave, log_dev = loaded_model.encoder(image.view(-1, 302 * 403).to(torch.float32)) 32 reconstructed_image = loaded_model.decoder(z).view(-1).detach().cpu().numpy() 33 34 # 画像の形状を (302, 403) に変形 35 reconstructed_image = reconstructed_image.reshape(-1, 302, 403) 36 37 # Calculate anomaly score 38 mse = ((image.view(-1, 302, 403).numpy() - reconstructed_image) ** 2).mean() 39 kl_divergence = -0.5 * torch.sum(1 + log_dev - ave**2 - log_dev.exp()) 40 anomaly_score = mse + kl_divergence 41 42 # Determine if the image is defective 43 is_defective = anomaly_score > anomaly_score_threshold 44 45 # Convert torch.Tensor to NumPy array for JSON serialization 46 image_np = image.squeeze().permute(1, 2, 0).numpy() 47 return JSONResponse(content={"is_defective": is_defective, "anomaly_score": anomaly_score.item(), "image": image_np.tolist()}) 48 49@app.post("/predict") 50async def predict(file: UploadFile = File(...)): 51 return await process_image(file)

model2.py

1import torch 2import torch.nn as nn 3import torch.nn.functional as F 4 5class Encoder(nn.Module): 6 def __init__(self, z_dim): 7 super().__init__() 8 self.lr = nn.Linear(302*403, 300) 9 self.lr2 = nn.Linear(300, 100) 10 self.lr_ave = nn.Linear(100, z_dim) #average 11 self.lr_dev = nn.Linear(100, z_dim) #log(sigma^2) 12 self.relu = nn.ReLU() 13 14 def forward(self, x): 15 x = x.view(-1, 302 * 403) # 入力を平坦化 16 x = self.lr(x) 17 x = self.relu(x) 18 x = self.lr2(x) 19 x = self.relu(x) 20 ave = self.lr_ave(x) #average 21 log_dev = self.lr_dev(x) #log(sigma^2) 22 23 ep = torch.randn_like(ave) #平均0分散1の正規分布に従い生成されるz_dim次元の乱数 24 z = ave + torch.exp(log_dev / 2) * ep #再パラメータ化トリック 25 return z, ave, log_dev # 潜在変数 z とその統計量(平均 ave と対数分散 log_dev)を得る 26 27class Decoder(nn.Module): 28 def __init__(self, z_dim): 29 super().__init__() 30 self.lr = nn.Linear(z_dim, 100) 31 self.lr2 = nn.Linear(100, 300) 32 self.lr3 = nn.Linear(300, 302*403) 33 self.relu = nn.ReLU() 34 35 def forward(self, z): 36 x = self.lr(z) 37 x = self.relu(x) 38 x = self.lr2(x) 39 x = self.relu(x) 40 x = self.lr3(x) 41 x = torch.sigmoid(x) 42 return x.view(-1, 1, 302, 403) 43 44class VAE(nn.Module): 45 def __init__(self, z_dim): # クラスの初期化。Encoder クラスと Decoder クラスのインスタンスを作成。 46 super().__init__() 47 self.encoder = Encoder(z_dim) 48 self.decoder = Decoder(z_dim) 49 50 def forward(self, x): 51 z, ave, log_dev = self.encoder(x) 52 x = self.decoder(z) 53 return x, z, ave, log_dev 54 55def criterion(predict, target, ave, log_dev): 56 bce_loss = F.binary_cross_entropy(predict, target, reduction='sum') 57 kl_loss = -0.5 * torch.sum(1 + log_dev - ave**2 - log_dev.exp()) 58 loss = bce_loss + kl_loss 59 return loss 60 61# Create an instance of the VAE model 62z_dim = 2 63model = VAE(z_dim)

試したこと

main2.py_47行目

1return JSONResponse(content={"is_defective": is_defective, "anomaly_score": anomaly_score.item(), "image": image_np.tolist()})

上記コードを以下のように修正しましたが、エラーが解決しませんでした。

return JSONResponse(content={"is_defective": is_defective, "anomaly_score": anomaly_score.item(), "image": image.squeeze().permute(1, 2, 0).numpy().tolist()})

Torch.Tensor型だとJSON変換できないため、NumPy型に変換して検討していますが同じエラーが出続けております。過去の質問事例などを見ても解決できず、質問させていただいた次第です。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

json.dumpsを利用して、カスタムのJSONシリアライザ関数を定義することで解決しました。

main2.py

1def convert_to_json_serializable(obj): 2 if isinstance(obj, torch.Tensor): 3 return obj.tolist() 4 raise TypeError(f'Object of type {obj.__class__.__name__} is not JSON serializable') 5------------------------------------------------------------------------------------------------------------------------------- 6 # Serialize the response using json.dumps with custom serialization function 7 response_content = { 8 "is_defective": is_defective, 9 "anomaly_score": anomaly_score.item(), 10 "image": image_np, 11 "reconstructed_image": reconstructed_image_np, 12 } 13 json_response = JSONResponse(content=json.dumps(response_content, default=convert_to_json_serializable)) 14 15 return json_response

投稿2023/12/16 21:53

RYO777

総合スコア1

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問