実現したいこと
-
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/ツールのバージョンなど)
ここにより詳細な情報を記載してください。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。