99import joblib
1010import matplotlib .pyplot as plt
1111import os
12- import zipfile
12+
13+ # Directory paths
14+ datasets_dir = 'datasets'
15+ results_dir = 'results'
16+
17+ # Ensure the results directory exists
18+ os .makedirs (results_dir , exist_ok = True )
1319
1420# Load datasets
15- train_df = pd .read_csv ('train_FD001.txt' , sep = r'\s+' , header = None )
16- test_df = pd .read_csv ('test_FD001.txt' , sep = r'\s+' , header = None )
17- rul_df = pd .read_csv ('RUL_FD001.txt' , sep = r'\s+' , header = None )
21+ train_df = pd .read_csv (os . path . join ( datasets_dir , 'train_FD001.txt' ) , sep = r'\s+' , header = None )
22+ test_df = pd .read_csv (os . path . join ( datasets_dir , 'test_FD001.txt' ) , sep = r'\s+' , header = None )
23+ rul_df = pd .read_csv (os . path . join ( datasets_dir , 'RUL_FD001.txt' ) , sep = r'\s+' , header = None )
1824
1925# Set column names
2026column_names = ['id' , 'cycle' ] + ['setting1' , 'setting2' , 'setting3' ] + ['s' + str (i ) for i in range (1 , 22 )]
3440test_df [cols_normalize ] = scaler .transform (test_df [cols_normalize ])
3541
3642# Save the scaler
37- joblib .dump (scaler , 'scaler.pkl' )
43+ joblib .dump (scaler , os . path . join ( results_dir , 'scaler.pkl' ) )
3844
3945# Dataset class
4046class TurbofanDataset (Dataset ):
@@ -55,37 +61,33 @@ def __getitem__(self, idx):
5561
5662# Definition of LSTM model
5763class LSTMModel (nn .Module ):
58-
5964 def __init__ (self , input_dim , hidden_dim , num_layers , output_dim ):
6065 super (LSTMModel , self ).__init__ ()
61- self .hidden_dim = hidden_dim # Number of features in the hidden state
62- self .num_layers = num_layers # Number of recurrent layers in the LSTM
63- self .lstm = nn .LSTM (input_dim , hidden_dim , num_layers , batch_first = True , dropout = 0.5 ) # LSTM layer
64- self .fc = nn .Linear (hidden_dim , output_dim ) # Fully connected layer for output
66+ self .hidden_dim = hidden_dim
67+ self .num_layers = num_layers
68+ self .lstm = nn .LSTM (input_dim , hidden_dim , num_layers , batch_first = True , dropout = 0.5 )
69+ self .fc = nn .Linear (hidden_dim , output_dim )
6570
6671 def forward (self , x ):
67- # Initialize hidden state and cell state with zeros
6872 h0 = torch .zeros (self .num_layers , x .size (0 ), self .hidden_dim ).to (x .device )
6973 c0 = torch .zeros (self .num_layers , x .size (0 ), self .hidden_dim ).to (x .device )
70- # Get the output from the LSTM layer
7174 out , _ = self .lstm (x , (h0 , c0 ))
72- # Pass the output of the last time step through the fully connected layer
7375 out = self .fc (out [:, - 1 , :])
7476 return out
7577
7678# Training settings
77- sequence_length = 50 # Number of time steps in each sequence (experimentally chosen)
78- input_dim = len (cols_normalize ) # Number of input features
79- hidden_dim = 128 # Number of hidden units (experimentally chosen)
80- num_layers = 3 # Number of LSTM layers (experimentally chosen)
81- output_dim = 1 # Single output for RUL prediction
79+ sequence_length = 50
80+ input_dim = len (cols_normalize )
81+ hidden_dim = 128
82+ num_layers = 3
83+ output_dim = 1
8284device = 'cuda' if torch .cuda .is_available () else 'cpu'
8385
8486# Model initialization and training settings
8587model = LSTMModel (input_dim , hidden_dim , num_layers , output_dim )
8688model = model .to (device )
8789criterion = nn .MSELoss ()
88- optimizer = optim .Adam (model .parameters (), lr = 0.0001 , weight_decay = 1e-5 ) # Adam optimizer with learning rate 0.0001 and weight decay applied to model parameters to prevent overfitting
90+ optimizer = optim .Adam (model .parameters (), lr = 0.0001 , weight_decay = 1e-5 )
8991
9092# Training data
9193train_dataset = TurbofanDataset (train_df , sequence_length )
@@ -96,16 +98,14 @@ def forward(self, x):
9698val_loader = DataLoader (val_dataset , batch_size = 32 , shuffle = False , drop_last = True , num_workers = 4 )
9799
98100# Model training
99- def train_model (model , train_loader , val_loader , criterion , optimizer , num_epochs , target_r2_score = 0.82 ): #early stopping criteria, r2 score is set to 0.82
101+ def train_model (model , train_loader , val_loader , criterion , optimizer , num_epochs , target_r2_score = 0.82 ):
100102 train_losses = []
101103 val_losses = []
102104 val_r2_scores = []
103105 early_stopping_patience = 10
104106 early_stopping_counter = 0
105107 best_val_loss = float ('inf' )
106- scheduler = optim .lr_scheduler .ReduceLROnPlateau (optimizer , 'min' , patience = 3 , factor = 0.5 ) # min': Monitoring mode, learning rate will be adjusted based on minimizing validation loss
107- #patience: Number of epochs with no improvement after which learning rate will be reduced
108- #factor: Factor by which the learning rate will be reduced. New learning rate = old learning rate * factor
108+ scheduler = optim .lr_scheduler .ReduceLROnPlateau (optimizer , 'min' , patience = 3 , factor = 0.5 )
109109
110110 for epoch in range (num_epochs ):
111111 model .train ()
@@ -117,7 +117,7 @@ def train_model(model, train_loader, val_loader, criterion, optimizer, num_epoch
117117 outputs = model (sequences )
118118 loss = criterion (outputs .squeeze (), targets )
119119 loss .backward ()
120- torch .nn .utils .clip_grad_norm_ (model .parameters (), max_norm = 1.0 ) # Maximum norm value beyond which gradients are clipped to prevent them from growing too large
120+ torch .nn .utils .clip_grad_norm_ (model .parameters (), max_norm = 1.0 )
121121 optimizer .step ()
122122 running_loss += loss .item ()
123123
@@ -150,7 +150,7 @@ def train_model(model, train_loader, val_loader, criterion, optimizer, num_epoch
150150 if val_loss < best_val_loss :
151151 best_val_loss = val_loss
152152 early_stopping_counter = 0
153- torch .save (model .state_dict (), 'model.pth' ) # Save the best model
153+ torch .save (model .state_dict (), os . path . join ( results_dir , 'model.pth' ))
154154 else :
155155 early_stopping_counter += 1
156156
@@ -165,13 +165,12 @@ def train_model(model, train_loader, val_loader, criterion, optimizer, num_epoch
165165 return train_losses , val_losses , val_r2_scores
166166
167167num_epochs = 100
168- target_r2_score = 0.82 #r2 score is set to 0.82
168+ target_r2_score = 0.82
169169train_losses , val_losses , val_r2_scores = train_model (model , train_loader , val_loader , criterion , optimizer , num_epochs , target_r2_score )
170170
171171def plot_training_history (train_losses , val_losses , val_r2_scores ):
172172 epochs = range (1 , len (train_losses ) + 1 )
173173
174- # Plotting training and validation loss
175174 plt .figure (figsize = (14 , 6 ))
176175
177176 plt .subplot (1 , 2 , 1 )
@@ -182,7 +181,6 @@ def plot_training_history(train_losses, val_losses, val_r2_scores):
182181 plt .ylabel ('Loss' )
183182 plt .legend ()
184183
185- # Plotting validation R2 score
186184 plt .subplot (1 , 2 , 2 )
187185 plt .plot (epochs , val_r2_scores , 'g-' , label = 'Validation R2 Score' )
188186 plt .title ('Validation R2 Score' )
@@ -191,18 +189,9 @@ def plot_training_history(train_losses, val_losses, val_r2_scores):
191189 plt .legend ()
192190
193191 plt .tight_layout ()
194- plt .savefig ('training_history.png' )
192+ plt .savefig (os . path . join ( results_dir , 'training_history.png' ) )
195193 plt .close ()
196194
197195plot_training_history (train_losses , val_losses , val_r2_scores )
198196
199- # Create a zip file containing model.pth and training_history.png
200- with zipfile .ZipFile ('result.zip' , 'w' ) as zipf :
201- zipf .write ('model.pth' )
202- zipf .write ('training_history.png' )
203-
204- # Cleanup
205- os .remove ('model.pth' )
206- os .remove ('training_history.png' )
207-
208- print ("Zipped the model and training history plot into result.zip" )
197+ print (f"Model and training history plot saved in '{ results_dir } '" )
0 commit comments