def fit(self, X, y, quiet=True):
        for epoch in range(100):
            running_loss = 0
            _skf = StratifiedKFold(n_splits=10, shuffle=True)
            for more, less in _skf.split(X, y):
                # Get data and labels
                inputs = torch.from_numpy(X[more])
                labels = torch.FloatTensor(np.array([y[more]]).T * 1.0)

                # Make sure positive and negative samples have the same number
                inputs = inputs[:torch.sum(labels).type(torch.int16) * 2]
                labels = labels[:torch.sum(labels).type(torch.int16) * 2]

                # wrap them in Variable
                inputs = Variable(inputs.cuda())
                labels = Variable(labels.cuda())

                # zero the parameter gradients
                self.optimizer.zero_grad()

                # forward + backward + optimize
                outputs = self.net(inputs)
                loss = self.criterion(outputs, labels)
                loss.backward()

                self.optimizer.step()

                running_loss += loss.data

            self.scheduler.step()

            if not quiet:
                if epoch % 10 == 0:
                    print(f'Epoch {epoch}: {running_loss}')
 def predict(self, X):
     inputs = torch.from_numpy(X)
     inputs = Variable(inputs.cuda())
     return self.net(inputs)