{"cells":[{"metadata":{},"cell_type":"markdown","source":"## **<div id=\"I\">I. Importing Tools</div>**\n\n### **<div id=\"I1\">1. Dependencies</div>**"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import time\nstart_time = time.time()\n\n# Data analysis and wrangling\nimport numpy as np\nimport pandas as pd\n\n# Visualization\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport IPython\nimport IPython.display\nimport librosa\nimport librosa.display\nimport random\nfrom tqdm import tqdm_notebook\nfrom fastai import *\nfrom fastai.vision import *\nfrom fastai.vision.data import *\nfrom fastai.imports import *\nfrom fastai.callback import *\nfrom fastai.callbacks import *\n\n# Machine learning\nfrom sklearn import preprocessing\nimport sklearn.metrics\nfrom sklearn.metrics import label_ranking_average_precision_score\n\n# File handling\nfrom pathlib import Path\nimport gc\nimport os\nprint(os.listdir(\"../input\"))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### **<div id=\"I2\">2. lwlrap</div>**"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# from official code https://colab.research.google.com/drive/1AgPdhSp7ttY18O3fEoHOQKlt_3HJDLi8#scrollTo=cRCaCIb9oguU\ndef _one_sample_positive_class_precisions(scores, truth):\n    \"\"\"Calculate precisions for each true class for a single sample.\n\n    Args:\n      scores: np.array of (num_classes,) giving the individual classifier scores.\n      truth: np.array of (num_classes,) bools indicating which classes are true.\n\n    Returns:\n      pos_class_indices: np.array of indices of the true classes for this sample.\n      pos_class_precisions: np.array of precisions corresponding to each of those\n        classes.\n    \"\"\"\n    num_classes = scores.shape[0]\n    pos_class_indices = np.flatnonzero(truth > 0)\n    # Only calculate precisions if there are some true classes.\n    if not len(pos_class_indices):\n        return pos_class_indices, np.zeros(0)\n    # Retrieval list of classes for this sample.\n    retrieved_classes = np.argsort(scores)[::-1]\n    # class_rankings[top_scoring_class_index] == 0 etc.\n    class_rankings = np.zeros(num_classes, dtype=np.int)\n    class_rankings[retrieved_classes] = range(num_classes)\n    # Which of these is a true label?\n    retrieved_class_true = np.zeros(num_classes, dtype=np.bool)\n    retrieved_class_true[class_rankings[pos_class_indices]] = True\n    # Num hits for every truncated retrieval list.\n    retrieved_cumulative_hits = np.cumsum(retrieved_class_true)\n    # Precision of retrieval list truncated at each hit, in order of pos_labels.\n    precision_at_hits = (\n            retrieved_cumulative_hits[class_rankings[pos_class_indices]] /\n            (1 + class_rankings[pos_class_indices].astype(np.float)))\n    return pos_class_indices, precision_at_hits\n\n\ndef calculate_per_class_lwlrap(truth, scores):\n    \"\"\"Calculate label-weighted label-ranking average precision.\n\n    Arguments:\n      truth: np.array of (num_samples, num_classes) giving boolean ground-truth\n        of presence of that class in that sample.\n      scores: np.array of (num_samples, num_classes) giving the classifier-under-\n        test's real-valued score for each class for each sample.\n\n    Returns:\n      per_class_lwlrap: np.array of (num_classes,) giving the lwlrap for each\n        class.\n      weight_per_class: np.array of (num_classes,) giving the prior of each\n        class within the truth labels.  Then the overall unbalanced lwlrap is\n        simply np.sum(per_class_lwlrap * weight_per_class)\n    \"\"\"\n    assert truth.shape == scores.shape\n    num_samples, num_classes = scores.shape\n    # Space to store a distinct precision value for each class on each sample.\n    # Only the classes that are true for each sample will be filled in.\n    precisions_for_samples_by_classes = np.zeros((num_samples, num_classes))\n    for sample_num in range(num_samples):\n        pos_class_indices, precision_at_hits = (\n            _one_sample_positive_class_precisions(scores[sample_num, :],\n                                                  truth[sample_num, :]))\n        precisions_for_samples_by_classes[sample_num, pos_class_indices] = (\n            precision_at_hits)\n    labels_per_class = np.sum(truth > 0, axis=0)\n    weight_per_class = labels_per_class / float(np.sum(labels_per_class))\n    # Form average of each column, i.e. all the precisions assigned to labels in\n    # a particular class.\n    per_class_lwlrap = (np.sum(precisions_for_samples_by_classes, axis=0) /\n                        np.maximum(1, labels_per_class))\n    # overall_lwlrap = simple average of all the actual per-class, per-sample precisions\n    #                = np.sum(precisions_for_samples_by_classes) / np.sum(precisions_for_samples_by_classes > 0)\n    #           also = weighted mean of per-class lwlraps, weighted by class label prior across samples\n    #                = np.sum(per_class_lwlrap * weight_per_class)\n    return per_class_lwlrap, weight_per_class\n\n# Wrapper for fast.ai library\ndef lwlrap(scores, truth, **kwargs):\n    score, weight = calculate_per_class_lwlrap(to_np(truth), to_np(scores))\n    return torch.Tensor([(score * weight).sum()])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## **<div id=\"II\">II. Gather data</div>**"},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_pkl(filename):\n    \"\"\"Load pickle object from file.\"\"\"\n    with open(filename, 'rb') as f:\n        return pickle.load(f)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"testing_df_X = pd.read_csv('../input/freesound-audio-tagging-2019/sample_submission.csv')\ntesting_df_LH = pd.read_csv('../input/freesound-audio-tagging-2019/sample_submission.csv')\ntesting_df = pd.read_csv('../input/freesound-audio-tagging-2019/sample_submission.csv')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## **<div id=\"III\">III. Preprocessing sound</div>**\n\n### **<div id=\"III1\">1. EasyDict dependency</div>**"},{"metadata":{"trusted":true},"cell_type":"code","source":"#EasyDict allows to access dict values as attributes (works recursively). A Javascript-like properties dot notation for python dicts.\n#It is mandatory in order to use the library below\n# Special thanks to https://github.com/makinacorpus/easydict/blob/master/easydict/__init__.py\nclass EasyDict(dict):\n\n    def __init__(self, d=None, **kwargs):\n        if d is None:\n            d = {}\n        if kwargs:\n            d.update(**kwargs)\n        for k, v in d.items():\n            setattr(self, k, v)\n        # Class attributes\n        for k in self.__class__.__dict__.keys():\n            if not (k.startswith('__') and k.endswith('__')) and not k in ('update', 'pop'):\n                setattr(self, k, getattr(self, k))\n\n    def __setattr__(self, name, value):\n        if isinstance(value, (list, tuple)):\n            value = [self.__class__(x)\n                     if isinstance(x, dict) else x for x in value]\n        elif isinstance(value, dict) and not isinstance(value, self.__class__):\n            value = self.__class__(value)\n        super(EasyDict, self).__setattr__(name, value)\n        super(EasyDict, self).__setitem__(name, value)\n\n    __setitem__ = __setattr__\n\n    def update(self, e=None, **f):\n        d = e or dict()\n        d.update(f)\n        for k in d:\n            setattr(self, k, d[k])\n\n    def pop(self, k, d=None):\n        delattr(self, k)\n        return super(EasyDict, self).pop(k, d)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### **<div id=\"III2\">2. Utilities for preprocessing (Librosa, custom preprocessing...)</div>**"},{"metadata":{"trusted":true},"cell_type":"code","source":"#-------------------------------------------------------------------------------------------\n#Librosa functions\n#-------------------------------------------------------------------------------------------\n#Thanks to https://github.com/daisukelab/ml-sound-classifier\ndef read_audio(conf, pathname, trim_long_data):\n    y, sr = librosa.load(pathname, sr=conf.sampling_rate) #Loads an audio file as a floating point time series. This functions samples the sound\n    # trim silence\n    if 0 < len(y): # workaround: 0 length causes error\n        y, _ = librosa.effects.trim(y) # trim, top_db=default(60)\n    # make it unified length to conf.samples\n    if len(y) > conf.samples: # long enough\n        if trim_long_data:\n            y = y[0:0+conf.samples]\n    else: # pad blank\n        padding = conf.samples - len(y)    # add padding at both ends\n        offset = padding // 2\n        y = np.pad(y, (offset, conf.samples - len(y) - offset), 'constant')\n    return y\n\ndef audio_to_melspectrogram(conf, audio):\n    spectrogram = librosa.feature.melspectrogram(audio, \n                                                 sr=conf.sampling_rate,\n                                                 n_mels=conf.n_mels,\n                                                 hop_length=conf.hop_length,\n                                                 n_fft=conf.n_fft,\n                                                 fmin=conf.fmin,\n                                                 fmax=conf.fmax)\n    spectrogram = librosa.power_to_db(spectrogram)\n    spectrogram = spectrogram.astype(np.float32) #Returns an 128 x L array corresponding to the spectrogram of the sound (L = 128*n° of s)\n    return spectrogram\n\ndef melspectrogram_to_delta(mels):\n    return librosa.feature.delta(mels)\n\ndef show_melspectrogram(conf, mels, title='Log-frequency power spectrogram'):\n    librosa.display.specshow(mels, x_axis='time', y_axis='mel', \n                             sr=conf.sampling_rate, hop_length=conf.hop_length,\n                            fmin=conf.fmin, fmax=conf.fmax)\n    plt.colorbar(format='%+2.0f dB')\n    plt.title(title)\n    plt.show()\n\ndef read_as_melspectrogram(conf, pathname, trim_long_data, debug_display=False):\n    x = read_audio(conf, pathname, trim_long_data)\n    mels = audio_to_melspectrogram(conf, x)\n    if debug_display:\n        delta = melspectrogram_to_delta(mels)\n        delta_squared = melspectrogram_to_delta(delta)\n        IPython.display.display(IPython.display.Audio(x, rate=conf.sampling_rate))\n        show_melspectrogram(conf, mels)\n        show_melspectrogram(conf, delta)\n        show_melspectrogram(conf, delta_squared)\n    return mels\n\n\n#-------------------------------------------------------------------------------------------\n#Spectrogram preprocessing\n#-------------------------------------------------------------------------------------------\n\"\"\"\nThe mels_preprocessing function takes as an input the spectrogram of our sound (list of array, see above). \nIt stacks it three times, so that it has the same shape as a classic RGB image.\nThen it standardize the array (take a matrix and change it so that its mean is equal to 0 and variance is 1). This improves performance.\nThen it normalizes each value between 0 and 255 (gray scale). \n\"\"\"\n\n#def mels_preprocessing(X1, X2, X3, mean=None, std=None, norm_max=None, norm_min=None, eps=1e-6):\ndef mels_preprocessing(X, mean=None, std=None, norm_max=None, norm_min=None, eps=1e-6):\n    # Stack X as [X,X,X]\n    #X = np.stack([X1, X2, X3], axis=-1)\n    X = np.stack([X, X, X], axis=-1)\n\n    # Standardize\n    mean = mean or X.mean()\n    std = std or X.std()\n    #Standardization. Xstd has 0 mean and 1 variance\n    Xstd = (X - mean) / (std + eps)\n    _min, _max = Xstd.min(), Xstd.max()\n    norm_max = norm_max or _max\n    norm_min = norm_min or _min\n    if (_max - _min) > eps:\n        # Scale to [0, 255]\n        V = Xstd\n        V[V < norm_min] = norm_min\n        V[V > norm_max] = norm_max\n        V = 255 * (V - norm_min) / (norm_max - norm_min)\n        V = V.astype(np.uint8)\n    else:\n        # Just zero\n        V = np.zeros_like(Xstd, dtype=np.uint8)\n    return V\n\n#-------------------------------------------------------------------------------------------\n#High resolution conversion with no cut\n#-------------------------------------------------------------------------------------------\ndef convert_wav_to_image(df, source, img_dest, conf):\n    X = []\n    for i, row in tqdm_notebook(df.iterrows()):\n        x1 = read_as_melspectrogram(conf, source/str(row.fname), trim_long_data=False)\n        x1 = mels_preprocessing(x1)\n        #x2 = melspectrogram_to_delta(x1)\n        #x3 = melspectrogram_to_delta(x2)\n        #x_preprocessed = mels_preprocessing(x1, x2, x3)\n        X.append(x1)\n    return df, X\n\n#-------------------------------------------------------------------------------------------\n#Low resolution conversion with splits\n#-------------------------------------------------------------------------------------------\ndef split_long_data(conf, X):\n    # Splits long mel-spectrogram data with small overlap\n    L = X.shape[1]\n    one_length = conf['dims'][1]\n    loop_length = int(one_length * 0.9)\n    min_length = int(one_length * 0.2)\n    #print(' sample length', L, 'to cut every', one_length)\n    for idx in range(L // loop_length):\n        cur = loop_length * idx\n        rest = L - cur\n        if one_length <= rest:\n            yield X[:, cur:cur+one_length]\n        elif min_length <= rest:\n            cur = L - one_length\n            yield X[:, cur:cur+one_length]\n            \ndef convert_X(df, conf, datapath):\n    # Convert all files listed on df.fname\n    # Then generates X (contains mel-spectrograms)\n    # and index mapping to original sample order\n    df_x = pd.DataFrame({'fname': [], 'labels': []})\n    X = []\n    for i, row in tqdm_notebook(df.iterrows()):\n        j = 1\n        x1 = read_as_melspectrogram(conf, datapath / row.fname, trim_long_data=False)\n        x1 = mels_preprocessing(x1)\n        #x2 = melspectrogram_to_delta(x1)\n        #x3 = melspectrogram_to_delta(x2)\n        #x_preprocessed = mels_preprocessing(x1, x2, x3)\n        for chunk in split_long_data(conf, x1):\n            X.append(np.expand_dims(chunk, axis=-1))\n            df_x = df_x.append({'fname': str(j) + '-' + df.fname[i], 'labels':df.labels[i]}, ignore_index=True)\n            f = open('/kaggle/working/trn_curated_X/' + str(j) + '-' + df.fname[i],\"w+\")\n            j += 1\n    return df_x, X\n\ndef convert_X_test(df, conf, datapath):\n    df_x = pd.DataFrame({'fname': []})\n    X = []\n    for i, row in tqdm_notebook(df.iterrows()):\n        j = 1\n        x1 = read_as_melspectrogram(conf, datapath / row.fname, trim_long_data=False)\n        x1 = mels_preprocessing(x1)\n        #x2 = melspectrogram_to_delta(x1)\n        #x3 = melspectrogram_to_delta(x2)\n        #x_preprocessed = mels_preprocessing(x1, x2, x3)\n        for chunk in split_long_data(conf, x1):\n            X.append(np.expand_dims(chunk, axis=-1))\n            df_x = df_x.append({'fname': str(j) + '-' + df.fname[i]}, ignore_index=True)\n            f = open('/kaggle/working/test_X/' + str(j) + '-' + df.fname[i],\"w+\")\n            j += 1\n    return df_x, X","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### **<div id=\"III3\">3. Configuration values</div>**"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Approach LH parameters: highest resolutions\nconf_LH = EasyDict()\nconf_LH.sampling_rate = 44100\nconf_LH.duration = 2\nconf_LH.hop_length = 347 * conf_LH.duration # to make time steps 128\nconf_LH.fmin = 20\nconf_LH.fmax = conf_LH.sampling_rate // 2\nconf_LH.n_mels = 128\nconf_LH.n_fft = conf_LH.n_mels * 20\nconf_LH.samples = conf_LH.sampling_rate * conf_LH.duration\nconf_LH.dims = (conf_LH.n_mels, 1 + int(np.floor(conf_LH.samples/conf_LH.hop_length)), 1)\n\n# Approach X uses longer sound, then it uses suppressed\nconf_X = EasyDict()\nconf_X.sampling_rate = 44100\nconf_X.duration = 8\nconf_X.hop_length = 347 * conf_X.duration # to make time steps 128 #700 * conf_X.duration # to make time steps 64\nconf_X.fmin = 20\nconf_X.fmax = conf_X.sampling_rate // 2\nconf_X.n_mels = 128\nconf_X.n_fft = conf_X.n_mels * 20\nconf_X.samples = conf_X.sampling_rate * conf_X.duration\nconf_X.dims = (conf_X.n_mels, 1 + int(np.floor(conf_X.samples/conf_X.hop_length)), 1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### **<div id=\"III5\">4. Converting audio to image</div>**"},{"metadata":{"trusted":true},"cell_type":"code","source":"testing_df_X, X_test_X = convert_wav_to_image(testing_df, source=Path('../input/freesound-audio-tagging-2019/test'), img_dest=Path('test'), conf = conf_X)\ntesting_df_LH, X_test_LH = convert_wav_to_image(testing_df, source=Path('../input/freesound-audio-tagging-2019/test'), img_dest=Path('test'), conf = conf_LH)\n\nprint(f\"Finished data conversion at {(time.time()-start_time)/3600} hours\")\nprint (len(X_test_X))\nprint (len(testing_df_X))\nprint (len(X_test_LH))\nprint (len(testing_df_LH))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## **<div id=\"III\">III. Modeling</div>**\n\n### **<div id=\"III\">1. Utilities for modeling</div>**"},{"metadata":{"trusted":true},"cell_type":"code","source":"CUR_X_FILES, CUR_X = list(testing_df_X.fname.values), X_test_X\n\n#Custom open_image for fast.ai library to load data from memory. Random cropping 1 sec, this is working like augmentation.\ndef open_fat2019_image(fn, convert_mode, after_open)->Image:\n    # open\n    idx = CUR_X_FILES.index(fn.split('/')[-1])\n    x = PIL.Image.fromarray(CUR_X[idx])\n    # crop\n    time_dim, base_dim = x.size\n    crop_x = random.randint(0, time_dim - base_dim)\n    x = x.crop([crop_x, 0, crop_x+base_dim, base_dim])    \n    # standardize\n    return Image(pil2tensor(x, np.float32).div_(255))\n\nvision.data.open_image = open_fat2019_image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Adding TTA\ndef _tta_only(learn:Learner, ds_type:DatasetType=DatasetType.Valid, num_pred:int=5) -> Iterator[List[Tensor]]:\n    \"Computes the outputs for several augmented inputs for TTA\"\n    dl = learn.dl(ds_type)\n    ds = dl.dataset\n    old = ds.tfms\n    aug_tfms = [o for o in learn.data.train_ds.tfms]\n    try:\n        pbar = master_bar(range(num_pred))\n        for i in pbar:\n            ds.tfms = aug_tfms\n            yield get_preds(learn.model, dl, pbar=pbar)[0]\n    finally: ds.tfms = old\n\nLearner.tta_only = _tta_only\n\ndef _TTA(learn:Learner, beta:float=0, ds_type:DatasetType=DatasetType.Valid, num_pred:int=5, with_loss:bool=False) -> Tensors:\n    \"Applies TTA to predict on `ds_type` dataset.\"\n    preds,y = learn.get_preds(ds_type)\n    all_preds = list(learn.tta_only(ds_type=ds_type, num_pred=num_pred))\n    avg_preds = torch.stack(all_preds).mean(0)\n    if beta is None: return preds,avg_preds,y\n    else:            \n        final_preds = preds*beta + avg_preds*(1-beta)\n        if with_loss: \n            with NoneReduceOnCPU(learn.loss_func) as lf: loss = lf(final_preds, y)\n            return final_preds, y, loss\n        return final_preds, y\n\nLearner.TTA = _TTA","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### **<div id=\"V2\">2. Modeling long chunks</div>**"},{"metadata":{"trusted":true},"cell_type":"code","source":"CUR_X_FILES, CUR_X = list(testing_df_X.fname.values), X_test_X\ntest_X = ImageList.from_csv(Path('/kaggle/working'), Path('../input/freesound-audio-tagging-2019/sample_submission.csv'), folder=Path('../input/freesound-audio-tagging-2019/test'))\n\npredictions_X = torch.from_numpy(np.zeros((3361,80))).float()\nprint(predictions_X.shape)\nnum_folds = 5\n\nfor i in range(num_folds):\n    learn_X = load_learner(path = '.', file=Path('/kaggle/input/fat-curated-ensemble-mixup-tta/FAT2019_X_1D_mixup_TTA_Kfold_'+str(i)+'.pkl'), test=test_X)\n    preds_X, _ = learn_X.TTA(ds_type=DatasetType.Test)\n    print(preds_X.shape)\n    predictions_X = predictions_X + preds_X\n    \npredictions_X = predictions_X/num_folds\ntesting_df_X[learn_X.data.classes] = predictions_X\ntesting_df_X.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# CUR_X_FILES, CUR_X = list(testing_df_X.fname.values), X_test_X\n\n# test_X = ImageList.from_csv(Path('/kaggle/working'), Path('../input/freesound-audio-tagging-2019/sample_submission.csv'), folder=Path('../input/freesound-audio-tagging-2019/test'))\n# learn_X = load_learner(path = '.', file=Path('/kaggle/input/fat-curated-ensemble-mixup-tta/FAT2019_X_1D_mixup_TTA.pkl'), test=test_X)\n# # preds_X, _ = learn_X.get_preds(ds_type=DatasetType.Test)\n# preds_X, _ = learn_X.TTA(ds_type=DatasetType.Test)\n\n# testing_df_X[learn_X.data.classes] = preds_X\n# testing_df_X.head()\n\n# #Removing fake files\n# #shutil.rmtree('trn_curated_X')\n\n# print(preds_X.type)\n# print(preds_X.shape)\n# testing_df_X.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### **<div id=\"V3\">3. Modeling beginning of sound</div>**"},{"metadata":{"trusted":true},"cell_type":"code","source":"CUR_X_FILES, CUR_X = list(testing_df_LH.fname.values), X_test_LH\ntest_LH = ImageList.from_csv(Path('/kaggle/working'), Path('../input/freesound-audio-tagging-2019/sample_submission.csv'), folder=Path('../input/freesound-audio-tagging-2019/test'))\n\npredictions_LH = torch.from_numpy(np.zeros((3361,80))).float()\nprint(predictions_LH.shape)\nnum_folds = 5\n\nfor i in range(num_folds):\n    learn_LH = load_learner(path = '.', file=Path('/kaggle/input/fat-curated-ensemble-mixup-tta/FAT2019_LH_1D_mixup_TTA_Kfold_'+str(i)+'.pkl'), test=test_LH)\n    preds_LH, _ = learn_LH.TTA(ds_type=DatasetType.Test)\n    print(preds_LH.shape)\n    predictions_LH = predictions_LH + preds_LH\n    \npredictions_LH = predictions_LH/num_folds\ntesting_df_LH[learn_LH.data.classes] = predictions_LH\ntesting_df_LH.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# CUR_X_FILES, CUR_X = list(testing_df_LH.fname.values), X_test_LH\n\n# test_LH = ImageList.from_csv(Path('/kaggle/working'), Path('../input/freesound-audio-tagging-2019/sample_submission.csv'), folder=Path('../input/freesound-audio-tagging-2019/test'))\n# learn_LH = load_learner(path = '.', file=Path('/kaggle/input/fat-curated-ensemble-mixup-tta/FAT2019_LH_1D_mixup_TTA.pkl'), test=test_LH)\n# # preds_LH, _ = learn_LH.get_preds(ds_type=DatasetType.Test)\n# preds_LH, _ = learn_LH.TTA(ds_type=DatasetType.Test)\n\n# testing_df_LH[learn_LH.data.classes] = preds_LH\n\n# print(preds_LH.type)\n# print(preds_LH.shape)\n# testing_df_LH.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## **<div id=\"V\">V. Ensembling</div>**"},{"metadata":{"trusted":true},"cell_type":"code","source":"# #Taking the geometric average of preds_X and preds_LH\n# preds = (preds_X * preds_LH)**(.5)\n# #Taking the arithmetic average (because we are using TTA) of preds_X and preds_LH\n# preds = (preds_X + preds_LH) / 2\npreds = (predictions_X + predictions_LH) / 2\n\ntesting_df[learn_X.data.classes] = preds\ntesting_df.to_csv('submission.csv', index=False)\ntesting_df.head(20)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}