Commit 4f821b92 authored by PauTheu's avatar PauTheu
Browse files
parents 76a8859d 37089085
This source diff could not be displayed because it is too large. You can view the blob instead.
%% Cell type:code id:6b0d97d2 tags:
``` python
import pandas as pd
import seaborn as sns
from sklearn.metrics import confusion_matrix, accuracy_score, recall_score, precision_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.tree import DecisionTreeClassifier
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
from tqdm import trange
```
%% Cell type:markdown id:02c7a9b0 tags:
# Windturbineausfall Vorhersage
%% Cell type:code id:7911fb2a tags:
``` python
def prep_data(data):
# split data from labels
X,y = data.drop(columns=['label']), data.label
categorical = pd.DataFrame()
categorical_embedding_sizes = []
numerical = pd.DataFrame()
for column in X.columns:
# transform categorical data into numerical vector
if column == 'region':
X[column].fillna('not specified', inplace=True)
# transform text into categories
c = X[column].astype('category')
# add numerical code of categories to dataset
categorical[column] = c.cat.codes.values
# calculate number of embeddings for categorical input, max 50
categorical_embedding_sizes.append((len(c.cat.categories),
min(50, (len(c.cat.categories) + 1) // 2)))
else:
numerical[column] = X[column]
return [torch.tensor(numerical.to_numpy(), dtype=torch.float),
torch.tensor(categorical.to_numpy(), dtype=torch.int64),
categorical_embedding_sizes,
torch.tensor(y.values, dtype=torch.int64).flatten()]
```
%% Cell type:code id:5c15a7f7 tags:
``` python
class ClassificationDataSet(Dataset):
def __init__(self, dataframe):
numerical_data, self.categorical_data, self.embeddings, self.labels = prep_data(data=dataframe)
#numerical_data, self.labels = prep_data(data=dataframe)
self.scaler = MinMaxScaler()
self.numerical_data = torch.tensor(self.scaler.fit_transform(numerical_data), dtype=torch.float)
def __len__(self):
return len(self.labels)
def __getitem__(self, idx):
return {'numerical': self.numerical_data[idx],
'categorical': self.categorical_data[idx],
'label': self.labels[idx]}
#return torch.tensor(self.numerical_data[idx], self.categorical_data[idx]), self.labels[idx]
```
%% Cell type:code id:859718c5 tags:
``` python
class Classifier(nn.Module):
def __init__(self, num_numerical_columns, output_size, layers_size, embeddings_size, p=0.4):
#def __init__(self, num_numerical_columns, output_size, layers_size, p=0.4):
super().__init__()
# a list of BatchNorm1d objects for all the numerical columns
self.batch_norm_num = nn.BatchNorm1d(num_numerical_columns)
# objects for all categorical columns
self.embeddings = nn.ModuleList([nn.Embedding(ni, nf) for ni, nf in embeddings_size])
# dropout for embeddings to avoid overfitting
self.embedding_dropout = nn.Dropout(p)
num_categorical_columns = sum(nf for ni, nf in embeddings_size)
#num_categorical_columns = 0
all_layers = nn.ModuleList()
# all_layers = []
input_size = num_numerical_columns + num_categorical_columns
for i in layers_size:
all_layers.append(nn.Linear(input_size, i))
# activation function
all_layers.append(nn.ReLU(inplace=True))
#all_layers.append(nn.Tanh())
# batch normalization to the numerical columns
all_layers.append(nn.BatchNorm1d(i))
all_layers.append(nn.Dropout(p))
input_size = i
all_layers.append(nn.Linear(layers_size[-1], output_size))
all_layers.append(nn.Softmax(dim=1))
self.layers = nn.Sequential(*all_layers)
def forward(self, x_num, x_cat):
#def forward(self, x):
#def forward(self, x_num):
#x_num = x[:-1]
#x_cat= x[-1]
embs = []
x = self.batch_norm_num(x_num.float())
#x = x_num.float()
if x_cat is not None:
for i, e in enumerate(self.embeddings):
embs.append(e(x_cat[:, i].long()))
x_cat = torch.cat(embs, 1)
x_cat = self.embedding_dropout(x_cat)
x = torch.cat([x_cat, x], 1)
x = self.layers(x)
return x
```
%% Cell type:code id:337ffeb9 tags:
``` python
def train(model, train_dataloader, validation_data, epochs, lr):
aggregated_train_losses = []
aggregated_val_losses = []
aggregated_val_accs = []
optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=0.0003)
loss_function = nn.NLLLoss()
#loss_function = nn.NLLLoss()
for i in trange(epochs):
oracle.train()
train_loss = 0
for i_batch, samples in enumerate(train_dataloader):
output = model(samples['numerical'], samples['categorical'])
#output = model(samples['numerical'])
single_loss = loss_function(output, samples['label'])
train_loss += single_loss.item()
optimizer.zero_grad()
single_loss.backward()
optimizer.step()
train_loss = train_loss / len(train_dataloader)
aggregated_train_losses.append(train_loss)
oracle.eval()
with torch.no_grad():
output = oracle(validation_data.numerical_data, validation_data.categorical_data)
#output = oracle(validation_data.numerical_data)
val_loss = loss_function(output, validation_data.labels).item()
aggregated_val_losses.append(val_loss)
output = torch.argmax(output, dim=1)
val_acc = accuracy_score(validation_data.labels, output)
aggregated_val_accs.append(val_acc)
return aggregated_train_losses, aggregated_val_losses, aggregated_val_accs
```
%% Cell type:code id:f2bdcc50 tags:
``` python
#train_df = pd.read_pickle('data/train_ten_best_features.pkl')
#test_df = pd.read_pickle('data/test_ten_best_features.pkl')
#test_df = test_df.loc[test_df.label.notna()]
train_df = pd.read_pickle('data/train_selected_features.pkl')
# drop columns that are nan in test data
test_df = pd.read_pickle('data/test_ten_best_features_over_reg.pkl')
for col in test_df.columns():
test_df = pd.read_pickle('data/test_selected_features.pkl')
#test_df = test_df.loc[test_df.label.notna()]
#test_df = train_df.loc[train_df.region==18].drop(columns=['region'])
#train_df = train_df.loc[train_df.region!=18].drop(columns=['region'])
#test_df = test_df.drop(columns=['region'])
#train_df = train_df.drop(columns=['region'])
# region
#train_df = train_df.loc[train_df.region==60].drop(columns=['region'])
#test_df = test_df.drop(columns=['region'])
train_df, test_df = train_test_split(train_df, test_size=0.2, random_state=1)
train_df, val_df = train_test_split(train_df, test_size=0.2, random_state=1)
train_dataset = ClassificationDataSet(dataframe=train_df)
val_dataset = ClassificationDataSet(dataframe=val_df)
test_dataset = ClassificationDataSet(dataframe=test_df)
train_loader = DataLoader(train_dataset, batch_size=30, shuffle=True, drop_last=True)
```
%% Cell type:code id:1cbb6022 tags:
``` python
train_df.shape
```
%%%% Output: execute_result
(21288, 41)
%% Cell type:code id:927c9ce4 tags:
``` python
l1 = int(train_df.shape[1] - 1)
l2 = int(l1 ** 2)
l3 = int(l2 / 2)
l4 = int(l3 / 2)
oracle = Classifier(num_numerical_columns = train_dataset.numerical_data.shape[1],
output_size = 2,
#layers_size = [l1, l2, l3, l4],
layers_size = [train_df.shape[1] - 1, 40, 10, 5],
embeddings_size = train_dataset.embeddings,
p=0.4)
training_epochs = 100
lr = 0.0004
train_losses, val_losses, val_accs = train(oracle, train_loader, val_dataset, training_epochs, lr)
```
%% Cell type:code id:db3ef579 tags:
``` python
train_dataset.labels
```
%%%% Output: execute_result
tensor([0, 1, 0, ..., 1, 0, 1])
%% Cell type:code id:2e09221f tags:
``` python
for p, _ in oracle.named_parameters():
print(p)
```
%% Cell type:code id:2f34c976 tags:
``` python
sns.lineplot(data= train_losses, label='training loss')
sns.lineplot(data= val_losses, label='validation loss')
#sns.lineplot(data= val_accs, label='validation accuracy')
```
%%%% Output: execute_result
<AxesSubplot:>
%%%% Output: display_data
![](data:image/png;base64,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)
%% Cell type:code id:1cb5e2b3 tags:
``` python
loss_func = nn.NLLLoss()
oracle.eval()
with torch.no_grad():
y_val = oracle(test_dataset.numerical_data,
test_dataset.categorical_data)
loss = loss_func(y_val, test_dataset.labels)
out = torch.argmax(y_val, dim=1)
```
%% Cell type:code id:58fa9cbf tags:
``` python
y_val.sum(dim=0)
test_dataset.labels.sum()/len(test_dataset.labels)
```
%%%% Output: execute_result
tensor(0.4953)
%% Cell type:code id:18b5e4f3 tags:
``` python
print("Loss:", loss.item())
acc = accuracy_score(test_dataset.labels, out)
print("Accuracy:", acc)
recall = recall_score(test_dataset.labels, out)
print("Recall:", recall)
precision = precision_score(test_dataset.labels, out)
print("Precision:", precision)
```
%% Cell type:code id:cde855e6 tags:
``` python
cf_matrix = confusion_matrix(test_dataset.labels, out, normalize=None)
sns.heatmap(cf_matrix, annot=True, fmt='d')
```
%%%% Output: execute_result
<AxesSubplot:>
%%%% Output: display_data
![](data:image/png;base64,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)
%% Cell type:code id:7a0d2c30 tags:
``` python
train_df
```
%%%% Output: execute_result
Inverter INU temperature__maximum Inverter INU temperature__median \
18624 38.0 37.0
4983 66.0 64.0
7037 31.0 29.0
25838 0.0 0.0
9197 47.0 46.0
... ... ...
8247 30.0 29.0
20052 36.0 34.0
25093 41.0 37.0
18611 40.0 37.0
21907 0.0 0.0
blade 3 angle__maximum blade 3 pitch motor temperature__abs_energy \
18624 0.27 475893.0
4983 7.35 1960200.0
7037 0.49 4437335.0
25838 0.00 0.0
9197 0.59 1545564.0
... ... ...
8247 0.52 1398262.0
20052 10.56 625922.0
25093 0.24 554496.0
18611 0.30 665970.0
21907 90.86 74725.0
inverter inlet pressure__maximum \
18624 0.3
4983 0.7
7037 0.4
25838 0.0
9197 0.8
... ...
8247 0.1
20052 0.1
25093 0.2
18611 0.3
21907 0.0
inverter inlet pressure__standard_deviation \
18624 0.047979
4983 0.037661
7037 0.055476
25838 0.000000
9197 0.055319
... ...
8247 0.048412
20052 0.022701
25093 0.009502
18611 0.046817
21907 0.000000
inverter outlet pressure__abs_energy \
18624 5040.63
4983 3590.13
7037 2078.13
25838 0.00
9197 3480.96
... ...
8247 2108.54
20052 3594.13
25093 3105.68
18611 5231.48
21907 648.00
inverter outlet pressure__absolute_sum_of_changes \
18624 8.8
4983 15.6
7037 29.4
25838 0.0
9197 11.2
... ...
8247 13.2
20052 45.0
25093 228.8
18611 15.0
21907 0.0
inverter outlet pressure__maximum inverter outlet pressure__median \
18624 3.5 3.4
4983 2.9 2.8
7037 2.3 2.2
25838 0.0 0.0
9197 2.8 2.8
... ... ...
8247 2.3 2.2
20052 3.0 2.9
25093 3.7 2.5
18611 3.5 3.4
21907 1.2 1.2
... main bearing temperature 1__maximum \
18624 ... 46.6
4983 ... 62.6
7037 ... 34.3
25838 ... -8.5
9197 ... 61.6
... ... ...
8247 ... 47.3
20052 ... 57.5
25093 ... 37.4
18611 ... 64.3
21907 ... -4.5
main bearing temperature 1__median \
18624 46.6
4983 62.5
7037 33.4
25838 -8.6
9197 61.5
... ...
8247 47.2
20052 57.2
25093 36.9
18611 64.1
21907 -4.5
main bearing temperature 2__abs_energy \
18624 1066966.31
4983 1706222.52
7037 495015.15
25838 29600.70
9197 1653138.75
... ...
8247 941833.67
20052 1345442.36
25093 633424.00
18611 2024975.25
21907 9480.14
main bearing temperature 2__maximum \
18624 49.7
4983 61.6
7037 34.5
25838 -8.1
9197 61.1
... ...
8247 46.9
20052 57.0
25093 38.6
18611 67.3
21907 -4.5
main bearing temperature 2__median \
18624 49.4
4983 61.6
7037 33.7
25838 -8.1
9197 61.0
... ...
8247 46.7
20052 56.7
25093 37.9
18611 67.1
21907 -4.6
reactive power control status__abs_energy region \
18624 437.0 49
4983 450.0 15
7037 437.0 18
25838 449.0 60
9197 444.0 20
... ... ...
8247 431.0 20
20052 3762.0 52
25093 3969.0 57
18611 450.0 49
21907 450.0 55
wind tower ambient temperature__abs_energy \
18624 120973.96
4983 219862.51
7037 158461.85
25838 107872.25
9197 170008.61
... ...
8247 157455.60
20052 101724.48
25093 57379.94
18611 163326.89
21907 41153.03
wind tower ambient temperature__maximum \
18624 16.8
4983 22.3
7037 19.1
25838 -15.5
9197 19.7
... ...
8247 19.3
20052 15.6
25093 11.5
18611 19.3
21907 -9.5
wind tower ambient temperature__median
18624 16.6
4983 22.1
7037 19.0
25838 -15.5
9197 19.6
... ...
8247 19.1
20052 15.6
25093 11.4
18611 19.0
21907 -9.6
[21288 rows x 22 columns]
%% Cell type:markdown id:3342901f tags:
# Region Vorhersage
%% Cell type:code id:d01750f1 tags:
``` python
# find region similarity
region_data = pd.read_pickle('data/train_selected_features.pkl')
X = region_data.drop(columns=['region'])
y = region_data.region
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 0)
dtree_model = DecisionTreeClassifier(max_depth = 10).fit(X_train, y_train)
dtree_predictions = dtree_model.predict(X_test)
accuracy_score(y_test, dtree_predictions)
```
%%%% Output: execute_result
1.0
%% Cell type:code id:881a4604-4f0c-48ad-a438-6a38c528251c tags:
``` python
region_data = pd.read_pickle('data/train_selected_features.pkl')
region_data_sample = pd.DataFrame()
n_samples = 12
for reg in region_data.region.unique():
print(reg)
reg_data_0 = region_data.loc[(region_data.region == reg) & (region_data.label == 0)]
print(len(reg_data_0))
reg_data_1 = region_data.loc[(region_data.region == reg) & (region_data.label == 1)]
print(len(reg_data_1))
region_data_sample = region_data_sample.append(reg_data_0.sample(n=n_samples))
region_data_sample = region_data_sample.append(reg_data_1.sample(n=n_samples))
X = region_data_sample.append(reg_data_0).drop(columns=['region'])
y = region_data_sample.append(reg_data_0).region
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 0)
```
%% Cell type:code id:9e8240dd-4119-4e9d-9f6a-13b6f30b36eb tags:
``` python
region_data_sample
```
%%%% Output: execute_result
Aircraft weather station wind speed__abs_energy \
7459 14957.07
7715 2835.32
7372 22540.88