{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# BASIC IDEA OF THE KERNEL\n\n# The data consists of a one dimensional time series x with 600 Mio data points. \n# At test time, we will see a time series of length 150'000 to predict the next earthquake.\n# The idea of this kernel is to randomly sample chunks of length 150'000 from x, derive some\n# features and use them to update weights of a recurrent neural net with 150'000 / 1000 = 150\n# time steps. \n\nimport numpy as np \nimport pandas as pd\nimport os\nfrom tqdm import tqdm\n\n# Fix seeds\nfrom numpy.random import seed\nseed(639)\nfrom tensorflow import set_random_seed\nset_random_seed(5944)\n\n# Import\nfloat_data = pd.read_csv(\"../input/train.csv\", dtype={\"acoustic_data\": np.float32, \"time_to_failure\": np.float32}).values","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"# Helper function for the data generator. Extracts mean, standard deviation, and quantiles per time step.\n# Can easily be extended. Expects a two dimensional array.\ndef extract_features(z):\n    \n    return np.c_[z.mean(axis=1), \n                 z.min(axis=1),\n                 z.max(axis=1),\n                 z.std(axis=1)\n                 ]\n    \ndef extract_features_roll(z):\n    \n    df_z = pd.DataFrame(z)\n    df_roll_std = df_z.rolling(50, axis=1).std().values[:, 49:]\n    df_roll_skew = df_z.rolling(50, axis=1).skew().values[:, 49:]\n    df_roll_kurt = df_z.rolling(50, axis=1).kurt().values[:, 49:]\n    \n    \n    return np.c_[np.quantile(df_roll_std, 0.05, axis=1),\n                 np.quantile(df_roll_std, 0.10, axis=1),\n                 np.quantile(df_roll_skew, 0.05, axis=1),\n                 np.quantile(df_roll_skew, 0.10, axis=1),\n                 np.quantile(df_roll_kurt, 0.05, axis=1),\n                 np.quantile(df_roll_kurt, 0.10, axis=1),\n                 ]\n\n# For a given ending position \"last_index\", we split the last 150'000 values \n# of \"x\" into 150 pieces of length 1000 each. So n_steps * step_length should equal 150'000.\n# From each piece, a set features are extracted. This results in a feature matrix \n# of dimension (150 time steps x features).  \ndef create_X(x, last_index=None, n_steps=150, step_length=1000):\n    if last_index == None:\n        last_index=len(x)\n       \n    assert last_index - n_steps * step_length >= 0\n\n    # Reshaping and approximate standardization with mean 5 and std 3.\n    temp = (x[(last_index - n_steps * step_length):last_index].reshape(n_steps, -1) - 5 ) / 3\n    \n    # print(temp.shape)\n    \n    # Extracts features of sequences of full length 1000, of the last 100 values and finally also \n    # of the last 10 observations. \n    return np.c_[extract_features(temp),\n                 extract_features(temp[:, -step_length // 10:]),\n                 extract_features(temp[:, -step_length // 100:]),\n                 extract_features_roll(temp)\n                 ]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Query \"create_X\" to figure out the number of features\nn_features = create_X(float_data[0:150000, 0]).shape[1]\nprint(\"Our RNN is based on %i features\"% n_features)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# The generator endlessly selects \"batch_size\" ending positions of sub-time series. For each ending position,\n# the \"time_to_failure\" serves as target, while the features are created by the function \"create_X\".\ndef generator(data, min_index=0, max_index=None, batch_size=16, n_steps=150, step_length=1000):\n    if max_index is None:\n        max_index = len(data) - 1\n     \n    while True:\n        # Pick indices of ending positions\n        rows = np.random.randint(min_index + n_steps * step_length, max_index, size=batch_size)\n         \n        # Initialize feature matrices and targets\n        samples = np.zeros((batch_size, n_steps, n_features))\n        targets = np.zeros(batch_size, )\n        \n        for j, row in enumerate(rows):\n            samples[j] = create_X(data[:, 0], last_index=row, n_steps=n_steps, step_length=step_length)\n            targets[j] = data[row - 1, 1]\n        yield samples, targets","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch_size = 32\n\n# Position of second (of 16) earthquake. Used to have a clean split\n# between train and validation\nsecond_earthquake = 50085877\nfloat_data[second_earthquake, 1]\n\n# Initialize generators\ntrain_gen = generator(float_data, batch_size=batch_size) # Use this for better score\n# train_gen = generator(float_data, batch_size=batch_size, min_index=second_earthquake + 1)\nvalid_gen = generator(float_data, batch_size=batch_size, max_index=second_earthquake)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Define model\nfrom keras.models import Sequential\nfrom keras.layers import Dense, CuDNNGRU\nfrom keras.optimizers import adam\nfrom keras.callbacks import ModelCheckpoint\n\ncb = [ModelCheckpoint(\"model.hdf5\", save_best_only=True, period=3)]\n\nmodel = Sequential()\nmodel.add(CuDNNGRU(48, input_shape=(None, n_features)))\nmodel.add(Dense(10, activation='relu'))\nmodel.add(Dense(1))\n\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Compile and fit model\nmodel.compile(optimizer=adam(lr=0.0005), loss=\"mae\")\n\nhistory = model.fit_generator(train_gen,\n                              steps_per_epoch=1000,\n                              epochs=10,\n                              verbose=1,\n                              callbacks=cb,\n                              validation_data=valid_gen,\n                              validation_steps=200)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Visualize accuracies\nimport matplotlib.pyplot as plt\n\ndef perf_plot(history, what = 'loss'):\n    x = history.history[what]\n    val_x = history.history['val_' + what]\n    epochs = np.asarray(history.epoch) + 1\n    \n    plt.plot(epochs, x, 'bo', label = \"Training \" + what)\n    plt.plot(epochs, val_x, 'b', label = \"Validation \" + what)\n    plt.title(\"Training and validation \" + what)\n    plt.xlabel(\"Epochs\")\n    plt.legend()\n    plt.show()\n    return None\n\nperf_plot(history)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Load submission file\nsubmission = pd.read_csv('../input/sample_submission.csv', index_col='seg_id', dtype={\"time_to_failure\": np.float32})\n\n# Load each test data, create the feature matrix, get numeric prediction\nfor i, seg_id in enumerate(tqdm(submission.index)):\n  #  print(i)\n    seg = pd.read_csv('../input/test/' + seg_id + '.csv')\n    x = seg['acoustic_data'].values\n    submission.time_to_failure[i] = model.predict(np.expand_dims(create_X(x), 0))\n\nsubmission.head()\n\n# Save\nsubmission.to_csv('submission.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}