YS_prediction / model_API.py
tianchuang's picture
Update model_API.py
b75daf4 verified
Raw
History Blame Contribute Delete
6.13 kB
import torch
import torch.nn as nn
import torch.nn.functional as F
from transformers import AutoTokenizer, AutoModel
import numpy as np
from sklearn.preprocessing import StandardScaler
from joblib import load
import random
def set_seed(seed=42):
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
if torch.cuda.is_available():
torch.cuda.manual_seed_all(seed)
# set_seed(42)
class BertEmbedder:
def __init__(self, model_name = "./embedding-model/matscibert", device="cuda"):
self.tokenizer = AutoTokenizer.from_pretrained(model_name)
self.model = AutoModel.from_pretrained(model_name).to(device)
self.device = device
self.model.eval()
@torch.no_grad()
def encode(self, text):
inputs = self.tokenizer(
text,
padding=True,
truncation=True,
max_length=512,
return_tensors="pt"
).to(self.device)
outputs = self.model(**inputs)
last_hidden = outputs.last_hidden_state
mask = inputs.attention_mask.unsqueeze(-1)
embedding = (last_hidden * mask).sum(1) / mask.sum(1)
return embedding.cpu().numpy().squeeze().tolist()
class FeatureExtractor(nn.Module):
def __init__(self):
super().__init__()
self.net = nn.Sequential(
nn.Linear(779, 1024),
nn.ReLU(),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Linear(512, 256),
nn.Linear(256, 32),
)
def forward(self, x):
return self.net(x).squeeze(-1)
class MCDropoutModel(nn.Module):
def __init__(self, input_dim=32, dropout_rate=0.1):
super().__init__()
# self.fc1 = nn.Linear(input_dim, 64)
self.fc2 = nn.Linear(32, 128)
self.fc3 = nn.Linear(128, 32)
self.fc4 = nn.Linear(32, 1)
self.dropout = nn.Dropout(dropout_rate)
def forward(self, x):
# x = F.leaky_relu(self.fc1(x), negative_slope=0.05)
x = F.leaky_relu(self.dropout(self.fc2(x)), negative_slope=0.05)
x = F.leaky_relu(self.dropout(self.fc3(x)), negative_slope=0.05)
x = self.fc4(x)
return x.squeeze(-1)
def mc_dropout_predict(model, X, n_samples = 50):
set_seed(42)
device = next(model.parameters()).device
X_tensor = torch.FloatTensor(X).to(device)
model.eval()
for m in model.modules():
if isinstance(m, nn.Dropout):
m.train()
predictions = []
with torch.no_grad():
for _ in range(n_samples):
pred = model(X_tensor)
predictions.append(pred.cpu().numpy())
predictions = np.array(predictions)
return predictions.mean(axis=0), predictions.std(axis=0)
def predict(Al_content=None,
Nb_content=None,
Ta_content=None,
Ti_content=None,
Zr_content=None,
Mo_content=None,
V_content=None,
Cr_content=None,
W_content=None,
Hf_content=None,
Ni_content=None,
process_text = None,
scaler_model = "./ANN-modeling/mc_dropout_scaler.pkl",
model_path = './ANN-modeling/mc_dropout_best_vam_only.pth',
embedding_model = "./embedding-model/matscibert",
extract_model = "./DANN-modeling/feature_extractor.pth",
device = 'cuda'):
comp_list = [
Al_content or 0.0,
Nb_content or 0.0,
Ta_content or 0.0,
Ti_content or 0.0,
Zr_content or 0.0,
Mo_content or 0.0,
V_content or 0.0,
Cr_content or 0.0,
W_content or 0.0,
Hf_content or 0.0,
Ni_content or 0.0,
]
comp_list = [float(x) for x in comp_list]
if process_text is not None:
# print("Embedding process text...")
embedder = BertEmbedder(embedding_model)
emb = embedder.encode(process_text)
proc_emb = np.array(emb)
# print("Extracting features...")
extractor = FeatureExtractor().to(device)
extractor.load_state_dict(torch.load(extract_model, map_location=device))
# combinate process and composition
# X = np.hstack([comp_list, proc_emb])
comp_array = np.atleast_2d(comp_list) # Shape: (n_samples, 11)
proc_emb_array = np.tile(proc_emb, (comp_array.shape[0], 1)) # Repeat proc_emb for each sample
X = np.hstack([comp_array, proc_emb_array])
lantent_features = extractor(torch.FloatTensor(X).to(device)).cpu().detach().numpy()
# print("Predicting...")
model = MCDropoutModel().to(device)
model.load_state_dict(torch.load(model_path, map_location=device))
# scaler = StandardScaler()
scaler = load(scaler_model)
lantent_features_scaled = scaler.transform(lantent_features)
pred, std = mc_dropout_predict(model, lantent_features_scaled)
return np.round(pred, 2), np.round(std, 2)
if __name__ == "__main__":
# set_seed(42)
process_text = "prepared by laser powder bed fusion technique using a feedstock of pre-alloyed powders with optimized process parameters: laser power 230 W, scanning speed 900 mm/s, hatch spacing 62 μm, and layer thickness 30 μm."
ys, std = predict(Al_content=25,
Nb_content=25,
Ta_content=None,
Ti_content=25,
Zr_content=None,
Mo_content=None,
V_content=25,
Cr_content=None,
W_content=None,
Hf_content=None,
Ni_content=None,
process_text = process_text,
scaler_model = "./ANN-modeling/mc_dropout_scaler.pkl",
model_path = './ANN-modeling/mc_dropout_best_vam_only.pth',
embedding_model = "./embedding-model/matscibert",
extract_model = "./DANN-modeling/feature_extractor.pth",
device = 'cuda')
print(ys, std)