text: import os
  import sys
  import argparse
  import tensorly as tl
  import numpy as np
  import copy
  from sklearn.linear_model import LogisticRegression
  from imblearn.pipeline import Pipeline
  from sklearn.preprocessing import StandardScaler
  from sklearn.metrics import f1_score
  from sklearn.metrics import accuracy_score
  
  sys.path.insert(0, os.path.join(
      os.path.dirname(os.path.realpath(__file__)), "../"))
  
  import utils.dataloading as dataloading
  
  
  def one_NN(Z_train, Z_test, y_train, y_test):
      y_preds = []
      for z_test in Z_test:
          smallest_dist = np.infty
          prediction = -1
  
          for z, label in zip(Z_train, y_train):
              dist = tl.norm(z - z_test).item()
              if dist < smallest_dist:
                  smallest_dist = dist
                  prediction = label
  
          y_preds += [int(prediction)]
  
      acc = (y_preds==tl.to_numpy(y_test)).mean()
      print(acc)
      return acc
  
  
  class MPCA():
      def __init__(self, rank, total_iters):
          self.rank = rank
          self.total_iters = total_iters
  
      def fit(self, x_train, y_train, x_test, y_test):
  
          print("Training MPCA")
          x_train = tl.tensor(x_train)
  
          self.mean_tensor = tl.mean(x_train, axis=0)
          x_train = x_train - self.mean_tensor
  
          num_modes = len(x_train.shape) - 1
          print("Number of modes: {}".format(num_modes))
  
          metrics = []
          its = []
  
          # initialise the factor matrices
          self.factors = [tl.ones((dim, self.rank)) for i, dim in enumerate(list(x_train.shape)[1:])]
          metrics += [self.compute_metric(x_train, x_test, y_train, y_test)]
          its += [0]
          best_factors = []
          best_score = -1
          for t in range(1, self.total_iters + 1):
              print("Iteration {}".format(t))
              for k in range(num_modes):
                  scatter = self.compute_modek_total_scatter(k, x_train)
                  U, _, _ = tl.partial_svd(scatter, n_eigenvecs=self.rank, random_state=42)
                  self.factors[k] = U
              metrics += [self.compute_metric(x_train, x_test, y_train, y_test)]
              if metrics[-1] > best_score:
                  best_factors = copy.deepcopy(self.factors)
              its += [t]
  
          print('...done')
          print('best metric for validation is {} at iteration {}. '.format(
              np.max(np.array(metrics)), its[np.argmax(np.array(metrics))]))
          self.factors = best_factors
  
      def transform(self, x):
          x = tl.tensor(x)
          x = x - self.mean_tensor
          modes = [idx + 1 for idx in range(len(x.shape))]
          return tl.tenalg.multi_mode_dot(x, self.factors, modes=modes, transpose=True)
  
      def embedding(self, x):
          x_transformed = self.transform(x)
          return tl.unfold(x_transformed, mode=0)
  
      def compute_modek_total_scatter(self, mode, x):
          scatter = 0
  
          for m in range(len(x)):
              proj_but_k = tl.unfold(
                  tl.tenalg.multi_mode_dot(
                      x[m], self.factors, transpose=True, skip=mode), mode)
              scatter += tl.dot(proj_but_k, proj_but_k.T)
  
          return scatter
  
      def compute_metric(self, x_train, x_test, y_train, y_test):
          z_train = self.embedding(x_train)
          z_test = self.embedding(x_test)
  
          # return one_NN(Z_train, Z_test, y_train, y_test)
          clf = LogisticRegression(random_state=42, max_iter=10000)
          clf.fit(z_train, y_train)
  
          preds = clf.predict(z_test)
          acc_2 = accuracy_score(y_test, preds)
          f1_binary = f1_score(y_test, preds, average='weighted')
          print("(accuracy, f1) = ({}, {})".format(acc_2, f1_binary))
  
          return f1_binary
  
  
  def train_mpca(dataset_name, rank, total_iters=5):
      tl.check_random_state(42)
      np.random.seed(42)
  
      dataset = dataloading.dataset_features(dataset_name)
  
      x_train, y_train, x_val, y_val, x_test, y_test = dataloading.classification_dataset(
          dataset_name, dataset, 0)
  
      mpca = MPCA(rank=rank, total_iters=total_iters)
      mpca.fit(x_train, y_train, x_val, y_val)
      x_train = np.concatenate((x_train, x_val))
      y_train = y_train + y_val
      print("Results on test set:")
      mpca.compute_metric(x_train, x_test, y_train, y_test)
      return mpca
  
  
  if __name__ == "__main__":
  
      parser = argparse.ArgumentParser()
      parser.add_argument('-d',
                          '--dataset',
                          type=str,
                          required=True,
                          help='Dataset (eg. cmumosei, cmumosi, iemocap)'
                          )
      parser.add_argument(
          '-r',
          '--rank',
          type=int,
          required=True,
          help='Rank of MPCA')
      parser.add_argument('-i',
                          '--total_iters',
                          type=int,
                          required=False,
                          default=5,
                          help='Number of MPCA iterations')
  
      args = parser.parse_args()
      train_mpca(args.dataset, args.rank, args.total_iters)