{"metadata":{"colab":{"collapsed_sections":[],"name":"baseline_noID (2).ipynb","provenance":[]},"kernelspec":{"display_name":"condakaggle","language":"python","name":"condakaggle"},"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.8.11"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import librosa\nimport numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n#import torchsummary\nimport os\nfrom os import listdir\nfrom os.path import isfile, join\nimport wave\nimport matplotlib.pyplot as plt\nimport librosa.display\nfrom torch.utils.data import TensorDataset, DataLoader\nimport pytorch_lightning as pl","metadata":{"id":"b952584b"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data explo","metadata":{"id":"d21b32cb"}},{"cell_type":"code","source":"devpath=os.getcwd()+'/eurecom-aml-2022-challenge-2/dev_data/dev_data/slider/'\nevalpath=os.getcwd()+'/eurecom-aml-2022-challenge-2/eval_data/eval_data/slider/'\ndevdatatrain = [f for f in listdir(devpath+'train/') if isfile(join(devpath+'train/', f))] \ndevdatatest = [f for f in listdir(devpath+'test/') if isfile(join(devpath+'test/', f))]\nevaldatatrain = [f for f in listdir(evalpath+'train/') if isfile(join(evalpath+'train/', f))] \nevaldatatest = [f for f in listdir(evalpath+'test/') if isfile(join(evalpath+'test/', f))] \nif '.DS_Store' in devdatatrain:\n    devdatatrain.remove('.DS_Store')\n    \nif '.DS_Store' in devdatatest:\n    devdatatest.remove('.DS_Store')\n    \nif '.DS_Store' in evaldatatrain:\n    evaldatatrain.remove('.DS_Store')\n    \nif '.DS_Store' in evaldatatest:\n    evaldatatest.remove('.DS_Store')","metadata":{"id":"f6d00459"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"there are \"+str(len(devdatatrain))+\" samples in the dev training data and \"+str(len(devdatatest))+\" samples in the dev test data\")","metadata":{"id":"e2546aaa","outputId":"b46f6038-3709-4e1c-9592-2aa4ba318486"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"there are \"+str(len(evaldatatrain))+\" samples in the eval training data and \"+str(len(evaldatatest))+\" samples in the eval test data\")","metadata":{"id":"d9865540","outputId":"c7eb7670-3f42-46c6-f037-e13a5ca6ca67"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"devtrain={\"00\":[],\"02\":[],\"04\":[]}  # take these to construct graph and also show anomaly repartition between the anomalies\nfor i in devdatatrain:\n    if i.split(\"id_\")[1][:2]==\"00\":\n        devtrain[\"00\"].append(i)\n    elif i.split(\"id_\")[1][:2]==\"02\":\n        devtrain[\"02\"].append(i)\n    else:\n        devtrain[\"04\"].append(i)\n        \ndevtest={\"00\":[],\"02\":[],\"04\":[]}\nfor i in devdatatest:\n    if i.split(\"id_\")[1][:2]==\"00\":\n        devtest[\"00\"].append(i)\n    elif i.split(\"id_\")[1][:2]==\"02\":\n        devtest[\"02\"].append(i)\n    else:\n        devtest[\"04\"].append(i)\n        \nevaltrain={\"01\":[],\"03\":[],\"05\":[]}\nfor i in evaldatatrain:\n    if i.split(\"id_\")[1][:2]==\"01\":\n        evaltrain[\"01\"].append(i)\n    elif i.split(\"id_\")[1][:2]==\"03\":\n        evaltrain[\"03\"].append(i)\n    else:\n        evaltrain[\"05\"].append(i)\n        \nevaltest={\"01\":[],\"03\":[],\"05\":[]}\nfor i in evaldatatest:\n    if i.split(\"id_\")[1][:2]==\"01\":\n        evaltest[\"01\"].append(i)\n    elif i.split(\"id_\")[1][:2]==\"03\":\n        evaltest[\"03\"].append(i)\n    else:\n        evaltest[\"05\"].append(i)\n        ","metadata":{"id":"9a356a27"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#----Plot data----\n# set width of bar\nbarWidth = 0.25\nfig = plt.subplots(figsize =(12, 8))\n\n# set height of bar\ndevtrainset = [len(devtrain[\"00\"]), len(devtrain[\"02\"]), len(devtrain[\"04\"])]\ndevtestset = [len(devtest[\"00\"]),len(devtest[\"02\"]), len(devtest[\"04\"])]\n\n# Set position of bar on X axis\nbr1 = np.arange(len(devtrain))\nbr2 = [x + barWidth for x in br1]\nbr3 = [x + barWidth for x in br2]\n \n# Make the plot\nplt.bar(br1, devtrainset, color ='tab:blue', width = barWidth,\n        edgecolor ='grey', label ='Train')\nplt.bar(br2, devtestset, color ='tab:orange', width = barWidth,\n        edgecolor ='grey', label ='Test')\n\nplt.xlabel('Table 4.a: Distribution of data for the dev dataset', fontweight ='bold', fontsize = 15)\nplt.ylabel('Number of samples', fontweight ='bold', fontsize = 15)\nplt.xticks([r + barWidth for r in range(len(devtestset))],\n        ['00', '02', '04'])\n \nplt.legend()\nplt.show()","metadata":{"id":"nWKbY7n6zKzh"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#----Plot data----\n# set width of bar\nbarWidth = 0.25\nfig = plt.subplots(figsize =(12, 8))\n\n# set height of bar\nevaltrainset = [len(evaltrain[\"01\"]), len(evaltrain[\"03\"]), len(evaltrain[\"05\"])]\nevaltestset = [len(evaltest[\"01\"]),len(evaltest[\"03\"]), len(evaltest[\"05\"])]\n\n# Set position of bar on X axis\nbr1 = np.arange(len(devtrain))\nbr2 = [x + barWidth for x in br1]\nbr3 = [x + barWidth for x in br2]\n \n# Make the plot\nplt.bar(br1, devtrainset, color ='tab:blue', width = barWidth,\n        edgecolor ='grey', label ='Train')\nplt.bar(br2, devtestset, color ='tab:orange', width = barWidth,\n        edgecolor ='grey', label ='Test')\n\nplt.xlabel('Table 4.b: Distribution of data for the eval dataset', fontweight ='bold', fontsize = 15)\nplt.ylabel('Number of samples', fontweight ='bold', fontsize = 15)\nplt.xticks([r + barWidth for r in range(len(devtestset))],\n        ['01', '03', '05'])\n \nplt.legend()\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"devtest\ndevtest_={\"00\":{\"anomaly\":[],\"normal\":[]},\"02\":{\"anomaly\":[],\"normal\":[]},\"04\":{\"anomaly\":[],\"normal\":[]}}\nfor i in devdatatest:\n    if i.split(\"id_\")[1][:2]==\"00\": \n        if i[:6]==\"normal\":\n            devtest_[\"00\"][\"normal\"].append(i)\n        else:\n            devtest_[\"00\"][\"anomaly\"].append(i)\n    if i.split(\"id_\")[1][:2]==\"02\": \n        if i[:6]==\"normal\":\n            devtest_[\"02\"][\"normal\"].append(i)\n        else:\n            devtest_[\"02\"][\"anomaly\"].append(i)\n    if i.split(\"id_\")[1][:2]==\"04\": \n        if i[:6]==\"normal\":\n            devtest_[\"04\"][\"normal\"].append(i)\n        else:\n            devtest_[\"04\"][\"anomaly\"].append(i)","metadata":{"id":"d90969ca"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#PLOT of Anomalies\n# set width of bar\nbarWidth = 0.25\nfig = plt.subplots(figsize =(12, 8))\n\n# set height of bar\ndev_anomaly = [len(devtest_[\"00\"][\"anomaly\"]), len(devtest_[\"02\"][\"anomaly\"]), len(devtest_[\"04\"][\"anomaly\"])]\ndev_normal = [len(devtest_[\"00\"][\"normal\"]),len(devtest_[\"02\"][\"normal\"]), len(devtest_[\"04\"][\"normal\"])]\n\n# Set position of bar on X axis\nbr1 = np.arange(len(dev_anomaly))\nbr2 = [x + barWidth for x in br1]\nbr3 = [x + barWidth for x in br2]\n \n# Make the plot\nplt.bar(br1, dev_anomaly, color ='tab:blue', width = barWidth,\n        edgecolor ='grey', label ='Anomaly')\nplt.bar(br2, dev_normal, color ='tab:orange', width = barWidth,\n        edgecolor ='grey', label ='Normal')\n\nplt.xlabel('Table 2: Distribution of data', fontweight ='bold', fontsize = 15)\nplt.ylabel('Number of samples', fontweight ='bold', fontsize = 15)\nplt.xticks([r + barWidth for r in range(len(devtestset))],\n        ['00', '02', '04'])\n \nplt.legend()\nplt.show()","metadata":{"id":"_pbW_QX1zS6f"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"!!! eval folder does not contain the same ids !!!  \n\nshall we train the model with eval training data as well and make models aware of id infos ??? test the model on it at least, is it allowed?\n\nor that means that no information on ids are needed for modelling in this competition -> would overfit, ids should be generated by the same process\n\nShould be ok to start with dev set only and cluster features to see how ids are relevant, then possibly model ids with one-hot encoding for example, or by constructing different models ","metadata":{"id":"9ab6a431"}},{"cell_type":"code","source":"","metadata":{"id":"8646d514"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Sample rates and signal lengths","metadata":{"id":"171141f0"}},{"cell_type":"markdown","source":"Note add eval data","metadata":{"id":"ab0aff58"}},{"cell_type":"code","source":"SRsTr=[]\nfor keys in devtrain.keys():\n    for i in devtrain[keys]:\n        wav, sr=librosa.load(devpath+'train/'+i,sr=None)\n        SRsTr.append(sr)\n        \nSRsTt=[]\nfor keys in devtest.keys():\n    for i in devtest[keys]:\n        wav, sr=librosa.load(devpath+'test/'+i,sr=None)\n        SRsTt.append(sr)\n        ","metadata":{"id":"1f916ba5"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SRsTr=np.array(SRsTr)\nSRsTt=np.array(SRsTt)\nprint(\"the dev training samples have sample rate mean \"+str(SRsTr.mean())+\" and std \"+str(SRsTr.std()))\nprint(\"the dev testing samples have sample rate mean \"+str(SRsTt.mean())+\" and std \"+str(SRsTt.std()))","metadata":{"id":"3a607421","outputId":"c6c3cdf2-1696-4157-c743-723e42311bfd"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LENsTr=[]\ndevtrain_={}\nfor keys in devtrain.keys():\n    devtrain_[keys]=[]\n    for i in devtrain[keys]:\n        wav, sr=librosa.load(devpath+'train/'+i,sr=None)\n        devtrain_[keys].append(wav)\n        LENsTr.append(len(wav))\n        \nLENsTt=[]\ndevtest_={}\nfor keys in devtest.keys():\n    devtest_[keys]=[]\n    for i in devtest[keys]:\n        wav, sr=librosa.load(devpath+'test/'+i,sr=None)\n        devtest_[keys].append(wav)\n        LENsTt.append(len(wav))","metadata":{"id":"b31e83e2"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LENsTr=np.array(LENsTr)\nLENsTt=np.array(LENsTt)\nprint(\"the dev training samples have mean sampling lengths of \"+str(LENsTr.mean())+\" and std \"+str(LENsTr.std()))\nprint(\"the dev training samples have mean sampling lengths of \"+str(LENsTt.mean())+\" and std \"+str(LENsTt.std()))","metadata":{"id":"e2521eac","outputId":"629a1225-24ac-4f54-d803-881e037c5fe2"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The sampling rate is equal to 16000 for all samples in the dev dataset. That suggests that this rate does not need to be changing, we also consider it irrelevent because it could bring errors in interpolation because a lot of processes seem to be needed in the litterature to ensure it is done proiperly such as aliasing. The sample length are also similar which is very handy if we are to use convolutional layers for example. ","metadata":{"id":"913913f1"}},{"cell_type":"markdown","source":"# Spectograms","metadata":{"id":"acb8cb7c"}},{"cell_type":"code","source":"def get_log_mel_spectrogram(signal, n_fft, hop_length, win_length):\n    if win_length is None:\n        win_length = n_fft\n    if hop_length is None:\n        hop_length = int(win_length // 4)\n    mel_spectrogram = librosa.feature.melspectrogram(y=signal, sr=16000, n_fft=n_fft, S=None, hop_length=hop_length, win_length=win_length, power=2)\n    S_dB = librosa.power_to_db(mel_spectrogram, ref=np.max)\n    return S_dB","metadata":{"id":"b64ecccb"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"librosa.load(evalpath+'test/'+evaltest[\"01\"][0], sr=None)[0]","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"S_dB= get_log_mel_spectrogram(librosa.load(evalpath+'test/'+evaltest[\"01\"][0], sr=None)[0], n_fft=2048, hop_length=None, win_length=None)\nfig, ax = plt.subplots()\nimg = librosa.display.specshow(S_dB, x_axis='time',\n                         y_axis='mel', sr=sr,\n                         ax=ax)\nfig.colorbar(img, ax=ax, format='%+2.0f dB')\nax.set(title='Figure 3.b: Abnormal Mel-frequency spectrogram')\nplt.show()","metadata":{"id":"5bf27c69","outputId":"0f9a3833-d56f-4c72-e749-ef8b2d316c7a"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"S_dB.shape","metadata":{"id":"fa9b243a","outputId":"70f2485b-6885-4c98-df33-ef5a413e05bc"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# dataset building","metadata":{"id":"730d7f63"}},{"cell_type":"code","source":"class dataset_1DCNN(): # note IDs not suffled\n    def __init__(self, n_fft, hop_length, win_length):  # note this computes minmax scaler taking into account all channels\n        self.max=0\n        self.min=1000\n        self.n_fft=n_fft\n        if win_length is None:\n            self.win_length = self.n_fft\n        else:\n            self.win_length =win_length\n        if hop_length is None:\n            self.hop_length = int(self.win_length // 4)  \n        else:\n            self.hop_length =hop_length\n            \n    def minmax(self, x, _min_, _max_):\n        return (x-_min_)/(_max_-_min_)\n    \n    def get_log_mel_spectrogram(self, signal):\n        mel_spectrogram = librosa.feature.melspectrogram(y=signal, sr=16000, n_fft=self.n_fft, S=None, hop_length=self.hop_length, win_length=self.win_length, power=2)\n        S_dB = librosa.power_to_db(mel_spectrogram, ref=np.max)\n        return S_dB\n    \n    def fit_transform_train(self, dict_): \n        k=list(dict_.keys())\n        k=k[0]\n        S_dB= self.get_log_mel_spectrogram(dict_[k][0])\n        S_dB=np.flip(S_dB.transpose(),0)\n        data=S_dB.reshape(1,S_dB.shape[0],S_dB.shape[1])\n        for i in dict_.keys():\n            for j in range(1,len(dict_[i])):\n                S_dB= self.get_log_mel_spectrogram(dict_[i][j])\n                max_=S_dB.max()\n                min_=S_dB.min()\n                S_dB=np.flip(S_dB.transpose(),0)\n                S_dB=S_dB.reshape(1,S_dB.shape[0],S_dB.shape[1])\n                data=np.concatenate((data,S_dB),axis=0)\n                if max_>self.max:\n                    self.max=max_\n                if min_<self.min:\n                    self.min=min_\n        for i in range(data.shape[0]):\n            data[i,:,:]=self.minmax(data[i,:,:],self.min,self.max)\n        return data   \n    \n    def fit_test(self, dict_):\n        k=list(dict_.keys())\n        k=k[0]\n        S_dB= self.get_log_mel_spectrogram(dict_[k][0])\n        S_dB=self.minmax(S_dB,self.min,self.max)\n        S_dB=np.flip(S_dB.transpose(),0)\n        data=S_dB.reshape(1,S_dB.shape[0],S_dB.shape[1])\n        for i in dict_.keys():\n            for j in range(1,len(dict_[i])):\n                S_dB= self.get_log_mel_spectrogram(dict_[i][j]) \n                S_dB=self.minmax(S_dB,self.min,self.max)\n                S_dB=np.flip(S_dB.transpose(),0)\n                S_dB=S_dB.reshape(1,S_dB.shape[0],S_dB.shape[1])\n                data=np.concatenate((data,S_dB),axis=0)\n        return data          \n        ","metadata":{"id":"f9a28f00"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datasetbuild=dataset_1DCNN(n_fft=2048,hop_length=None,win_length=None)\ndatatrain=datasetbuild.fit_transform_train(devtrain_)\ndatatest=datasetbuild.fit_test(devtest_)  ","metadata":{"id":"ce495288"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Modelling","metadata":{"id":"cd8f4c48"}},{"cell_type":"code","source":"class Flatten(nn.Module):\n    def forward(self, input):\n        return input.view(input.size(0), -1)\n\nclass UnFlatten(nn.Module):\n    def forward(self, input, size):\n        return input.view(input.size(0), size, 1, 1)\n\nclass VAE(nn.Module):\n    def __init__(self, in_channels, h_dim, z_dim):\n        super(VAE, self).__init__()\n        self.h_dim=h_dim\n        self.z_dim=z_dim\n        self.in_channels=in_channels\n        \n        self.encoder = nn.Sequential(\n            nn.Conv1d(self.in_channels, 64, kernel_size=4, stride=2),\n            nn.ReLU(),\n            nn.Conv1d(64, 64, kernel_size=6, stride=2),\n            nn.ReLU(),\n            nn.AvgPool1d(2, ),\n            nn.Conv1d(64, 64, kernel_size=6, stride=2),\n            nn.ReLU(),\n            nn.AvgPool1d(2, ),\n            nn.Conv1d(64, 64, kernel_size=4, stride=2),\n            nn.ReLU(),\n            Flatten()\n        )\n        \n        self.fc1 = nn.Linear(h_dim, z_dim)\n        self.fc2 = nn.Linear(h_dim, z_dim)\n        self.fc3 = nn.Linear(z_dim, h_dim)\n        \n        self.decoder = nn.Sequential(\n            UnFlatten(),\n            nn.ConvTranspose1d(h_dim, 64, kernel_size=4, stride=2),\n            nn.ReLU(),\n            nn.MaxPool1d(2,),\n            nn.ConvTranspose1d(64, 64, kernel_size=6, stride=2),\n            nn.ReLU(),\n            nn.MaxPool1d(2,),\n            nn.ConvTranspose1d(64, 32, kernel_size=6, stride=2),\n            nn.ReLU(),\n            nn.ConvTranspose1d(32, self.in_channels, kernel_size=4, stride=2),\n            nn.Sigmoid(),\n        )\n    \n    \n    def reparameterize(self, mu, logvar):\n        std = logvar.mul(0.5).exp_()\n        # return torch.normal(mu, std)\n        esp = torch.randn(*mu.size())\n        z = mu + std * esp\n        return z\n    \n    def bottleneck(self, h):\n        mu, logvar = self.fc1(h), self.fc2(h)\n        z = self.reparameterize(mu, logvar)\n        return z, mu, logvar\n\n    def encode(self, x):\n        h = self.encoder(x)\n        z, mu, logvar = self.bottleneck(h)\n        return z, mu, logvar\n\n    def decode(self, z):\n        z = self.fc3(z)\n        z = self.decoder(z)\n        return z\n\n    def forward(self, x):\n        z, mu, logvar = self.encode(x)\n        z = self.decode(z)\n        return z, mu, logvar","metadata":{"id":"3a21c498"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def VAE_loss_function(recon_x, x, mu, logvar, reconst_loss='mse', a_RECONST=1., a_KLD=1.):\n    func = (F.mse_loss if reconst_loss == 'mse'\n            else F.binary_cross_entropy if reconst_loss == 'bce'\n            else 'Unknown reconst_loss')\n    RECONST = func(recon_x, x.view(-1, x_dim), reduction='sum')\n    KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())\n    return RECONST*a_RECONST + KLD*a_KLD","metadata":{"id":"99c3c581"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"params={\n\"lr\": 0.001,\n\"b1\": 0.9,\n\"b2\": 0.999,\n\"weight_decay\": 0.0,\n\"epochs\" : 100,\n\"batch_size\" : 1000,\n\"shuffle\" : True,\n\"validation_split\" : 0.1,\n\"verbose\" : 1}","metadata":{"id":"68f116f7"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class VAELightning(pl.LightningModule):\n    def __init__(self, model, params, trainds, testds):\n        self.model=model\n        self.params=params\n        self.trainds=trainds\n        self.testds=testds\n        self.mseloss = torch.nn.MSELoss()\n        \n    def forward(self, x):\n        return self.model(x)\n    \n    def training_step(self, batch, batch_nb):\n        x, y = batch\n        y_hat, z, mu, logvar = self.model.forward_all(x)\n        loss = VAE_loss_function(recon_x=y_hat, x=x, mu=mu, logvar=logvar,\n                                 reconst_loss='mse',\n                                 a_RECONST=1.,\n                                 a_KLD=.5)\n        tensorboard_logs = {'train_loss': loss}\n        return {'loss': loss, 'log': tensorboard_logs}\n    \n    def validation_step(self, batch, batch_nb):\n        x, y = batch\n        y_hat = self.forward(x)\n        return {'val_loss': self.mseloss(y_hat, y)}\n\n    def validation_epoch_end(self, outputs):\n        avg_loss = torch.stack([x['val_loss'] for x in outputs]).mean()\n        tensorboard_logs = {'val_loss': avg_loss}\n        return {'avg_val_loss': avg_loss, 'log': tensorboard_logs}\n    \n    def configure_optimizers(self):\n        return torch.optim.Adam(vae.parameters(), lr=self.params[\"lr\"],\n                                betas=(self.params.fit[\"b1\"], self.params.fit[\"b2\"]),\n                                weight_decay=self.params[\"weight_decay\"])\n        \n    def dataloader(self, ds, for_what):\n        ds=torch.Tensor(ds)\n        return torch.utils.data.DataLoader(ds, batch_size=self.params.fit.batch_size,\n                          shuffle=(self.params.fit.shuffle if for_what == 'train' else False))\n        \n    def Traindataloader(self):\n        return self.dataloader(self.trainds,'train')\n    \n    def Testdataloader(self):\n        return self.dataloader(self.testds,'test')","metadata":{"id":"49c4f64d"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nvae = VAE(313,128,56).to(device)\nvae","metadata":{"id":"4e78fc47","outputId":"ceccba15-388f-48c1-eca7-9b5d3acc9970"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"conf=VAELightning(vae,params,datatrain,datatest)\ntrainer = pl.Trainer(max_epochs=params[\"epochs\"], gpus=torch.cuda.device_count())\ntrainer.fit(config)","metadata":{"id":"15828c7f","outputId":"82b24364-1d56-4f5e-80ed-5ce507d3a22c"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"927bb027"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"34bd1630"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}