### Install MemTorch from Source using setup.py Source: https://github.com/coreylammie/memtorch/blob/master/README.md Clone the repository and run `python setup.py install` to install MemTorch from its source code. ```bash git clone --recursive https://github.com/coreylammie/MemTorch cd MemTorch python setup.py install ``` -------------------------------- ### Install MemTorch from Source using pip Source: https://github.com/coreylammie/memtorch/blob/master/README.md Clone the repository and run `pip install .` to install MemTorch from its source code using pip. ```bash git clone --recursive https://github.com/coreylammie/MemTorch cd MemTorch pip install . ``` -------------------------------- ### Install and Configure Pre-commit Hooks Source: https://github.com/coreylammie/memtorch/blob/master/CONTRIBUTING.md Install necessary tools for code formatting and linting, and set up pre-commit hooks. ```bash pip install pre-commit black isort && pre-commit install ``` -------------------------------- ### Install Code Formatting Tools (Linux) Source: https://github.com/coreylammie/memtorch/blob/master/CONTRIBUTING.md Install clang and clang-format on Linux systems for C++ code formatting. ```bash apt install clang clang-format ``` -------------------------------- ### Install and Configure Code Formatters Source: https://github.com/coreylammie/memtorch/blob/master/README.md Install necessary Python packages for code formatting and pre-commit hooks. For C++ formatting, install clang-format on Linux or use Chocolatey on Windows. ```bash pip install pre-commit black isort && pre-commit install ``` ```bash apt install clang clang-format ``` ```bash choco install llvm uncrustify cppcheck ``` -------------------------------- ### Install Code Formatting Tools (Windows) Source: https://github.com/coreylammie/memtorch/blob/master/CONTRIBUTING.md Install LLVM, uncrustify, and cppcheck on Windows systems for code formatting and analysis. ```bash choco install llvm uncrustify cppcheck ``` -------------------------------- ### Install MemTorch with CUDA (pip) Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Tutorial.ipynb Install MemTorch with CUDA support directly using pip. This is a convenient method for users who have CUDA installed. ```python # Installation of MemTorch (with CUDA functionality) using pip !pip install memtorch ``` -------------------------------- ### Enter Development Mode Source: https://github.com/coreylammie/memtorch/blob/master/CONTRIBUTING.md Install Memtorch in development mode within the cloned repository directory. ```bash python setup.py develop ``` -------------------------------- ### Install MemTorch with CUDA (Jupyter) Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Tutorial.ipynb Install MemTorch with CUDA support from source using pip within a Jupyter notebook. This involves cloning the repository, modifying setup.py, and then installing. ```python # Installation of MemTorch (with CUDA functionality) from source using pip !git clone --recursive https://github.com/coreylammie/MemTorch %cd MemTorch !sed -i 's/CUDA = False/CUDA = True/g' setup.py !pip install . ``` -------------------------------- ### Install MemTorch via pip (CPU or CUDA) Source: https://github.com/coreylammie/memtorch/blob/master/README.md Install MemTorch using pip. Use `memtorch-cpu` for CPU-only support or `memtorch` for CUDA and CPU support. Ensure CUDA Toolkit 10.1 and Microsoft Visual C++ Build Tools are installed if CUDA support is desired. ```bash pip install memtorch-cpu # Supports normal operation ``` ```bash pip install memtorch # Supports CUDA and normal operation ``` -------------------------------- ### Train VGG CNN on CIFAR-10 Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/legacy/NovelSimulations.ipynb Sets up the training environment, loads the CIFAR-10 dataset, initializes the VGG model, and runs the training loop. Includes optimizer setup, loss calculation, backpropagation, and periodic learning rate adjustments. Model accuracy is evaluated on the test set after each epoch, and the best performing model is saved. ```python device = torch.device('cpu' if 'cpu' in memtorch.__version__ else 'cuda') epochs = 50 train_loader, validation_loader, test_loader = LoadCIFAR10(batch_size=256, validation=False) model = Net().to(device) criterion = nn.CrossEntropyLoss() learning_rate = 1e-2 optimizer = optim.Adam(model.parameters(), lr=learning_rate) best_accuracy = 0 for epoch in range(0, epochs): print('Epoch: [%d]\t\t' % (epoch + 1), end='') if epoch % 20 == 0: learning_rate = learning_rate * 0.1 for param_group in optimizer.param_groups: param_group['lr'] = learning_rate model.train() for batch_idx, (data, target) in enumerate(train_loader): optimizer.zero_grad() output = model(data.to(device)) loss = criterion(output, target.to(device)) loss.backward() optimizer.step() accuracy = test(model, test_loader) print('%2.2f%%' % accuracy) if accuracy > best_accuracy: torch.save(model.state_dict(), 'trained_model.pt') best_accuracy = accuracy ``` -------------------------------- ### Install MemTorch without CUDA (Jupyter) Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Tutorial.ipynb Install MemTorch without CUDA support from source using pip within a Jupyter notebook. This involves cloning the repository and then installing. ```python # Installation of MemTorch (without CUDA functionality) from source using pip !git clone --recursive https://github.com/coreylammie/MemTorch %cd MemTorch !pip install . ``` -------------------------------- ### Seizure Detection Training and Testing Utilities Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/legacy/CaseStudy.ipynb Contains functions for adjusting learning rate, training the neural network, and testing its performance. It also includes data loading and K-Fold cross-validation setup. ```python import sklearn from sklearn.model_selection import KFold init_lr = 1e-1 batch_size = 1024 device = torch.device('cpu' if 'cpu' in memtorch.__version__ else 'cuda') def adjust_lr(optimizer, epoch): lr = init_lr * (0.1 ** (epoch // 20)) for param_group in optimizer.param_groups: param_group['lr'] = lr return lr def train(net, train_loader, test_loader, epochs=10, fold=0): print('fold %d' % fold) best_f1_score = 0 for epoch in range(epochs): lr = adjust_lr(optimizer, epoch) running_loss = 0 for data in train_loader: inputs, labels = data inputs = inputs.float() if device == torch.device('cuda'): inputs = inputs.cuda() labels = labels.cuda() optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() f1_score = test(net, test_loader) if f1_score > best_f1_score: torch.save(net.state_dict(), 'trained_net_fold_%d.pt' % fold) best_f1_score = f1_score print('[Epoch %d] lr: %.4f f1_score: %.4f\ttraining loss: %.4f' % (epoch + 1, lr, f1_score, running_loss / len(train_loader))) def test(net, test_loader): confusion_matrix = torch.zeros(2, 2) correct = 0 total = 0 with torch.no_grad(): for data in test_loader: inputs, labels = data inputs = inputs.float() if device == torch.device('cuda'): inputs = inputs.cuda() labels = labels.cuda() outputs = net(inputs) _, predicted = torch.max(outputs.data, 1) for t, p in zip(labels.view(-1), predicted.view(-1)): confusion_matrix[t.long(), p.long()] += 1 total += labels.size(0) correct += (predicted == labels).sum().item() f1_score = 2 * confusion_matrix[0][0] / (2 * confusion_matrix[0][0] + confusion_matrix[0][1] + confusion_matrix[1][0]) return f1_score.item() dataset = SeizureDataset(csv_path) torch.manual_seed(0) kf = KFold(n_splits=5, shuffle=True) train_loaders = [] test_loaders = [] for i, (train_index, test_index) in enumerate(kf.split(dataset)): train_ = torch.utils.data.Subset(dataset, train_index) test_ = torch.utils.data.Subset(dataset, test_index) train_loaders.append(torch.utils.data.DataLoader(train_, batch_size=batch_size, shuffle=True)) test_loaders.append(torch.utils.data.DataLoader(test_, batch_size=batch_size, shuffle=False)) torch.manual_seed(torch.initial_seed()) torch.save(test_loaders, 'test_loaders.pth') assert(len(train_loaders) == len(test_loaders)) ``` -------------------------------- ### Install MemTorch without CUDA (pip) Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Tutorial.ipynb Install MemTorch without CUDA support using pip. This is suitable for systems without a CUDA-enabled GPU. ```python # Installation of MemTorch (without CUDA functionality) using pip !pip install memtorch-cpu ``` -------------------------------- ### Train MobileNetV2 on CIFAR-10 Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Exemplar_Simulations.ipynb This snippet trains a MobileNetV2 model on the CIFAR-10 dataset. It includes data preprocessing, model definition, training loop, and model saving. Ensure you have torchvision and memtorch installed. ```python import torch from torch.autograd import Variable import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import numpy as np import random import torchvision import torchvision.transforms as transforms def set_all_seeds(seed): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed(seed) torch.backends.cudnn.deterministic = True def test(model, test_loader): correct = 0 for batch_idx, (data, target) in enumerate(test_loader): output = model(data.to(device)) pred = output.data.max(1)[1] correct += pred.eq(target.to(device).data.view_as(pred)).cpu().sum() return 100. * float(correct) / float(len(test_loader.dataset)) set_all_seeds(0) device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') epochs = 100 transform_train = transforms.Compose([ transforms.RandomCrop(32, padding=4), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)), ]) transform_test = transforms.Compose([ transforms.ToTensor(), transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)), ]) train_set = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train) train_loader = torch.utils.data.DataLoader(train_set, batch_size=256, shuffle=True, num_workers=1) test_set = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform_test) test_loader = torch.utils.data.DataLoader(test_set, batch_size=128, shuffle=False, num_workers=1) model = MobileNetV2().to(device) criterion = nn.CrossEntropyLoss() learning_rate = 0.1 optimizer = optim.SGD(model.parameters(), lr=learning_rate, momentum=0.9) scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=40, gamma=0.1) best_accuracy = 0 for epoch in range(0, epochs): print('Epoch: [%d]\t\t' % (epoch + 1), end='') model.train() for batch_idx, (data, target) in enumerate(train_loader): optimizer.zero_grad() output = model(data.to(device)) loss = criterion(output, target.to(device)) loss.backward() optimizer.step() scheduler.step() model.eval() accuracy = test(model, test_loader) print('%2.2f%%' % accuracy) if accuracy > best_accuracy: print('Saving model...') torch.save(model.state_dict(), 'trained_model.pt') best_accuracy = accuracy ``` -------------------------------- ### Iterate and Log Simulation Results Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Exemplar_Simulations.ipynb Iterates through different hardware configurations (tile shape, ADC resolution, conductance states), runs simulations using the 'trial' function, and saves the results to a CSV file named '1_BF.csv'. ```python df = pd.DataFrame(columns=['tile_shape', 'ADC_resolution', 'conductance_states', 'test_set_accuracy']) torch.backends.cudnn.benchmark = False tile_shape = [(128, 128), (256, 64)] ADC_resolution = np.linspace(2, 10, num=5, endpoint=True, dtype=int) conductance_states = np.linspace(2, 10, num=5, endpoint=True, dtype=int) for tile_shape_ in tile_shape: for ADC_resolution_ in ADC_resolution: for conductance_states_ in conductance_states: print('tile_shape: %s; ADC_resolution: %d; conductance_states: %d' % (tile_shape_, ADC_resolution_, conductance_states_)) df = df.append({'tile_shape': tile_shape_, 'ADC_resolution': ADC_resolution_, 'conductance_states': conductance_states_, 'test_set_accuracy': trial(r_on, r_off, tile_shape_, ADC_resolution_, conductance_states_)}, ignore_index=True) df.to_csv('1_BF.csv', index=False) ``` -------------------------------- ### BibTeX for MemTorch Repository Source: https://github.com/coreylammie/memtorch/blob/master/README.md Use this entry to cite the initial release of the coreylammie/MemTorch repository on Zenodo. ```bibtex @software{corey_lammie_2020_3760696, author={Corey Lammie and Wei Xiang and Bernab\'e Linares-Barranco and Mostafa Rahimi Azghadi}, title={{coreylammie/MemTorch: Initial Release}}, month=Apr., year={2020}, publisher={Zenodo}, doi={10.5281/zenodo.3760695}, url={https://doi.org/10.5281/zenodo.3760696} } ``` -------------------------------- ### Initialize and Configure Memristor Crossbar Source: https://github.com/coreylammie/memtorch/blob/master/docs/memtorch.bh.rst Initializes a memristor crossbar with specified device models, resistance values, and shapes. Demonstrates writing a conductance matrix and setting individual device states. ```python import torch import memtorch crossbar = memtorch.bh.crossbar.Crossbar(memtorch.bh.memristor.VTEAM, {"r_on": 1e2, "r_off": 1e4}, shape=(100, 100), tile_shape=(64, 64)) crossbar.write_conductance_matrix(torch.zeros(100, 100).uniform_(1e-2, 1e-4), transistor=True) crossbar.devices[0][0][0].set_conductance(1e-4) crossbar.update(from_devices=True, parallelize=True) ``` -------------------------------- ### Apply Naive Mapping to Individual Linear Layer Source: https://github.com/coreylammie/memtorch/blob/master/docs/memtorch.map.rst Demonstrates how to apply the naive_map parameter mapping method when creating a memtorch.mn.Linear layer. ```python from memtorch.map.Parameter import naive_map m = memtorch.mn.Linear(torch.nn.Linear(10, 10), memtorch.bh.memristor.VTEAM, {}, tile_shape=(64, 64), mapping_routine=naive_map) ``` -------------------------------- ### Apply Naive Scaling to Individual Linear Layer Source: https://github.com/coreylammie/memtorch/blob/master/docs/memtorch.map.rst Demonstrates how to apply the naive_scale input encoding method when creating a memtorch.mn.Linear layer. ```python from memtorch.map.Input import naive_scale m = memtorch.mn.Linear(torch.nn.Linear(10, 10), memtorch.bh.memristor.VTEAM, {}, tile_shape=(64, 64), scaling_routine=naive_scale) ``` -------------------------------- ### Apply Non-Linear Device Characteristics (Inference Simulation) Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Tutorial.ipynb Applies non-linear device characteristics by simulating each device during inference. Ensure `memtorch.bh.nonideality.NonLinear` is imported and the model is deep-copied. ```python from memtorch.bh.nonideality.NonIdeality import apply_nonidealities patched_model_ = apply_nonidealities(copy.deepcopy(patched_model), non_idealities=[memtorch.bh.nonideality.NonIdeality.NonLinear], simulate=True) ``` ```python print(test(patched_model_, test_loader)) ``` -------------------------------- ### Apply Naive Mapping to Patched PyTorch Model Source: https://github.com/coreylammie/memtorch/blob/master/docs/memtorch.map.rst Shows how to apply the naive_map parameter mapping method to an entire PyTorch model using patch_model. ```python import copy from memtorch.mn.Module import patch_model from memtorch.map.Parameter import naive_map import Net model = Net() patched_model = patch_model(copy.deepcopy(model), memtorch.bh.memristor.VTEAM, {}, module_parameters_to_patch=[torch.nn.Linear], mapping_routine=naive_map) ``` -------------------------------- ### Apply Naive Scaling to Patched PyTorch Model Source: https://github.com/coreylammie/memtorch/blob/master/docs/memtorch.map.rst Shows how to apply the naive_scale input encoding method to an entire PyTorch model using patch_model. ```python import copy from memtorch.mn.Module import patch_model from memtorch.map.Input import naive_scale import Net model = Net() patched_model = patch_model(copy.deepcopy(model), memtorch.bh.memristor.VTEAM, {}, module_parameters_to_patch=[torch.nn.Linear], scaling_routine=naive_scale) ``` -------------------------------- ### BibTeX for MemTorch Paper Source: https://github.com/coreylammie/memtorch/blob/master/README.md Use this entry to cite the research paper 'MemTorch: An Open-source Simulation Framework for Memristive Deep Learning Systems'. ```bibtex @Article{Lammie2022, author = {Corey Lammie and Wei Xiang and Bernabé Linares-Barranco and Mostafa Rahimi Azghadi}, title = {{MemTorch: An Open-source Simulation Framework for Memristive Deep Learning Systems}}, journal = {Neurocomputing}, year = {2022}, issn = {0925-2312}, doi = {https://doi.org/10.1016/j.neucom.2022.02.043}, keywords = {Memristors, RRAM, Non-Ideal Device Characteristics, Deep Learning, Simulation Framework}, url = {https://www.sciencedirect.com/science/article/pii/S0925231222002053}, } ``` -------------------------------- ### Apply Finite Conductance States Model Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Tutorial.ipynb Models a device with a finite number of discrete conductance states. Sets the number of conductance states to 5, evenly distributed between low and high conductance. ```python from memtorch.bh.nonideality.NonIdeality import apply_nonidealities patched_model_ = apply_nonidealities(copy.deepcopy(patched_model), non_idealities=[memtorch.bh.nonideality.NonIdeality.FiniteConductanceStates], conductance_states=5) ``` -------------------------------- ### Simulating Memristor Behavior in a PyTorch Model Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/legacy/NovelSimulations.ipynb This snippet shows how to patch a PyTorch model with a reference memristor, apply non-idealities, and tune it for simulation. It iterates through different standard deviations, conductance ratios, and conductance states to evaluate test set accuracy. ```python from memtorch.mn.Module import patch_model from memtorch.map.Parameter import naive_map from memtorch.bh.crossbar.Program import naive_program from memtorch.bh.nonideality.NonIdeality import apply_nonidealities def trial(num_conductance_states, g_ratio, sigma): model_ = copy.deepcopy(model) r_on = 200 reference_memristor = memtorch.bh.memristor.VTEAM reference_memristor_params = {'time_series_resolution': 1e-10, 'r_off': memtorch.bh.StochasticParameter(loc=r_on*g_ratio, scale=sigma*2, min=1), 'r_on': memtorch.bh.StochasticParameter(loc=r_on, scale=sigma, min=1)} patched_model = patch_model(copy.deepcopy(model_), memristor_model=reference_memristor, memristor_model_params=reference_memristor_params, module_parameters_to_patch=[torch.nn.Linear, torch.nn.Conv2d], mapping_routine=naive_map, transistor=True, programming_routine=None) patched_model = apply_nonidealities(patched_model, non_idealities=[memtorch.bh.nonideality.NonIdeality.FiniteConductanceStates], conductance_states=int(num_conductance_states)) patched_model.tune_() return test(patched_model, test_loader) std_devs = [0, 20, 100] g_ratios = [2 ** n for n in range(6)] conductance_states = np.linspace(2, 10, 9) for std_dev in std_devs: df = pd.DataFrame(columns=['conductance_states', 'g_ratio', 'test_set_accuracy']) for g_ratio in g_ratios: for num_conductance_states in conductance_states: test_set_accuracy = trial(num_conductance_states, g_ratio, std_dev) df = df.append({'conductance_states': num_conductance_states, 'g_ratio': g_ratio, 'test_set_accuracy': test_set_accuracy}, ignore_index=True) df.to_csv('S1_std_dev_%d.csv' % std_dev, index=False) ``` -------------------------------- ### Load and Test Trained Network Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/legacy/NovelSimulations.ipynb Loads a pre-trained PyTorch model from 'trained_model.pt' and evaluates its accuracy on the test set. Ensure 'trained_model.pt' exists in the same directory. ```python import copy import pandas as pd import matplotlib import matplotlib.pyplot as plt import numpy as np model = Net().to(device) try: model.load_state_dict(torch.load('trained_model.pt'), strict=False) except: raise Exception('trained_model.pt has not been found.') print('Test Set Accuracy: %2.2f%%' % test(model, test_loader)) ``` -------------------------------- ### Simulate Memristor Neural Network with Non-Idealities Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Exemplar_Simulations.ipynb Creates a patched memristor model with specified memristor parameters, mapping, and programming routines. It then applies device faults and tunes the model before testing its accuracy. ```python r_on = 1.4e4 r_off = 5e7 def trial(r_on, r_off, tile_shape, ADC_resolution, failure_percentage): model_ = copy.deepcopy(model) reference_memristor = memtorch.bh.memristor.VTEAM reference_memristor_params = {'time_series_resolution': 1e-10, 'r_off': r_off, 'r_on': r_on} patched_model = patch_model(copy.deepcopy(model_), memristor_model=reference_memristor, memristor_model_params=reference_memristor_params, module_parameters_to_patch=[torch.nn.Linear, torch.nn.Conv2d], mapping_routine=naive_map, transistor=True, programming_routine=None, scheme=memtorch.bh.Scheme.DoubleColumn, tile_shape=tile_shape, max_input_voltage=0.3, ADC_resolution=int(ADC_resolution), ADC_overflow_rate=0., quant_method='linear') patched_model = apply_nonidealities(patched_model, non_idealities=[memtorch.bh.nonideality.NonIdeality.DeviceFaults], lrs_proportion=0., hrs_proportion=failure_percentage, electroform_proportion=0.) patched_model.tune_() return test(patched_model, test_loader) ``` -------------------------------- ### Clone Memtorch Repository Source: https://github.com/coreylammie/memtorch/blob/master/CONTRIBUTING.md Clone the Memtorch project to your local machine. Ensure to use the --recursive flag to include submodules. ```bash git clone --recursive ``` -------------------------------- ### Patching Model and Applying Non-Idealities Source: https://github.com/coreylammie/memtorch/blob/master/docs/memtorch.bh.nonideality.rst This snippet demonstrates how to patch a PyTorch model with a memristor model and then apply non-ideal device characteristics. It's useful for simulating realistic memristor behavior in neural networks. ```python import copy import Net from memtorch.mn.Module import patch_model from memtorch.map.Parameter import naive_map from memtorch.map.Input import naive_scale model = Net() reference_memristor = memtorch.bh.memristor.VTEAM patched_model = patch_model(copy.deepcopy(model), memristor_model=reference_memristor, memristor_model_params={}, module_parameters_to_patch=[torch.nn.Linear, torch.nn.Conv2d], mapping_routine=naive_map, transistor=True, programming_routine=None, tile_shape=(128, 128), max_input_voltage=0.3, scaling_routine=naive_scale, ADC_resolution=8, ADC_overflow_rate=0., quant_method='linear') # Example usage of memtorch.bh.nonideality.NonIdeality.DeviceFaults patched_model = patched_model.apply_nonidealities(patched_model, non_idealities=[memtorch.bh.nonideality.NonIdeality.DeviceFaults], lrs_proportion=0.25, hrs_proportion=0.10, electroform_proportion=0) ``` -------------------------------- ### Define Memristor Crossbar with Stochastic Parameters Source: https://github.com/coreylammie/memtorch/blob/master/docs/memtorch.bh.rst Initializes a memristor crossbar using stochastic parameters for device resistance, allowing for variability in device behavior. ```python import torch import memtorch crossbar = memtorch.bh.crossbar.Crossbar(memtorch.bh.memristor.VTEAM, {"r_on": memtorch.bh.StochasticParameter(min=1e3, max=1e2), "r_off": 1e4}, shape=(100, 100), tile_shape=(64, 64)) ``` -------------------------------- ### Investigating Non-linear IV Characteristics with EEGNet Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/legacy/CaseStudy.ipynb This code snippet demonstrates how to load a pre-trained EEGNet model, apply non-linear memristor characteristics using MemTorch, tune the patched model, and evaluate its performance using F1 scores across multiple folds. It requires PyTorch, Pandas, NumPy, and MemTorch libraries. ```python # Determine the F1 score df = pd.DataFrame(columns=['sigma', 'mean', 'std']) sigma_values = np.linspace(0, 500, 11) f1_scores = [] for fold in range(len(test_loaders)): net = EEGNet() net.load_state_dict(torch.load('trained_net_fold_%d.pt' % fold), strict=False).to(device) patched_net = patch_model(net, memristor_model=reference_memristor, memristor_model_params=reference_memristor_params, module_parameters_to_patch=[torch.nn.Linear], mapping_routine=naive_map, transistor=True, programming_routine=None, scheme=memtorch.bh.Scheme.DoubleColumn) patched_net = apply_nonidealities(patched_net, non_idealities=[memtorch.bh.nonideality.NonIdeality.NonLinear], sweep_duration=2, sweep_voltage_signal_amplitude=1, sweep_voltage_signal_frequency=0.5) patched_net.tune_() f1_score = test(patched_net, test_loaders[fold]) f1_scores.append(f1_score) print('mean: %0.4f\tstddev: %0.4f' % (np.mean(f1_scores), np.std(f1_scores))) ``` -------------------------------- ### Simulation Loop for Parameter Sweeping Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Exemplar_Simulations.ipynb Iterates through different tile shapes, ADC resolutions, and sigma values to run simulation trials and saves the results to a CSV file. This helps in analyzing the impact of various parameters on model accuracy. ```python df = pd.DataFrame(columns=['tile_shape', 'ADC_resolution', 'sigma', 'test_set_accuracy']) tile_shape = [(256, 64)] ADC_resolution = np.linspace(2, 10, num=5, endpoint=True, dtype=int) sigma = np.logspace(6, 7, endpoint=True, num=5) for tile_shape_ in tile_shape: for ADC_resolution_ in ADC_resolution: for sigma_ in sigma: print('tile_shape: %s; ADC_resolution: %d; sigma: %d' % (tile_shape_, ADC_resolution_, sigma_)) df = df.append({'tile_shape': tile_shape_, 'ADC_resolution': ADC_resolution_, 'sigma': sigma_, 'test_set_accuracy': trial(r_on, r_off, tile_shape_, ADC_resolution_, sigma_)}), ignore_index=True) df.to_csv('1_AE.csv', index=False) ``` -------------------------------- ### Run Novel Simulation with Memristor Non-Idealities Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/legacy/NovelSimulations.ipynb This function simulates a memristor model with configurable conductance states, LRS/HRS failure rates, and standard deviation. It applies non-idealities and tunes the model before testing. ```python from memtorch.mn.Module import patch_model from memtorch.map.Parameter import naive_map from memtorch.bh.crossbar.Program import naive_program from memtorch.bh.nonideality.NonIdeality import apply_nonidealities def trial(num_conductance_states, lrs_failure_rate, hrs_failure_rate, sigma): model_ = copy.deepcopy(model) r_on = 200 r_off = 500 reference_memristor = memtorch.bh.memristor.VTEAM reference_memristor_params = {'time_series_resolution': 1e-10, 'r_off': memtorch.bh.StochasticParameter(loc=r_on*g_ratio, scale=sigma*2, min=1), 'r_on': memtorch.bh.StochasticParameter(loc=r_off, scale=sigma, min=1)} patched_model = patch_model(copy.deepcopy(model_), memristor_model=reference_memristor, memristor_model_params=reference_memristor_params, module_parameters_to_patch=[torch.nn.Linear, torch.nn.Conv2d], mapping_routine=naive_map, transistor=True, programming_routine=None) patched_model = apply_nonidealities(patched_model, non_idealities=[memtorch.bh.nonideality.NonIdeality.FiniteConductanceStates, memtorch.bh.nonideality.NonIdeality.DeviceFaults], conductance_states=int(num_conductance_states), lrs_proportion=lrs_failure_rate, hrs_proportion=hrs_failure_rate, electroform_proportion=0) patched_model.tune_() return test(patched_model, test_loader) ``` -------------------------------- ### Load and Evaluate Trained Model Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Exemplar_Simulations.ipynb Loads a pre-trained MobileNetV2 model from 'trained_model.pt' and evaluates its accuracy on the CIFAR10 test set. It handles potential file not found errors. ```python device = torch.device('cuda') transform_test = transforms.Compose([ transforms.ToTensor(), transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)), ]) test_set = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform_test) test_loader = torch.utils.data.DataLoader(test_set, batch_size=256, shuffle=False, num_workers=1) model = MobileNetV2().to(device) try: model.load_state_dict(torch.load('trained_model.pt'), strict=False) model.eval() except: raise Exception('trained_model.pt has not been found.') print('Test Set Accuracy: %2.2f%%' % test(model, test_loader)) ``` -------------------------------- ### Simulate Device Failures and Test Accuracy Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/legacy/NovelSimulations.ipynb This snippet simulates device failures by applying non-idealities to a patched model and then tests the model's accuracy. It saves the results for different failure proportions to CSV files. ```python from memtorch.mn.Module import patch_model from memtorch.map.Parameter import naive_map from memtorch.bh.crossbar.Program import naive_program from memtorch.bh.nonideality.NonIdeality import apply_nonidealities def trial(r_on, r_off, lrs_proportion, hrs_proportion): model_ = copy.deepcopy(model) reference_memristor = memtorch.bh.memristor.VTEAM reference_memristor_params = {'time_series_resolution': 1e-10, 'r_off': r_off, 'r_on': r_on} patched_model = patch_model(copy.deepcopy(model_), memristor_model=reference_memristor, memristor_model_params=reference_memristor_params, module_parameters_to_patch=[torch.nn.Linear, torch.nn.Conv2d], mapping_routine=naive_map, transistor=True, programming_routine=None) patched_model = apply_nonidealities(patched_model, non_idealities=[memtorch.bh.nonideality.NonIdeality.DeviceFaults], lrs_proportion=lrs_proportion, hrs_proportion=hrs_proportion, electroform_proportion=0) patched_model.tune_() return test(patched_model, test_loader) df_lrs_hrs = pd.DataFrame(columns=['failure_percentage', 'test_set_accuracy']) df_lrs = pd.DataFrame(columns=['failure_percentage', 'test_set_accuracy']) df_hrs = pd.DataFrame(columns=['failure_percentage', 'test_set_accuracy']) r_on = 200 r_off = 500 failures = np.linspace(0, 0.25, 11) for failure in failures: df_lrs_hrs = df_lrs_hrs.append({'failure_percentage': failure, 'test_set_accuracy': trial(r_on, r_off, failure, failure)}, ignore_index=True) df_lrs = df_lrs.append({'failure_percentage': failure, 'test_set_accuracy': trial(r_on, r_off, failure, 0)}, ignore_index=True) df_hrs = df_hrs.append({'failure_percentage': failure, 'test_set_accuracy': trial(r_on, r_off, 0, failure)}, ignore_index=True) df_lrs_hrs.to_csv('failure_lrs_hrs.csv', index=False) df_lrs.to_csv('failure_lrs.csv', index=False) df_hrs.to_csv('failure_hrs.csv', index=False) ``` -------------------------------- ### Load and Preprocess Seizure Detection Dataset Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/legacy/CaseStudy.ipynb Loads the seizure detection dataset from a CSV file and preprocesses the features using scikit-learn's scaling. This snippet defines a custom PyTorch Dataset. ```python import torch import memtorch from torch.utils.data import Dataset import torch.nn.functional as F import torch.nn as nn import pandas as pd import numpy as np import sklearn from sklearn import preprocessing class SeizureDataset(Dataset): def __init__(self, path_to_csv): self.features = pd.read_csv(path_to_csv) self.labels = self.features.pop('y') self.features = preprocessing.scale(self.features.iloc[:, 1:], axis=0) def __len__(self): return len(self.labels) def __getitem__(self, i): if self.labels[i] == 1: label = 1 else: label = 0 return np.asarray(self.features[i, :]).astype(np.float), label csv_path = 'http://archive.ics.uci.edu/ml/machine-learning-databases/00388/data.csv' dataset = SeizureDataset(path_to_csv=csv_path) ``` -------------------------------- ### Memristor Simulation Trial Function Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Exemplar_Simulations.ipynb Configures and tests a patched neural network model with specified memristor parameters, tile shape, ADC resolution, and non-ideality sigma. It returns the test set accuracy. ```python def trial(r_on, r_off, tile_shape, ADC_resolution, sigma): model_ = copy.deepcopy(model) reference_memristor = memtorch.bh.memristor.VTEAM if sigma == 0.: reference_memristor_params = {'time_series_resolution': 1e-10, 'r_off': r_off, 'r_on': r_on} else: reference_memristor_params = {'time_series_resolution': 1e-10, 'r_off': memtorch.bh.StochasticParameter(loc=r_off, scale=sigma*2, min=1), 'r_on': memtorch.bh.StochasticParameter(loc=r_on, scale=sigma, min=1)} patched_model = patch_model(copy.deepcopy(model_), memristor_model=reference_memristor, memristor_model_params=reference_memristor_params, module_parameters_to_patch=[torch.nn.Linear, torch.nn.Conv2d], mapping_routine=naive_map, transistor=True, programming_routine=None, scheme=memtorch.bh.Scheme.DoubleColumn, tile_shape=tile_shape, max_input_voltage=0.3, ADC_resolution=int(ADC_resolution), ADC_overflow_rate=0., quant_method='linear') patched_model.tune_() return test(patched_model, test_loader) ``` -------------------------------- ### Characterize Memristor with Stochastic Parameters Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Tutorial.ipynb Defines a memristor object using stochastic parameters for low and high resistance states. Stochastic parameters are resampled each time the object is instantiated. Requires `memtorch` import. ```python import memtorch reference_memristor = memtorch.bh.memristor.VTEAM reference_memristor_params = {'time_series_resolution': 1e-10, 'r_off': memtorch.bh.StochasticParameter(loc=1000, scale=200, min=2), 'r_on': memtorch.bh.StochasticParameter(loc=5000, scale=sigma, min=1)} memristor = reference_memristor(**reference_memristor_params) memristor.plot_hysteresis_loop() memristor.plot_bipolar_switching_behaviour() ``` -------------------------------- ### Define and Plot Memristor Model Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Tutorial.ipynb Defines a reference memristor model and its parameters, instantiates a memristor object, and plots its hysteresis loop and bipolar switching behavior. This is a prerequisite for model conversion. ```python reference_memristor = memtorch.bh.memristor.VTEAM reference_memristor_params = {'time_series_resolution': 1e-10} memristor = reference_memristor(**reference_memristor_params) memristor.plot_hysteresis_loop() memristor.plot_bipolar_switching_behavior() ``` -------------------------------- ### Evaluate Model Accuracy with Memtorch Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Exemplar_Simulations.ipynb Loads a pre-trained MobileNetV2 model, evaluates its accuracy on the CIFAR-10 test set, and prints the result. This snippet requires a 'trained_model.pt' file. ```python import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torchvision import datasets, transforms import memtorch from memtorch.utils import LoadCIFAR10 import numpy as np import pandas as pd import torchvision import copy from memtorch.mn.Module import patch_model from memtorch.map.Parameter import naive_map from memtorch.bh.crossbar.Program import naive_program from memtorch.bh.nonideality.NonIdeality import apply_nonidealities def test(model, test_loader): correct = 0 for batch_idx, (data, target) in enumerate(test_loader): output = model(data.to(device)) pred = output.data.max(1)[1] correct += pred.eq(target.to(device).data.view_as(pred)).cpu().sum() return 100. * float(correct) / float(len(test_loader.dataset)) device = torch.device('cuda') transform_test = transforms.Compose([ transforms.ToTensor(), transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)), ]) test_set = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform_test) test_loader = torch.utils.data.DataLoader(test_set, batch_size=256, shuffle=False, num_workers=1) model = MobileNetV2().to(device) try: model.load_state_dict(torch.load('trained_model.pt'), strict=False) model.eval() except: raise Exception('trained_model.pt has not been found.') print('Test Set Accuracy: \t%2.2f%%' % test(model, test_loader)) model = MobileNetV2().to(device) model.load_state_dict(torch.load('trained_model.pt'), strict=True) model.eval() print(test(model, test_loader)) ``` -------------------------------- ### Re-evaluate Model with Strict Loading Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/Exemplar_Simulations.ipynb Loads a pre-trained MobileNetV2 model with strict state dictionary matching and evaluates its accuracy. This ensures all model parameters are loaded correctly. ```python model = MobileNetV2().to(device) model.load_state_dict(torch.load('trained_model.pt'), strict=True) model.eval() print(test(model, test_loader)) ``` -------------------------------- ### Investigating Device Variability with Memtorch and F1 Scores Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/legacy/CaseStudy.ipynb This snippet analyzes the impact of device variability (controlled by sigma) on model performance. It trains and tests a patched neural network with memristors exhibiting different stochastic parameters and calculates F1 scores. ```python # Determine the F1 score df = pd.DataFrame(columns=['sigma', 'mean', 'std']) sigma_values = np.linspace(0, 500, 21) for sigma in sigma_values: non_linear_reference_memristor_params = {'time_series_resolution': 1e-6, 'alpha_off': 1, 'alpha_on': 3, 'v_off': 0.5, 'v_on': -0.53, 'r_off': memtorch.bh.StochasticParameter(loc=2.5e3, scale=sigma*2, min=1), 'r_on': memtorch.bh.StochasticParameter(loc=100, scale=sigma, min=1), 'k_off': 4.03e-8, 'k_on': -80, 'd': 10e-9, 'x_on': 0, 'x_off': 10e-9} f1_scores = [] for fold in range(len(test_loaders)): net = EEGNet() net.load_state_dict(torch.load('trained_net_fold_%d.pt' % fold), strict=True).to(device) patched_net = patch_model(copy.deepcopy(net), memristor_model=reference_memristor, memristor_model_params=non_linear_reference_memristor_params, module_parameters_to_patch=[torch.nn.Linear], mapping_routine=naive_map, transistor=True, programming_routine=None, scheme=memtorch.bh.Scheme.DoubleColumn) patched_net.tune_() f1_score = test(patched_net, test_loaders[fold]) f1_scores.append(f1_score) df = df.append({'sigma': sigma, 'mean': np.mean(f1_scores), 'std': np.std(f1_scores)}, ignore_index=True) df.to_csv('variability.csv', index=False) ``` -------------------------------- ### Plotting Simulation Results with Seaborn and Matplotlib Source: https://github.com/coreylammie/memtorch/blob/master/memtorch/examples/legacy/NovelSimulations.ipynb This snippet visualizes the test set accuracy results from the memristor simulations using bar plots. It reads CSV data and generates plots for different standard deviations, showing the impact of conductance states and ratios on accuracy. ```python import seaborn as sns from matplotlib.ticker import FormatStrFormatter f = plt.figure(figsize=(16, 4)) plt.subplot(1, len(std_devs), 1) for plot_index, std_dev in enumerate(std_devs): plt.subplot(1, len(std_devs), plot_index + 1) plt.axhline(y=10, color='k', linestyle='--', zorder=1) data = pd.read_csv('S1_std_dev_%d.csv' % std_dev) h = sns.barplot(x="conductance_states", hue="g_ratio", y="test_set_accuracy", data=data, zorder=2, edgecolor='black', linewidth='1', palette=sns.color_palette(palette), saturation=1) plt.gca().xaxis.set_major_formatter(FormatStrFormatter('%1.0f')) plt.xticks(np.arange(0, len(conductance_states)), map(lambda n: "%d" % n, conductance_states)) leg = h.axes.get_legend() leg.set_title('RON/ROFF Ratio') h.legend(loc=1) plt.title('$\\sigma$ = %d' % std_dev) if plot_index == 0: plt.xlabel('Number of Finite States') plt.ylabel('CIFAR-10 Test-set Accuracy (%)') else: plt.xlabel('') plt.ylabel('') plt.grid() f.tight_layout() plt.savefig("S1.svg") plt.show() ```