<jupyter_start><jupyter_text><jupyter_code># -*- coding: utf-8 -*-
"""BiLSTM_Classification_Draft.ipynb

"""

import numpy as np
import pickle
import torch
import torch.nn as nn
import torch.nn.utils.rnn as rnn_utils
from torch.utils.data import DataLoader
from torch.utils.data import Dataset
from torch.utils.data.sampler import SubsetRandomSampler

# parameters: 8 for force, 12 for force & light
nFeatrue = 8

# check if "nFeatrue" is defined 
try:
  nFeatrue
except NameError:
  print("well, nFeatrue WASN'T defined after all!")
else:
  print("sure, nFeatrue was defined.")
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print("cuda :", torch.cuda.is_available())

# inherited from class Dataset
class SensorDataset(Dataset):

  def __init__(self, Data, Label):
    self.Data = Data
    self.Label = Label

  def __len__(self):
    return len(self.Data)

  def __getitem__(self, index):
    data = torch.Tensor(self.Data[index]).to(device)
    label = torch.cuda.LongTensor([self.Label[index]]).to(device)
    # print(self.Label[index], type(self.Label[index]))
    return (data, label)

# collate_fn for the datalaoder 
def my_collate(data):
  data.sort(key=lambda x: len(x[0]), reverse=True)
 
  context = [ i[0] for i in data ]
  label = [ i[1] for i in data ]
  # print(label)
  label = torch.cuda.LongTensor(label)
  data_length = [len(i)/nFeatrue for i in context]
  padded_context = rnn_utils.pad_sequence(context, batch_first=True, padding_value=0)
  # final_data = [[a,b] for a,b in zip(padded_context, label)]
  # final_data = torch.FloatTensor(final_data)
  
  return (padded_context, label), data_length

# load DATA
open_file = open('TrainForce.pkl', "rb")
TrainForce = pickle.load(open_file)
open_file.close()

open_file = open('TrainLabel.pkl', "rb")
TrainLabel = pickle.load(open_file)
open_file.close()

open_file = open('ValForce.pkl', "rb")
ValForce = pickle.load(open_file)
open_file.close()

open_file = open('ValLabel.pkl', "rb")
ValLabel = pickle.load(open_file)
open_file.close()

# print(ValLabel)

"""# 提示: **数据按以下格式存储**

[

[s1[0],...,sn[0],s1[1],...,sn[1], ..., s1[t1],...,sn[t1]],

[s1[0],...,sn[0],s1[1],...,sn[1], ..., s1[t2],...,sn[t2]],

[s1[0],...,sn[0],s1[1],...,sn[1], ..., s1[t3],...,sn[t3]],

...

]
"""


train_dataset = SensorDataset(TrainForce, TrainLabel)
val_dataset = SensorDataset(ValForce, ValLabel)
train_dataloader = DataLoader(train_dataset, batch_size=16, collate_fn=my_collate, shuffle=True)
validation_dataloader = DataLoader(val_dataset, batch_size=16, collate_fn=my_collate)

# BiLSTM Model

class RNN(nn.Module):
  def __init__(self, input_size, hidden_size, num_layers, num_classes, if_bidirectional):
    super(RNN, self).__init__()
    self.num_layers = num_layers
    self.hidden_size = hidden_size
    self.if_bidirectional = if_bidirectional
    self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True, bidirectional=if_bidirectional)

    if if_bidirectional == True:
      self.fc = nn.Linear(hidden_size * 2, num_classes)
    else:
      self.fc = nn.Linear(hidden_size, num_classes)
    

  def forward(self, x):
    D = 2 if self.if_bidirectional == True else 1
    Batch = x.batch_sizes[0]

    h0 = torch.zeros(D * self.num_layers, Batch, self.hidden_size).to(device)  
    c0 = torch.zeros(D * self.num_layers, Batch, self.hidden_size).to(device) 
    x.to(device)
    _, (h_n, _) = self.lstm(x, (h0, c0))
    final_state  = h_n.view(self.num_layers, D, Batch, self.hidden_size)[-1]     # num_layers, num_directions, batch, hidden_size

    if D == 1:
      X = final_state.squeeze()
    elif D == 2: 
      h_1, h_2 = final_state[0], final_state[1]  # forward & backward pass
      #X = h_1 + h_2                # Add both states
      X = torch.cat((h_1, h_2), 1)         # Concatenate both states, X-size: (Batch, hidden_size * 2）

    output = self.fc(X) # fully-connected layer

    return output

      
model = RNN(input_size = nFeatrue, hidden_size = 8, num_layers = 3, num_classes = 18, if_bidirectional = True).to(device)
loss_func = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.02)
scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.95)

print(model)

# training 
for ep in range(50):
  train_correct = 0
  train_total = 0
  val_correct = 0
  val_total = 0
  for (x, y), length in train_dataloader: 
    batch_size = x.shape[0]
    v = x.view(batch_size, -1, nFeatrue)
    data = rnn_utils.pack_padded_sequence(v.type(torch.FloatTensor), length, batch_first=True).to(device)
    # print(data.batch_sizes[0])
    # print(data)
    out = model(data)
    loss = loss_func(out, y) 
    # print(loss)

    optimizer.zero_grad()   # clear gradients for next train
    loss.backward()         # backpropagation, compute gradients
    optimizer.step()        # apply gradients
    
    predicted = torch.max(torch.nn.functional.softmax(out), 1)[1]
    train_total += y.size(0)
    train_correct += (predicted == y).sum().item()

    
  scheduler.step()
  

  for (x, y), length in validation_dataloader: 
    batch_size = x.shape[0]
    v = x.view(batch_size, -1, nFeatrue)
    data = rnn_utils.pack_padded_sequence(v.type(torch.FloatTensor), length, batch_first=True).to(device)
    out = model(data)
    loss = loss_func(out, y)     
    
    predicted = torch.max(torch.nn.functional.softmax(out), 1)[1]
    val_total += y.size(0)
    val_correct += (predicted == y).sum().item()

  print("epoch: ", ep + 1, 'Accuracy of the Train: %d %%' % (100 * train_correct / train_total), 'Accuracy of the Test: %d %%' % (100 * val_correct / val_total))

# # save model net
filename = "aaa.pkl"
torch.save(model, filename)

# # test 
# net2 = torch.load("net.pkl")
# for (x, y), length in train_dataloader:  
#     batch_size = x.shape[0]
#     v = x.view(batch_size, -1, nFeatrue)
#     data = rnn_utils.pack_padded_sequence(v.type(torch.FloatTensor), length, batch_first=True)
#     # print(data.batch_sizes[0])
#     # print(data)
#     out = net2(data)
#     loss = loss_func(out, y) 
#     # print(loss)

#     optimizer.zero_grad()   # clear gradients for next train
#     loss.backward()         # backpropagation, compute gradients
#     optimizer.step()        # apply gradients
#     print("predict: ", torch.max(torch.nn.functional.softmax(out), 1)[1])
#     print("ground_truth ", y )
    

GT = []
Pred = []
val_total = 0
val_correct = 0

for (x, y), length in train_dataloader: 
  batch_size = x.shape[0]
  v = x.view(batch_size, -1, nFeatrue)
  data = rnn_utils.pack_padded_sequence(v.type(torch.FloatTensor), length, batch_first=True).to(device)
  out = model(data)
  loss = loss_func(out, y)     
  
  predicted = torch.max(torch.nn.functional.softmax(out), 1)[1]
  GT += y
  Pred += predicted
  val_total += y.size(0)
  val_correct += (predicted == y).sum().item()
print("acuracy: ", val_correct / val_total) 
import pandas as pd
px = pd.DataFrame(Pred)
px.columns = ["Pred"]
py = pd.DataFrame(GT)
py.columns = ["GT"]
pc = pd.concat([px, py], axis=1)
pc.head()
import matplotlib.pyplot as plt
import seaborn as sns

count = np.zeros([18, 18])
for item in zip(GT, Pred):
  i = int(item[0])
  j = int(item[1])
  count[i][j] += 1

Index = ['F0Ball',
 'F1Bag',
 'F2LipGel',
 'F3ElasticCylinder',
 'F4Tissue',
 'F5Bottle',
 'F6Battery',
 'F7MakerPen',
 'F8Potato',
 'F9Poker',
 'F10Tape',
 'F11Banana',
 'F12Lime',
 'F13ChewingGum',
 'F14Stone',
 'F15SolidGlue',
 'F16DesinfektionHandGel',
 'F17Egg']
Cols = Index
df = pd.DataFrame(data=count, index=Index, columns=Cols)

sns.heatmap(df, annot=True)


df<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15302771574937607, 'fraction_numerical': 0.01878365952975174, 'mean_word_length': 3.8776425368353618, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '275326', 'license': 'MIT', 'n_tokens_mistral': 3013, 'n_tokens_neox': 2911, 'n_words': 596, 'path': 'BiLSTMCuda_pynb.ipynb', 'repo_name': 'popnut123/PoseCNN', 'size': '7613'}