From 3359eb67a9da618075cd7452b3d590a244a7d5f7 Mon Sep 17 00:00:00 2001 From: "dsuseendar@gmail.com" <47862632+dsuseendar@users.noreply.github.com> Date: Mon, 3 Jul 2023 11:44:46 -0400 Subject: [PATCH 1/4] Importing libraries for PCA - LDA analysis --- Neural_Decoding/decoders.py | 112 ++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/Neural_Decoding/decoders.py b/Neural_Decoding/decoders.py index 42b3a28..e697f65 100644 --- a/Neural_Decoding/decoders.py +++ b/Neural_Decoding/decoders.py @@ -30,6 +30,8 @@ from sklearn import linear_model #For Wiener Filter and Wiener Cascade from sklearn.svm import SVR #For support vector regression (SVR) from sklearn.svm import SVC #For support vector classification (SVM) + from sklearn.decomposition import PCA #For PCA decomposition (PCA - LDA) + from sklearn import discriminant_analysis as da # For LDA decomposition (PCA - LDA) except ImportError: print("\nWARNING: scikit-learn is not installed. You will be unable to use the Wiener Filter or Wiener Cascade Decoders") pass @@ -1683,3 +1685,113 @@ def predict(self,X_flat_test): bst=self.model #Get fit model y_test_predicted = bst.predict(dtest) #Make prediction return y_test_predicted + + +##################### PRINCIPAL COMPONENT ANALYSIS - LINEAR DISCRIMINANT CLASSIFIER ########################## + +class PcaLdaClassification(object): + """ + Class for the PCA - LDA Classifier + + Parameters + ---------- + explained variance: integer, optional, default=80 + the number of modes that explain the cumulative variance of the dataset + + da_type: string, optional, default=lda + type of discriminant analysis; lda or qda + + """ + + def __init__(self, explained_variance=80, da_type='lda'): + self.explained_variance = explained_variance + self.da_type = da_type + + + def fit(self, X_flat_train, y_train): + + """ + Train XGBoost Decoder + + Parameters + ---------- + X_flat_train: numpy 2d array of shape [n_samples,n_features] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 1d array of shape (n_samples), with integers representing classes + or 2d array of shape [n_samples, n_outputs] in 1-hot form + This is the outputs that are being predicted + """ + + # turn to categorial (not 1-hat) + if (y_train.ndim == 2): + if (y_train.shape[1] == 1): + y_train = np.reshape(y_train, -1) + else: + y_train = np.argmax(y_train, axis=1, out=None) + + # Get number of classes + n_classes = len(np.unique(y_train)) + + # Set parameters for XGBoost + param = {'objective': "multi:softmax", # or softprob + 'eval_metric': "mlogloss", # loglikelihood loss + # 'eval_metric': "merror", + 'max_depth': self.max_depth, # this is the only parameter we have set, it's one of the way or regularizing + 'eta': self.eta, + 'num_class': n_classes, # y_train.shape[1], + 'seed': 2925, # for reproducibility + 'silent': 1} + if self.gpu < 0: + param['nthread'] = -1 # with -1 it will use all available threads + else: + param['gpu_id'] = self.gpu + param['updater'] = 'grow_gpu' + + dtrain = xgb.DMatrix(X_flat_train, label=y_train) # Put in correct format for XGB + bst = xgb.train(param, dtrain, self.num_round) # Train model + + self.model = bst + + def predict(self, X_flat_test): + + """ + Predict outcomes using trained XGBoost Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 1d array with integers as classes + The predicted outputs + """ + + dtest = xgb.DMatrix(X_flat_test) # Put in XGB format + bst = self.model # Get fit model + y_test_predicted = bst.predict(dtest) # Make prediction + return y_test_predicted + + def predict(self,X_flat_test): + + """ + Predict outcomes using trained XGBoost Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + dtest = xgb.DMatrix(X_flat_test) #Put in XGB format + bst=self.model #Get fit model + y_test_predicted = bst.predict(dtest) #Make prediction + return y_test_predicted \ No newline at end of file From f088f74f66a73e68eac388a09861df69c6790212 Mon Sep 17 00:00:00 2001 From: "dsuseendar@gmail.com" <47862632+dsuseendar@users.noreply.github.com> Date: Mon, 3 Jul 2023 12:50:30 -0400 Subject: [PATCH 2/4] Importing makepipeline for pca lda analysis --- Neural_Decoding/decoders.py | 97 ++++++++----------------------------- 1 file changed, 21 insertions(+), 76 deletions(-) diff --git a/Neural_Decoding/decoders.py b/Neural_Decoding/decoders.py index e697f65..ae754ee 100644 --- a/Neural_Decoding/decoders.py +++ b/Neural_Decoding/decoders.py @@ -27,6 +27,7 @@ #Import scikit-learn (sklearn) if it is installed try: + from sklearn.pipeline import make_pipeline as mp from sklearn import linear_model #For Wiener Filter and Wiener Cascade from sklearn.svm import SVR #For support vector regression (SVR) from sklearn.svm import SVC #For support vector classification (SVM) @@ -1664,27 +1665,7 @@ def predict(self, X_flat_test): bst = self.model # Get fit model y_test_predicted = bst.predict(dtest) # Make prediction return y_test_predicted - - def predict(self,X_flat_test): - - """ - Predict outcomes using trained XGBoost Decoder - - Parameters - ---------- - X_flat_test: numpy 2d array of shape [n_samples,n_features] - This is the neural data being used to predict outputs. - - Returns - ------- - y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] - The predicted outputs - """ - - dtest = xgb.DMatrix(X_flat_test) #Put in XGB format - bst=self.model #Get fit model - y_test_predicted = bst.predict(dtest) #Make prediction - return y_test_predicted + ##################### PRINCIPAL COMPONENT ANALYSIS - LINEAR DISCRIMINANT CLASSIFIER ########################## @@ -1703,7 +1684,7 @@ class PcaLdaClassification(object): """ - def __init__(self, explained_variance=80, da_type='lda'): + def __init__(self, explained_variance=0.8, da_type='lda'): self.explained_variance = explained_variance self.da_type = da_type @@ -1711,7 +1692,7 @@ def __init__(self, explained_variance=80, da_type='lda'): def fit(self, X_flat_train, y_train): """ - Train XGBoost Decoder + Train PCA - LDA classifier Parameters ---------- @@ -1719,45 +1700,28 @@ def fit(self, X_flat_train, y_train): This is the neural data. See example file for an example of how to format the neural data correctly - y_train: numpy 1d array of shape (n_samples), with integers representing classes - or 2d array of shape [n_samples, n_outputs] in 1-hot form + y_train: numpy 1d array of shape (n_samples), with integers representing classes This is the outputs that are being predicted """ - - # turn to categorial (not 1-hat) - if (y_train.ndim == 2): - if (y_train.shape[1] == 1): - y_train = np.reshape(y_train, -1) - else: - y_train = np.argmax(y_train, axis=1, out=None) - - # Get number of classes - n_classes = len(np.unique(y_train)) - - # Set parameters for XGBoost - param = {'objective': "multi:softmax", # or softprob - 'eval_metric': "mlogloss", # loglikelihood loss - # 'eval_metric': "merror", - 'max_depth': self.max_depth, # this is the only parameter we have set, it's one of the way or regularizing - 'eta': self.eta, - 'num_class': n_classes, # y_train.shape[1], - 'seed': 2925, # for reproducibility - 'silent': 1} - if self.gpu < 0: - param['nthread'] = -1 # with -1 it will use all available threads + + # choose discriminant type + if (self.da_type == 'lda'): + da_model = da.LinearDiscriminantAnalysis() # linear discriminant analysis else: - param['gpu_id'] = self.gpu - param['updater'] = 'grow_gpu' + da_model = da.QuadraticDiscriminantAnalysis() # Quadratic discriminant analysis - dtrain = xgb.DMatrix(X_flat_train, label=y_train) # Put in correct format for XGB - bst = xgb.train(param, dtrain, self.num_round) # Train model + # Create a pipeline classifier + pca_lda = mp(PCA(n_components=self.explained_variance), da_model) - self.model = bst + # Fit the model + pca_lda.fit(X_flat_train,y_train) + + self.model = pca_lda def predict(self, X_flat_test): """ - Predict outcomes using trained XGBoost Decoder + Predict outcomes using trained PCA LDA Decoder Parameters ---------- @@ -1770,28 +1734,9 @@ def predict(self, X_flat_test): The predicted outputs """ - dtest = xgb.DMatrix(X_flat_test) # Put in XGB format - bst = self.model # Get fit model - y_test_predicted = bst.predict(dtest) # Make prediction + + pca_lda_fit = self.model # Get fit model + y_test_predicted = pca_lda_fit.predict(X_flat_test) # Make prediction return y_test_predicted - def predict(self,X_flat_test): - - """ - Predict outcomes using trained XGBoost Decoder - - Parameters - ---------- - X_flat_test: numpy 2d array of shape [n_samples,n_features] - This is the neural data being used to predict outputs. - - Returns - ------- - y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] - The predicted outputs - """ - - dtest = xgb.DMatrix(X_flat_test) #Put in XGB format - bst=self.model #Get fit model - y_test_predicted = bst.predict(dtest) #Make prediction - return y_test_predicted \ No newline at end of file + \ No newline at end of file From 1a6dd55d5c217bc0bd48617c58cee8ab678aaa11 Mon Sep 17 00:00:00 2001 From: "dsuseendar@gmail.com" <47862632+dsuseendar@users.noreply.github.com> Date: Mon, 3 Jul 2023 15:31:25 -0400 Subject: [PATCH 3/4] Methods for PCA-LDA analysis --- Neural_Decoding/decoders.py | 39 ++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/Neural_Decoding/decoders.py b/Neural_Decoding/decoders.py index ae754ee..6b7f884 100644 --- a/Neural_Decoding/decoders.py +++ b/Neural_Decoding/decoders.py @@ -1711,7 +1711,7 @@ def fit(self, X_flat_train, y_train): da_model = da.QuadraticDiscriminantAnalysis() # Quadratic discriminant analysis # Create a pipeline classifier - pca_lda = mp(PCA(n_components=self.explained_variance), da_model) + pca_lda = mp(steps =['pca',PCA(n_components=self.explained_variance),'discriminant', da_model]) # Fit the model pca_lda.fit(X_flat_train,y_train) @@ -1738,5 +1738,42 @@ def predict(self, X_flat_test): pca_lda_fit = self.model # Get fit model y_test_predicted = pca_lda_fit.predict(X_flat_test) # Make prediction return y_test_predicted + + def get_params(self, deep=True): + """ + Get parameters of pca lda model + + Args: + deep (bool, optional): Defaults to True. + If True, will return the parameters of this estimators + + Returns: + params : dict + Parameter names mapped to their values + """ + return {"explained_variance": self.explained_variance, "da_type": self.da_type} + + def get_scores(self, deep=True): + """ + Get scores of pca and lda model + + Args: + deep (bool, optional): Defaults to True. + + Returns: + scores: dict + Returns fitted scores of PCA and LDA + """ + pca = self.model['pca'] + da = self.model['discriminant'] + scores = dict() + scores['pca'] = pca.componens_ + scores['discriminant'] = da.coef_ + return scores + + + + + \ No newline at end of file From 5f373dbc7d6eba32a7e3a304b60a43e207563b87 Mon Sep 17 00:00:00 2001 From: "dsuseendar@gmail.com" <47862632+dsuseendar@users.noreply.github.com> Date: Mon, 3 Jul 2023 19:30:46 -0400 Subject: [PATCH 4/4] Added class definition for PCA-decomposed decoder --- Neural_Decoding.egg-info/PKG-INFO | 182 ++ Neural_Decoding.egg-info/SOURCES.txt | 12 + Neural_Decoding.egg-info/dependency_links.txt | 1 + Neural_Decoding.egg-info/requires.txt | 1 + Neural_Decoding.egg-info/top_level.txt | 1 + Neural_Decoding/decoders.py | 146 +- build/lib/Neural_Decoding/__init__.py | 4 + build/lib/Neural_Decoding/decoders.py | 1685 +++++++++++++++++ build/lib/Neural_Decoding/metrics.py | 56 + .../Neural_Decoding/preprocessing_funcs.py | 119 ++ decoder_test.ipynb | 1570 +++++++++++++++ dist/Neural_Decoding-0.1.2.dev0-py3.10.egg | Bin 0 -> 30945 bytes 12 files changed, 3757 insertions(+), 20 deletions(-) create mode 100644 Neural_Decoding.egg-info/PKG-INFO create mode 100644 Neural_Decoding.egg-info/SOURCES.txt create mode 100644 Neural_Decoding.egg-info/dependency_links.txt create mode 100644 Neural_Decoding.egg-info/requires.txt create mode 100644 Neural_Decoding.egg-info/top_level.txt create mode 100644 build/lib/Neural_Decoding/__init__.py create mode 100644 build/lib/Neural_Decoding/decoders.py create mode 100644 build/lib/Neural_Decoding/metrics.py create mode 100644 build/lib/Neural_Decoding/preprocessing_funcs.py create mode 100644 decoder_test.ipynb create mode 100644 dist/Neural_Decoding-0.1.2.dev0-py3.10.egg diff --git a/Neural_Decoding.egg-info/PKG-INFO b/Neural_Decoding.egg-info/PKG-INFO new file mode 100644 index 0000000..4738687 --- /dev/null +++ b/Neural_Decoding.egg-info/PKG-INFO @@ -0,0 +1,182 @@ +Metadata-Version: 2.1 +Name: Neural-Decoding +Version: 0.1.2.dev0 +Summary: A python package that includes many methods for decoding neural activity. +Download-URL: https://github.com/KordingLab/Neural_Decoding.git +Maintainer: Josh Glaser +Maintainer-email: joshglaser88@gmail.com +License: BSD 3-Clause License +Platform: any +Classifier: Intended Audience :: Science/Research +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved +Classifier: Programming Language :: Python +Classifier: Topic :: Software Development +Classifier: Topic :: Scientific/Engineering +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: POSIX +Classifier: Operating System :: Unix +Classifier: Operating System :: MacOS +Description-Content-Type: text/markdown +License-File: LICENSE + +# Neural_Decoding: + +### A python package that includes many methods for decoding neural activity + +The package contains a mixture of classic decoding methods and modern machine learning methods. + +For regression, we currently include: Wiener Filter, Wiener Cascade, Kalman Filter, Naive Bayes, Support Vector Regression, XGBoost, Dense Neural Network, Recurrent Neural Net, GRU, LSTM. + +For classification, we currently include: Logistic Regression, Support Vector Classification, XGBoost, Dense Neural Network, Recurrent Neural Net, GRU, LSTM. + +This package was originally designed for regression and classification functions were just added - therefore, the ReadMe, examples, and preprocessing functions are still catered for regression. We are in the process of adding more for classification. + + +## Our manuscript and datasets +This package accompanies a [manuscript](https://arxiv.org/abs/1708.00909) that compares the performance of these methods on several datasets. We would appreciate if you cite that manuscript if you use our code or data for your research. + +Code used for the paper is in the "Paper_code" folder. It is described further at the bottom of this read-me. + +All 3 datasets (motor cortex, somatosensory cortex, and hippocampus) used in the paper can be downloaded [here](https://www.dropbox.com/sh/n4924ipcfjqc0t6/AACPWjxDKPEzQiXKUUFriFkJa?dl=0). They are in both matlab and python formats, and can be used in the example files described below. + +## Installation + +This package can be installed via `pip` at the command line by typing +```buildoutcfg +pip install Neural-Decoding +``` +or manually via +```buildoutcfg +git clone https://github.com/KordingLab/Neural_Decoding.git +cd Neural_Decoding +python setup.py install +``` +You'll have to install each dependency yourself if you install manually. We've designed the code so that not all machine learning packages +need to be installed for the others to work. + +## Dependencies +All packages will be installed automatically when installing from `pip` (because of the `requirements.txt` file). + +If installing manually via `python setup.py install`: +In order to run all the decoders based on neural networks, you need to install [Keras](https://keras.io/#installation)
+In order to run the XGBoost Decoder, you need to install [XGBoost](https://pypi.python.org/pypi/xgboost/)
+In order to run the Wiener Filter, Wiener Cascade, or Support Vector Regression you will need [scikit-learn](http://scikit-learn.org/stable/install.html).
+In order to do hyperparameter optimization, you need to install [BayesianOptimization](https://github.com/fmfn/BayesianOptimization) + +## Getting started +We have included jupyter notebooks that provide detailed examples of how to use the decoders. + - The file **`central_concepts_in_ML_for_decoding.ipynb`** is designed for users who are new to machine learning. It builds basic concepts and shows some examples, and also has several exercises to make sure you know your stuff. (Link to the solutions is inside). + - The file **`Examples_kf_decoder.ipynb`** is for the Kalman filter decoder + - The file **`Examples_all_decoders.ipynb`** is for all other decoders. These examples work well with the somatosensory and motor cortex datasets. + - There are minor differences in the hippocampus dataset, so we have included a folder, **`Examples_hippocampus`**, with analogous example files. This folder also includes an example file for using the Naive Bayes decoder (since it works much better on our hippocampus dataset). + - We have also included a notebook, **`Example_hyperparam_opt.ipynb`**, that demonstrates how to do hyperparameter optimization for the decoders. + +Here we provide a basic example where we are using a LSTM decoder.
+For this example we assume we have already loaded matrices: + - "neural_data": a matrix of size "total number of time bins" x "number of neurons," where each entry is the firing rate of a given neuron in a given time bin. + - "y": the output variable that you are decoding (e.g. velocity), and is a matrix of size "total number of time bins" x "number of features you are decoding."
+ +We have provided a Jupyter notebook, **`Example_format_data.ipynb`** with an example of how to get Matlab data into this format. +
+ +First we will import the necessary functions +```python +from Neural_Decoding.decoders import LSTMDecoder #Import LSTM decoder +from Neural_Decoding.preprocessing_funcs import get_spikes_with_history #Import function to get the covariate matrix that includes spike history from previous bins +``` +Next, we will define the time period we are using spikes from (relative to the output we are decoding) +```python +bins_before=13 #How many bins of neural data prior to the output are used for decoding +bins_current=1 #Whether to use concurrent time bin of neural data +bins_after=0 #How many bins of neural data after the output are used for decoding +``` + +Next, we will compute the covariate matrix that includes the spike history from previous bins +```python +# Function to get the covariate matrix that includes spike history from previous bins +X=get_spikes_with_history(neural_data,bins_before,bins_after,bins_current) +``` +In this basic example, we will ignore some additional preprocessing we do in the example notebooks. Let's assume we have now divided the data into a training set (X_train, y_train) and a testing set (X_test,y_test). + +We will now finally train and test the decoder: +```python +#Declare model and set parameters of the model +model_lstm=LSTMDecoder(units=400,num_epochs=5) + +#Fit model +model_lstm.fit(X_train,y_train) + +#Get predictions +y_test_predicted_lstm=model_lstm.predict(X_test) +``` + +## What's Included +There are 3 files with functions. An overview of the functions are below. More details can be found in the comments within the files. + +### decoders.py: +This file provides all of the decoders. Each decoder is a class with functions "fit" and "predict". + +First, we will describe the format of data that is necessary for the decoders +- For all the decoders, you will need to decide the time period of spikes (relative to the output) that you are using for decoding. +- For all the decoders other than the Kalman filter, you can set "bins_before" (the number of bins of spikes preceding the output), "bins_current" (whether to use the bin of spikes concurrent with the output), and "bins_after" (the number of bins of spikes after the output). Let "surrounding_bins" = bins_before+bins_current+bins_after. This allows us to get a 3d covariate matrix "X" that has size "total number of time bins" x "surrounding_bins" x "number of neurons." We use this input format for the recurrent neural networks (SimpleRNN, GRU, LSTM). We can also flatten the matrix, so that there is a vector of features for every time bin, to get "X_flat" which is a 2d matrix of size "total number of time bins" x "surrounding_bins x number of neurons." This input format is used for the Wiener Filter, Wiener Cascade, Support Vector Regression, XGBoost, and Dense Neural Net. +- For the Kalman filter, you can set the "lag" - what time bin of the neural data (relative to the output) is used to predict the output. The input format for the Kalman filter is simply the 2d matrix of size "total number of time bins" x "number of neurons," where each entry is the firing rate of a given neuron in a given time bin. +- The output, "y" is a 2d matrix of size "total number of time bins" x "number of output features." + +
Here are all the decoders within "decoders.py" for performing regression: +1. **WienerFilterDecoder** + - The Wiener Filter is simply multiple linear regression using X_flat as an input. + - It has no input parameters +2. **WienerCascadeDecoder** + - The Wiener Cascade (also known as a linear nonlinear model) fits a linear regression (the Wiener filter) followed by fitting a static nonlearity. + - It has parameter *degree* (the degree of the polynomial used for the nonlinearity) +3. **KalmanFilterDecoder** + - We used a Kalman filter similar to that implemented in [Wu et al. 2003](https://papers.nips.cc/paper/2178-neural-decoding-of-cursor-motion-using-a-kalman-filter.pdf). In the Kalman filter, the measurement was the neural spike trains, and the hidden state was the kinematics. + - We have one parameter *C* (which is not in the previous implementation). This parameter scales the noise matrix associated with the transition in kinematic states. It effectively allows changing the weight of the new neural evidence in the current update. +4. **NaiveBayesDecoder** + - We used a Naive Bayes decoder similar to that implemented in [Zhang et al. 1998](https://www.physiology.org/doi/abs/10.1152/jn.1998.79.2.1017) (see manuscript for details). + - It has parameters *encoding_model* (for either a linear or quadratic encoding model) and *res* (to set the resolution of predicted values) +5. **SVRDecoder** + - This decoder uses support vector regression using X_flat as an input. + - It has parameters *C* (the penalty of the error term) and *max_iter* (the maximum number of iterations). + - It works best when the output ("y") has been normalized +6. **XGBoostDecoder** + - We used the Extreme Gradient Boosting [XGBoost](http://xgboost.readthedocs.io/en/latest/model.html) algorithm to relate X_flat to the outputs. XGBoost is based on the idea of boosted trees. + - It has parameters *max_depth* (the maximum depth of the trees), *num_round* (the number of trees that are fit), *eta* (the learning rate), and *gpu* (if you have the [gpu version](https://github.com/dmlc/xgboost/tree/master/plugin/updater_gpu) of XGBoost installed, you can select which gpu to use) +7. **DenseNNDecoder** + - Using the Keras library, we created a dense feedforward neural network that uses X_flat to predict the outputs. It can have any number of hidden layers. + - It has parameters *units* (the number of units in each layer), *dropout* (the proportion of units that get dropped out), *num_epochs* (the number of epochs used for training), and *verbose* (whether to display progress of the fit after each epoch) +8. **SimpleRNNDecoder** + - Using the Keras library, we created a neural network architecture where the spiking input (from matrix X) was fed into a standard recurrent neural network (RNN) with a relu activation. The units from this recurrent layer were fully connected to the output layer. + - It has parameters *units*, *dropout*, *num_epochs*, and *verbose* +9. **GRUDecoder** + - Using the Keras library, we created a neural network architecture where the spiking input (from matrix X) was fed into a network of gated recurrent units (GRUs; a more sophisticated RNN). The units from this recurrent layer were fully connected to the output layer. + - It has parameters *units*, *dropout*, *num_epochs*, and *verbose* +10. **LSTMDecoder** + - All methods were the same as for the GRUDecoder, except Long Short Term Memory networks (LSTMs; another more sophisticated RNN) were used rather than GRUs. + - It has parameters *units*, *dropout*, *num_epochs*, and *verbose* + +When designing the XGBoost and neural network decoders, there were many additional parameters that could have been utilized (e.g. regularization). To simplify ease of use, we only included parameters that were sufficient for producing good fits. + +### metrics.py: +The file has functions for metrics to evaluate model fit. It currently has functions to calculate: + - ![equation](https://latex.codecogs.com/gif.latex?%24R%5E2%3D1-%5Csum_%7Bi%3D1%7D%5E%7Bn%7D%7B%7D%5Cfrac%7B%5Cleft%28y_i-%5Cwidehat%7By_i%7D%20%5Cright%20%29%5E2%7D%7B%5Cleft%28y_i-%5Cbar%7By_i%7D%20%5Cright%20%29%5E2%7D) + - ![equation](https://latex.codecogs.com/gif.latex?%24%5Crho%24) : The pearson correlation coefficient + +### preprocessing_funcs.py +The file contains functions for preprocessing data that may be useful for putting the neural activity and outputs in the correct format for our decoding functions + - **bin_spikes**: converts spike times to the number of spikes within time bins + - **bin_output**: converts a continuous stream of outputs to the average output within time bins + - **get_spikes_with_history**: using binned spikes as input, this function creates a covariate matrix of neural data that incorporates spike history + +## Paper code +In the folder "Paper_code", we include code used for the manuscript. + - Files starting with "ManyDecoders" use all decoders except the Kalman Filter and Naive Bayes + - Files starting with "KF" use the Kalman filter + - Files starting with "BayesDecoder" use the Naive Bayes decoder + - Files starting with "Plot" create the figures in the paper + - Files ending with "FullData" are for figures 3/4 + - Files ending with "DataAmt" are for figures 5/6 + - Files ending with "FewNeurons" are for figure 7 + - Files ending with "BinSize" are for figure 8 + - Files mentioning "Hyperparams" are for figure 9 diff --git a/Neural_Decoding.egg-info/SOURCES.txt b/Neural_Decoding.egg-info/SOURCES.txt new file mode 100644 index 0000000..e93ca25 --- /dev/null +++ b/Neural_Decoding.egg-info/SOURCES.txt @@ -0,0 +1,12 @@ +LICENSE +README.md +setup.py +Neural_Decoding/__init__.py +Neural_Decoding/decoders.py +Neural_Decoding/metrics.py +Neural_Decoding/preprocessing_funcs.py +Neural_Decoding.egg-info/PKG-INFO +Neural_Decoding.egg-info/SOURCES.txt +Neural_Decoding.egg-info/dependency_links.txt +Neural_Decoding.egg-info/requires.txt +Neural_Decoding.egg-info/top_level.txt \ No newline at end of file diff --git a/Neural_Decoding.egg-info/dependency_links.txt b/Neural_Decoding.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Neural_Decoding.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/Neural_Decoding.egg-info/requires.txt b/Neural_Decoding.egg-info/requires.txt new file mode 100644 index 0000000..b762719 --- /dev/null +++ b/Neural_Decoding.egg-info/requires.txt @@ -0,0 +1 @@ +numpy>=1.16.3 diff --git a/Neural_Decoding.egg-info/top_level.txt b/Neural_Decoding.egg-info/top_level.txt new file mode 100644 index 0000000..8d74684 --- /dev/null +++ b/Neural_Decoding.egg-info/top_level.txt @@ -0,0 +1 @@ +Neural_Decoding diff --git a/Neural_Decoding/decoders.py b/Neural_Decoding/decoders.py index 6b7f884..709eb84 100644 --- a/Neural_Decoding/decoders.py +++ b/Neural_Decoding/decoders.py @@ -27,12 +27,13 @@ #Import scikit-learn (sklearn) if it is installed try: - from sklearn.pipeline import make_pipeline as mp + from sklearn.pipeline import Pipeline from sklearn import linear_model #For Wiener Filter and Wiener Cascade from sklearn.svm import SVR #For support vector regression (SVR) from sklearn.svm import SVC #For support vector classification (SVM) from sklearn.decomposition import PCA #For PCA decomposition (PCA - LDA) from sklearn import discriminant_analysis as da # For LDA decomposition (PCA - LDA) + from sklearn.base import BaseEstimator except ImportError: print("\nWARNING: scikit-learn is not installed. You will be unable to use the Wiener Filter or Wiener Cascade Decoders") pass @@ -1670,7 +1671,7 @@ def predict(self, X_flat_test): ##################### PRINCIPAL COMPONENT ANALYSIS - LINEAR DISCRIMINANT CLASSIFIER ########################## -class PcaLdaClassification(object): +class PcaLdaClassification(BaseEstimator): """ Class for the PCA - LDA Classifier @@ -1711,7 +1712,7 @@ def fit(self, X_flat_train, y_train): da_model = da.QuadraticDiscriminantAnalysis() # Quadratic discriminant analysis # Create a pipeline classifier - pca_lda = mp(steps =['pca',PCA(n_components=self.explained_variance),'discriminant', da_model]) + pca_lda = Pipeline(steps =[('pca',PCA(n_components=self.explained_variance)),('discriminant', da_model)]) # Fit the model pca_lda.fit(X_flat_train,y_train) @@ -1737,22 +1738,8 @@ def predict(self, X_flat_test): pca_lda_fit = self.model # Get fit model y_test_predicted = pca_lda_fit.predict(X_flat_test) # Make prediction - return y_test_predicted + return y_test_predicted - def get_params(self, deep=True): - """ - Get parameters of pca lda model - - Args: - deep (bool, optional): Defaults to True. - If True, will return the parameters of this estimators - - Returns: - params : dict - Parameter names mapped to their values - """ - return {"explained_variance": self.explained_variance, "da_type": self.da_type} - def get_scores(self, deep=True): """ Get scores of pca and lda model @@ -1771,9 +1758,128 @@ def get_scores(self, deep=True): scores['discriminant'] = da.coef_ return scores + def score(self, X, y, sample_weight=None): + """Returns the mean accuracy on the given test data and labels. + + In multi-label classification, this is the subset accuracy + which is a harsh metric since you require for each sample that + each label set be correctly predicted. + + Parameters + ---------- + X : array-like, shape = (n_samples, n_features) + Test samples. + + y : array-like, shape = (n_samples) or (n_samples, n_outputs) + True labels for X. + + sample_weight : array-like, shape = [n_samples], optional + Sample weights. + + Returns + ------- + score : float + Mean accuracy of self.predict(X) wrt. y. + + """ + from sklearn.metrics import accuracy_score + return accuracy_score(y, self.predict(X), sample_weight=sample_weight) + ##################### PRINCIPAL COMPONENT ANALYSIS Wrapper for classification function ########################## - +from sklearn.base import BaseEstimator +from sklearn.decomposition import PCA +from sklearn.pipeline import Pipeline +from sklearn.svm import SVC +from sklearn.metrics import accuracy_score + +class PcaEstimateDecoder(BaseEstimator): + """ + Class for the PCA - SVM Classifier + + Parameters + ---------- + explained_variance: float, optional, default=0.8 + the cumulative explained variance ratio required for PCA + + clf: object, optional, default=SVC() + the classifier object to use for classification + + clf_params: dict, optional + Additional parameters to be passed to the classifier (e.g., {'param_name': value}) + + """ + + def __init__(self, explained_variance=0.8, clf=SVC(), clf_params=None): + self.explained_variance = explained_variance + self.clf = clf + self.clf_params = clf_params + self._initialize_model() + + def _initialize_model(self): + self.pca = PCA(n_components=self.explained_variance) + if self.clf_params is not None: + + self.model = Pipeline(steps=[('pca', self.pca), ('model', self.clf.set_params(**self.clf_params))]) + else: + print('No initial parameters') + self.model = Pipeline(steps=[('pca', self.pca), ('model', self.clf)]) + + def fit(self, X_flat_train, y_train): + """ + Train PCA - SVM classifier + + Parameters + ---------- + X_flat_train: numpy 2d array of shape [n_samples, n_features] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 1d array of shape (n_samples), with integers representing classes + This is the outputs that are being predicted + """ + self._initialize_model() + self.model.fit(X_flat_train, y_train) + + def predict(self, X_flat_test): + """ + Predict outcomes using trained PCA - SVM Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples, n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 1d array with integers as classes + The predicted outputs + """ + return self.model.predict(X_flat_test) + + + + def score(self, X, y, sample_weight=None): + """ + Returns the mean accuracy on the given test data and labels. + + Parameters + ---------- + X : array-like, shape = (n_samples, n_features) + Test samples. + + y : array-like, shape = (n_samples,) or (n_samples, n_outputs) + True labels for X. + + sample_weight : array-like, shape = [n_samples], optional + Sample weights. + + Returns + ------- + score : float + Mean accuracy of self.predict(X) wrt. y. + + """ + return accuracy_score(y, self.predict(X), sample_weight=sample_weight) - \ No newline at end of file diff --git a/build/lib/Neural_Decoding/__init__.py b/build/lib/Neural_Decoding/__init__.py new file mode 100644 index 0000000..3539b10 --- /dev/null +++ b/build/lib/Neural_Decoding/__init__.py @@ -0,0 +1,4 @@ +from .decoders import WienerFilterDecoder, WienerCascadeDecoder, KalmanFilterDecoder,\ + DenseNNDecoder, SimpleRNNDecoder, GRUDecoder, LSTMDecoder, XGBoostDecoder, SVRDecoder, NaiveBayesDecoder +from .metrics import get_R2, get_rho +from .preprocessing_funcs import bin_output, bin_spikes, get_spikes_with_history \ No newline at end of file diff --git a/build/lib/Neural_Decoding/decoders.py b/build/lib/Neural_Decoding/decoders.py new file mode 100644 index 0000000..42b3a28 --- /dev/null +++ b/build/lib/Neural_Decoding/decoders.py @@ -0,0 +1,1685 @@ +############### IMPORT PACKAGES ################## + +import numpy as np +from numpy.linalg import inv as inv #Used in kalman filter + +#Used for naive bayes decoder +try: + import statsmodels.api as sm +except ImportError: + print("\nWARNING: statsmodels is not installed. You will be unable to use the Naive Bayes Decoder") + pass +try: + import math +except ImportError: + print("\nWARNING: math is not installed. You will be unable to use the Naive Bayes Decoder") + pass +try: + from scipy.spatial.distance import pdist + from scipy.spatial.distance import squareform + from scipy.stats import norm + from scipy.spatial.distance import cdist +except ImportError: + print("\nWARNING: scipy is not installed. You will be unable to use the Naive Bayes Decoder") + pass + + + +#Import scikit-learn (sklearn) if it is installed +try: + from sklearn import linear_model #For Wiener Filter and Wiener Cascade + from sklearn.svm import SVR #For support vector regression (SVR) + from sklearn.svm import SVC #For support vector classification (SVM) +except ImportError: + print("\nWARNING: scikit-learn is not installed. You will be unable to use the Wiener Filter or Wiener Cascade Decoders") + pass + +#Import XGBoost if the package is installed +try: + import xgboost as xgb #For xgboost +except ImportError: + print("\nWARNING: Xgboost package is not installed. You will be unable to use the xgboost decoder") + pass + +#Import functions for Keras if Keras is installed +#Note that Keras has many more built-in functions that I have not imported because I have not used them +#But if you want to modify the decoders with other functions (e.g. regularization), import them here +try: + import keras + keras_v1=int(keras.__version__[0])<=1 + from keras.models import Sequential + from keras.layers import Dense, LSTM, SimpleRNN, GRU, Activation, Dropout + from keras.utils import np_utils +except ImportError: + print("\nWARNING: Keras package is not installed. You will be unable to use all neural net decoders") + pass + +try: + from sklearn.preprocessing import OneHotEncoder +except ImportError: + print("\nWARNING: Sklearn OneHotEncoder not installed. You will be unable to use XGBoost for Classification") + pass + + + +##################### DECODER FUNCTIONS ########################## + + + +##################### WIENER FILTER ########################## + +class WienerFilterRegression(object): + + """ + Class for the Wiener Filter Decoder + + There are no parameters to set. + + This simply leverages the scikit-learn linear regression. + """ + + def __init__(self): + return + + + def fit(self,X_flat_train,y_train): + + """ + Train Wiener Filter Decoder + + Parameters + ---------- + X_flat_train: numpy 2d array of shape [n_samples,n_features] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + self.model=linear_model.LinearRegression() #Initialize linear regression model + self.model.fit(X_flat_train, y_train) #Train the model + + + def predict(self,X_flat_test): + + """ + Predict outcomes using trained Wiener Cascade Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + y_test_predicted=self.model.predict(X_flat_test) #Make predictions + return y_test_predicted + + + + +##################### WIENER CASCADE ########################## + +class WienerCascadeRegression(object): + + """ + Class for the Wiener Cascade Decoder + + Parameters + ---------- + degree: integer, optional, default 3 + The degree of the polynomial used for the static nonlinearity + """ + + def __init__(self,degree=3): + self.degree=degree + + + def fit(self,X_flat_train,y_train): + + """ + Train Wiener Cascade Decoder + + Parameters + ---------- + X_flat_train: numpy 2d array of shape [n_samples,n_features] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + num_outputs=y_train.shape[1] #Number of outputs + models=[] #Initialize list of models (there will be a separate model for each output) + for i in range(num_outputs): #Loop through outputs + #Fit linear portion of model + regr = linear_model.LinearRegression() #Call the linear portion of the model "regr" + regr.fit(X_flat_train, y_train[:,i]) #Fit linear + y_train_predicted_linear=regr.predict(X_flat_train) # Get outputs of linear portion of model + #Fit nonlinear portion of model + p=np.polyfit(y_train_predicted_linear,y_train[:,i],self.degree) + #Add model for this output (both linear and nonlinear parts) to the list "models" + models.append([regr,p]) + self.model=models + + + def predict(self,X_flat_test): + + """ + Predict outcomes using trained Wiener Cascade Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + num_outputs=len(self.model) #Number of outputs being predicted. Recall from the "fit" function that self.model is a list of models + y_test_predicted=np.empty([X_flat_test.shape[0],num_outputs]) #Initialize matrix that contains predicted outputs + for i in range(num_outputs): #Loop through outputs + [regr,p]=self.model[i] #Get the linear (regr) and nonlinear (p) portions of the trained model + #Predictions on test set + y_test_predicted_linear=regr.predict(X_flat_test) #Get predictions on the linear portion of the model + y_test_predicted[:,i]=np.polyval(p,y_test_predicted_linear) #Run the linear predictions through the nonlinearity to get the final predictions + return y_test_predicted + + + +##################### KALMAN FILTER ########################## + +class KalmanFilterRegression(object): + + """ + Class for the Kalman Filter Decoder + + Parameters + ----------- + C - float, optional, default 1 + This parameter scales the noise matrix associated with the transition in kinematic states. + It effectively allows changing the weight of the new neural evidence in the current update. + + Our implementation of the Kalman filter for neural decoding is based on that of Wu et al 2003 (https://papers.nips.cc/paper/2178-neural-decoding-of-cursor-motion-using-a-kalman-filter.pdf) + with the exception of the addition of the parameter C. + The original implementation has previously been coded in Matlab by Dan Morris (http://dmorris.net/projects/neural_decoding.html#code) + """ + + def __init__(self,C=1): + self.C=C + + + def fit(self,X_kf_train,y_train): + + """ + Train Kalman Filter Decoder + + Parameters + ---------- + X_kf_train: numpy 2d array of shape [n_samples(i.e. timebins) , n_neurons] + This is the neural data in Kalman filter format. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples(i.e. timebins), n_outputs] + This is the outputs that are being predicted + """ + + #First we'll rename and reformat the variables to be in a more standard kalman filter nomenclature (specifically that from Wu et al, 2003): + #xs are the state (here, the variable we're predicting, i.e. y_train) + #zs are the observed variable (neural data here, i.e. X_kf_train) + X=np.matrix(y_train.T) + Z=np.matrix(X_kf_train.T) + + #number of time bins + nt=X.shape[1] + + #Calculate the transition matrix (from x_t to x_t+1) using least-squares, and compute its covariance + #In our case, this is the transition from one kinematic state to the next + X2 = X[:,1:] + X1 = X[:,0:nt-1] + A=X2*X1.T*inv(X1*X1.T) #Transition matrix + W=(X2-A*X1)*(X2-A*X1).T/(nt-1)/self.C #Covariance of transition matrix. Note we divide by nt-1 since only nt-1 points were used in the computation (that's the length of X1 and X2). We also introduce the extra parameter C here. + + #Calculate the measurement matrix (from x_t to z_t) using least-squares, and compute its covariance + #In our case, this is the transformation from kinematics to spikes + H = Z*X.T*(inv(X*X.T)) #Measurement matrix + Q = ((Z - H*X)*((Z - H*X).T)) / nt #Covariance of measurement matrix + params=[A,W,H,Q] + self.model=params + + def predict(self,X_kf_test,y_test): + + """ + Predict outcomes using trained Kalman Filter Decoder + + Parameters + ---------- + X_kf_test: numpy 2d array of shape [n_samples(i.e. timebins) , n_neurons] + This is the neural data in Kalman filter format. + + y_test: numpy 2d array of shape [n_samples(i.e. timebins),n_outputs] + The actual outputs + This parameter is necesary for the Kalman filter (unlike other decoders) + because the first value is nececessary for initialization + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples(i.e. timebins),n_outputs] + The predicted outputs + """ + + #Extract parameters + A,W,H,Q=self.model + + #First we'll rename and reformat the variables to be in a more standard kalman filter nomenclature (specifically that from Wu et al): + #xs are the state (here, the variable we're predicting, i.e. y_train) + #zs are the observed variable (neural data here, i.e. X_kf_train) + X=np.matrix(y_test.T) + Z=np.matrix(X_kf_test.T) + + #Initializations + num_states=X.shape[0] #Dimensionality of the state + states=np.empty(X.shape) #Keep track of states over time (states is what will be returned as y_test_predicted) + P_m=np.matrix(np.zeros([num_states,num_states])) + P=np.matrix(np.zeros([num_states,num_states])) + state=X[:,0] #Initial state + states[:,0]=np.copy(np.squeeze(state)) + + #Get predicted state for every time bin + for t in range(X.shape[1]-1): + #Do first part of state update - based on transition matrix + P_m=A*P*A.T+W + state_m=A*state + + #Do second part of state update - based on measurement matrix + K=P_m*H.T*inv(H*P_m*H.T+Q) #Calculate Kalman gain + P=(np.matrix(np.eye(num_states))-K*H)*P_m + state=state_m+K*(Z[:,t+1]-H*state_m) + states[:,t+1]=np.squeeze(state) #Record state at the timestep + y_test_predicted=states.T + return y_test_predicted + + + + + + + + + +##################### DENSE (FULLY-CONNECTED) NEURAL NETWORK ########################## + +class DenseNNRegression(object): + + """ + Class for the dense (fully-connected) neural network decoder + + Parameters + ---------- + + units: integer or vector of integers, optional, default 400 + This is the number of hidden units in each layer + If you want a single layer, input an integer (e.g. units=400 will give you a single hidden layer with 400 units) + If you want multiple layers, input a vector (e.g. units=[400,200]) will give you 2 hidden layers with 400 and 200 units, repsectively. + The vector can either be a list or an array + + dropout: decimal, optional, default 0 + Proportion of units that get dropped out + + num_epochs: integer, optional, default 10 + Number of epochs used for training + + verbose: binary, optional, default=0 + Whether to show progress of the fit after each epoch + """ + + def __init__(self,units=400,dropout=0,num_epochs=10,verbose=0): + self.dropout=dropout + self.num_epochs=num_epochs + self.verbose=verbose + + #If "units" is an integer, put it in the form of a vector + try: #Check if it's a vector + units[0] + except: #If it's not a vector, create a vector of the number of units for each layer + units=[units] + self.units=units + + #Determine the number of hidden layers (based on "units" that the user entered) + self.num_layers=len(units) + + def fit(self,X_flat_train,y_train): + + """ + Train DenseNN Decoder + + Parameters + ---------- + X_flat_train: numpy 2d array of shape [n_samples,n_features] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + model=Sequential() #Declare model + #Add first hidden layer + model.add(Dense(self.units[0],input_dim=X_flat_train.shape[1])) #Add dense layer + model.add(Activation('relu')) #Add nonlinear (tanh) activation + # if self.dropout!=0: + if self.dropout!=0: model.add(Dropout(self.dropout)) #Dropout some units if proportion of dropout != 0 + + #Add any additional hidden layers (beyond the 1st) + for layer in range(self.num_layers-1): #Loop through additional layers + model.add(Dense(self.units[layer+1])) #Add dense layer + model.add(Activation('relu')) #Add nonlinear (tanh) activation + if self.dropout!=0: model.add(Dropout(self.dropout)) #Dropout some units if proportion of dropout != 0 + + #Add dense connections to all outputs + model.add(Dense(y_train.shape[1])) #Add final dense layer (connected to outputs) + + #Fit model (and set fitting parameters) + model.compile(loss='mse',optimizer='adam',metrics=['accuracy']) #Set loss function and optimizer + if keras_v1: + model.fit(X_flat_train,y_train,nb_epoch=self.num_epochs,verbose=self.verbose) #Fit the model + else: + model.fit(X_flat_train,y_train,epochs=self.num_epochs,verbose=self.verbose) #Fit the model + self.model=model + + + def predict(self,X_flat_test): + + """ + Predict outcomes using trained DenseNN Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + y_test_predicted = self.model.predict(X_flat_test) #Make predictions + return y_test_predicted + + + + +##################### SIMPLE RECURRENT NEURAL NETWORK ########################## + +class SimpleRNNRegression(object): + + """ + Class for the simple recurrent neural network decoder + + Parameters + ---------- + units: integer, optional, default 400 + Number of hidden units in each layer + + dropout: decimal, optional, default 0 + Proportion of units that get dropped out + + num_epochs: integer, optional, default 10 + Number of epochs used for training + + verbose: binary, optional, default=0 + Whether to show progress of the fit after each epoch + """ + + def __init__(self,units=400,dropout=0,num_epochs=10,verbose=0): + self.units=units + self.dropout=dropout + self.num_epochs=num_epochs + self.verbose=verbose + + + def fit(self,X_train,y_train): + + """ + Train SimpleRNN Decoder + + Parameters + ---------- + X_train: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + model=Sequential() #Declare model + #Add recurrent layer + if keras_v1: + model.add(SimpleRNN(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout_W=self.dropout,dropout_U=self.dropout,activation='relu')) #Within recurrent layer, include dropout + else: + model.add(SimpleRNN(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout=self.dropout,recurrent_dropout=self.dropout,activation='relu')) #Within recurrent layer, include dropout + if self.dropout!=0: model.add(Dropout(self.dropout)) #Dropout some units (recurrent layer output units) + + #Add dense connections to output layer + model.add(Dense(y_train.shape[1])) + + #Fit model (and set fitting parameters) + model.compile(loss='mse',optimizer='rmsprop',metrics=['accuracy']) #Set loss function and optimizer + if keras_v1: + model.fit(X_train,y_train,nb_epoch=self.num_epochs,verbose=self.verbose) #Fit the model + else: + model.fit(X_train,y_train,epochs=self.num_epochs,verbose=self.verbose) #Fit the model + self.model=model + + + def predict(self,X_test): + + """ + Predict outcomes using trained SimpleRNN Decoder + + Parameters + ---------- + X_test: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + y_test_predicted = self.model.predict(X_test) #Make predictions + return y_test_predicted + + + +##################### GATED RECURRENT UNIT (GRU) DECODER ########################## + +class GRURegression(object): + + """ + Class for the gated recurrent unit (GRU) decoder + + Parameters + ---------- + units: integer, optional, default 400 + Number of hidden units in each layer + + dropout: decimal, optional, default 0 + Proportion of units that get dropped out + + num_epochs: integer, optional, default 10 + Number of epochs used for training + + verbose: binary, optional, default=0 + Whether to show progress of the fit after each epoch + """ + + def __init__(self,units=400,dropout=0,num_epochs=10,verbose=0): + self.units=units + self.dropout=dropout + self.num_epochs=num_epochs + self.verbose=verbose + + + def fit(self,X_train,y_train): + + """ + Train GRU Decoder + + Parameters + ---------- + X_train: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + model=Sequential() #Declare model + #Add recurrent layer + if keras_v1: + model.add(GRU(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout_W=self.dropout,dropout_U=self.dropout)) #Within recurrent layer, include dropout + else: + model.add(GRU(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout=self.dropout,recurrent_dropout=self.dropout)) + if self.dropout!=0: model.add(Dropout(self.dropout)) #Dropout some units (recurrent layer output units) + + #Add dense connections to output layer + model.add(Dense(y_train.shape[1])) + + #Fit model (and set fitting parameters) + model.compile(loss='mse',optimizer='rmsprop',metrics=['accuracy']) #Set loss function and optimizer + if keras_v1: + model.fit(X_train,y_train,nb_epoch=self.num_epochs,verbose=self.verbose) #Fit the model + else: + model.fit(X_train,y_train,epochs=self.num_epochs,verbose=self.verbose) #Fit the model + self.model=model + + + def predict(self,X_test): + + """ + Predict outcomes using trained GRU Decoder + + Parameters + ---------- + X_test: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + y_test_predicted = self.model.predict(X_test) #Make predictions + return y_test_predicted + + + +#################### LONG SHORT TERM MEMORY (LSTM) DECODER ########################## + +class LSTMRegression(object): + + """ + Class for the gated recurrent unit (GRU) decoder + + Parameters + ---------- + units: integer, optional, default 400 + Number of hidden units in each layer + + dropout: decimal, optional, default 0 + Proportion of units that get dropped out + + num_epochs: integer, optional, default 10 + Number of epochs used for training + + verbose: binary, optional, default=0 + Whether to show progress of the fit after each epoch + """ + + def __init__(self,units=400,dropout=0,num_epochs=10,verbose=0): + self.units=units + self.dropout=dropout + self.num_epochs=num_epochs + self.verbose=verbose + + + def fit(self,X_train,y_train): + + """ + Train LSTM Decoder + + Parameters + ---------- + X_train: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + model=Sequential() #Declare model + #Add recurrent layer + if keras_v1: + model.add(LSTM(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout_W=self.dropout,dropout_U=self.dropout)) #Within recurrent layer, include dropout + else: + model.add(LSTM(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout=self.dropout,recurrent_dropout=self.dropout)) #Within recurrent layer, include dropout + if self.dropout!=0: model.add(Dropout(self.dropout)) #Dropout some units (recurrent layer output units) + + #Add dense connections to output layer + model.add(Dense(y_train.shape[1])) + + #Fit model (and set fitting parameters) + model.compile(loss='mse',optimizer='rmsprop',metrics=['accuracy']) #Set loss function and optimizer + if keras_v1: + model.fit(X_train,y_train,nb_epoch=self.num_epochs,verbose=self.verbose) #Fit the model + else: + model.fit(X_train,y_train,epochs=self.num_epochs,verbose=self.verbose) #Fit the model + self.model=model + + + def predict(self,X_test): + + """ + Predict outcomes using trained LSTM Decoder + + Parameters + ---------- + X_test: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + y_test_predicted = self.model.predict(X_test) #Make predictions + return y_test_predicted + + + +##################### EXTREME GRADIENT BOOSTING (XGBOOST) ########################## + +class XGBoostRegression(object): + + """ + Class for the XGBoost Decoder + + Parameters + ---------- + max_depth: integer, optional, default=3 + the maximum depth of the trees + + num_round: integer, optional, default=300 + the number of trees that are fit + + eta: float, optional, default=0.3 + the learning rate + + gpu: integer, optional, default=-1 + if the gpu version of xgboost is installed, this can be used to select which gpu to use + for negative values (default), the gpu is not used + """ + + def __init__(self,max_depth=3,num_round=300,eta=0.3,gpu=-1): + self.max_depth=max_depth + self.num_round=num_round + self.eta=eta + self.gpu=gpu + + def fit(self,X_flat_train,y_train): + + """ + Train XGBoost Decoder + + Parameters + ---------- + X_flat_train: numpy 2d array of shape [n_samples,n_features] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + + num_outputs=y_train.shape[1] #Number of outputs + + #Set parameters for XGBoost + param = {'objective': "reg:linear", #for linear output + 'eval_metric': "logloss", #loglikelihood loss + 'max_depth': self.max_depth, #this is the only parameter we have set, it's one of the way or regularizing + 'eta': self.eta, + 'seed': 2925, #for reproducibility + 'silent': 1} + if self.gpu<0: + param['nthread'] = -1 #with -1 it will use all available threads + else: + param['gpu_id']=self.gpu + param['updater']='grow_gpu' + + models=[] #Initialize list of models (there will be a separate model for each output) + for y_idx in range(num_outputs): #Loop through outputs + dtrain = xgb.DMatrix(X_flat_train, label=y_train[:,y_idx]) #Put in correct format for XGB + bst = xgb.train(param, dtrain, self.num_round) #Train model + models.append(bst) #Add fit model to list of models + + self.model=models + + + def predict(self,X_flat_test): + + """ + Predict outcomes using trained XGBoost Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + dtest = xgb.DMatrix(X_flat_test) #Put in XGB format + num_outputs=len(self.model) #Number of outputs + y_test_predicted=np.empty([X_flat_test.shape[0],num_outputs]) #Initialize matrix of predicted outputs + for y_idx in range(num_outputs): #Loop through outputs + bst=self.model[y_idx] #Get fit model for this output + y_test_predicted[:,y_idx] = bst.predict(dtest) #Make prediction + return y_test_predicted + + +##################### SUPPORT VECTOR REGRESSION ########################## + +class SVRegression(object): + + """ + Class for the Support Vector Regression (SVR) Decoder + This simply leverages the scikit-learn SVR + + Parameters + ---------- + C: float, default=3.0 + Penalty parameter of the error term + + max_iter: integer, default=-1 + the maximum number of iteraations to run (to save time) + max_iter=-1 means no limit + Typically in the 1000s takes a short amount of time on a laptop + """ + + def __init__(self,max_iter=-1,C=3.0): + self.max_iter=max_iter + self.C=C + return + + + def fit(self,X_flat_train,y_train): + + """ + Train SVR Decoder + + Parameters + ---------- + X_flat_train: numpy 2d array of shape [n_samples,n_features] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + num_outputs=y_train.shape[1] #Number of outputs + models=[] #Initialize list of models (there will be a separate model for each output) + for y_idx in range(num_outputs): #Loop through outputs + model=SVR(C=self.C, max_iter=self.max_iter) #Initialize SVR model + model.fit(X_flat_train, y_train[:,y_idx]) #Train the model + models.append(model) #Add fit model to list of models + self.model=models + + + def predict(self,X_flat_test): + + """ + Predict outcomes using trained SVR Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + num_outputs=len(self.model) #Number of outputs + y_test_predicted=np.empty([X_flat_test.shape[0],num_outputs]) #Initialize matrix of predicted outputs + for y_idx in range(num_outputs): #Loop through outputs + model=self.model[y_idx] #Get fit model for that output + y_test_predicted[:,y_idx]=model.predict(X_flat_test) #Make predictions + return y_test_predicted + + + + +#GLM helper function for the NaiveBayesDecoder +def glm_run(Xr, Yr, X_range): + + X2 = sm.add_constant(Xr) + + poiss_model = sm.GLM(Yr, X2, family=sm.families.Poisson()) + try: + glm_results = poiss_model.fit() + Y_range=glm_results.predict(sm.add_constant(X_range)) + except np.linalg.LinAlgError: + print("\nWARNING: LinAlgError") + Y_range=np.mean(Yr)*np.ones([X_range.shape[0],1]) + + return Y_range + + +class NaiveBayesRegression(object): + + """ + Class for the Naive Bayes Decoder + + Parameters + ---------- + encoding_model: string, default='quadratic' + what encoding model is used + + res:int, default=100 + resolution of predicted values + This is the number of bins to divide the outputs into (going from minimum to maximum) + larger values will make decoding slower + """ + + def __init__(self,encoding_model='quadratic',res=100): + self.encoding_model=encoding_model + self.res=res + return + + def fit(self,X_b_train,y_train): + + """ + Train Naive Bayes Decoder + + Parameters + ---------- + X_b_train: numpy 2d array of shape [n_samples,n_neurons] + This is the neural training data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted (training data) + """ + + #### FIT TUNING CURVE #### + #First, get the output values (x/y position or velocity) that we will be creating tuning curves over + #Create the range for x and y (position/velocity) values + input_x_range=np.arange(np.min(y_train[:,0]),np.max(y_train[:,0])+.01,np.round((np.max(y_train[:,0])-np.min(y_train[:,0]))/self.res)) + input_y_range=np.arange(np.min(y_train[:,1]),np.max(y_train[:,1])+.01,np.round((np.max(y_train[:,1])-np.min(y_train[:,1]))/self.res)) + #Get all combinations of x/y values + input_mat=np.meshgrid(input_x_range,input_y_range) + #Format so that all combinations of x/y values are in 2 columns (first column x, second column y). This is called "input_xy" + xs=np.reshape(input_mat[0],[input_x_range.shape[0]*input_y_range.shape[0],1]) + ys=np.reshape(input_mat[1],[input_x_range.shape[0]*input_y_range.shape[0],1]) + input_xy=np.concatenate((xs,ys),axis=1) + + #If quadratic model: + # -make covariates have squared components and mixture of x and y + # -do same thing for "input_xy", which are the values for creating the tuning curves + if self.encoding_model=='quadratic': + input_xy_modified=np.empty([input_xy.shape[0],5]) + input_xy_modified[:,0]=input_xy[:,0]**2 + input_xy_modified[:,1]=input_xy[:,0] + input_xy_modified[:,2]=input_xy[:,1]**2 + input_xy_modified[:,3]=input_xy[:,1] + input_xy_modified[:,4]=input_xy[:,0]*input_xy[:,1] + y_train_modified=np.empty([y_train.shape[0],5]) + y_train_modified[:,0]=y_train[:,0]**2 + y_train_modified[:,1]=y_train[:,0] + y_train_modified[:,2]=y_train[:,1]**2 + y_train_modified[:,3]=y_train[:,1] + y_train_modified[:,4]=y_train[:,0]*y_train[:,1] + + #Create tuning curves + + num_nrns=X_b_train.shape[1] #Number of neurons to fit tuning curves for + tuning_all=np.zeros([num_nrns,input_xy.shape[0]]) #Matrix that stores tuning curves for all neurons + + #Loop through neurons and fit tuning curves + for j in range(num_nrns): #Neuron number + + if self.encoding_model=='linear': + tuning=glm_run(y_train,X_b_train[:,j:j+1],input_xy) + if self.encoding_model=='quadratic': + tuning=glm_run(y_train_modified,X_b_train[:,j:j+1],input_xy_modified) + #Enter tuning curves into matrix + tuning_all[j,:]=np.squeeze(tuning) + + #Save tuning curves to be used in "predict" function + self.tuning_all=tuning_all + self.input_xy=input_xy + + #Get information about the probability of being in one state (position/velocity) based on the previous state + #Here we're calculating the standard deviation of the change in state (velocity/acceleration) in the training set + n=y_train.shape[0] + dx=np.zeros([n-1,1]) + for i in range(n-1): + dx[i]=np.sqrt((y_train[i+1,0]-y_train[i,0])**2+(y_train[i+1,1]-y_train[i,1])**2) #Change in state across time steps + std=np.sqrt(np.mean(dx**2)) #dx is only positive. this gets approximate stdev of distribution (if it was positive and negative) + self.std=std #Save for use in "predict" function + + #Get probability of being in each state - we are not using this since it did not help decoding performance + # n_x=np.empty([input_xy.shape[0]]) + # for i in range(n): + # loc_idx=np.argmin(cdist(y_train[0:1,:],input_xy)) + # n_x[loc_idx]=n_x[loc_idx]+1 + # p_x=n_x/n + # self.p_x=p_x + + def predict(self,X_b_test,y_test): + + """ + Predict outcomes using trained tuning curves + + Parameters + ---------- + X_b_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + y_test: numpy 2d array of shape [n_samples,n_outputs] + The actual outputs + This parameter is necesary for the NaiveBayesDecoder (unlike most other decoders) + because the first value is nececessary for initialization + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + #Get values saved in "fit" function + tuning_all=self.tuning_all + input_xy=self.input_xy + std=self.std + + #Get probability of going from one state to the next + dists = squareform(pdist(input_xy, 'euclidean')) #Distance between all states in "input_xy" + #Probability of going from one state to the next, based on the above calculated distances + #The probability is calculated based on the distances coming from a Gaussian with standard deviation of std + prob_dists=norm.pdf(dists,0,std) + + #Initializations + loc_idx= np.argmin(cdist(y_test[0:1,:],input_xy)) #The index of the first location + num_nrns=tuning_all.shape[0] #Number of neurons + y_test_predicted=np.empty([X_b_test.shape[0],2]) #Initialize matrix of predicted outputs + num_ts=X_b_test.shape[0] #Number of time steps we are predicting + + #Loop across time and decode + for t in range(num_ts): + rs=X_b_test[t,:] #Number of spikes at this time point (in the interval we've specified including bins_before and bins_after) + + probs_total=np.ones([tuning_all[0,:].shape[0]]) #Vector that stores the probabilities of being in any state based on the neural activity (does not include probabilities of going from one state to the next) + for j in range(num_nrns): #Loop across neurons + lam=np.copy(tuning_all[j,:]) #Expected spike counts given the tuning curve + r=rs[j] #Actual spike count + probs=np.exp(-lam)*lam**r/math.factorial(r) #Probability of the given neuron's spike count given tuning curve (assuming poisson distribution) + probs_total=np.copy(probs_total*probs) #Update the probability across neurons (probabilities are multiplied across neurons due to the independence assumption) + prob_dists_vec=np.copy(prob_dists[loc_idx,:]) #Probability of going to all states from the previous state + probs_final=probs_total*prob_dists_vec #Get final probability (multiply probabilities based on spike count and previous state) + # probs_final=probs_total*prob_dists_vec*self.p_x #Get final probability when including p(x), i.e. prior about being in states, which we're not using + loc_idx=np.argmax(probs_final) #Get the index of the current state (that w/ the highest probability) + y_test_predicted[t,:]=input_xy[loc_idx,:] #The current predicted output + + return y_test_predicted #Return predictions + + + +######### ALIASES for Regression ######## + +WienerFilterDecoder = WienerFilterRegression +WienerCascadeDecoder = WienerCascadeRegression +KalmanFilterDecoder = KalmanFilterRegression +DenseNNDecoder = DenseNNRegression +SimpleRNNDecoder = SimpleRNNRegression +GRUDecoder = GRURegression +LSTMDecoder = LSTMRegression +XGBoostDecoder = XGBoostRegression +SVRDecoder = SVRegression +NaiveBayesDecoder = NaiveBayesRegression + + + + +####################################### CLASSIFICATION #################################################### + + + + +class WienerFilterClassification(object): + + """ + Class for the Wiener Filter Decoder + + There are no parameters to set. + + This simply leverages the scikit-learn logistic regression. + """ + + def __init__(self,C=1): + self.C=C + return + + + def fit(self,X_flat_train,y_train): + + """ + Train Wiener Filter Decoder + + Parameters + ---------- + X_flat_train: numpy 2d array of shape [n_samples,n_features] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + # if self.C>0: + self.model=linear_model.LogisticRegression(C=self.C,multi_class='auto') #Initialize linear regression model + # else: + # self.model=linear_model.LogisticRegression(penalty='none',solver='newton-cg') #Initialize linear regression model + self.model.fit(X_flat_train, y_train) #Train the model + + + def predict(self,X_flat_test): + + """ + Predict outcomes using trained Wiener Cascade Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + y_test_predicted=self.model.predict(X_flat_test) #Make predictions + return y_test_predicted + + + + +##################### SUPPORT VECTOR REGRESSION ########################## + +class SVClassification(object): + + """ + Class for the Support Vector Classification Decoder + This simply leverages the scikit-learn SVM + + Parameters + ---------- + C: float, default=3.0 + Penalty parameter of the error term + + max_iter: integer, default=-1 + the maximum number of iteraations to run (to save time) + max_iter=-1 means no limit + Typically in the 1000s takes a short amount of time on a laptop + """ + + def __init__(self,max_iter=-1,C=3.0): + self.max_iter=max_iter + self.C=C + return + + + def fit(self,X_flat_train,y_train): + + """ + Train SVR Decoder + + Parameters + ---------- + X_flat_train: numpy 2d array of shape [n_samples,n_features] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + model=SVC(C=self.C, max_iter=self.max_iter) #Initialize model + model.fit(X_flat_train, y_train) #Train the model + self.model=model + + + def predict(self,X_flat_test): + + """ + Predict outcomes using trained SV Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + model=self.model #Get fit model for that output + y_test_predicted=model.predict(X_flat_test) #Make predictions + return y_test_predicted + + +##################### DENSE (FULLY-CONNECTED) NEURAL NETWORK ########################## + +class DenseNNClassification(object): + + """ + Class for the dense (fully-connected) neural network decoder + + Parameters + ---------- + + units: integer or vector of integers, optional, default 400 + This is the number of hidden units in each layer + If you want a single layer, input an integer (e.g. units=400 will give you a single hidden layer with 400 units) + If you want multiple layers, input a vector (e.g. units=[400,200]) will give you 2 hidden layers with 400 and 200 units, repsectively. + The vector can either be a list or an array + + dropout: decimal, optional, default 0 + Proportion of units that get dropped out + + num_epochs: integer, optional, default 10 + Number of epochs used for training + + verbose: binary, optional, default=0 + Whether to show progress of the fit after each epoch + """ + + def __init__(self,units=400,dropout=0,num_epochs=10,verbose=0): + self.dropout=dropout + self.num_epochs=num_epochs + self.verbose=verbose + + #If "units" is an integer, put it in the form of a vector + try: #Check if it's a vector + units[0] + except: #If it's not a vector, create a vector of the number of units for each layer + units=[units] + self.units=units + + #Determine the number of hidden layers (based on "units" that the user entered) + self.num_layers=len(units) + + def fit(self,X_flat_train,y_train): + + """ + Train DenseNN Decoder + + Parameters + ---------- + X_flat_train: numpy 2d array of shape [n_samples,n_features] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + #Use one-hot coding for y + if y_train.ndim==1: + y_train=np_utils.to_categorical(y_train.astype(int)) + elif y_train.shape[1]==1: + y_train=np_utils.to_categorical(y_train.astype(int)) + + model=Sequential() #Declare model + #Add first hidden layer + model.add(Dense(self.units[0],input_dim=X_flat_train.shape[1])) #Add dense layer + model.add(Activation('relu')) #Add nonlinear (tanh) activation + # if self.dropout!=0: + if self.dropout!=0: model.add(Dropout(self.dropout)) #Dropout some units if proportion of dropout != 0 + + #Add any additional hidden layers (beyond the 1st) + for layer in range(self.num_layers-1): #Loop through additional layers + model.add(Dense(self.units[layer+1])) #Add dense layer + model.add(Activation('tanh')) #Add nonlinear (tanh) activation - can also make relu + if self.dropout!=0: model.add(Dropout(self.dropout)) #Dropout some units if proportion of dropout != 0 + + #Add dense connections to all outputs + model.add(Dense(y_train.shape[1])) #Add final dense layer (connected to outputs) + model.add(Activation('softplus')) + + #Fit model (and set fitting parameters) + model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy']) #Set loss function and optimizer + if keras_v1: + model.fit(X_flat_train,y_train,nb_epoch=self.num_epochs,verbose=self.verbose) #Fit the model + else: + model.fit(X_flat_train,y_train,epochs=self.num_epochs,verbose=self.verbose) #Fit the model + self.model=model + + def predict(self,X_flat_test): + + """ + Predict outcomes using trained DenseNN Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + y_test_predicted_raw = self.model.predict(X_flat_test) #Make predictions + + y_test_predicted=np.argmax(y_test_predicted_raw,axis=1) + + return y_test_predicted + + + +##################### SIMPLE RNN DECODER ########################## + +class SimpleRNNClassification(object): + + """ + Class for the RNN decoder + + Parameters + ---------- + units: integer, optional, default 400 + Number of hidden units in each layer + + dropout: decimal, optional, default 0 + Proportion of units that get dropped out + + num_epochs: integer, optional, default 10 + Number of epochs used for training + + verbose: binary, optional, default=0 + Whether to show progress of the fit after each epoch + """ + + def __init__(self,units=400,dropout=0,num_epochs=10,verbose=0): + self.units=units + self.dropout=dropout + self.num_epochs=num_epochs + self.verbose=verbose + + + def fit(self,X_train,y_train): + + """ + Train GRU Decoder + + Parameters + ---------- + X_train: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + + #Use one-hot coding for y + if y_train.ndim==1: + y_train=np_utils.to_categorical(y_train.astype(int)) + elif y_train.shape[1]==1: + y_train=np_utils.to_categorical(y_train.astype(int)) + + model=Sequential() #Declare model + #Add recurrent layer + + #### MAKE RELU ACTIVATION BELOW LIKE IN REGRESSION????? #### + if keras_v1: + model.add(SimpleRNN(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout_W=self.dropout,dropout_U=self.dropout)) #Within recurrent layer, include dropout + else: + model.add(SimpleRNN(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout=self.dropout,recurrent_dropout=self.dropout)) #Within recurrent layer, include dropout + if self.dropout!=0: model.add(Dropout(self.dropout)) #Dropout some units (recurrent layer output units) + + #Add dense connections to output layer + model.add(Dense(y_train.shape[1])) + model.add(Activation('softplus')) + + #Fit model (and set fitting parameters) + model.compile(loss='categorical_crossentropy',optimizer='rmsprop',metrics=['accuracy']) #Set loss function and optimizer + if keras_v1: + model.fit(X_train,y_train,nb_epoch=self.num_epochs,verbose=self.verbose) #Fit the model + else: + model.fit(X_train,y_train,epochs=self.num_epochs,verbose=self.verbose) #Fit the model + self.model=model + + + def predict(self,X_test): + + """ + Predict outcomes using trained LSTM Decoder + + Parameters + ---------- + X_test: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + y_test_predicted_raw = self.model.predict(X_test) #Make predictions + y_test_predicted=np.argmax(y_test_predicted_raw,axis=1) + + return y_test_predicted + + + + + + +##################### GATED RECURRENT UNIT (GRU) DECODER ########################## + +class GRUClassification(object): + + """ + Class for the gated recurrent unit (GRU) decoder + + Parameters + ---------- + units: integer, optional, default 400 + Number of hidden units in each layer + + dropout: decimal, optional, default 0 + Proportion of units that get dropped out + + num_epochs: integer, optional, default 10 + Number of epochs used for training + + verbose: binary, optional, default=0 + Whether to show progress of the fit after each epoch + """ + + def __init__(self,units=400,dropout=0,num_epochs=10,verbose=0): + self.units=units + self.dropout=dropout + self.num_epochs=num_epochs + self.verbose=verbose + + + def fit(self,X_train,y_train): + + """ + Train GRU Decoder + + Parameters + ---------- + X_train: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + + #Use one-hot coding for y + if y_train.ndim==1: + y_train=np_utils.to_categorical(y_train.astype(int)) + elif y_train.shape[1]==1: + y_train=np_utils.to_categorical(y_train.astype(int)) + + model=Sequential() #Declare model + #Add recurrent layer + if keras_v1: + model.add(GRU(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout_W=self.dropout,dropout_U=self.dropout)) #Within recurrent layer, include dropout + else: + model.add(GRU(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout=self.dropout,recurrent_dropout=self.dropout)) #Within recurrent layer, include dropout + if self.dropout!=0: model.add(Dropout(self.dropout)) #Dropout some units (recurrent layer output units) + + #Add dense connections to output layer + model.add(Dense(y_train.shape[1])) + model.add(Activation('softplus')) + + #Fit model (and set fitting parameters) + model.compile(loss='categorical_crossentropy',optimizer='rmsprop',metrics=['accuracy']) #Set loss function and optimizer + if keras_v1: + model.fit(X_train,y_train,nb_epoch=self.num_epochs,verbose=self.verbose) #Fit the model + else: + model.fit(X_train,y_train,epochs=self.num_epochs,verbose=self.verbose) #Fit the model + self.model=model + + + def predict(self,X_test): + + """ + Predict outcomes using trained LSTM Decoder + + Parameters + ---------- + X_test: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + y_test_predicted_raw = self.model.predict(X_test) #Make predictions + y_test_predicted=np.argmax(y_test_predicted_raw,axis=1) + + return y_test_predicted + + + + + +#################### LONG SHORT TERM MEMORY (LSTM) DECODER ########################## + +class LSTMClassification(object): + + """ + Class for the LSTM decoder + + Parameters + ---------- + units: integer, optional, default 400 + Number of hidden units in each layer + + dropout: decimal, optional, default 0 + Proportion of units that get dropped out + + num_epochs: integer, optional, default 10 + Number of epochs used for training + + verbose: binary, optional, default=0 + Whether to show progress of the fit after each epoch + """ + + def __init__(self,units=400,dropout=0,num_epochs=10,verbose=0): + self.units=units + self.dropout=dropout + self.num_epochs=num_epochs + self.verbose=verbose + + + def fit(self,X_train,y_train): + + """ + Train LSTM Decoder + + Parameters + ---------- + X_train: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 2d array of shape [n_samples, n_outputs] + This is the outputs that are being predicted + """ + + + #Use one-hot coding for y + if y_train.ndim==1: + y_train=np_utils.to_categorical(y_train.astype(int)) + elif y_train.shape[1]==1: + y_train=np_utils.to_categorical(y_train.astype(int)) + + model=Sequential() #Declare model + #Add recurrent layer + if keras_v1: + model.add(LSTM(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout_W=self.dropout,dropout_U=self.dropout)) #Within recurrent layer, include dropout + else: + model.add(LSTM(self.units,input_shape=(X_train.shape[1],X_train.shape[2]),dropout=self.dropout,recurrent_dropout=self.dropout)) #Within recurrent layer, include dropout + if self.dropout!=0: model.add(Dropout(self.dropout)) #Dropout some units (recurrent layer output units) + + #Add dense connections to output layer + model.add(Dense(y_train.shape[1])) + model.add(Activation('softplus')) + + #Fit model (and set fitting parameters) + model.compile(loss='categorical_crossentropy',optimizer='rmsprop',metrics=['accuracy']) #Set loss function and optimizer + if keras_v1: + model.fit(X_train,y_train,nb_epoch=self.num_epochs,verbose=self.verbose) #Fit the model + else: + model.fit(X_train,y_train,epochs=self.num_epochs,verbose=self.verbose) #Fit the model + self.model=model + + + def predict(self,X_test): + + """ + Predict outcomes using trained LSTM Decoder + + Parameters + ---------- + X_test: numpy 3d array of shape [n_samples,n_time_bins,n_neurons] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + y_test_predicted_raw = self.model.predict(X_test) #Make predictions + y_test_predicted=np.argmax(y_test_predicted_raw,axis=1) + + return y_test_predicted + + + + +##################### EXTREME GRADIENT BOOSTING (XGBOOST) ########################## + +class XGBoostClassification(object): + """ + Class for the XGBoost Decoder + + Parameters + ---------- + max_depth: integer, optional, default=3 + the maximum depth of the trees + + num_round: integer, optional, default=300 + the number of trees that are fit + + eta: float, optional, default=0.3 + the learning rate + + gpu: integer, optional, default=-1 + if the gpu version of xgboost is installed, this can be used to select which gpu to use + for negative values (default), the gpu is not used + """ + + def __init__(self, max_depth=3, num_round=300, eta=0.3, gpu=-1): + self.max_depth = max_depth + self.num_round = num_round + self.eta = eta + self.gpu = gpu + + def fit(self, X_flat_train, y_train): + + """ + Train XGBoost Decoder + + Parameters + ---------- + X_flat_train: numpy 2d array of shape [n_samples,n_features] + This is the neural data. + See example file for an example of how to format the neural data correctly + + y_train: numpy 1d array of shape (n_samples), with integers representing classes + or 2d array of shape [n_samples, n_outputs] in 1-hot form + This is the outputs that are being predicted + """ + + # turn to categorial (not 1-hat) + if (y_train.ndim == 2): + if (y_train.shape[1] == 1): + y_train = np.reshape(y_train, -1) + else: + y_train = np.argmax(y_train, axis=1, out=None) + + # Get number of classes + n_classes = len(np.unique(y_train)) + + # Set parameters for XGBoost + param = {'objective': "multi:softmax", # or softprob + 'eval_metric': "mlogloss", # loglikelihood loss + # 'eval_metric': "merror", + 'max_depth': self.max_depth, # this is the only parameter we have set, it's one of the way or regularizing + 'eta': self.eta, + 'num_class': n_classes, # y_train.shape[1], + 'seed': 2925, # for reproducibility + 'silent': 1} + if self.gpu < 0: + param['nthread'] = -1 # with -1 it will use all available threads + else: + param['gpu_id'] = self.gpu + param['updater'] = 'grow_gpu' + + dtrain = xgb.DMatrix(X_flat_train, label=y_train) # Put in correct format for XGB + bst = xgb.train(param, dtrain, self.num_round) # Train model + + self.model = bst + + def predict(self, X_flat_test): + + """ + Predict outcomes using trained XGBoost Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 1d array with integers as classes + The predicted outputs + """ + + dtest = xgb.DMatrix(X_flat_test) # Put in XGB format + bst = self.model # Get fit model + y_test_predicted = bst.predict(dtest) # Make prediction + return y_test_predicted + + def predict(self,X_flat_test): + + """ + Predict outcomes using trained XGBoost Decoder + + Parameters + ---------- + X_flat_test: numpy 2d array of shape [n_samples,n_features] + This is the neural data being used to predict outputs. + + Returns + ------- + y_test_predicted: numpy 2d array of shape [n_samples,n_outputs] + The predicted outputs + """ + + dtest = xgb.DMatrix(X_flat_test) #Put in XGB format + bst=self.model #Get fit model + y_test_predicted = bst.predict(dtest) #Make prediction + return y_test_predicted diff --git a/build/lib/Neural_Decoding/metrics.py b/build/lib/Neural_Decoding/metrics.py new file mode 100644 index 0000000..f4a6a1a --- /dev/null +++ b/build/lib/Neural_Decoding/metrics.py @@ -0,0 +1,56 @@ +import numpy as np + +########## R-squared (R2) ########## + +def get_R2(y_test,y_test_pred): + + """ + Function to get R2 + + Parameters + ---------- + y_test - the true outputs (a matrix of size number of examples x number of outputs) + y_test_pred - the predicted outputs (a matrix of size number of examples x number of outputs) + + Returns + ------- + R2_array: An array of R2s for each output + """ + + R2_list=[] #Initialize a list that will contain the R2s for all the outputs + for i in range(y_test.shape[1]): #Loop through outputs + #Compute R2 for each output + y_mean=np.mean(y_test[:,i]) + R2=1-np.sum((y_test_pred[:,i]-y_test[:,i])**2)/np.sum((y_test[:,i]-y_mean)**2) + R2_list.append(R2) #Append R2 of this output to the list + R2_array=np.array(R2_list) + return R2_array #Return an array of R2s + + + + +########## Pearson's correlation (rho) ########## + +def get_rho(y_test,y_test_pred): + + """ + Function to get Pearson's correlation (rho) + + Parameters + ---------- + y_test - the true outputs (a matrix of size number of examples x number of outputs) + y_test_pred - the predicted outputs (a matrix of size number of examples x number of outputs) + + Returns + ------- + rho_array: An array of rho's for each output + """ + + rho_list=[] #Initialize a list that will contain the rhos for all the outputs + for i in range(y_test.shape[1]): #Loop through outputs + #Compute rho for each output + y_mean=np.mean(y_test[:,i]) + rho=np.corrcoef(y_test[:,i].T,y_test_pred[:,i].T)[0,1] + rho_list.append(rho) #Append rho of this output to the list + rho_array=np.array(rho_list) + return rho_array #Return the array of rhos diff --git a/build/lib/Neural_Decoding/preprocessing_funcs.py b/build/lib/Neural_Decoding/preprocessing_funcs.py new file mode 100644 index 0000000..7c4539f --- /dev/null +++ b/build/lib/Neural_Decoding/preprocessing_funcs.py @@ -0,0 +1,119 @@ +import numpy as np + + +######## BIN_SPIKES ######## +def bin_spikes(spike_times,dt,wdw_start,wdw_end): + """ + Function that puts spikes into bins + + Parameters + ---------- + spike_times: an array of arrays + an array of neurons. within each neuron's array is an array containing all the spike times of that neuron + dt: number (any format) + size of time bins + wdw_start: number (any format) + the start time for putting spikes in bins + wdw_end: number (any format) + the end time for putting spikes in bins + + Returns + ------- + neural_data: a matrix of size "number of time bins" x "number of neurons" + the number of spikes in each time bin for each neuron + """ + edges=np.arange(wdw_start,wdw_end,dt) #Get edges of time bins + num_bins=edges.shape[0]-1 #Number of bins + num_neurons=spike_times.shape[0] #Number of neurons + neural_data=np.empty([num_bins,num_neurons]) #Initialize array for binned neural data + #Count number of spikes in each bin for each neuron, and put in array + for i in range(num_neurons): + neural_data[:,i]=np.histogram(spike_times[i],edges)[0] + return neural_data + + + +######## BIN_OUTPUT ####### +def bin_output(outputs,output_times,dt,wdw_start,wdw_end,downsample_factor=1): + """ + Function that puts outputs into bins + + Parameters + ---------- + outputs: matrix of size "number of times the output was recorded" x "number of features in the output" + each entry in the matrix is the value of the output feature + output_times: a vector of size "number of times the output was recorded" + each entry has the time the output was recorded + dt: number (any format) + size of time bins + wdw_start: number (any format) + the start time for binning the outputs + wdw_end: number (any format) + the end time for binning the outputs + downsample_factor: integer, optional, default=1 + how much to downsample the outputs prior to binning + larger values will increase speed, but decrease precision + + Returns + ------- + outputs_binned: matrix of size "number of time bins" x "number of features in the output" + the average value of each output feature in every time bin + """ + + ###Downsample output### + #We just take 1 out of every "downsample_factor" values# + if downsample_factor!=1: #Don't downsample if downsample_factor=1 + downsample_idxs=np.arange(0,output_times.shape[0],downsample_factor) #Get the idxs of values we are going to include after downsampling + outputs=outputs[downsample_idxs,:] #Get the downsampled outputs + output_times=output_times[downsample_idxs] #Get the downsampled output times + + ###Put outputs into bins### + edges=np.arange(wdw_start,wdw_end,dt) #Get edges of time bins + num_bins=edges.shape[0]-1 #Number of bins + output_dim=outputs.shape[1] #Number of output features + outputs_binned=np.empty([num_bins,output_dim]) #Initialize matrix of binned outputs + #Loop through bins, and get the mean outputs in those bins + for i in range(num_bins): #Loop through bins + idxs=np.where((np.squeeze(output_times)>=edges[i]) & (np.squeeze(output_times)\"Open" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "w2FCVtm3EhuL" + }, + "source": [ + "# Decoding neural activity\n", + "_Machine learning for mind reading_\n", + "\n", + "This tutorial introduces concepts that are central to the practice of decoding neural activity using machine learning (or any method). We will make heavy use of our [Python package for neural decoding](https://github.com/KordingLab/Neural_Decoding).\n", + "\n", + "This tutorial accompanies these [lecture slides](https://).\n", + "\n", + "The solutions to the exercises can be found in [this completed Colab](https://colab.research.google.com/drive/1SxXwmTgW2Ro34BQEy91zOXHs9JhMqcBJ).\n", + "\n", + "### Outline\n", + "\n", + "1. Overfitting\n", + "2. Crossvalidation\n", + "3. Regularization\n", + "4. Applying recurrent neural networks\n", + "5. What methods work best and when?" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "ufp0LsaTwe5B" + }, + "source": [ + "## Preliminaries\n", + "\n", + "Import modules and simulate data" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "ih_NKq_Xn98m" + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "from matplotlib import pyplot as plt\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "6zqKK3iOwK6X" + }, + "source": [ + "### Let's simulate some data" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "aKOAseCQmd5U" + }, + "outputs": [], + "source": [ + "# Generate some fake trial data\n", + "n_trials = 250\n", + "n_neurons = 10\n", + "n_bins_per_trial = 50\n", + "\n", + "# And generate some fake neural recordings\n", + "# We'll pretend we have a drift diffusion model\n", + "\n", + "def generate_neural_data(n_trials, n_neurons = 25, n_bins_per_trial = 50,\n", + " noise_variance = 1, drift_rate = 0.07,\n", + " mean_rate = 25):\n", + " \"\"\"Generates fake neural data of shape (n_trials, n_neurons, n_bins_per_trial\n", + " according to a drift diffusion process with given parameters.\n", + " Also generates decisions, which is 0 or 1 depending on the \"animal's decision\"\n", + " and is returned as an array of shape (n_trials,) \n", + " \n", + " Returns: (neural_data, decisions)\n", + " \"\"\"\n", + "\n", + " decisions = np.random.binomial(1,.5,size = n_trials)\n", + " \n", + " neural_recordings = np.zeros((n_trials,n_neurons,n_bins_per_trial))\n", + "\n", + " for t in range(n_bins_per_trial):\n", + " if t==0:\n", + " neural_recordings[:,:,t] = mean_rate + np.random.randn(n_trials,n_neurons) * noise_variance\n", + " else:\n", + " neural_recordings[:,:,t] = neural_recordings[:,:,t-1] \\\n", + " + np.reshape(drift_rate*(decisions*2-1),(len(decisions),1)) \\\n", + " + np.random.randn(n_trials,n_neurons) * noise_variance\n", + " \n", + " return neural_recordings, decisions\n", + "\n", + "neural_recordings, decisions = generate_neural_data(n_trials, \n", + " n_neurons, n_bins_per_trial)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 374 + }, + "colab_type": "code", + "id": "bN82ZMD7q0X1", + "outputId": "86300c04-0da6-4d08-9e92-9388bac8e82f" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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RMSd9mWCfRnhYPp8SKqvrwcgKSnJzZWIiIiIiIgnqK+vJzQ09KDbTcbhYlQv53A4KCoqIjg4GJPJ5NZa6urqSEpKYs+ePYSEhLi1Ful9NH7keGj8yLHS2JHjofEjx6M7xo9hGNTX15OQkICX18GvPOrzM0leXl7069fP3WV0EhISoh8Ucsw0fuR4aPzIsdLYkeOh8SPHo6vHz6FmkPZR4wYREREREZEOFJJEREREREQ6UEjqQWazmQceeACz2ezuUqQX0viR46HxI8dKY0eOh8aPHA93jp8+37hBRERERETkaGgmSUREREREpAOFJBERERERkQ4UkkRERERERDpQSBIREREREelAIakHPffcc6SmpuLv78+ECRNYvXq1u0sSN/vmm28499xzSUhIwGQy8cEHH3TabhgG999/P/Hx8QQEBDBt2jR27drVaZ+qqiquvPJKQkJCCAsL48Ybb6ShoaEH34W4y2OPPcb48eMJDg4mJiaG2bNns2PHjk77tLS0MGfOHCIjI7FYLFx00UWUlpZ22qegoIBZs2YRGBhITEwM99xzDzabrSffivSwF154gczMTNcCjZMmTeKzzz5zbde4kaPx+OOPYzKZmDt3rusxjSE5mAcffBCTydTpNnjwYNd2Txk7Ckk95J133mHevHk88MADrF+/npEjRzJjxgzKysrcXZq4UWNjIyNHjuS555474PY//elPPP3007z44ousWrWKoKAgZsyYQUtLi2ufK6+8ki1btrBw4UI+/vhjvvnmG2655ZaeegviRkuXLmXOnDmsXLmShQsX0tbWxvTp02lsbHTt88tf/pKPPvqI9957j6VLl1JUVMSFF17o2m6325k1axatra189913zJ8/n1dffZX777/fHW9Jeki/fv14/PHHWbduHWvXrmXq1Kmcf/75bNmyBdC4kSO3Zs0a/v73v5OZmdnpcY0hOZRhw4ZRXFzsui1btsy1zWPGjiE94qSTTjLmzJnj+tputxsJCQnGY4895saqxJMAxoIFC1xfOxwOIy4uzvjzn//seqympsYwm83GW2+9ZRiGYWzdutUAjDVr1rj2+eyzzwyTyWQUFhb2WO3iGcrKygzAWLp0qWEYzvHi6+trvPfee659tm3bZgDGihUrDMMwjE8//dTw8vIySkpKXPu88MILRkhIiGG1Wnv2DYhbhYeHGy+99JLGjRyx+vp6IyMjw1i4cKHxk5/8xLjzzjsNw9DPHjm0Bx54wBg5cuQBt3nS2NFMUg9obW1l3bp1TJs2zfWYl5cX06ZNY8WKFW6sTDxZbm4uJSUlncZNaGgoEyZMcI2bFStWEBYWxrhx41z7TJs2DS8vL1atWtXjNYt71dbWAhAREQHAunXraGtr6zSGBg8eTHJycqcxNGLECGJjY137zJgxg7q6OtesgvRtdrudt99+m8bGRiZNmqRxI0dszpw5zJo1q9NYAf3skcPbtWsXCQkJ9O/fnyuvvJKCggLAs8aOT5e9khxURUUFdru90/9MgNjYWLZv3+6mqsTTlZSUABxw3OzbVlJSQkxMTKftPj4+REREuPaRE4PD4WDu3LlMmTKF4cOHA87x4efnR1hYWKd9fzyGDjTG9m2TvmvTpk1MmjSJlpYWLBYLCxYsYOjQoWRlZWncyGG9/fbbrF+/njVr1uy3TT975FAmTJjAq6++yqBBgyguLuahhx7ilFNOYfPmzR41dhSSRET6gDlz5rB58+ZO53WLHMqgQYPIysqitraW999/n2uvvZalS5e6uyzpBfbs2cOdd97JwoUL8ff3d3c50svMnDnTdT8zM5MJEyaQkpLCu+++S0BAgBsr60yn2/WAqKgovL299+vMUVpaSlxcnJuqEk+3b2wcatzExcXt1/zDZrNRVVWlsXUC+fnPf87HH3/MkiVL6Nevn+vxuLg4Wltbqamp6bT/j8fQgcbYvm3Sd/n5+TFgwADGjh3LY489xsiRI3nqqac0buSw1q1bR1lZGWPGjMHHxwcfHx+WLl3K008/jY+PD7GxsRpDcsTCwsIYOHAg2dnZHvXzRyGpB/j5+TF27FgWLVrkeszhcLBo0SImTZrkxsrEk6WlpREXF9dp3NTV1bFq1SrXuJk0aRI1NTWsW7fOtc/ixYtxOBxMmDChx2uWnmUYBj//+c9ZsGABixcvJi0trdP2sWPH4uvr22kM7dixg4KCgk5jaNOmTZ3C9sKFCwkJCWHo0KE980bEIzgcDqxWq8aNHNYZZ5zBpk2byMrKct3GjRvHlVde6bqvMSRHqqGhgZycHOLj4z3r50+XtYCQQ3r77bcNs9lsvPrqq8bWrVuNW265xQgLC+vUmUNOPPX19caGDRuMDRs2GIDx17/+1diwYYORn59vGIZhPP7440ZYWJjxv//9z9i4caNx/vnnG2lpaUZzc7PrNc466yxj9OjRxqpVq4xly5YZGRkZxhVXXOGutyQ96PbbbzdCQ0ONr7/+2iguLnbdmpqaXPvcdtttRnJysrF48WJj7dq1xqRJk4xJkya5tttsNmP48OHG9OnTjaysLOPzzz83oqOjjXvvvdcdb0l6yG9+8xtj6dKlRm5urrFx40bjN7/5jWEymYwvv/zSMAyNGzl6HbvbGYbGkBzcXXfdZXz99ddGbm6usXz5cmPatGlGVFSUUVZWZhiG54wdhaQe9MwzzxjJycmGn5+fcdJJJxkrV650d0niZkuWLDGA/W7XXnutYRjONuD33XefERsba5jNZuOMM84wduzY0ek1KisrjSuuuMKwWCxGSEiIcf311xv19fVueDfS0w40dgDjlVdece3T3Nxs/OxnPzPCw8ONwMBA44ILLjCKi4s7vU5eXp4xc+ZMIyAgwIiKijLuuusuo62trYffjfSkG264wUhJSTH8/PyM6Oho44wzznAFJMPQuJGj9+OQpDEkB3PZZZcZ8fHxhp+fn5GYmGhcdtllRnZ2tmu7p4wdk2EYRtfNS4mIiIiIiPRuuiZJRERERESkA4UkERERERGRDhSSREREREREOlBIEhERERER6UAhSUREREREpAOFJBERERERkQ4UkkRERERERDpQSBIREREREelAIUlERNzquuuuY/bs2W47/tVXX82jjz7aba+/detW+vXrR2NjY7cdQ0REupbJMAzD3UWIiEjfZDKZDrn9gQce4Je//CWGYRAWFtYzRXXw/fffM3XqVPLz87FYLN12nIsvvpiRI0dy3333ddsxRESk6ygkiYhItykpKXHdf+edd7j//vvZsWOH6zGLxdKt4eRwbrrpJnx8fHjxxRe79TiffPIJN998MwUFBfj4+HTrsURE5PjpdDsREek2cXFxrltoaCgmk6nTYxaLZb/T7U477TTuuOMO5s6dS3h4OLGxsfzzn/+ksbGR66+/nuDgYAYMGMBnn33W6VibN29m5syZWCwWYmNjufrqq6moqDhobXa7nffff59zzz230+Opqak8/PDDXHPNNVgsFlJSUvjwww8pLy/n/PPPx2KxkJmZydq1a13Pyc/P59xzzyU8PJygoCCGDRvGp59+6tp+5plnUlVVxdKlS4/zOyoiIj1BIUlERDzO/PnziYqKYvXq1dxxxx3cfvvtXHLJJUyePJn169czffp0rr76apqamgCoqalh6tSpjB49mrVr1/L5559TWlrKpZdeetBjbNy4kdraWsaNG7fftieffJIpU6awYcMGZs2axdVXX80111zDVVddxfr160lPT+eaa65h38kYc+bMwWq18s0337Bp0yaeeOKJTjNkfn5+jBo1im+//baLv1MiItIdFJJERMTjjBw5kt///vdkZGRw77334u/vT1RUFDfffDMZGRncf//9VFZWsnHjRgCeffZZRo8ezaOPPsrgwYMZPXo0//rXv1iyZAk7d+484DHy8/Px9vYmJiZmv21nn302t956q+tYdXV1jB8/nksuuYSBAwfy61//mm3btlFaWgpAQUEBU6ZMYcSIEfTv359zzjmHU089tdNrJiQkkJ+f38XfKRER6Q4KSSIi4nEyMzNd9729vYmMjGTEiBGux2JjYwEoKysDnA0YlixZ4rrGyWKxMHjwYABycnIOeIzm5mbMZvMBm0t0PP6+Yx3q+L/4xS94+OGHmTJlCg888IArvHUUEBDgmvkSERHPppAkIiIex9fXt9PXJpOp02P7go3D4QCgoaGBc889l6ysrE63Xbt27Tejs09UVBRNTU20trYe8vj7jnWo4990003s3r2bq6++mk2bNjFu3DieeeaZTq9ZVVVFdHT0kX0DRETErRSSRESk1xszZgxbtmwhNTWVAQMGdLoFBQUd8DmjRo0CnOsYdYWkpCRuu+02/vvf/3LXXXfxz3/+s9P2zZs3M3r06C45loiIdC+FJBER6fXmzJlDVVUVV1xxBWvWrCEnJ4cvvviC66+/HrvdfsDnREdHM2bMGJYtW3bcx587dy5ffPEFubm5rF+/niVLljBkyBDX9ry8PAoLC5k2bdpxH0tERLqfQpKIiPR6CQkJLF++HLvdzvTp0xkxYgRz584lLCwML6+D/6q76aabeOONN477+Ha7nTlz5jBkyBDOOussBg4cyPPPP+/a/tZbbzF9+nRSUlKO+1giItL9tJisiIicsJqbmxk0aBDvvPMOkyZN6pZjtLa2kpGRwZtvvsmUKVO65RgiItK1NJMkIiInrICAAF577bVDLjp7vAoKCvjtb3+rgCQi0otoJklERERERKQDzSSJiIiIiIh0oJAkIiIiIiLSgUKSiIiIiIhIBwpJIiIiIiIiHSgkiYiIiIiIdKCQJCIiIiIi0oFCkoiIiIiISAcKSSIiIiIiIh0oJImIiIiIiHTw/0Ej1uBf9HecAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# plot out some trials for one neuron\n", + "\n", + "neuron_id = 0\n", + "\n", + "plt.figure(figsize=(10,5))\n", + "plt.plot(np.arange(0,500,10),neural_recordings[:10,neuron_id,:].T)\n", + "plt.xlabel(\"Time (ms)\")\n", + "plt.ylabel(\"Spike rate (Hz)\")\n", + "plt.legend([\"Trial {}\".format(i) for i in range(1,6)])" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "euk_r7MYJ9PS" + }, + "source": [ + "#### Exercise 0: Look at the distribution of neural activity \n", + "\n", + "Let's gain an intuition for the data. Plot out the average neural activity for each of the two choices. \n", + "\n", + "Average across trials **and** neurons — we're going to assume they have the same response properties. Then, plot out the averages for trials with a choices of 0 vs a choice of 1.\n", + "\n", + "If you have extra time, overlay the standard deviations." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "3r6MNcOQN7Kc" + }, + "outputs": [], + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "JhQtKkGZgrvB" + }, + "source": [ + "## 1. Overfitting\n", + "\n", + "\n", + "\n", + "In common parlance, we call a classifier or regressor 'overfit' when it has learned to explain noise in the training set at the expense of its ability to generalize to new data.\n", + "\n", + "In that one-sentence description, we invoked the concepts of _training set_ and _generalization_. These are absolutely key to any modeling effort, including decoding.\n", + "\n", + "##### Training sets vs. testing sets\n", + "You need to train your decoder, obviously, and for that you'll need training data. No one cares how well your decoder works on your training data, though. What we care about is its _performance on data not used for training_. That is, we are interested in how well your decoder **generalizes** to new data. The only way to rigorously know how well your decoder generalizes is to test it on data not used for training. " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "8ge2NEhXUD8E" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "WARNING: Keras package is not installed. You will be unable to use all neural net decoders\n" + ] + } + ], + "source": [ + "from sklearn import linear_model\n", + "from Neural_Decoding.decoders import PcaLdaClassification, PcaEstimateDecoder" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + }, + "colab_type": "code", + "id": "u1EhoS2kgsZT", + "outputId": "2b9cc4fa-06ba-489d-8b1a-8f78e04da00a" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "R2 was 0.904\n" + ] + } + ], + "source": [ + "## Fit a decoder using all your data\n", + "\n", + "# We'll predict each decision using all neurons's activity throughout the trials\n", + "X = np.reshape(neural_recordings, (n_trials,-1))\n", + "\n", + "# initalize the model\n", + "#my_naive_model = linear_model.LinearRegression()\n", + "my_pca_model = PcaLdaClassification(explained_variance=0.6,da_type='qda')\n", + "#fit\n", + "my_pca_model.fit(X, decisions)\n", + "\n", + "# And see how we did on our data set,\n", + "print(\"R2 was\",my_pca_model.score(X,decisions))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "aATf_EwnnQyC" + }, + "source": [ + "**Looks great!** \n", + "\n", + "#### Exercise 1.1: \n", + "Now, suppose you release your decoder in the world. Will it work? Can't be better than perfect, right?\n", + "\n", + "Create some new data and use the `score` function to see the $R^2$ of your model on new data." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "3OmY3-jDnWjR" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "R2 was 0.924\n" + ] + } + ], + "source": [ + "# Let's do new electrophysiology and take new data. This cost $2,000,000 in \n", + "# NIH funding so it better work.\n", + "new_neural_recordings, new_decisions = generate_neural_data(n_trials, \n", + " n_neurons, n_bins_per_trial)\n", + "new_X = np.reshape(new_neural_recordings, (n_trials,-1))\n", + "\n", + "\n", + "# Now you: score the model on this new data\n", + "print(\"R2 was\",my_pca_model.score(new_X,new_decisions))" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "PcaEstimateDecoder(explained_variance=0.8, clf=SVC(), clf_params=None)\n" + ] + }, + { + "ename": "ValueError", + "evalue": "\nAll the 90 fits failed.\nIt is very likely that your model is misconfigured.\nYou can try to debug the error by setting error_score='raise'.\n\nBelow are more details about the failures:\n--------------------------------------------------------------------------------\n90 fits failed with the following error:\nTraceback (most recent call last):\n File \"d:\\gitlab\\.venv\\lib\\site-packages\\sklearn\\model_selection\\_validation.py\", line 686, in _fit_and_score\n estimator.fit(X_train, y_train, **fit_params)\nAttributeError: 'NoneType' object has no attribute 'fit'\n", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[9], line 19\u001b[0m\n\u001b[0;32m 12\u001b[0m param_grid \u001b[39m=\u001b[39m {\n\u001b[0;32m 13\u001b[0m \u001b[39m'\u001b[39m\u001b[39mexplained_variance\u001b[39m\u001b[39m'\u001b[39m: [\u001b[39m0.8\u001b[39m, \u001b[39m0.9\u001b[39m, \u001b[39m0.95\u001b[39m],\n\u001b[0;32m 14\u001b[0m \u001b[39m'\u001b[39m\u001b[39mclf__C\u001b[39m\u001b[39m'\u001b[39m: [\u001b[39m1\u001b[39m, \u001b[39m10\u001b[39m, \u001b[39m100\u001b[39m],\n\u001b[0;32m 15\u001b[0m \u001b[39m'\u001b[39m\u001b[39mclf__kernel\u001b[39m\u001b[39m'\u001b[39m: [\u001b[39m'\u001b[39m\u001b[39mlinear\u001b[39m\u001b[39m'\u001b[39m, \u001b[39m'\u001b[39m\u001b[39mrbf\u001b[39m\u001b[39m'\u001b[39m],\n\u001b[0;32m 16\u001b[0m }\n\u001b[0;32m 18\u001b[0m clf \u001b[39m=\u001b[39m GridSearchCV(pca_clf_model,param_grid)\n\u001b[1;32m---> 19\u001b[0m clf\u001b[39m.\u001b[39;49mfit(X, decisions)\n\u001b[0;32m 21\u001b[0m \u001b[39mprint\u001b[39m(\u001b[39m\"\u001b[39m\u001b[39mR2 was\u001b[39m\u001b[39m\"\u001b[39m,clf\u001b[39m.\u001b[39mscore(new_X,new_decisions))\n\u001b[0;32m 23\u001b[0m \u001b[39m# Print the best parameters\u001b[39;00m\n", + "File \u001b[1;32md:\\gitlab\\.venv\\lib\\site-packages\\sklearn\\model_selection\\_search.py:874\u001b[0m, in \u001b[0;36mBaseSearchCV.fit\u001b[1;34m(self, X, y, groups, **fit_params)\u001b[0m\n\u001b[0;32m 868\u001b[0m results \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_format_results(\n\u001b[0;32m 869\u001b[0m all_candidate_params, n_splits, all_out, all_more_results\n\u001b[0;32m 870\u001b[0m )\n\u001b[0;32m 872\u001b[0m \u001b[39mreturn\u001b[39;00m results\n\u001b[1;32m--> 874\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_run_search(evaluate_candidates)\n\u001b[0;32m 876\u001b[0m \u001b[39m# multimetric is determined here because in the case of a callable\u001b[39;00m\n\u001b[0;32m 877\u001b[0m \u001b[39m# self.scoring the return type is only known after calling\u001b[39;00m\n\u001b[0;32m 878\u001b[0m first_test_score \u001b[39m=\u001b[39m all_out[\u001b[39m0\u001b[39m][\u001b[39m\"\u001b[39m\u001b[39mtest_scores\u001b[39m\u001b[39m\"\u001b[39m]\n", + "File \u001b[1;32md:\\gitlab\\.venv\\lib\\site-packages\\sklearn\\model_selection\\_search.py:1388\u001b[0m, in \u001b[0;36mGridSearchCV._run_search\u001b[1;34m(self, evaluate_candidates)\u001b[0m\n\u001b[0;32m 1386\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39m_run_search\u001b[39m(\u001b[39mself\u001b[39m, evaluate_candidates):\n\u001b[0;32m 1387\u001b[0m \u001b[39m \u001b[39m\u001b[39m\"\"\"Search all candidates in param_grid\"\"\"\u001b[39;00m\n\u001b[1;32m-> 1388\u001b[0m evaluate_candidates(ParameterGrid(\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mparam_grid))\n", + "File \u001b[1;32md:\\gitlab\\.venv\\lib\\site-packages\\sklearn\\model_selection\\_search.py:851\u001b[0m, in \u001b[0;36mBaseSearchCV.fit..evaluate_candidates\u001b[1;34m(candidate_params, cv, more_results)\u001b[0m\n\u001b[0;32m 844\u001b[0m \u001b[39melif\u001b[39;00m \u001b[39mlen\u001b[39m(out) \u001b[39m!=\u001b[39m n_candidates \u001b[39m*\u001b[39m n_splits:\n\u001b[0;32m 845\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mValueError\u001b[39;00m(\n\u001b[0;32m 846\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mcv.split and cv.get_n_splits returned \u001b[39m\u001b[39m\"\u001b[39m\n\u001b[0;32m 847\u001b[0m \u001b[39m\"\u001b[39m\u001b[39minconsistent results. Expected \u001b[39m\u001b[39m{}\u001b[39;00m\u001b[39m \u001b[39m\u001b[39m\"\u001b[39m\n\u001b[0;32m 848\u001b[0m \u001b[39m\"\u001b[39m\u001b[39msplits, got \u001b[39m\u001b[39m{}\u001b[39;00m\u001b[39m\"\u001b[39m\u001b[39m.\u001b[39mformat(n_splits, \u001b[39mlen\u001b[39m(out) \u001b[39m/\u001b[39m\u001b[39m/\u001b[39m n_candidates)\n\u001b[0;32m 849\u001b[0m )\n\u001b[1;32m--> 851\u001b[0m _warn_or_raise_about_fit_failures(out, \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49merror_score)\n\u001b[0;32m 853\u001b[0m \u001b[39m# For callable self.scoring, the return type is only know after\u001b[39;00m\n\u001b[0;32m 854\u001b[0m \u001b[39m# calling. If the return type is a dictionary, the error scores\u001b[39;00m\n\u001b[0;32m 855\u001b[0m \u001b[39m# can now be inserted with the correct key. The type checking\u001b[39;00m\n\u001b[0;32m 856\u001b[0m \u001b[39m# of out will be done in `_insert_error_scores`.\u001b[39;00m\n\u001b[0;32m 857\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mcallable\u001b[39m(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39mscoring):\n", + "File \u001b[1;32md:\\gitlab\\.venv\\lib\\site-packages\\sklearn\\model_selection\\_validation.py:367\u001b[0m, in \u001b[0;36m_warn_or_raise_about_fit_failures\u001b[1;34m(results, error_score)\u001b[0m\n\u001b[0;32m 360\u001b[0m \u001b[39mif\u001b[39;00m num_failed_fits \u001b[39m==\u001b[39m num_fits:\n\u001b[0;32m 361\u001b[0m all_fits_failed_message \u001b[39m=\u001b[39m (\n\u001b[0;32m 362\u001b[0m \u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39mAll the \u001b[39m\u001b[39m{\u001b[39;00mnum_fits\u001b[39m}\u001b[39;00m\u001b[39m fits failed.\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39m\"\u001b[39m\n\u001b[0;32m 363\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mIt is very likely that your model is misconfigured.\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39m\"\u001b[39m\n\u001b[0;32m 364\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mYou can try to debug the error by setting error_score=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mraise\u001b[39m\u001b[39m'\u001b[39m\u001b[39m.\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39m\\n\u001b[39;00m\u001b[39m\"\u001b[39m\n\u001b[0;32m 365\u001b[0m \u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mBelow are more details about the failures:\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39m{\u001b[39;00mfit_errors_summary\u001b[39m}\u001b[39;00m\u001b[39m\"\u001b[39m\n\u001b[0;32m 366\u001b[0m )\n\u001b[1;32m--> 367\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mValueError\u001b[39;00m(all_fits_failed_message)\n\u001b[0;32m 369\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[0;32m 370\u001b[0m some_fits_failed_message \u001b[39m=\u001b[39m (\n\u001b[0;32m 371\u001b[0m \u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39m{\u001b[39;00mnum_failed_fits\u001b[39m}\u001b[39;00m\u001b[39m fits failed out of a total of \u001b[39m\u001b[39m{\u001b[39;00mnum_fits\u001b[39m}\u001b[39;00m\u001b[39m.\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39m\"\u001b[39m\n\u001b[0;32m 372\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mThe score on these train-test partitions for these parameters\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 376\u001b[0m \u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mBelow are more details about the failures:\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39m{\u001b[39;00mfit_errors_summary\u001b[39m}\u001b[39;00m\u001b[39m\"\u001b[39m\n\u001b[0;32m 377\u001b[0m )\n", + "\u001b[1;31mValueError\u001b[0m: \nAll the 90 fits failed.\nIt is very likely that your model is misconfigured.\nYou can try to debug the error by setting error_score='raise'.\n\nBelow are more details about the failures:\n--------------------------------------------------------------------------------\n90 fits failed with the following error:\nTraceback (most recent call last):\n File \"d:\\gitlab\\.venv\\lib\\site-packages\\sklearn\\model_selection\\_validation.py\", line 686, in _fit_and_score\n estimator.fit(X_train, y_train, **fit_params)\nAttributeError: 'NoneType' object has no attribute 'fit'\n" + ] + } + ], + "source": [ + "# Perform hyperparameter optimization\n", + "\n", + "from sklearn.model_selection import GridSearchCV\n", + "from sklearn.svm import SVC, SVR\n", + "from sklearn.linear_model import LogisticRegression\n", + "\n", + "pca_clf_model = PcaEstimateDecoder()\n", + "\n", + "print(pca_clf_model)\n", + "\n", + "\n", + "param_grid = {\n", + " 'explained_variance': [0.8, 0.9, 0.95],\n", + " 'clf': [SVC()],\n", + " 'clf_params': [\n", + " {'C': [0.1, 1, 10], 'gamma': [0.1, 0.01], 'kernel': ['rbf']}\n", + " ]\n", + "}\n", + "\n", + "clf = GridSearchCV(pca_clf_model,param_grid)\n", + "clf.fit(X, decisions)\n", + "\n", + "print(\"R2 was\",clf.score(new_X,new_decisions))\n", + "\n", + "# Print the best parameters\n", + "print(clf.best_params_)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "iBrTBP3oZ16v" + }, + "source": [ + "#### Exercise 1.2: \n", + "You may have noticed that we're using linear *regression*, even though we have a classification problem.\n", + "It'd be better to use logistic regression. \n", + "\n", + "Fit and score this logistic regression method using your original data.\n", + "\n", + "Then, also score this method with the new data you just obtained with your R01 funds. (That is, print both the test and train accuracy.)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "C13c7lGIYZZa" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training R2 was 1.0\n", + "Training R2 was 0.888\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "d:\\gitlab\\.venv\\lib\\site-packages\\sklearn\\linear_model\\_logistic.py:1173: FutureWarning: `penalty='none'`has been deprecated in 1.2 and will be removed in 1.4. To keep the past behaviour, set `penalty=None`.\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "log_reg = linear_model.LogisticRegression(penalty='none', solver = 'lbfgs',\n", + " max_iter = 1000)\n", + "\n", + "# fit\n", + "log_reg.fit(X, decisions)\n", + "\n", + "\n", + "\n", + "# now score on both test and train\n", + "print(\"Training R2 was\",log_reg.score(X,decisions))\n", + "print(\"Training R2 was\",log_reg.score(new_X,new_decisions))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "aYdsXI596Gck" + }, + "source": [ + "Once you've completed that, just run this next cell. \n", + "\n", + "It shows the coefficients of the fit you just made. Does it match your intuitions? " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "dMYFYr5VzPXy" + }, + "outputs": [ + { + "data": { + "image/png": "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U0FBgQIDAzVt2rRqFQcAAAAAwKmsSk23y+Xy+pNhgYGBOvvss9WtWzeNHz9e7du3r3aBVXVuGyk0vHoZoc48O8VICguwl2V04t9Ir4gil7+VHEmKbVFkJScyINtKjiT5O+z8RnygybeSI0lHHPWs5OT4nWElR5L2hna3khMVk2slR5LauDZayfFz2dkHJKkwIMhaVmB+jpWcAmeolRxJKoxtZSVnXXY7KzmS1CDUzleU6gcetpIjSWH56daybAnKy7CSk++s5oNmCcZh7/Fld+M/WckJMfYeX446wqzktAzcayVHkqId+6zkFPiFWMmRpBxHlJWcrUeaWMmRpE4JaVZysgvtXU+BjgIrObmy95gQVXjQWlZBfHMrOYFpu63kSJIJtnNdGT97x7oWB763kpNdz979JTTDznElO9re89ZGKUut5OT//KOVnMLcivV4VWq6d+7cWZXFAAAAAAA4rfjsRGoAAAAAAJzuqvROd7H8/Hx99dVX2rJli7Kzs/Xwww9LknJzc5WZmanY2Fj5+dHXAwAAAABOT1XuiP/73/+qSZMmGjJkiO69915NmTLFPe/nn39Wo0aN9Pbbb9uoEQAAAACAU1KVmu6lS5fqz3/+s4KCgvSPf/xD1113ncf87t27q1WrVvrggw+qVNTevXv117/+VfXr11dISIg6dOig1atXVykLAAAAAICaUqWPl0+dOlXR0dFas2aNYmNjdejQoTJjunbtqhUrVlQ6+/Dhw+rdu7f69++vzz//XA0aNNC2bdtUr56dsz4DAAAAAHCyVKnpXrFihf785z8rNja23DGJiYn6+OOPK5391FNPKTExUXPmzHFPa97czk8NAAAAAABwMlXp4+V5eXmKjIw87pj09PQqnUTtv//9r7p27aqrr75aDRs21DnnnKPZs2cft5bMzEyPPwAAAAAAaoMqNd0tWrTQqlWrjjtm2bJlatu2baWzf/nlF82aNUutW7fWwoULNXbsWN1xxx2aN2+e1/HTpk1TVFSU+y8xMbHS6wQAAAAAwBeq1HRfddVVWrp0qcdHwEuaPn26NmzYoOHDh1c62+Vy6dxzz9UTTzyhc845R2PGjNHo0aP18ssvex0/ceJEZWRkuP/27NlT6XUCAAAAAOALVfpO93333acPPvhAN998s958803l5eVJku6//34tW7ZMP/zwgzp37qzx48dX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s2LFCve0W2+91TRp0sR8/fXXZvXq1aZnz56mZ8+eNbEJ1bJr1y7z448/mkceecSEh4ebH3/80fz444/myJEj7jFt2rQxH374oTHGmCNHjph7773XLFu2zKSkpJivvvrKnHvuuaZ169YmNze3pjajSiq77cYY8+STT5ro6Gjz8ccfm59//tkMHTrUNG/e3Bw9erQmNqHKBg0aZM455xyzYsUK8/3335vWrVuba6+91j2/9D6/fft28+ijj5rVq1eblJQU8/HHH5sWLVqYPn361NQmVNjbb79tgoKCzNy5c82mTZvMmDFjTHR0tElNTTXGGHP99debBx980D1+6dKlJiAgwEyfPt1s3rzZTJ482QQGBpr169fX1CZUWWW3/ZFHHjELFy40O3bsMGvWrDF/+ctfTHBwsNm4cWNNbUKVHDlyxH1/lmSeffZZ8+OPP5pdu3YZY4x58MEHzfXXX+8e/8svv5jQ0FBz3333mc2bN5uZM2caf39/88UXX9TUJlRZZbf9ueeeMx999JHZtm2bWb9+vbnzzjuNn5+f+eqrr2pqE6ps7NixJioqyiQlJXk8lufk5LjH1OX7O1Ab0XQDMMYc+4kcSV7/iqWkpBhJ5ptvvnFPO3r0qLnttttMvXr1TGhoqLniiis8GvVTxciRI71ue8ltlWTmzJljjDEmJyfHXHzxxaZBgwYmMDDQNG3a1IwePdr9JP5UUtltN+bYz4Y9/PDDJi4uzgQFBZkLL7zQJCcnn/ziq+nQoUPm2muvNeHh4SYyMtLcdNNNHi82lN7nd+/ebfr06WNiYmJMUFCQadWqlbnvvvtMRkZGDW1B5bzwwgumSZMmxul0mu7du5vly5e75/Xt29eMHDnSY/y7775rzjzzTON0Ok379u3Np59+epIrtqcy2z5hwgT32Li4OHPppZeatWvX1kDV1VP8M1il/4q3deTIkaZv375lluncubNxOp2mRYsWHvf7U0llt/2pp54yLVu2NMHBwSYmJsb069fPfP311zVTfDWV91he8ras6/d3oLZxGGOML99JBwAAAADgdMXZywEAAAAA8BGabgAAAAAAfISmGwAAAAAAH6HpBgAAAADAR2i6AQAAAADwEZpuAAAAAAB8hKYbAAAAAAAfoekGAAAAAMBHaLoBnHamTJmizp07uy/feOONGjZs2ElZV0169dVXlZiYKD8/P82YMaPM/J07d8rhcGjdunXlZiQlJcnhcCg9Pd1ndVZXs2bNvG7fycizve6K6tevnyZMmHDS14uqmTt3rqKjo2u6DKsqcqyryDHGF2yvtzJ5NbXNAGoXmm4APpWamqrbb79dLVq0UFBQkBITEzVkyBAtXrzY6noq03Tce++91tcvSQ6HQx999NFJWVdlZWZmavz48XrggQe0d+9ejRkzpko5vXr10v79+xUVFVXlWk6Fxr2kVatWVfj6qsxYmz788ENNnTrVfdlG89+vXz/NnTtX+fn5io2N1ZNPPul13NSpUxUXF6eCgoLj5lWn+XA4HNq5c2e582vqxQ78T+ljnbcXMxMTE7V//36dffbZJ7k6uyqzHXVlmwFUT0BNFwCg7tq5c6d69+6t6Oho/f3vf1eHDh1UUFCghQsXaty4cdqyZctJrccYo6KiIoWHhys8PPykrPNkrut4du/erYKCAg0ePFiNGjWqco7T6VR8fLzFymq/Bg0a+GSsTTExMT7Ldjqd+utf/6o5c+bowQcf9JhnjNHcuXN1ww03KDAw0Gc1nKry8/PldDpruoyToiLHOn9//zpx/KjMdtSVbQZQPbzTDcBnbrvtNjkcDq1cuVJXXXWVzjzzTLVv31533323li9f7h63e/duDR06VOHh4YqMjNQ111yjAwcOuOcXf2zx3//+t5o1a6aoqCj95S9/0ZEjRyQde0dlyZIl+sc//iGHw+F+V6z4HdXPP/9cXbp0UVBQkL7//vtyPwb5yCOPqEGDBoqMjNStt96q/Px89zxv76R17txZU6ZMcc+XpCuuuEIOh8N9ufS6XC6XHn30UTVu3FhBQUHq3LmzvvjiC/f84ncDP/zwQ/Xv31+hoaHq1KmTli1bdtzr+njX4dy5c9WhQwdJUosWLU74ruGWLVvUq1cvBQcH6+yzz9aSJUvc80q/S138MdmFCxeqXbt2Cg8P16BBg7R//36v2Tt37lT//v0lSfXq1ZPD4dCNN94oScrLy9Mdd9yhhg0bKjg4WOeff75WrVp13O1OS0vTkCFDFBISoubNm+uNN94oMyY9PV0333yz+7a94IIL9NNPP3mM+eSTT9StWzcFBwcrNjZWV1xxhXteydveGKMpU6aoSZMmCgoKUkJCgu644w6vY6Xq79sVVfKTHv369dOuXbt01113ue8PkrRr1y4NGTJE9erVU1hYmNq3b6/PPvusQvmjRo3S1q1b9f3333tMX7JkiX755ReNGjXqhPt28+bNJUnnnHOOHA6H+vXr5573z3/+U+3atVNwcLDatm2rl156qVLb7m17JemDDz5Q+/btFRQUpGbNmumZZ55xz3vxxRc93n386KOP5HA49PLLL7unDRgwQH/7298kSTt27NDQoUMVFxen8PBwdevWTV999ZVHLc2aNdPUqVN1ww03KDIy0v2ph7lz56pJkyYKDQ3VFVdcoUOHDnks99NPP6l///6KiIhQZGSkunTpotWrV5e7zc8++6w6dOigsLAwJSYm6rbbblNWVtZxryeHw6FZs2bpkksuUUhIiFq0aKH333/fY8z69et1wQUXKCQkRPXr19eYMWM8cpOSktS9e3eFhYUpOjpavXv31q5duyR5HuumTJmiefPm6eOPP3bfJklJSR6fdnC5XGrcuLFmzZrlUcOPP/4oPz8/d25F7r+lrVy5Uuecc46Cg4PVtWtX/fjjj2XGbNiwQZdcconCw8MVFxen66+/XgcPHnTPd7lcevrpp9WqVSsFBQWpSZMmevzxxyWV/dTG4cOHNWLECDVo0EAhISFq3bq15syZ43WsdOx+0717dwUFBalRo0Z68MEHVVhY6J7fr18/3XHHHbr//vsVExOj+Ph492MNgFOUAQAfOHTokHE4HOaJJ5447riioiLTuXNnc/7555vVq1eb5cuXmy5dupi+ffu6x0yePNmEh4ebK6+80qxfv958++23Jj4+3jz00EPGGGPS09NNz549zejRo83+/fvN/v37TWFhofnmm2+MJNOxY0fz5Zdfmu3bt5tDhw6ZyZMnm06dOrnzR44cacLDw83w4cPNhg0bzIIFC0yDBg3c+cYY07RpU/Pcc8951N6pUyczefJkY4wxaWlpRpKZM2eO2b9/v0lLS3PXXnJdzz77rImMjDRvvfWW2bJli7n//vtNYGCg2bp1qzHGmJSUFCPJtG3b1ixYsMAkJyebP//5z6Zp06amoKCgStdhTk6O+eqrr4wks3LlSvf1U1rxuhs3bmzef/99s2nTJnPzzTebiIgIc/DgQWOMcV+nhw8fNsYYM2fOHBMYGGgGDBhgVq1aZdasWWPatWtnrrvuOq+1FhYWmg8++MBIMsnJyWb//v0mPT3dGGPMHXfcYRISEsxnn31mNm7caEaOHGnq1atnDh065DXLGGMuueQS06lTJ7Ns2TKzevVq06tXLxMSEuJxWw0YMMAMGTLErFq1ymzdutXcc889pn79+u7cBQsWGH9/fzNp0iSzadMms27dOo/9tuRt/95775nIyEjz2WefmV27dpkVK1aYV1991etYG/t28XV8oofrvn37mjvvvNMYc+y+17hxY/Poo4+67w/GGDN48GBz0UUXmZ9//tns2LHDfPLJJ2bJkiXHzZwzZ477crdu3cxNN93kMeaGG24wvXr1MsaceN9euXKlkWS++uors3//fvf1/5///Mc0atTIfPDBB+aXX34xH3zwgYmJiTFz5851r0eSSUlJ8Vpnedu7evVq4+fnZx599FGTnJxs5syZY0JCQtzb9PPPPxuHw+G+r06YMMHExsaa4cOHG2OMyc/PN6GhoWbRokXGGGPWrVtnXn75ZbN+/XqzdetW87e//c0EBwebXbt2uWtp2rSpiYyMNNOnTzfbt28327dvN8uXLzd+fn7mqaeeMsnJyeYf//iHiY6ONlFRUe7l2rdvb/7617+azZs3m61bt5p3333XrFu3rtzb5rnnnjNff/21SUlJMYsXLzZt2rQxY8eOLXd88XVYv359M3v2bJOcnGz+9re/GX9/f7Np0yZjjDFZWVmmUaNG7n1x8eLFpnnz5mbkyJHGGGMKCgpMVFSUuffee8327dvNpk2bzNy5c93bX/JYd+TIEXPNNdeYQYMGuW+TvLw89zHmxx9/NMYYc++995rzzz/fo8577rnHY9qJ7r+lHTlyxDRo0MBcd911ZsOGDeaTTz4xLVq08Fjv4cOHTYMGDczEiRPN5s2bzdq1a81FF11k+vfv7865//77Tb169czcuXPN9u3bzXfffWdmz55tjDFltmPcuHGmc+fOZtWqVSYlJcUsWrTI/Pe///U69tdffzWhoaHmtttuM5s3bzbz5883sbGx7scSY47d9yIjI82UKVPM1q1bzbx584zD4TBffvnlcW9jALUXTTcAn1ixYoWRZD788MPjjvvyyy+Nv7+/2b17t3vaxo0b3Q2iMceezIWGhprMzEz3mPvuu8/06NHDfblk01GsuEH86KOPPKZ7a7pjYmJMdna2e9qsWbNMeHi4KSoqMsacuOk25tiT2vnz5x93XQkJCebxxx/3GNOtWzdz2223GWP+9wTtn//8Z5nrY/Pmzcab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5d0fEhMTdeutt+rDDz/UPffco9mzZ1cqd9SoUfr++++1YMEC/fDDDxo1apSkiu3b3m73uLg4JSQk6Jdffilz+xSfeK2q29uuXTuv9Zx55pny9/eXJPXt21ebNm3Se++95z6xW79+/fTVV19p6dKlHid7W7p0qW688UZdccUV6tChg+Lj4497QsKSdaxYscJjmrdG9cwzz9Rdd92lL7/8UldeeaX7xY3S1qxZI5fLpWeeeUbnnXeezjzzTO3bt++EdXhb7/Lly9337Xbt2umnn37yOF4vXbpUfn5+atOmjXvaOeeco4kTJ+qHH37Q2Wef7W6YS6voMfm6667Thg0btGbNGr3//vsaMWKEe15F7r+ltWvXTj///LNyc3PL3e5zzz1XGzduVLNmzcrkhoWFqXXr1goJCanUcaFBgwYaOXKk/vOf/2jGjBl69dVXy61v2bJlHi9MLl26VBEREWrcuHGF1wfg1ELTDcBnZs6cqaKiInXv3l0ffPCBtm3bps2bN+v55593f9xvwIAB6tChg0aMGKG1a9dq5cqVuuGGG9S3b98KfSy8WLNmzbRixQrt3LlTBw8erPQ7Avn5+Ro1apQ2bdqkzz77TJMnT9b48ePl53fsMHnBBRfo3//+t7777jutX79eI0eOdD9xL1nD4sWLlZqaqsOHD3tdz3333aennnpK77zzjpKTk/Xggw9q3bp1uvPOOytVb0m2rsNiM2fO1Pz587VlyxaNGzdOhw8f1v/93/9Vub7SmjZtKofDoQULFui3335TVlaWwsLCNHbsWN1333364osvtGnTJo0ePVo5OTnuxq60Nm3aaNCgQbrlllu0YsUKrVmzRjfffLPHu1QDBgxQz549NWzYMH355ZfauXOnfvjhB/2///f/3GeHnjx5st566y1NnjxZmzdv1vr16/XUU095XefcuXP12muvacOGDfrll1/0n//8RyEhIWratGmZsbZvl8po1qyZvv32W+3du9d9RuYJEyZo4cKFSklJ0dq1a/XNN99U+sWUPn36qFWrVrrhhhvUtm1b9erVyz3vRPt2w4YNFRISoi+++EIHDhxQRkaGpGO/GjBt2jQ9//zz2rp1q9avX685c+bo2Wefrdb23nPPPVq8eLGmTp2qrVu3at68eXrxxRc93oHs2LGj6tWrpzfffNOj6f7oo4+Ul5fn8fH01q1b68MPP9S6dev0008/6brrrqvQceaOO+7QF198oenTp2vbtm168cUXPc7qfvToUY0fP15JSUnatWuXli5dqlWrVpV727Rq1UoFBQV64YUX9Msvv+jf//63xxnXj+e9997T66+/rq1bt2ry5MlauXKlxo8fL+nYO87BwcEaOXKkNmzYoG+++Ua33367rr/+esXFxSklJUUTJ07UsmXLtGvXLn355Zfatm1buXU2a9ZMP//8s5KTk3Xw4MFyPw3SrFkz9erVS6NGjVJRUZEuv/xy97yK3H9Lu+666+RwODR69Gj38Xz69OkeY8aNG6fff/9d1157rVatWqUdO3Zo4cKFuummm1RUVKTg4GA98MADuv/++/Wvf/1LO3bs0PLly/Xaa695XeekSZP08ccfa/v27dq4caMWLFhQ7vVy2223ac+ePbr99tu1ZcsWffzxx5o8ebLuvvtu9+NNRdxwww2aOHFihccDqGE1+5VyAHXdvn37zLhx40zTpk2N0+k0Z5xxhrn88svNN9984x6za9cuc/nll5uwsDATERFhrr76apOamuqeX/oEPcYcO3tv06ZN3ZeTk5PNeeedZ0JCQtwnDPN2wi5vecUn/Jk0aZKpX7++CQ8PN6NHj/Y4eU9GRoYZPny4iYyMNImJiWbu3LllTqT23//+17Rq1coEBAS4ayu9rqKiIjNlyhRzxhlnmMDAQNOpUyfz+eefu+d7O9nU4cOHjSSP66y0E12HlTmR2ptvvmm6d+9unE6nOeuss8zXX3/tHuPtRGolTwhljDHz588/4dm2H330URMfH28cDof77MhHjx41t99+u4mNjTVBQUGmd+/eHidJ82b//v1m8ODBJigoyDRp0sT861//KnNSrczMTHP77bebhIQEExgYaBITE82IESM8TnD2wQcfmM6dOxun02liY2PNlVde6Z5XMm/+/PmmR48eJjIy0oSFhZnzzjvPfPXVV17HGmNn367s2cuNMWbZsmWmY8eOJigoyL3s+PHjTcuWLU1QUJBp0KCBuf76691npa+MJ554wkgqc4K7E+3bxhgze/Zsk5iYaPz8/DzO4v7GG2+4r/969eqZPn36nPAkjCV5215jjHn//ffNWWedZQIDA02TJk3M3//+9zLLDh061AQEBLhPEFdUVGTq1atnzjvvPI9xKSkppn///iYkJMQkJiaaF198sUInsDPGmNdee800btzYhISEmCFDhpjp06e77zd5eXnmL3/5i0lMTDROp9MkJCSY8ePHe5wIrLRnn33WNGrUyISEhJiBAweaf/3rX16PdSVJMjNnzjQXXXSRCQoKMs2aNTPvvPOOx5iff/7Z9O/f3wQHB5uYmBgzevRo9/WSmppqhg0bZho1amScTqdp2rSpmTRpkvvkX6X35bS0NHPRRReZ8PBw9/GrvJPpvfTSS0aSueGGG8rUXZH7b2nLli0znTp1Mk6n03Tu3Nn9iwkl17t161ZzxRVXmOjoaBMSEmLatm1rJkyY4D7BWVFRkXnsscdM06ZN3ftP8a8alN6OqVOnmnbt2pmQkBATExNjhg4dan755RevY40xJikpyXTr1s04nU4THx9vHnjgAY9fp/B2YtChQ4e6j5XFY0peBlC7OYypJV+8AwAAZUyePFlLlixRUlJSTZeCU5jD4dD8+fM1bNiwmi4FAE47ATVdAAAAKN/nn3+uF198sabLAAAAVUTTDQBALbZy5cqaLgEAAFQDTTcAAEAdx7cJAaDmcPZyAAAAAAB8hKYbAAAAAAAfoekGAAAAAMBHaLoBAAAAAPARmm4AAAAAAHyEphsAAAAAAB+h6QYAAAAAwEdougEAAAAA8JH/D4ui4g8pHpN4AAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "def plot_coefs(fit_model):\n", + " \"\"\"Makes a nice plot of the coefficients. fit_model is the model instance after fitting.\"\"\"\n", + " # get the coefficients of your fit\n", + " coefficients = fit_model.coef_.reshape(n_neurons, n_bins_per_trial)\n", + " \n", + "\n", + " # show them\n", + " plt.figure(figsize = (10,5))\n", + " plt.imshow(coefficients, cmap = 'coolwarm', vmin = -np.max(coefficients), \n", + " vmax = np.max(coefficients))\n", + "\n", + " #make it pretty\n", + " plt.ylabel(\"Neuron #\", fontsize = 14)\n", + " plt.xlabel(\"Time (ms)\", fontsize = 14)\n", + " plt.colorbar(orientation = 'horizontal', shrink = .6, \n", + " label=\"Contribution of bin to decision; its 'Vote' towards a positive decision.\")\n", + " plt.tight_layout()\n", + " plt.show()\n", + " \n", + "plot_coefs(log_reg)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "ED41_d9dniIE" + }, + "source": [ + "## 2. Crossvalidation\n", + "\n", + "We saw in the last section that if we used all of our training data to fit a method, we have no idea how our method will work \n", + "on new data. This a problem for any engineering purpose.\n", + "\n", + "We also have no idea if our coefficients are meaningful or reflect random noise in the data. This is a problem for the science.\n", + "\n", + "The way to address this problem is to **split your data into a training segment and a validation segment**. We'll try an 80%/20% split." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "ZwRNhIco_nrS" + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (786722591.py, line 3)", + "output_type": "error", + "traceback": [ + "\u001b[1;36m Cell \u001b[1;32mIn[10], line 3\u001b[1;36m\u001b[0m\n\u001b[1;33m training_data =\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "split = int(n_trials*4/5)\n", + "\n", + "training_data = \n", + "validation_data = \n", + "\n", + "training_decisions = \n", + "validation_decisions = " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "Xii4Ow-nAQVV" + }, + "outputs": [], + "source": [ + "# fit on the training data. (Don't forget to reinitialize your decoder first.)\n", + "log_reg = \n", + "\n", + "\n", + "# fit and score on training\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "SeUInXtmAQYQ" + }, + "outputs": [], + "source": [ + "# score on the validation data" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "Bo94tWYoAQbF" + }, + "source": [ + "But right now we're only testing on 20% of the data! Small data means high variance, so maybe we can't trust these scores much.\n", + "\n", + "A common practice is therefore to perform __k-fold crossvalidation__. This just means we rotate which segment of the original data is the validation set. We can then average the scores." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "CK6-aoITAQel" + }, + "outputs": [], + "source": [ + "# Just run this.\n", + "def get_test_train_splits(data, decisions, n_folds=5):\n", + " \"\"\"\n", + " Returns a tuple of matched train sets and validation sets, rotating through the data.\n", + " \n", + " Note that there are scikit-learn functions that do this, too.\"\"\"\n", + " \n", + " fold_size = len(data)//n_folds\n", + " \n", + " training_sets = [np.roll(data,fold_size*i, axis=0)[fold_size:] for i in range(n_folds)]\n", + " val_sets = [np.roll(data,fold_size*i, axis=0)[:fold_size] for i in range(n_folds)]\n", + " \n", + " training_Y = [np.roll(decisions,fold_size*i, axis=0)[fold_size:] for i in range(n_folds)]\n", + " val_Y = [np.roll(decisions,fold_size*i, axis=0)[:fold_size] for i in range(n_folds)]\n", + " \n", + "\n", + " return (training_sets, training_Y), (val_sets, val_Y)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "0EVx8pdAI7aB" + }, + "source": [ + "#### Excercise 2\n", + "\n", + "Fill out the missing gaps in the script below. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "j3KLNF9vGDnb" + }, + "outputs": [], + "source": [ + "(training_sets, training_Ys), (val_sets, val_Ys) = get_test_train_splits(X, decisions)\n", + "\n", + "scores = []\n", + "\n", + "# Iterate through the k=5 folds\n", + "for fold in range(5):\n", + " print(\"Fold {} of 5\".format(fold))\n", + " \n", + " training_X = training_sets[fold]\n", + " training_Y = training_Ys[fold]\n", + " \n", + " validation_X = val_sets[fold]\n", + " validation_Y = val_Ys[fold]\n", + " \n", + " # Redefine the logistic regression model. (important to do this inside the loop)\n", + " this_model = \n", + " \n", + " # Now fit on the training data\n", + " \n", + " \n", + " # score on the validation data\n", + " this_accuracy = \n", + " \n", + " scores.append(this_accuracy)\n", + " \n", + " # score on the new dataset (new_X, new_decisions from above)\n", + " accuracy_on_test_data = \n", + " \n", + " print(\" Validation accuracy of {}\".format( this_accuracy ))\n", + " print(\" True test set accuracy of {}\".format( accuracy_on_test_data ))\n", + " plot_coefs(this_model)\n", + " \n", + "print(\"Mean validation accuracy: {}\".format(np.mean(scores)))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "ItAke3ZhGDpt" + }, + "source": [ + "How close is the validation accuracy to the test set accuracy? \n", + "\n", + "How much did using 80% of the data affect the test set accuracy?\n", + "\n", + "## 3. Regularization\n", + "\n", + "Here we'll apply regularization, as talked about in the lecture.\n", + "\n", + "\n", + "#### Exercise 3.1\n", + "\n", + "Go to the [scikit-learn docs](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression) and decide which form of regularization you would like to use with logistic regression.\n", + "\n", + "#### Exercise 3.2\n", + "\n", + "Copy and paste the cell from _Excercise 2_, but this time change the `penalty` flag in the `LogisticRegression` call to the form of regularization you chose. \n", + "\n", + "\n", + "First all other default parameters. Then set `C=1e-6` and see what happens.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "rkVb9JB3GDrq" + }, + "outputs": [], + "source": [ + "# copy, paste, and regularize Exercise 2" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "fBksWszaLgi5" + }, + "source": [ + "#### Exercise 3.3: Choose the best regularization penalty\n", + "\n", + "Let's automate the above process so that we can choose the best performing value of `C`.\n", + "\n", + "First, write a function (largely copy and paste from the last exercise) that returns the mean validation accuracy for\n", + "an arbitrary value of `C`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "UXsa18cbqt67" + }, + "outputs": [], + "source": [ + "# First complete this function that takes data (e.g. X) \n", + "# and a model, and returns the average validation accuracy from 5-fold CV\n", + "# (Largely copy and past from above, but deleting print statements)\n", + "def get_kfold_validation_score(data, decisions, C):\n", + " \n", + " \n", + " \n", + " return mean_validation_accuracy" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "7QFQQAj-rFIF" + }, + "source": [ + "Now let's create a loop for various values of `C` and see what's the best.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "4cobrMeXLgoZ" + }, + "outputs": [], + "source": [ + "# decide on a logarithmic schedule of Cs. \n", + "Cs_to_test = \n", + "\n", + "validation_accuracy_vs_C = []\n", + "for C in Cs_to_test:\n", + " \n", + " # get the mean score on k-fold cross-validation using your function above\n", + " mean_validation_accuracy = \n", + " \n", + " validation_accuracy_vs_C.append(mean_validation_accuracy)\n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "30dujMtRNSFP" + }, + "outputs": [], + "source": [ + "# Now plot the lists you just made. (Just run this.)\n", + "plt.semilogx(Cs_to_test, validation_accuracy_vs_C,\"o-\")\n", + "plt.xlabel(\"C\",fontsize=16)\n", + "plt.ylabel(\"validation acc.\",fontsize=16)\n", + "plt.ylim([.8,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "KiuHUp2QSqvy" + }, + "outputs": [], + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "zaPCPWdJSqSf" + }, + "source": [ + "## 4. Applying recurrent neural networks\n", + "\n", + "This section is going to be a bit of an introduction to our [python package for neural decoding](https://github.com/KordingLab/Neural_Decoding).\n", + "\n", + "First let's install the package. This will also install all the dependencies we need." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "nIwIoxB3SqSg" + }, + "outputs": [], + "source": [ + "!pip install Neural-Decoding --upgrade" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "n7R8Wu-iSqSk" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "WARNING: Keras package is not installed. You will be unable to use all neural net decoders\n" + ] + } + ], + "source": [ + "from Neural_Decoding import decoders\n", + "\n", + "import warnings\n", + "warnings.filterwarnings('ignore')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "mNRHoZ8kSqSm" + }, + "source": [ + "Let's take a look at the documentation of the decoder we'll use." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "PfPChxogSqSo" + }, + "outputs": [], + "source": [ + "# Run me\n", + "?decoders.SimpleRNNClassification" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "CWLHbPsR_-rb" + }, + "outputs": [], + "source": [ + "?decoders.SimpleRNNClassification.fit" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "sLQd5QKsaKdz" + }, + "source": [ + "You'll notice that the shape of the training inputs is now **3-dimensional**. This is because we can now explitly model the effect of time! Hooray! \n", + "\n", + "Recall that recurrent neural networks contain a \"hidden state\". The way this decoder works is that it reads all the neural activities in at the first time bin (out of `n_time_bins`) and then updates its hidden state accordingly. The value of this hidden state informs how the hidden state will evolve over time in each trial. After the hidden state updates `n_time_bin` times, it outputs its prediction for the animal's choice.\n", + "\n", + "\n", + "Lets apply this classifier to the data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "ZGDcn7g6AVeN" + }, + "outputs": [], + "source": [ + "# lets re-split our original 3-dimensional trials/neurons/time input data.\n", + "split = int(n_trials*4/5)\n", + "\n", + "training_data = neural_recordings[:split]\n", + "validation_data = neural_recordings[split:]\n", + "\n", + "training_decisions = decisions[:split]\n", + "validation_decisions = decisions[split:]\n", + "\n", + "training_data = np.swapaxes(training_data, 1, 2)\n", + "validation_data = np.swapaxes(validation_data, 1, 2)\n", + "\n", + "print(\"Training input data is of shape\", training_data.shape)\n", + "print(\"Validation input data is of shape\", validation_data.shape)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "D5CLevam9m6N" + }, + "outputs": [], + "source": [ + "\n", + "# first we instantiate the decoder\n", + "my_RNN_classifier = decoders.SimpleRNNClassification(units = 50,\n", + " dropout = 0,\n", + " num_epochs =250,\n", + " verbose = 1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "g2V2ttwE-SG9" + }, + "outputs": [], + "source": [ + "# now we fit to our training data, like before\n", + "my_RNN_classifier.fit(training_data, training_decisions)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "p7kc5I2xB5ya" + }, + "outputs": [], + "source": [ + "# predict on the validation data\n", + "\n", + "predictions = my_RNN_classifier.predict(validation_data)\n", + "predictions" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "l9ihnQ0zHS6Z" + }, + "source": [ + "##### Excercise 4.0\n", + "\n", + "Get the percentage of the predictions that were made correctly." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "vZyVFSJDF6hD" + }, + "outputs": [], + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "MUU4_IKwGh4n" + }, + "source": [ + "This is not as quite as good as logistic regression yet. There are a lot of parameters to choose for RNNs, and we haven't tried that yet.\n", + "\n", + "\n", + "#### Looking inside the model\n", + "\n", + "Within the `my_RNN_classifier` object you just fit, there is an actual Keras model. We can look at it, change its parameters, and use Keras methods." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "cEu_9fToHM_g" + }, + "outputs": [], + "source": [ + "# Put the cursor after model, and press tab to see the methods we can call\n", + "my_RNN_classifier.model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "J9Z-T3diH9ze" + }, + "outputs": [], + "source": [ + "# for example, we can use Keras's in-built method for calculating accuracy\n", + "from keras.utils import np_utils\n", + "acc = my_RNN_classifier.model.test_on_batch(validation_data, \n", + " np_utils.to_categorical(validation_decisions))\n", + "print(\"Accuracy is {} %\".format(100*acc[1]))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "IPVi_UFOLOM6" + }, + "source": [ + "#### Excercise 4.1: Tuning the RNN\n", + "\n", + "Train an RNN decoder again, but this time use 1000 hidden units instead of 50." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "i3IIljjbLfRD" + }, + "outputs": [], + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "aQSc7xswSqTZ" + }, + "source": [ + "## 5. Compare many methods on actual neural data\n", + "\n", + "### Preliminaries\n", + "\n", + "**STOP** Make sure you're running a **GPU runtime** for this section. (Runtime -> Change runtime type). Otherwise running the RNNs will take forever.\n", + "\n", + "First we need to download the data. I created a script to download and process the Steinmetz data into the format we need. Since the processing script takes about 15 minutes, we'll skip that step, and you can just download the processed data from my Google Drive.\n", + "\n", + "This dataset is specifically `Cori_2016-12-18`. If you're interested in loading a different session, I've copied my downloading and preprocessing script in the bottom of this notebook and you can run it right here." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "u0Wt68jUSqTZ" + }, + "outputs": [], + "source": [ + "!pip install googledrivedownloader\n", + "\n", + "from google_drive_downloader import GoogleDriveDownloader as gdd\n", + "\n", + "gdd.download_file_from_google_drive(file_id='1W3TwEtC0Z6Qmbfuz8_AWRiQHfuDb9FIS',\n", + " dest_path='./Binned_data.zip',\n", + " unzip=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "sARtnvbYSqTe" + }, + "outputs": [], + "source": [ + "binned_spikes = np.load('binned_spikes.npy')\n", + "choices = np.load('choices.npy')+1\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "6LQ2cxR-SqTi" + }, + "source": [ + "### Predicting choices from neural population recordings\n", + "\n", + "We're going to try to predict the mouse's choices from the neuropixel recordings in the 1 second preceeding each choice. `binned_spikes.npy` is a numpy array containing the binned spike rates, and `choices.npy` contains the animal's choices. \n", + "\n", + "There are 228 trials, 1089 neurons, and 50 bins per trial (for a time of 20ms per bin).\n", + "\n", + "This is not a great situation for machine learning. As a rule of thumb, we would like more trials than datapoints per trial. (If doing this for realz, would suggest running PCA on this data and using the top components as inputs). But, it's what we got, so here goes!\n", + "\n", + "#### Exercise 5.0\n", + "\n", + "Print out the shape of `binned_spikes` and `choices`. Also print out the first 10 choices.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "korkcjUISqTi" + }, + "outputs": [], + "source": [ + "\n", + "print(binned_spikes.shape, choices.shape)\n", + "print(choices[:10])" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "LNDeXvE_cU94" + }, + "source": [ + "You'll notice that `choices` takes values 0, 1, and 2. We're going to try to decode this." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "VqEcdu4tX6oF" + }, + "source": [ + "#### Excercise 5.1\n", + "\n", + "Split this data into test and validation splits.\n", + "\n", + "(We'll skip the final testing phase in this exercise. In reality, make sure to do cross-validation and use both validation and testing data.)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "RuovaxSOX7Y8" + }, + "outputs": [], + "source": [ + "# make training and validation data\n", + "# Use an 80/20 split.|\n", + "split = \n", + "\n", + "training_spikes = \n", + "validation_spikes = \n", + "\n", + "training_choices = \n", + "validation_choices =" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "H1HVdWFEZrZl" + }, + "source": [ + "##### A fitting demo.\n", + "\n", + "This is basically what we did above, but with actual data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "LPjqE8_OSqTs" + }, + "outputs": [], + "source": [ + "\n", + "my_RNN_classifier = decoders.SimpleRNNClassification(units = 100,\n", + " dropout = 0,\n", + " num_epochs =10,\n", + " verbose = 1)\n", + "\n", + "my_RNN_classifier.fit(training_spikes, training_choices)\n", + "\n", + "\n", + "predictions = my_RNN_classifier.predict(validation_spikes)\n", + "accuracy = np.sum(predictions == validation_choices) / float(len(predictions))\n", + "\n", + "print(\"\\n validation accuracy: {} %\".format(100*accuracy))\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "Bpzpvy6PaKCv" + }, + "source": [ + "Note that the train accuracy reached about 100% in these 10 epochs, but the validation accuracy is quite low. Sounds like overfitting! We might want to try some regularization, like dropout." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "Xma2jUT5SqTx" + }, + "source": [ + "### Excercise 5.1\n", + "\n", + "Fit each of the following decoders:\n", + "\n", + "1. A Gated Recurrent Unit (`decoders.GRUClassification`)\n", + "2. An LSTM (`decoders.LSTMClassification`)\n", + "3. Gradient boosted trees (XGBoost) (`decoders.XGBoostClassification`)\n", + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "GvvopGtKaw0k" + }, + "outputs": [], + "source": [ + "# GRU\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "kaW868Paaw5C" + }, + "outputs": [], + "source": [ + "#LSTM\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "jjoE3Qo3aw2n" + }, + "outputs": [], + "source": [ + "# XGBoost\n", + "\n", + "# XGBoost is powerful but does not model time dependencies.\n", + "# Like for the logistic regression above, we have to flatten\n", + "# the inputs into shape (n_trials, n_neurons x n_time_bins)\n", + "\n", + "flat_train_data = np.reshape(training_spikes, (len(training_spikes),-1))\n", + "flat_val_data = np.reshape(validation_spikes, (len(validation_spikes),-1))\n", + "\n", + "\n", + "# now train it like above\n", + "\n", + "\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "mH2-UxhRLJEg" + }, + "source": [ + "### Extra credit exercise 1: reduce the dimension of data with PCA\n", + "\n", + "Create an instance of PCA (loading the module from scikit-learn). Then, fit it on your training data. Then transform both the validation and train data. (Note that we don't fit the PCA using train data.)\n", + "\n", + "You can either reduce the dimension across neurons only, preserving temporal structure, or decide to reduce across all dimensions.\n", + "\n", + "Does validation accuracy improve?" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "8dl5XbyPLdBp" + }, + "source": [ + "### Extra credit exercise 2: Set up a script to perform k-fold CV\n", + "\n", + "Using your favorite methods (e.g. scikit learn) or the script we wrote above, create a method to perform 5-fold cross-validation on the Neuropixels data. The function should take parameters to create a model as input, and it should output the average validation accuracy across the 5 validation sets. " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "rEpxVLe431kH" + }, + "source": [ + "### Extra credit exercise 3: find the best decoder\n", + "\n", + "Search across methods and hyperparameters for the best decoder. Try hyperopt, or random searches.\n", + "\n", + "If you're fancy and have lots of compute time, maybe try automated ML. (e.g. autosklearn)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "ucHs_lBqSqT7" + }, + "source": [ + "## Appendix: downloading a Neuropixels session and processing" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "9jeeJvVLSqT8" + }, + "source": [ + "This will take about 30 seconds to download the ~600M of data into your working folder, and 10 minutes to run the script." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "SI_K0MRkSqT9" + }, + "outputs": [], + "source": [ + "session = \"Cori_2016-12-18/\"\n", + "\n", + "!wget -np -r -nv http://data.cortexlab.net/taskData/$session\n", + "!mv data.cortexlab.net/taskData/ ." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "XVpyiQmWSqUB" + }, + "source": [ + "Now we'll extract this data into Python in the form of a dictionary." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "bKqX75s8SqUB" + }, + "outputs": [], + "source": [ + "from tqdm import tqdm as tqdm\n", + "\n", + "def load_data(session):\n", + " \"\"\"Takes a session in relative path ./taskData and loads it as a dictionary.\"\"\"\n", + " files = !ls taskData/$session/*.npy\n", + " all_files = {}\n", + " for file in files:\n", + " filename = file.split(\"/\")[1][:-4]\n", + " all_files[filename] = np.load(file)\n", + " return all_files\n", + " \n", + "def count_neurons(time_interval, all_files):\n", + " \"\"\"In this time interval, return the neurons with nonzero spikes, and how many\n", + " \n", + " Returns (ids, counts)\n", + " \"\"\"\n", + " \n", + " \n", + " t1,t2 = time_interval\n", + " \n", + " trial_spikes = all_files['spikes.times']\n", + "\n", + " interval = (trial_spikes > t1) & (trial_spikes < t2)\n", + "\n", + " trial_spikes = trial_spikes[interval]\n", + " ids = all_files['spikes.clusters'][interval]\n", + " \n", + " # ids has all the info we need\n", + " return np.unique(ids, return_counts = True)\n", + " \n", + " \n", + "\n", + "\n", + "def bin_into_array(all_files, time_before_response=1, n_bins = 50):\n", + " \n", + " ids = all_files['spikes.clusters']\n", + " idList = np.unique(ids)\n", + " \n", + " n_trials = len(all_files['trials.response_choice'])\n", + " n_neurons = len(idList)\n", + " \n", + " choices = np.reshape(all_files['trials.response_choice'],-1)\n", + " data = np.zeros((n_trials, n_neurons, n_bins))\n", + " \n", + " time_resolution = time_before_response/ float(n_bins)\n", + " \n", + " for trial in tqdm(range(n_trials)):\n", + " end_time = all_files['trials.response_times'][trial]\n", + " start_time = end_time - time_before_response\n", + " \n", + " data.trial\n", + " \n", + " for b in range(n_bins):\n", + " \n", + " which_neurons, n_spikes = count_neurons((start_time + b*time_resolution,\n", + " start_time + (b+1)*time_resolution),\n", + " all_files)\n", + " \n", + " data[trial,which_neurons,b] = n_spikes\n", + " \n", + " return data, choices\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "1kmTWMwSSqUD" + }, + "outputs": [], + "source": [ + "session = \"Cori_2016-12-18\"\n", + "all_files = load_data(session)\n", + "data, choices = bin_into_array(all_files)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "HJSdc0siSqUF" + }, + "outputs": [], + "source": [ + "#clean up the data we aren't using\n", + "!rm -r data.cortexlab.net/" + ] + } + ], + "metadata": { + "colab": { + "collapsed_sections": [], + "include_colab_link": true, + "name": "Neural decoding.ipynb", + "provenance": [], + "version": "0.3.2" + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/dist/Neural_Decoding-0.1.2.dev0-py3.10.egg b/dist/Neural_Decoding-0.1.2.dev0-py3.10.egg new file mode 100644 index 0000000000000000000000000000000000000000..eb81114aec4f248e173ac07e2ab725f1d9e6c20a GIT binary patch literal 30945 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 E2l9-a;s5{u literal 0 HcmV?d00001