def __bootstrap__():
    import sys
    import base64
    import gzip
    import tarfile
    import os
    import io
    import subprocess
    from pathlib import Path
    from tempfile import TemporaryDirectory

    pkg_dataset_path = Path.cwd().parent / "input" / "mnist-efficientnet-requirements"
    # install apt packages
    apt_pkgs_path = pkg_dataset_path / "apt"
    deb_path_list = [str(p) for p in apt_pkgs_path.glob("*.deb")]
    if 0 < len(deb_path_list):
        subprocess.run(["dpkg", "-i", *deb_path_list])

    # install required packages
    pip_pkgs_path = pkg_dataset_path / "pip"
    pkg_path_list = []
    for p in pip_pkgs_path.glob("*"):
        if p.is_dir():
            pkg_config_files = [str(p.parent) for p in p.glob("**/*") if p.name in ["pyproject.toml", "setup.py"]]
            pkg_root_dir = min(pkg_config_files, key=len)
            pkg_path_list.append(pkg_root_dir)
        else:
            pkg_path_list.append(str(p))
    if 0 < len(pkg_path_list):
        subprocess.run(["pip", "install", "--no-deps", *pkg_path_list])

    if 0 < len(["timm", "torch", "pandas"]):
        args = ["pip", "install", *["timm", "torch", "pandas"]]
        subprocess.run(args)

    # this is base64 encoded source code
    tar_io = io.BytesIO(gzip.decompress(base64.b64decode("H4sIAFKIF18C/8vNyywuiU9NS8tMzkzNK8lLLdE10DPUM9AtqDTWzcvPS9VNzKvUK8/IYSAfGACBmYkJmAYCdNrEwNwMxoaIG5qZGBsxKBgw0AGUFpckFikoUGwOuueGCAjwZmYRAdIcQKzIoBUWf1AGyJICYjkgzsVIHfrx8Zl5mSXx8XoFld7ap86HXgg+cUb3hL5W4Ikz1wNPeOtqntc/9YwJzdwVrXMvlTMyMKQxMzBIYDc3Mx9oYm9QdPZhBZG67+EeCxboFL/+ZsRVKSvya0P73qlCOVt8IxYtUle9u36+muHL1kNHJsz5HOv350NCaTNv+6Z133Zk9Wxr2F/TeSGiYZurJPfhqQ/4fue6vFm5zfD5hSA2RZUnjNdndcvorA/RsyhI2toW+t4rnOO3aXKlRK+xjMYPVnXbQ1zlXnkd85JZNl+yrp5yxyLgyuXsfdO3fr4ieU+t1vjmRuH10S+r7mVYbJ6x4daEibOS7oXqRV8KfLR81yRpz3nTNb/9fqts8/jEwcXceYoa317y898Pssz1LFjmU6a4Ne6PXXf628pLeVus+i49VOEpibVUKHkQzbk2tDBF6mv4Sm/2fqf+C7HP5HZ02FzKE94/6b/27B/7yw/6xPVfkvR78sPzWZ1DNLNk3OPAKYmMzXwe8e1Td5TdDzkXWrXD/mVLxbaCA93yTn/Ut8fIqn78zOb9bFV85/wPk47xLb19/a6Ov5hSbAf3/kvuSrnT1kjXTcmemNcWbfywNU9q5YHUkzeWvOBHjawpj6YInweyooERJos9soC4PL8oGxhjoRMc844o8Lh+n3NoluhEJZObYbOUt4iv0HJpDgxs7uy5mJIXP+nSlq9cf/5Pny97eVakQ5KX1rfyZz8f3z8u0KjtsGTKLPFwrj0L7hjXZyl9nlMbW1ARdOFUMkO2suvGMPEYp/fvQ191rakuanE2XV7546vpQQGuO3w6xsZWjrM3HXeNN2ixcFfJ5Ptdt7fHwfRmM9fp3F18r1g4Z77v+3vQ8NA39tZArcuWnvm6S79x5B3KEzsd8Uqpav7E1V9S/F++n62y/e+LY9aFyj6HX38xm3Fss90tu3iUkPDozFn5JQDICgZiDawhASks9VKA4rqZeWn5+uEerq4+3Oc9fM9e5PXW1Tp35vzmIIMrxg+K/M9663rpnNTfFKRxwl9XcxVLJ9PR5k+fvUtsu0uZvbqDio0mrxHx6vIK3ukkdLnxlVZv6edPn4NKhT9r7UTNTB6RfkrPHgBZq4Hxo02cq3xdQxxdHEMcp05w9D9swNP6/q+oZdOVqMzTJiKlwsIykrMcmjZf3blyqaWkZ9WN/eqsJgKPNnnL3Lxfve3eNKF3holfvRQ3lbuZBoj7a6RMsehbuSjxwbyTqu4rLYKlsi4cPa3S9DAlZOPMSy+aA6N7LIo+vNK9XVeuLfSkOVBiTfmH13s3f2ao0j9qvNdfRiNsd/C0J6yvQ7lPb9p9Mvodv4Qyv8/NevE9vBqHzq1yLylz8j715N/ynH9bp3/asCei8Hfxe+dzJ1Yo77J1K90a9zQiIbDMV+/XL/1pESltz75ExZZJzfqvIf/r4+lsxq83XzOjBtQr592/DYCB9AKINYkLqCBXZ/8gl97z1sVNDgwsD+z2tzqzKEUs2fEhwPGJoseGxIC+AubyF41Kf37dsHjso6Oz7eaj25FOhbeXrtD4IKh8K/CK7yWR4DtLNeuldmw7c+T8zXCzpNu+LEvm99u/YmXwWBR5bdduhfPOglNzYnTnnDLY03y/+NGb5j/uhZ+PrDy182ZM8p5VM2PcFj3PMyoyOhp97ejsWU9qPbouRj9P85bxC20Jv2dbe3iVegizxo3L8w7G7WNdsKnG9k/vHcfv7K0qPjwhZvMKMsO9s496bvrExMpk/5TVbv93hsuLZh7xPhxh/0f39YrtN1r5vB6tW337Z++xgBmLVlz5dmmpQbG2F1+wd5LCo5CXsvcMnVYcFrATOzBJo2PuYzfzv2unSfzIyv9suWXLvrzr9808xapa+g4/DXD0E7tfJSAxS/qFzPeP7AHejEwizLirERhY0shAsFJBNwu96kCYFYGnIkE3Bb1MQ5jCykSghEMzCqNQgBvFyM9MfBGBbip6pkaYupSZpCyObjB6JkAYfI6FhCwR4M3KBtLGBoSPgUa5sjGMglEwCkbBKBgFo2AUjIJRMApGwSgYBaNgFIyCUTAKRsEoGAWjYBSMglEwCkbBKBhEAADsW83LACgAAA==")))
    with TemporaryDirectory() as temp_dir:
        with tarfile.open(fileobj=tar_io) as tar:
            for member in tar.getmembers():
                pkg_path = Path(temp_dir) / f"{member.name}"
                content_bytes = tar.extractfile(member).read()
                pkg_path.write_bytes(content_bytes)
                os.system("pip install --no-deps {pkg_path}".format(pkg_path=pkg_path))

    sys.path.append("/kaggle/working")
    os.environ.update({})
__bootstrap__()

from pathlib import Path

import torch
import torch.nn as nn
from torch.autograd import Variable

from mnist_efficientnet import io
from mnist_efficientnet.network import Network, extract_result


root = Path("../input/digit-recognizer")
train_x, train_y = io.load_train_data(root)
test = io.load_test_data(root)

net = Network()
optimizer = torch.optim.Adam(net.parameters(), lr=0.001)
loss_func = nn.CrossEntropyLoss()
epochs = 10
batch_size = 50

loss_log = []
for e in range(epochs):
    loss = None
    for i in range(0, train_x.shape[0], batch_size):
        x_mini = train_x[i : i + batch_size]
        y_mini = train_y[i : i + batch_size]

        optimizer.zero_grad()
        net_out = net(Variable(x_mini))

        loss = loss_func(net_out, Variable(y_mini))
        loss.backward()
        optimizer.step()
    if loss is not None:
        print(f"Epoch: {e+1} - Loss: {loss.item():.6f}")

with torch.no_grad():
    net_out = net(test)
result = extract_result(net_out)
io.save_result(result)

