UFPs-Deploy / model.py
Chayanat's picture
Update model.py
a52baac verified
import torch
import torch.nn as nn
import numpy as np
import json
class GRUModel(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size, dropout_rate):
super(GRUModel, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
# ชั้น GRU
self.gru = nn.GRU(
input_size=input_size,
hidden_size=hidden_size,
num_layers=num_layers,
batch_first=True,
dropout=dropout_rate if num_layers > 1 else 0
)
# ชั้น Dropout
self.dropout = nn.Dropout(dropout_rate)
# ชั้น Fully Connected สำหรับเอาต์พุตสุดท้าย
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
# กำหนดค่าเริ่มต้นของ hidden state
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
# ส่งข้อมูลผ่านชั้น GRU
out, _ = self.gru(x, h0)
# เลือกผลลัพธ์สุดท้ายจากลำดับ
out = out[:, -1, :]
# ส่งผ่านชั้น Dropout
out = self.dropout(out)
# ส่งผ่านชั้น Fully Connected
out = self.fc(out)
return out
def extract_hyperparams_from_state_dict(state_dict):
"""
วิเคราะห์ค่า hyperparameters จาก state_dict ของโมเดล
"""
hyperparams = {
'input_size': None,
'hidden_size': None,
'num_layers': 1, # ค่าเริ่มต้น
'output_size': None,
'dropout_rate': 0.1 # ค่าเริ่มต้น
}
# ตรวจหาค่า hidden_size จาก weight ของ GRU
if 'gru.weight_ih_l0' in state_dict:
# รูปแบบของ weight_ih_l0 คือ [3*hidden_size, input_size]
weight_shape = state_dict['gru.weight_ih_l0'].shape
hyperparams['hidden_size'] = weight_shape[0] // 3
hyperparams['input_size'] = weight_shape[1]
# ตรวจหาค่า output_size จาก weight ของ fully connected layer
if 'fc.weight' in state_dict:
# รูปแบบของ fc.weight คือ [output_size, hidden_size]
fc_shape = state_dict['fc.weight'].shape
hyperparams['output_size'] = fc_shape[0]
# นับจำนวนชั้นของ GRU จากชื่อของ parameter
layer_num = 0
while f'gru.weight_ih_l{layer_num}' in state_dict:
layer_num += 1
hyperparams['num_layers'] = layer_num
print(f"สกัดค่า hyperparameters จาก state_dict: {hyperparams}")
return hyperparams
def load_model(model_path, device='cpu'):
"""
โหลดโมเดล GRU จากไฟล์ .pth
Args:
model_path (str): พาธไปยังไฟล์โมเดล
device (str): อุปกรณ์ที่ใช้ ('cpu' หรือ 'cuda')
Returns:
tuple: (model, hyperparams) - โมเดลและพารามิเตอร์ของโมเดล
"""
try:
# โหลดไฟล์โมเดล
checkpoint = torch.load(model_path, map_location=device)
# ตรวจสอบโครงสร้างของไฟล์โมเดล
model_state = None
hyperparams = None
# กรณีที่ 1: ไฟล์เป็น dictionary และมี model_state_dict
if isinstance(checkpoint, dict) and 'model_state_dict' in checkpoint:
model_state = checkpoint['model_state_dict']
# ดึง hyperparameters ถ้ามี
if 'hyperparameters' in checkpoint:
hyperparams = checkpoint['hyperparameters']
# กรณีที่ 2: ไฟล์เป็น dictionary แต่ไม่มี model_state_dict
elif isinstance(checkpoint, dict) and 'hyperparameters' in checkpoint:
# สมมติว่า state_dict อยู่ในระดับบนสุด
model_state = {k: v for k, v in checkpoint.items() if k != 'hyperparameters'}
hyperparams = checkpoint['hyperparameters']
# กรณีที่ 3: ไฟล์เป็น state_dict โดยตรง
else:
model_state = checkpoint
# ถ้าไม่มี hyperparams ให้สกัดจาก state_dict
if hyperparams is None and model_state is not None:
hyperparams = extract_hyperparams_from_state_dict(model_state)
# ตรวจสอบว่ามี hyperparams ครบหรือไม่
required_params = ['input_size', 'hidden_size', 'output_size', 'num_layers', 'dropout_rate']
if not all(param in hyperparams for param in required_params):
print(f"Warning: ไม่พบ hyperparameters บางตัว จะใช้ค่าเริ่มต้น")
# กำหนดค่าเริ่มต้นสำหรับพารามิเตอร์ที่ขาดหายไป
defaults = {'input_size': 10, 'hidden_size': 64, 'output_size': 1, 'num_layers': 2, 'dropout_rate': 0.1}
for param in required_params:
if param not in hyperparams:
hyperparams[param] = defaults[param]
# สร้างโมเดล
model = GRUModel(
input_size=hyperparams['input_size'],
hidden_size=hyperparams['hidden_size'],
num_layers=hyperparams['num_layers'],
output_size=hyperparams['output_size'],
dropout_rate=hyperparams['dropout_rate']
)
# โหลด state_dict เข้าไปในโมเดล
model.load_state_dict(model_state)
# ตั้งค่าโมเดลให้อยู่ในโหมดทำนาย
model.eval()
# แสดงข้อมูลโมเดล
print(f"โหลดโมเดลสำเร็จ: input_size={hyperparams['input_size']}, hidden_size={hyperparams['hidden_size']}, "
f"num_layers={hyperparams['num_layers']}, output_size={hyperparams['output_size']}")
return model, hyperparams
except Exception as e:
print(f"เกิดข้อผิดพลาดในการโหลดโมเดล: {str(e)}")
return None, None
def save_model_info(model, hyperparams, file_path):
"""
บันทึกข้อมูลโมเดลเป็นไฟล์ JSON
"""
try:
model_info = {
"hyperparameters": hyperparams,
"structure": {
"type": "GRU",
"layers": []
}
}
# เพิ่มข้อมูลเกี่ยวกับชั้นของโมเดล
model_info["structure"]["layers"].append({
"name": "GRU",
"input_size": hyperparams["input_size"],
"hidden_size": hyperparams["hidden_size"],
"num_layers": hyperparams["num_layers"],
"dropout_rate": hyperparams["dropout_rate"]
})
model_info["structure"]["layers"].append({
"name": "Dropout",
"rate": hyperparams["dropout_rate"]
})
model_info["structure"]["layers"].append({
"name": "Linear",
"in_features": hyperparams["hidden_size"],
"out_features": hyperparams["output_size"]
})
# บันทึกเป็นไฟล์ JSON
with open(file_path, 'w') as f:
json.dump(model_info, f, indent=4)
return True
except Exception as e:
print(f"เกิดข้อผิดพลาดในการบันทึกข้อมูลโมเดล: {str(e)}")
return False