braun-steven / simple-einet

An implementation of EinsumNetworks in PyTorch.
MIT License
18 stars 6 forks source link

How to conduct classification in EinsumNetworks? #1

Closed godlovxiari closed 2 years ago

godlovxiari commented 2 years ago

I have seen that ARt-SPN can be classified, and I plan to conduct the same classification in EinsumNetworks, but the training accuracy is very low, I can't find the reason, can you add its classification effect? I look forward to receiving your reply. Thank you.

braun-steven commented 2 years ago

Hey, sorry for the late reply. I've added a simple example on iris classification here. I hope this helps - let me know if you have further questions!

godlovxiari commented 2 years ago

I am very glad to receive the reply, but the training accuracy of the data set with high dimension (such as 1500 dimension) is not good. Is it possible that the SPN model cannot handle such high dimension data? I look forward to receiving your reply. Thank you.

braun-steven commented 2 years ago

Are you using the latest version of this repository? I've added some changes in this commit which fixed some issues regarding classification.

Please make sure, that you're running the latest code version. If it is still not working, feel free to provide more information about your setting (which dataset, how many classes, Einet parameters, etc.).

godlovxiari commented 2 years ago

hey, I use the latest code version for mnist dataset classification, but the results are not good, The code is as follows

!/usr/bin/env python3

from future import division from future import print_function import random import time import argparse import numpy as np import torch import torch.nn.functional as F import torch.optim as optim from tqdm import tqdm import argparse

from sklearn import datasets

from sklearn.model_selection import train_test_split from distributions import RatNormal from einet import Einet, EinetConfig import torch from utils1 import accuracy, load_mnist import os from torchvision import datasets, transforms

parser = argparse.ArgumentParser(description="PyTorch MNIST Example") parser.add_argument( "--batch-size", type=int, default=1024, metavar="N", help="input batch size for training (default: 64)", ) parser.add_argument( "--epochs", type=int, default=2000, metavar="N", help="number of epochs to train (default: 14)", ) parser.add_argument( "--lr", type=float, default=1.0, metavar="LR", help="learning rate (default: 1.0)" ) parser.add_argument("--seed", type=int, default=1, metavar="S", help="random seed (default: 1)") parser.add_argument( "--log-interval", type=int, default=10, metavar="N", help="how many batches to wait before logging training status", ) parser.add_argument( "--device", default="cuda", help="Device flag. Can be either 'cpu' or 'cuda'.", ) parser.add_argument("-K", type=int, default=10) parser.add_argument("-D", type=int, default=1) parser.add_argument("-R", type=int, default=20) args = parser.parse_args()

device = torch.device(args.device) torch.manual_seed(args.seed)

config = EinetConfig(in_features=784, D=args.D, S=args.K, I=args.K, R=args.R, C=10, leaf_base_class=RatNormal, leaf_base_kwargs={}, dropout=0.0) model = Einet(config).to(device) print("Number of parameters:", sum(p.numel() for p in model.parameters() if p.requires_grad))

optimizer = torch.optim.Adam(model.parameters(), lr=args.lr)

X_train, y_train, valid_x, valid_labels, X_test, y_test = load_mnist(data_dir='data')

X_train = torch.tensor(X_train).float().to(device) y_train = torch.tensor(y_train).long().to(device) X_test = torch.tensor(X_test).float().to(device) y_test = torch.tensor(y_test).long().to(device)

print(X_train, X_train.shape, y_train, y_train.shape)

def accuracy(model, X, y): with torch.no_grad(): outputs = model(X) predictions = outputs.argmax(-1) correct = (predictions == y).sum() total = y.shape[0] acc = correct / total * 100 return acc

cross_entropy = torch.nn.CrossEntropyLoss()

model.train() for epoch in range(args.epochs): optimizer.zero_grad()

outputs = model(X_train)
loss = cross_entropy(outputs, y_train)

loss.backward()
optimizer.step()

acc_train = accuracy(model, X_train, y_train)
acc_test = accuracy(model, X_test, y_test)
print(
    "Train Epoch: {}\tLoss: {:3.2f}\t\tAccuracy Train: {:2.2f} %\t\tAccuracy Test: {:2.2f} %".format(
        epoch,
        loss.item(),
        acc_train,
        acc_test,
    )
)

utils.py mport numpy as np import scipy.sparse as sp import torch import sys import pickle as pkl import networkx as nx from normalization import fetch_normalization, row_normalize from time import perf_counter import os

def load_mnist(data_dir): """Load MNIST"""

# save current random state
state = np.random.get_state()
np.random.seed(12345)

# make train/validation split
validation_frac = 0.1
num_valid = max(int(round(60000 * validation_frac)), 1)
rp = np.random.permutation(60000)
valid_idx = sorted(rp[0:num_valid])
train_idx = sorted(rp[num_valid:])

# restore random state
np.random.set_state(state)

fd = open(os.path.join(data_dir, 'train-images-idx3-ubyte'))
loaded = np.fromfile(file=fd, dtype=np.uint8)
train_x = loaded[16:].reshape((60000, 784)).astype(np.float32)

fd = open(os.path.join(data_dir, 'train-labels-idx1-ubyte'))
loaded = np.fromfile(file=fd, dtype=np.uint8)
train_labels = loaded[8:].reshape((60000)).astype(np.float32)

fd = open(os.path.join(data_dir, 't10k-images-idx3-ubyte'))
loaded = np.fromfile(file=fd, dtype=np.uint8)
test_x = loaded[16:].reshape((10000, 784)).astype(np.float32)

fd = open(os.path.join(data_dir, 't10k-labels-idx1-ubyte'))
loaded = np.fromfile(file=fd, dtype=np.uint8)
test_labels = loaded[8:].reshape((10000)).astype(np.float32)

train_labels = np.asarray(train_labels)
test_labels = np.asarray(test_labels)

valid_x = train_x[valid_idx, :]
valid_labels = train_labels[valid_idx]
train_x = train_x[train_idx, :]
train_labels = train_labels[train_idx]

return train_x, train_labels, valid_x, valid_labels, test_x, test_labels