sukhmani1303 commited on
Commit
2abfc42
·
verified ·
1 Parent(s): 8dda8f7

Upload inference.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. inference.py +37 -20
inference.py CHANGED
@@ -31,46 +31,63 @@ class ImprovedCashFlowLSTM(nn.Module):
31
  forecast = self.output_layers(last_hidden)
32
  return forecast
33
 
34
- def load_model_and_artifacts(model_path="new_best_improved_model.pth", scaler_path="scaler.pkl", feature_names_path="feature_names.json"):
35
- if not all(os.path.exists(path) for path in [model_path, scaler_path, feature_names_path]):
36
- raise FileNotFoundError("One or more artifact files are missing")
 
 
 
 
 
 
 
 
 
37
 
38
  with open(scaler_path, "rb") as f:
39
  scaler = pickle.load(f)
 
40
  with open(feature_names_path, "r") as f:
41
  feature_names = json.load(f)
42
 
43
- input_size = len(feature_names)
44
- model = ImprovedCashFlowLSTM(input_size=input_size)
 
 
 
 
 
 
45
  model.load_state_dict(torch.load(model_path, map_location=torch.device("cpu")))
46
  model.eval()
47
- return model, scaler, feature_names
48
 
49
- def forecast(model, scaler, sequences):
50
  device = torch.device("cpu")
51
  model.to(device)
52
 
53
  # Validate input shape: (batch_size, sequence_length=21, n_features=20)
54
- if sequences.shape[1] != 21 or sequences.shape[2] != model.lstm.input_size:
55
- raise ValueError(f"Invalid input shape. Expected (batch_size, 21, {model.lstm.input_size}), got {sequences.shape}")
56
 
 
57
  sequences = torch.tensor(sequences, dtype=torch.float32).to(device)
58
 
59
  # Generate predictions
60
  with torch.no_grad():
61
- predictions = model(sequences).cpu().numpy()
62
 
63
- # Inverse transform predictions (sales only)
64
- dummy = np.zeros((predictions.shape[0], scaler.n_features_in_))
65
- dummy[:, 0] = predictions[:, 0]
66
- rescaled = scaler.inverse_transform(dummy)
67
- predictions = rescaled[:, 0].reshape(-1, 13)
68
 
69
- # Clip predictions to realistic range based on training data
70
- predictions = np.clip(predictions, 3000, 20000)
 
71
 
72
- # Simplified uncertainty estimation
73
- uncertainties = np.std(predictions, axis=1, keepdims=True) + 100
74
  uncertainties = np.clip(uncertainties, 100, 500)
75
 
76
- return predictions, uncertainties
 
31
  forecast = self.output_layers(last_hidden)
32
  return forecast
33
 
34
+ def load_model_and_artifacts(
35
+ model_path="new_best_improved_model.pth",
36
+ scaler_path="scaler.pkl",
37
+ feature_names_path="feature_names.json",
38
+ config_path="model_config.json"
39
+ ):
40
+ if not all(os.path.exists(path) for path in [model_path, scaler_path, feature_names_path, config_path]):
41
+ missing = [path for path in [model_path, scaler_path, feature_names_path, config_path] if not os.path.exists(path)]
42
+ raise FileNotFoundError(f"Missing files: {missing}")
43
+
44
+ with open(config_path, "r") as f:
45
+ config = json.load(f)
46
 
47
  with open(scaler_path, "rb") as f:
48
  scaler = pickle.load(f)
49
+
50
  with open(feature_names_path, "r") as f:
51
  feature_names = json.load(f)
52
 
53
+ input_size = config["input_size"]
54
+ model = ImprovedCashFlowLSTM(
55
+ input_size=input_size,
56
+ hidden_size=config["hidden_size"],
57
+ num_layers=config["num_layers"],
58
+ forecast_horizon=config["forecast_horizon"],
59
+ dropout=config["dropout"]
60
+ )
61
  model.load_state_dict(torch.load(model_path, map_location=torch.device("cpu")))
62
  model.eval()
63
+ return model, scaler, feature_names, config
64
 
65
+ def predict(model, scaler, sequences):
66
  device = torch.device("cpu")
67
  model.to(device)
68
 
69
  # Validate input shape: (batch_size, sequence_length=21, n_features=20)
70
+ if len(sequences.shape) != 3 or sequences.shape[1] != 21 or sequences.shape[2] != model.lstm.input_size:
71
+ raise ValueError(f"Expected input shape (batch_size, 21, {model.lstm.input_size}), got {sequences.shape}")
72
 
73
+ # Convert to tensor
74
  sequences = torch.tensor(sequences, dtype=torch.float32).to(device)
75
 
76
  # Generate predictions
77
  with torch.no_grad():
78
+ predictions = model(sequences).cpu().numpy() # Shape: (batch_size, 13)
79
 
80
+ # Inverse transform predictions (sales is first feature)
81
+ dummy = np.zeros((predictions.shape[0] * predictions.shape[1], scaler.n_features_in_))
82
+ dummy[:, 0] = predictions.flatten()
83
+ rescaled = scaler.inverse_transform(dummy)[:, 0].reshape(predictions.shape)
 
84
 
85
+ # Ensure non-negative predictions and clip to training range
86
+ rescaled = np.maximum(rescaled, 0)
87
+ rescaled = np.clip(rescaled, 3000, 19372) # Training sales range: $3069–19372
88
 
89
+ # Estimate uncertainty (simplified: std of predictions + base uncertainty)
90
+ uncertainties = np.std(rescaled, axis=1, keepdims=True) + 100
91
  uncertainties = np.clip(uncertainties, 100, 500)
92
 
93
+ return rescaled, uncertainties