diff --git a/GenDs2.py b/GenDs2.py new file mode 100644 index 0000000..2ce825c --- /dev/null +++ b/GenDs2.py @@ -0,0 +1,99 @@ +# get data +import pandas as pd +import numpy as np +import tensorflow as tf + +from sklearn.preprocessing import StandardScaler,MinMaxScaler +raw_data = pd.read_pickle("./data/raw_feature.pkl") +X_train = pd.read_pickle("./data/X_train.pkl") +y_train = pd.read_pickle("./data/y_train.pkl") +X_test = pd.read_pickle("./data/X_test.pkl") +y_test = pd.read_pickle("./data/y_test.pkl") +def apply_sin(X,axis,range): + """Apply sin function on some time features""" + X = X.copy() + X[:,axis,:] = np.sin(X[:,axis,:]*2*np.pi/range) + return X +def apply_cos(X,axis,range): + """same for cos""" + X = X.copy() + X[:,axis,:] = np.cos(X[:,axis,:]*2*np.pi/range) + return X +def create_rolling_window(matrix,t): + """This function is used for create X for lstm""" + matrix_shape = matrix.shape + return_length = matrix_shape[0] - t + dataset = tf.data.Dataset.from_tensor_slices(matrix) + windows = dataset.window(t,shift = 1,drop_remainder=True) + windows = windows.take(return_length) + windows = windows.flat_map(lambda window: window.batch(t)) + + + return windows +def create_result_ds(matrix,delay): + """Creat Y target """ + dataset = tf.data.Dataset.from_tensor_slices(matrix) + dataset = dataset.skip(delay) + return dataset + + +def combine_ds(X_train,ds1,ds2): + """zip two dataset and returns a batch dataset""" + combined_ds = tf.data.Dataset.zip(((X_train,ds1),ds2)) + combined_ds = combined_ds.batch(batch_size=32) + return combined_ds +def gen_train_ds(X_train,y_train,step_len): + + X = create_rolling_window(y_train,step_len) + X_train_ds = create_result_ds(X_train,step_len) + y = create_result_ds(y_train,step_len) + + train_ds = combine_ds(X_train_ds,X,y) + return train_ds + +def gen_test_ds(X_test,y_test,step_len): + + X = create_rolling_window(y_test,step_len) + y = create_result_ds(y_test,step_len) + X_test_ds = create_result_ds(X_test,step_len) + + test_ds = combine_ds(X_test_ds,X,y) + return test_ds + +# preprocess data +"""Normalize the original data""" +std = StandardScaler() + +train_shape = y_train.shape +test_shape = y_test.shape +y_train = std.fit_transform(np.reshape(y_train,(-1,y_train.shape[-2]*y_train.shape[-1]))) +y_train = y_train.reshape(train_shape) +y_test = std.transform(np.reshape(y_test,(-1,y_test.shape[-2]*y_test.shape[-1]))) +y_test = y_test.reshape(test_shape) + + +X_train = X_train[:,1:,:].astype(np.float64) +X_test = X_test[:,1:,:].astype(np.float64) + +X_train = apply_sin(X_train,2,24) +X_train = apply_sin(X_test,2,24) + + +X_train = X_train/X_train.max() +X_test = X_test/X_test.max() + + + + +# gen dataset +time_step = 48 +train_ds = gen_train_ds(X_train,y_train,step_len=time_step) +test_ds = gen_test_ds(X_test,y_test,step_len=time_step) + +class GenDs(object): + def gen_train(time_step = 48): + train_ds = gen_train_ds(X_train,y_train,step_len=time_step) + return train_ds,std + def gen_test(time_step = 48): + test_ds = gen_test_ds(X_test,y_test,step_len=time_step) + return test_ds \ No newline at end of file diff --git a/GenFeature.py b/GenFeature.py new file mode 100644 index 0000000..03b4ce9 --- /dev/null +++ b/GenFeature.py @@ -0,0 +1,26 @@ +import pandas as pd +import numpy as np +spatio_data_file = "./data/SpatialFeatures.csv" +raw_spatio_feature = pd.read_csv(spatio_data_file) +def get_feauture_by_name(data,name): + feature = data[name] + feature = feature.fillna(0).to_numpy() + feature = feature/feature.max() + feature = feature.reshape(16,8) + feature = feature[::-1,:] + return feature + +def get_feature_list(data,name_list): + result_array = np.empty((len(name_list),16,8)) + for i in range(len(name_list)): + result_array[i] = get_feauture_by_name(data,name_list[i]) + + return result_array + + +feature_list = ["BikeLane_miles","AADT","Pop_Density","StationNum"] +def gen_features(feature_list = feature_list): + feature_array = get_feature_list(raw_spatio_feature,feature_list) + + + return feature_array \ No newline at end of file diff --git a/ModelPerformance.py b/ModelPerformance.py index 8f1b57d..62076f0 100644 --- a/ModelPerformance.py +++ b/ModelPerformance.py @@ -20,19 +20,25 @@ def compare_result(predict,real): # assert(np.array_equal(predict_flatten.reshape(original_shape), predict)) print(mean_squared_error(predict_flatten,real_flatten)) + + return (mean_squared_error(predict_flatten,real_flatten)) def plot_result(predict,real,batch =0,in_out = 0): - vmin = min(predict[batch].min(), real[batch].min()) - vmax = max(predict[batch].max(), real[batch].max()) + # vmin = min(predict[batch].min(), real[batch].min()) + vmin = 0 + vmax = max(predict[batch,in_out].max(), real[batch,in_out].max()) cmap = 'viridis' fig, axs = plt.subplots(1, 3) axs[0].set_title("predict") - axs[0].imshow(predict[batch,in_out,:,:],cmap = cmap,vmin = vmin,vmax = vmax) + predict_fig = axs[0].imshow(predict[batch,in_out,:,:],cmap = cmap,vmin = vmin,vmax = vmax) axs[1].set_title("real") - axs[1].imshow(real[batch,in_out,:,:],cmap = cmap,vmin = vmin,vmax = vmax) + real_fig = axs[1].imshow(real[batch,in_out,:,:],cmap = cmap,vmin = vmin,vmax = vmax) axs[2].set_title("diff") - axs[2].imshow(np.abs(predict[batch,in_out,:,:] - real[batch,in_out,:,:]), cmap = cmap,vmin = vmin,vmax = vmax) - + diff_matrix = np.abs(predict[batch,in_out,:,:] - real[batch,in_out,:,:]) + diff_fig = axs[2].imshow(diff_matrix, cmap = cmap,vmin = vmin,vmax = vmax) + plt.colorbar(predict_fig,ax=axs) + # plt.colorbar(real_fig,ax = axs) + print(diff_matrix.mean(),diff_matrix.shape) plt.show() diff --git a/TrainingData.h5 b/TrainingData.h5 new file mode 100644 index 0000000..2873bae Binary files /dev/null and b/TrainingData.h5 differ diff --git a/__pycache__/GenDs.cpython-310.pyc b/__pycache__/GenDs.cpython-310.pyc new file mode 100644 index 0000000..b638085 Binary files /dev/null and b/__pycache__/GenDs.cpython-310.pyc differ diff --git a/__pycache__/GenDs.cpython-311.pyc b/__pycache__/GenDs.cpython-311.pyc index 14b86bd..63993e1 100644 Binary files a/__pycache__/GenDs.cpython-311.pyc and b/__pycache__/GenDs.cpython-311.pyc differ diff --git a/__pycache__/GenDs.cpython-38.pyc b/__pycache__/GenDs.cpython-38.pyc new file mode 100644 index 0000000..0c3617c Binary files /dev/null and b/__pycache__/GenDs.cpython-38.pyc differ diff --git a/__pycache__/GenDs2.cpython-311.pyc b/__pycache__/GenDs2.cpython-311.pyc new file mode 100644 index 0000000..94d5726 Binary files /dev/null and b/__pycache__/GenDs2.cpython-311.pyc differ diff --git a/__pycache__/GenFeature.cpython-310.pyc b/__pycache__/GenFeature.cpython-310.pyc new file mode 100644 index 0000000..f3ad96b Binary files /dev/null and b/__pycache__/GenFeature.cpython-310.pyc differ diff --git a/__pycache__/GenFeature.cpython-311.pyc b/__pycache__/GenFeature.cpython-311.pyc new file mode 100644 index 0000000..19f0c3a Binary files /dev/null and b/__pycache__/GenFeature.cpython-311.pyc differ diff --git a/__pycache__/ModelPerformance.cpython-310.pyc b/__pycache__/ModelPerformance.cpython-310.pyc new file mode 100644 index 0000000..c74a5d2 Binary files /dev/null and b/__pycache__/ModelPerformance.cpython-310.pyc differ diff --git a/__pycache__/ModelPerformance.cpython-311.pyc b/__pycache__/ModelPerformance.cpython-311.pyc index c726795..67f4b91 100644 Binary files a/__pycache__/ModelPerformance.cpython-311.pyc and b/__pycache__/ModelPerformance.cpython-311.pyc differ diff --git a/base.h5 b/base.h5 index 814f01a..04426cd 100644 Binary files a/base.h5 and b/base.h5 differ diff --git a/cnn.h5 b/cnn.h5 new file mode 100644 index 0000000..2cdde05 Binary files /dev/null and b/cnn.h5 differ diff --git a/gen_dataset.ipynb b/gen_dataset.ipynb index 7d6f54a..a9b0331 100644 --- a/gen_dataset.ipynb +++ b/gen_dataset.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 10, + "execution_count": 320, "metadata": {}, "outputs": [], "source": [ @@ -23,7 +23,36 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# get weather data" + ] + }, + { + "cell_type": "code", + "execution_count": 321, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "((240, 5, 1), (1248, 5, 1))" + ] + }, + "execution_count": 321, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "X_test.shape,X_train.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 322, "metadata": {}, "outputs": [], "source": [ @@ -36,12 +65,136 @@ "y_train = y_train.reshape(train_shape)\n", "y_test = std.transform(np.reshape(y_test,(-1,y_test.shape[-2]*y_test.shape[-1])))\n", "y_test = y_test.reshape(test_shape)\n", + "\n", + "X_train = X_train[:,1:,:].astype(np.float64)\n", + "X_test = X_test[:,1:,:].astype(np.float64)" + ] + }, + { + "cell_type": "code", + "execution_count": 323, + "metadata": {}, + "outputs": [], + "source": [ + "sin_axis = np.sin(X_train[:,2,:]*2*np.pi/24).copy()" + ] + }, + { + "cell_type": "code", + "execution_count": 331, + "metadata": {}, + "outputs": [], + "source": [ + "X_train_prepared = X_train.copy()\n", + "X_train_prepared[:,2,:] = np.sin(X_train[:,2,:]*2*np.pi/24)" + ] + }, + { + "cell_type": "code", + "execution_count": 332, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0. ],\n", + " [ 0.25881905],\n", + " [ 0.25881905],\n", + " ...,\n", + " [-0.25881905],\n", + " [-0.25881905],\n", + " [ 0. ]])" + ] + }, + "execution_count": 332, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "X_train_prepared[:,2,:]" + ] + }, + { + "cell_type": "code", + "execution_count": 333, + "metadata": {}, + "outputs": [], + "source": [ + "def apply_sin(X,axis,range):\n", + " X = X.copy()\n", + " X[:,axis,:] = np.sin(X[:,axis,:]*2*np.pi/range)\n", + " return X\n", + "def apply_cos(X,axis,range):\n", + " X = X.copy()\n", + " X[:,axis,:] = np.cos(X[:,axis,:]*2*np.pi/range)\n", + " return X\n", "\n" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 346, + "metadata": {}, + "outputs": [], + "source": [ + "X = apply_sin(X_train,2,24)\n", + "X = apply_sin(X_train,1,30)" + ] + }, + { + "cell_type": "code", + "execution_count": 347, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[10. ],\n", + " [ 0.20791169],\n", + " [ 0. ],\n", + " [30. ]],\n", + "\n", + " [[10. ],\n", + " [ 0.20791169],\n", + " [ 1. ],\n", + " [ 0. ]],\n", + "\n", + " [[10. ],\n", + " [ 0.20791169],\n", + " [ 1. ],\n", + " [30. ]],\n", + "\n", + " ...,\n", + "\n", + " [[10. ],\n", + " [-0.74314483],\n", + " [23. ],\n", + " [ 0. ]],\n", + "\n", + " [[10. ],\n", + " [-0.74314483],\n", + " [23. ],\n", + " [30. ]],\n", + "\n", + " [[10. ],\n", + " [-0.58778525],\n", + " [ 0. ],\n", + " [ 0. ]]])" + ] + }, + "execution_count": 347, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "X" + ] + }, + { + "cell_type": "code", + "execution_count": 228, "metadata": {}, "outputs": [], "source": [ @@ -63,27 +216,30 @@ " dataset = dataset.skip(delay)\n", " return dataset\n", "\n", - "def combine_ds(ds1,ds2):\n", - " combined_ds = tf.data.Dataset.zip(((ds1),ds2))\n", + "def combine_ds(X_train,ds1,ds2):\n", + " combined_ds = tf.data.Dataset.zip((X_train,ds1,ds2))\n", " combined_ds = combined_ds.batch(batch_size=32)\n", " return combined_ds\n", "\n", "def gen_train_ds(X_train,y_train,step_len):\n", " X = create_rolling_window(y_train,step_len)\n", + " X_train_ds = create_result_ds(X_train,step_len)\n", " y = create_result_ds(y_train,step_len)\n", - " train_ds = combine_ds(X,y)\n", + " \n", + " train_ds = combine_ds(X_train_ds,X,y)\n", " return train_ds\n", "\n", "def gen_test_ds(X_test,y_test,step_len):\n", " X = create_rolling_window(y_test,step_len)\n", " y = create_result_ds(y_test,step_len)\n", - " test_ds = combine_ds(X,y)\n", + " X_test_ds = create_result_ds(X_test,step_len)\n", + " test_ds = combine_ds(X_test_ds,X,y)\n", " return test_ds" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 229, "metadata": {}, "outputs": [], "source": [ @@ -95,59 +251,59 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 230, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(16, 48, 2, 16, 8) (16, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(16, 4, 1) (16, 48, 2, 16, 8) (16, 2, 16, 8)\n", "38\n" ] } ], "source": [ "count = 0\n", - "for X,y in train_ds:\n", - " print (X.shape,y.shape)\n", + "for X_,X,y in train_ds:\n", + " print (X_.shape,X.shape,y.shape)\n", " count+=1\n", "print(count)\n", "\n" @@ -155,26 +311,59 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 231, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n", - "(32, 48, 2, 16, 8) (32, 2, 16, 8)\n" + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n" ] } ], "source": [ "\n", - "for X,y in test_ds:\n", - " print(X.shape,y.shape)" + "for X_,X,y in test_ds:\n", + " print(X_.shape,X.shape,y.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 232, + "metadata": {}, + "outputs": [], + "source": [ + "from GenDs2 import GenDs\n", + "test_ds = GenDs.gen_test()" + ] + }, + { + "cell_type": "code", + "execution_count": 233, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n", + "(32, 4, 1) (32, 48, 2, 16, 8) (32, 2, 16, 8)\n" + ] + } + ], + "source": [ + "for ((i,j),k) in test_ds:\n", + " print(i.shape,j.shape,k.shape)" ] }, { diff --git a/lstm_cnn.h5 b/lstm_cnn.h5 new file mode 100644 index 0000000..6c26c29 Binary files /dev/null and b/lstm_cnn.h5 differ diff --git a/lstm_cnn_v2.h5 b/lstm_cnn_v2.h5 new file mode 100644 index 0000000..927cb44 Binary files /dev/null and b/lstm_cnn_v2.h5 differ diff --git a/lstm_cnn_v2/fingerprint.pb b/lstm_cnn_v2/fingerprint.pb new file mode 100644 index 0000000..591025b --- /dev/null +++ b/lstm_cnn_v2/fingerprint.pb @@ -0,0 +1 @@ +ޱǧ)ǚ ꒼(ߥ2 \ No newline at end of file diff --git a/lstm_cnn_v2/keras_metadata.pb b/lstm_cnn_v2/keras_metadata.pb new file mode 100644 index 0000000..bd45ae2 --- /dev/null +++ b/lstm_cnn_v2/keras_metadata.pb @@ -0,0 +1,27 @@ + +root"_tf_keras_network*{"name": "model_14", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": false, "class_name": "Functional", "config": {"name": "model_14", "trainable": true, "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 48, 2, 16, 8]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "input_31"}, "name": "input_31", "inbound_nodes": []}, {"class_name": "Reshape", "config": {"name": "reshape_72", "trainable": true, "dtype": "float32", "target_shape": {"class_name": "__tuple__", "items": [-1, 16, 8]}}, "name": "reshape_72", "inbound_nodes": [[["input_31", 0, 0, {}]]]}, {"class_name": "Conv2D", "config": {"name": "conv2d_75", "trainable": true, "dtype": "float32", "filters": 32, "kernel_size": {"class_name": "__tuple__", "items": [2, 2]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_75", "inbound_nodes": [[["reshape_72", 0, 0, {}]]]}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_73", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_73", "inbound_nodes": [[["conv2d_75", 0, 0, {}]]]}, {"class_name": "Conv2D", "config": {"name": "conv2d_76", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [2, 2]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_76", "inbound_nodes": [[["max_pooling2d_73", 0, 0, {}]]]}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_74", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_74", "inbound_nodes": [[["conv2d_76", 0, 0, {}]]]}, {"class_name": "Conv2D", "config": {"name": "conv2d_77", "trainable": true, "dtype": "float32", "filters": 128, "kernel_size": {"class_name": "__tuple__", "items": [2, 2]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_77", "inbound_nodes": [[["max_pooling2d_74", 0, 0, {}]]]}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_75", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_75", "inbound_nodes": [[["conv2d_77", 0, 0, {}]]]}, {"class_name": "Reshape", "config": {"name": "reshape_71", "trainable": true, "dtype": "float32", "target_shape": {"class_name": "__tuple__", "items": [48, 256]}}, "name": "reshape_71", "inbound_nodes": [[["input_31", 0, 0, {}]]]}, {"class_name": "Flatten", "config": {"name": "flatten_25", "trainable": true, "dtype": "float32", "data_format": "channels_last"}, "name": "flatten_25", "inbound_nodes": [[["max_pooling2d_75", 0, 0, {}]]]}, {"class_name": "LSTM", "config": {"name": "lstm_23", "trainable": true, "dtype": "float32", "return_sequences": false, "return_state": false, "go_backwards": false, "stateful": false, "unroll": false, "time_major": false, "units": 512, "activation": "relu", "recurrent_activation": "sigmoid", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 16}, "recurrent_initializer": {"class_name": "Orthogonal", "config": {"gain": 1.0, "seed": null}, "shared_object_id": 17}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 18}, "unit_forget_bias": true, "kernel_regularizer": null, "recurrent_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "recurrent_constraint": null, "bias_constraint": null, "dropout": 0.2, "recurrent_dropout": 0.0, "implementation": 2}, "name": "lstm_23", "inbound_nodes": [[["reshape_71", 0, 0, {}]]]}, {"class_name": "Dense", "config": {"name": "dense_56", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_56", "inbound_nodes": [[["flatten_25", 0, 0, {}]]]}, {"class_name": "Dense", "config": {"name": "dense_55", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_55", "inbound_nodes": [[["lstm_23", 0, 0, {}]]]}, {"class_name": "Concatenate", "config": {"name": "concatenate_15", "trainable": true, "dtype": "float32", "axis": -1}, "name": "concatenate_15", "inbound_nodes": [[["dense_56", 0, 0, {}], ["dense_55", 0, 0, {}]]]}, {"class_name": "Dense", "config": {"name": "dense_57", "trainable": true, "dtype": "float32", "units": 256, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_57", "inbound_nodes": [[["concatenate_15", 0, 0, {}]]]}, {"class_name": "Dense", "config": {"name": "dense_58", "trainable": true, "dtype": "float32", "units": 256, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_58", "inbound_nodes": [[["dense_57", 0, 0, {}]]]}, {"class_name": "Reshape", "config": {"name": "reshape_73", "trainable": true, "dtype": "float32", "target_shape": {"class_name": "__tuple__", "items": [2, 16, 8]}}, "name": "reshape_73", "inbound_nodes": [[["dense_58", 0, 0, {}]]]}], "input_layers": [["input_31", 0, 0]], "output_layers": [["reshape_73", 0, 0]]}, "shared_object_id": 35, "input_spec": [{"class_name": "InputSpec", "config": {"dtype": null, "shape": {"class_name": "__tuple__", "items": [null, 48, 2, 16, 8]}, "ndim": 5, "max_ndim": null, "min_ndim": null, "axes": {}}}], "build_input_shape": {"class_name": "TensorShape", "items": [null, 48, 2, 16, 8]}, "is_graph_network": true, "full_save_spec": {"class_name": "__tuple__", "items": [[{"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 48, 2, 16, 8]}, "float32", "input_31"]}], {}]}, "save_spec": {"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 48, 2, 16, 8]}, "float32", "input_31"]}, "keras_version": "2.13.1", "backend": "tensorflow", "model_config": {"class_name": "Functional", "config": {"name": "model_14", "trainable": true, "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 48, 2, 16, 8]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "input_31"}, "name": "input_31", "inbound_nodes": [], "shared_object_id": 0}, {"class_name": "Reshape", "config": {"name": "reshape_72", "trainable": true, "dtype": "float32", "target_shape": {"class_name": "__tuple__", "items": [-1, 16, 8]}}, "name": "reshape_72", "inbound_nodes": [[["input_31", 0, 0, {}]]], "shared_object_id": 1}, {"class_name": "Conv2D", "config": {"name": "conv2d_75", "trainable": true, "dtype": "float32", "filters": 32, "kernel_size": {"class_name": "__tuple__", "items": [2, 2]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 2}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 3}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_75", "inbound_nodes": [[["reshape_72", 0, 0, {}]]], "shared_object_id": 4}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_73", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_73", "inbound_nodes": [[["conv2d_75", 0, 0, {}]]], "shared_object_id": 5}, {"class_name": "Conv2D", "config": {"name": "conv2d_76", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [2, 2]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 6}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 7}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_76", "inbound_nodes": [[["max_pooling2d_73", 0, 0, {}]]], "shared_object_id": 8}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_74", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_74", "inbound_nodes": [[["conv2d_76", 0, 0, {}]]], "shared_object_id": 9}, {"class_name": "Conv2D", "config": {"name": "conv2d_77", "trainable": true, "dtype": "float32", "filters": 128, "kernel_size": {"class_name": "__tuple__", "items": [2, 2]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 10}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 11}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_77", "inbound_nodes": [[["max_pooling2d_74", 0, 0, {}]]], "shared_object_id": 12}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_75", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_75", "inbound_nodes": [[["conv2d_77", 0, 0, {}]]], "shared_object_id": 13}, {"class_name": "Reshape", "config": {"name": "reshape_71", "trainable": true, "dtype": "float32", "target_shape": {"class_name": "__tuple__", "items": [48, 256]}}, "name": "reshape_71", "inbound_nodes": [[["input_31", 0, 0, {}]]], "shared_object_id": 14}, {"class_name": "Flatten", "config": {"name": "flatten_25", "trainable": true, "dtype": "float32", "data_format": "channels_last"}, "name": "flatten_25", "inbound_nodes": [[["max_pooling2d_75", 0, 0, {}]]], "shared_object_id": 15}, {"class_name": "LSTM", "config": {"name": "lstm_23", "trainable": true, "dtype": "float32", "return_sequences": false, "return_state": false, "go_backwards": false, "stateful": false, "unroll": false, "time_major": false, "units": 512, "activation": "relu", "recurrent_activation": "sigmoid", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 16}, "recurrent_initializer": {"class_name": "Orthogonal", "config": {"gain": 1.0, "seed": null}, "shared_object_id": 17}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 18}, "unit_forget_bias": true, "kernel_regularizer": null, "recurrent_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "recurrent_constraint": null, "bias_constraint": null, "dropout": 0.2, "recurrent_dropout": 0.0, "implementation": 2}, "name": "lstm_23", "inbound_nodes": [[["reshape_71", 0, 0, {}]]], "shared_object_id": 20}, {"class_name": "Dense", "config": {"name": "dense_56", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 21}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 22}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_56", "inbound_nodes": [[["flatten_25", 0, 0, {}]]], "shared_object_id": 23}, {"class_name": "Dense", "config": {"name": "dense_55", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 24}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 25}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_55", "inbound_nodes": [[["lstm_23", 0, 0, {}]]], "shared_object_id": 26}, {"class_name": "Concatenate", "config": {"name": "concatenate_15", "trainable": true, "dtype": "float32", "axis": -1}, "name": "concatenate_15", "inbound_nodes": [[["dense_56", 0, 0, {}], ["dense_55", 0, 0, {}]]], "shared_object_id": 27}, {"class_name": "Dense", "config": {"name": "dense_57", "trainable": true, "dtype": "float32", "units": 256, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 28}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 29}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_57", "inbound_nodes": [[["concatenate_15", 0, 0, {}]]], "shared_object_id": 30}, {"class_name": "Dense", "config": {"name": "dense_58", "trainable": true, "dtype": "float32", "units": 256, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 31}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 32}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_58", "inbound_nodes": [[["dense_57", 0, 0, {}]]], "shared_object_id": 33}, {"class_name": "Reshape", "config": {"name": "reshape_73", "trainable": true, "dtype": "float32", "target_shape": {"class_name": "__tuple__", "items": [2, 16, 8]}}, "name": "reshape_73", "inbound_nodes": [[["dense_58", 0, 0, {}]]], "shared_object_id": 34}], "input_layers": [["input_31", 0, 0]], "output_layers": [["reshape_73", 0, 0]]}}, "training_config": {"loss": "mse", "metrics": null, "weighted_metrics": null, "loss_weights": null, "optimizer_config": {"class_name": "Custom>RMSprop", "config": {"name": "RMSprop", "weight_decay": null, "clipnorm": null, "global_clipnorm": null, "clipvalue": null, "use_ema": false, "ema_momentum": 0.99, "ema_overwrite_frequency": 100, "jit_compile": false, "is_legacy_optimizer": false, "learning_rate": 0.0010000000474974513, "rho": 0.9, "momentum": 0.0, "epsilon": 1e-07, "centered": false}}}}2 + root.layer-0"_tf_keras_input_layer*{"class_name": "InputLayer", "name": "input_31", "dtype": "float32", "sparse": false, "ragged": false, "batch_input_shape": {"class_name": "__tuple__", "items": [null, 48, 2, 16, 8]}, "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 48, 2, 16, 8]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "input_31"}}2 + root.layer-1"_tf_keras_layer*{"name": "reshape_72", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Reshape", "config": {"name": "reshape_72", "trainable": true, "dtype": "float32", "target_shape": {"class_name": "__tuple__", "items": [-1, 16, 8]}}, "inbound_nodes": [[["input_31", 0, 0, {}]]], "shared_object_id": 1, "build_input_shape": {"class_name": "TensorShape", "items": [null, 48, 2, 16, 8]}}2 + +root.layer_with_weights-0"_tf_keras_layer* {"name": "conv2d_75", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Conv2D", "config": {"name": "conv2d_75", "trainable": true, "dtype": "float32", "filters": 32, "kernel_size": {"class_name": "__tuple__", "items": [2, 2]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 2}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 3}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["reshape_72", 0, 0, {}]]], "shared_object_id": 4, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 4, "axes": {"-1": 8}}, "shared_object_id": 37}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 96, 16, 8]}}2 + root.layer-3"_tf_keras_layer*{"name": "max_pooling2d_73", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_73", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "inbound_nodes": [[["conv2d_75", 0, 0, {}]]], "shared_object_id": 5, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {}}, "shared_object_id": 38}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 95, 15, 32]}}2 + +root.layer_with_weights-1"_tf_keras_layer* +{"name": "conv2d_76", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Conv2D", "config": {"name": "conv2d_76", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [2, 2]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 6}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 7}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["max_pooling2d_73", 0, 0, {}]]], "shared_object_id": 8, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 4, "axes": {"-1": 32}}, "shared_object_id": 39}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 47, 7, 32]}}2 + root.layer-5"_tf_keras_layer*{"name": "max_pooling2d_74", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_74", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "inbound_nodes": [[["conv2d_76", 0, 0, {}]]], "shared_object_id": 9, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {}}, "shared_object_id": 40}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 46, 6, 64]}}2 + +root.layer_with_weights-2"_tf_keras_layer* +{"name": "conv2d_77", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Conv2D", "config": {"name": "conv2d_77", "trainable": true, "dtype": "float32", "filters": 128, "kernel_size": {"class_name": "__tuple__", "items": [2, 2]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 10}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 11}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["max_pooling2d_74", 0, 0, {}]]], "shared_object_id": 12, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 4, "axes": {"-1": 64}}, "shared_object_id": 41}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 23, 3, 64]}}2 + root.layer-7"_tf_keras_layer*{"name": "max_pooling2d_75", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_75", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "inbound_nodes": [[["conv2d_77", 0, 0, {}]]], "shared_object_id": 13, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {}}, "shared_object_id": 42}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 22, 2, 128]}}2 +  root.layer-8"_tf_keras_layer*{"name": "reshape_71", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Reshape", "config": {"name": "reshape_71", "trainable": true, "dtype": "float32", "target_shape": {"class_name": "__tuple__", "items": [48, 256]}}, "inbound_nodes": [[["input_31", 0, 0, {}]]], "shared_object_id": 14, "build_input_shape": {"class_name": "TensorShape", "items": [null, 48, 2, 16, 8]}}2 + + root.layer-9"_tf_keras_layer*{"name": "flatten_25", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Flatten", "config": {"name": "flatten_25", "trainable": true, "dtype": "float32", "data_format": "channels_last"}, "inbound_nodes": [[["max_pooling2d_75", 0, 0, {}]]], "shared_object_id": 15, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 1, "axes": {}}, "shared_object_id": 43}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 11, 1, 128]}}2 +  root.layer_with_weights-3"_tf_keras_rnn_layer* {"name": "lstm_23", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "LSTM", "config": {"name": "lstm_23", "trainable": true, "dtype": "float32", "return_sequences": false, "return_state": false, "go_backwards": false, "stateful": false, "unroll": false, "time_major": false, "units": 512, "activation": "relu", "recurrent_activation": "sigmoid", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 16}, "recurrent_initializer": {"class_name": "Orthogonal", "config": {"gain": 1.0, "seed": null}, "shared_object_id": 17}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 18}, "unit_forget_bias": true, "kernel_regularizer": null, "recurrent_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "recurrent_constraint": null, "bias_constraint": null, "dropout": 0.2, "recurrent_dropout": 0.0, "implementation": 2}, "inbound_nodes": [[["reshape_71", 0, 0, {}]]], "shared_object_id": 20, "input_spec": [{"class_name": "InputSpec", "config": {"dtype": null, "shape": {"class_name": "__tuple__", "items": [null, null, 256]}, "ndim": 3, "max_ndim": null, "min_ndim": null, "axes": {}}, "shared_object_id": 44}], "build_input_shape": {"class_name": "TensorShape", "items": [null, 48, 256]}}2 + root.layer_with_weights-4"_tf_keras_layer*{"name": "dense_56", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Dense", "config": {"name": "dense_56", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 21}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 22}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["flatten_25", 0, 0, {}]]], "shared_object_id": 23, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 1408}}, "shared_object_id": 45}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 1408]}}2 + root.layer_with_weights-5"_tf_keras_layer*{"name": "dense_55", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Dense", "config": {"name": "dense_55", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 24}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 25}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["lstm_23", 0, 0, {}]]], "shared_object_id": 26, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 512}}, "shared_object_id": 46}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 512]}}2 + root.layer-13"_tf_keras_layer*{"name": "concatenate_15", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Concatenate", "config": {"name": "concatenate_15", "trainable": true, "dtype": "float32", "axis": -1}, "inbound_nodes": [[["dense_56", 0, 0, {}], ["dense_55", 0, 0, {}]]], "shared_object_id": 27, "build_input_shape": [{"class_name": "TensorShape", "items": [null, 128]}, {"class_name": "TensorShape", "items": [null, 128]}]}2 +root.layer_with_weights-6"_tf_keras_layer*{"name": "dense_57", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Dense", "config": {"name": "dense_57", "trainable": true, "dtype": "float32", "units": 256, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 28}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 29}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["concatenate_15", 0, 0, {}]]], "shared_object_id": 30, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 256}}, "shared_object_id": 47}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 256]}}2 +root.layer_with_weights-7"_tf_keras_layer*{"name": "dense_58", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Dense", "config": {"name": "dense_58", "trainable": true, "dtype": "float32", "units": 256, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 31}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 32}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["dense_57", 0, 0, {}]]], "shared_object_id": 33, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 256}}, "shared_object_id": 48}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 256]}}2 + root.layer-16"_tf_keras_layer*{"name": "reshape_73", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Reshape", "config": {"name": "reshape_73", "trainable": true, "dtype": "float32", "target_shape": {"class_name": "__tuple__", "items": [2, 16, 8]}}, "inbound_nodes": [[["dense_58", 0, 0, {}]]], "shared_object_id": 34, "build_input_shape": {"class_name": "TensorShape", "items": [null, 256]}}2 +aroot.layer_with_weights-3.cell"_tf_keras_layer*{"name": "lstm_cell", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "LSTMCell", "config": {"name": "lstm_cell", "trainable": true, "dtype": "float32", "units": 512, "activation": "relu", "recurrent_activation": "sigmoid", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 16}, "recurrent_initializer": {"class_name": "Orthogonal", "config": {"gain": 1.0, "seed": null}, "shared_object_id": 17}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 18}, "unit_forget_bias": true, "kernel_regularizer": null, "recurrent_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "recurrent_constraint": null, "bias_constraint": null, "dropout": 0.2, "recurrent_dropout": 0.0, "implementation": 2}, "shared_object_id": 19, "build_input_shape": {"class_name": "__tuple__", "items": [null, 256]}}2 +root.keras_api.metrics.0"_tf_keras_metric*{"class_name": "Mean", "name": "loss", "dtype": "float32", "config": {"name": "loss", "dtype": "float32"}, "shared_object_id": 49}2 \ No newline at end of file diff --git a/lstm_cnn_v2/saved_model.pb b/lstm_cnn_v2/saved_model.pb new file mode 100644 index 0000000..cedb96a Binary files /dev/null and b/lstm_cnn_v2/saved_model.pb differ diff --git a/lstm_cnn_v2/variables/variables.data-00000-of-00001 b/lstm_cnn_v2/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000..38c0732 Binary files /dev/null and b/lstm_cnn_v2/variables/variables.data-00000-of-00001 differ diff --git a/lstm_cnn_v2/variables/variables.index b/lstm_cnn_v2/variables/variables.index new file mode 100644 index 0000000..9d84554 Binary files /dev/null and b/lstm_cnn_v2/variables/variables.index differ diff --git a/lstm_cnn_v3.h5 b/lstm_cnn_v3.h5 new file mode 100644 index 0000000..8c88bef Binary files /dev/null and b/lstm_cnn_v3.h5 differ diff --git a/lstm_cnn_v4.h5 b/lstm_cnn_v4.h5 new file mode 100644 index 0000000..2555fd5 Binary files /dev/null and b/lstm_cnn_v4.h5 differ diff --git a/lstm_cnn_v5.h5 b/lstm_cnn_v5.h5 new file mode 100644 index 0000000..0fb9ca3 Binary files /dev/null and b/lstm_cnn_v5.h5 differ diff --git a/lstm_cnn_v6.h5 b/lstm_cnn_v6.h5 new file mode 100644 index 0000000..b648664 Binary files /dev/null and b/lstm_cnn_v6.h5 differ diff --git a/lstm_dropout.h5 b/lstm_dropout.h5 new file mode 100644 index 0000000..5691b72 Binary files /dev/null and b/lstm_dropout.h5 differ diff --git a/model_lab.ipynb b/model_lab.ipynb index 29a0e41..c52d744 100644 --- a/model_lab.ipynb +++ b/model_lab.ipynb @@ -2,77 +2,181 @@ "cells": [ { "cell_type": "code", - "execution_count": 4, + "execution_count": 80, "metadata": {}, "outputs": [], "source": [ + "import tensorflow as tf\n", "import keras\n", "from keras import layers\n", "from keras import models\n", - "from GenDs import GenDs" + "from GenDs2 import GenDs\n", + "from GenFeature import gen_features\n", + "import numpy as np" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 81, "metadata": {}, "outputs": [], "source": [ "time_step = 48\n", "train_ds,std = GenDs.gen_train (time_step)\n", - "test_ds = GenDs.gen_test(time_step)" + "test_ds = GenDs.gen_test(time_step)\n", + "feature_array = gen_features()[0].reshape(-1,16*8)" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 82, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 128)" + ] + }, + "execution_count": 82, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_array.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 83, "metadata": {}, "outputs": [], "source": [ "input_shape = (time_step,2,16,8)\n", + "time_input_shape = (4,1)\n", + "\n", + "time_inputs = layers.Input(shape = time_input_shape)\n", "\n", "inputs = layers.Input(shape = input_shape)\n", "\n", + "t = layers.Dense(32)(time_inputs)\n", + "\n", + "t = layers.Reshape(([-1]))(t)\n", + "\n", + "\n", + "\n", + "y = layers.Reshape((time_step,2*16*8))(inputs)\n", + "\n", + "y = layers.LSTM(512,dropout=0.2, activation = \"relu\")(y)\n", + "\n", + "y = layers.Dense(128)(y)\n", + "\n", + "\n", + "\n", + "x = layers.Reshape((-1,16,8))(inputs)\n", + "\n", + "x = layers.Conv2D(filters=32, kernel_size=2, activation=\"relu\")(x)\n", + "x = layers.MaxPooling2D(pool_size=2)(x)\n", + "x = layers.Conv2D(filters=64, kernel_size=2, activation=\"relu\")(x)\n", + "x = layers.MaxPooling2D(pool_size=2)(x)\n", + "x = layers.Conv2D(filters=128, kernel_size=2, activation=\"relu\")(x)\n", + "x = layers.MaxPooling2D(pool_size=2)(x)\n", + "\n", + "x = layers.Flatten()(x)\n", + "\n", + "x = layers.Dense(128,activation= \"relu\")(x)\n", + "\n", + "# replicated_static_feature = layers.Lambda(replicate_static_feature)(inputs)\n", + "\n", + "batch_size = tf.shape(inputs)[0]\n", + "concat = layers.concatenate([t,x,y,tf.tile(feature_array,[batch_size,1])])\n", + "\n", + "x = layers.Dense(512,activation=\"relu\")(concat)\n", + "\n", "\n", - "x = layers.Reshape((time_step,2*16*8))(inputs)\n", + "x = layers.Dense(2*16*8, activation = \"ELU\")(x)\n", "\n", - "x = layers.LSTM(512,dropout=0.2,recurrent_dropout=0.1, activation = \"relu\")(x)\n", "\n", - "x = layers.Dense(2*16*8, activation = \"relu\")(x)\n", "\n", "output = layers.Reshape((2,16,8))(x)\n", "\n", - "model = models.Model([inputs],outputs = output)" + "model = models.Model([time_inputs,inputs],outputs = output)" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 84, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Model: \"model_1\"\n", - "_________________________________________________________________\n", - " Layer (type) Output Shape Param # \n", - "=================================================================\n", - " input_2 (InputLayer) [(None, 48, 2, 16, 8)] 0 \n", - " \n", - " reshape_2 (Reshape) (None, 48, 256) 0 \n", - " \n", - " lstm_1 (LSTM) (None, 512) 1574912 \n", - " \n", - " dense_1 (Dense) (None, 256) 131328 \n", - " \n", - " reshape_3 (Reshape) (None, 2, 16, 8) 0 \n", - " \n", - "=================================================================\n", - "Total params: 1706240 (6.51 MB)\n", - "Trainable params: 1706240 (6.51 MB)\n", + "Model: \"model_10\"\n", + "__________________________________________________________________________________________________\n", + " Layer (type) Output Shape Param # Connected to \n", + "==================================================================================================\n", + " input_28 (InputLayer) [(None, 48, 2, 16, 8)] 0 [] \n", + " \n", + " reshape_51 (Reshape) (None, 96, 16, 8) 0 ['input_28[0][0]'] \n", + " \n", + " conv2d_36 (Conv2D) (None, 95, 15, 32) 1056 ['reshape_51[0][0]'] \n", + " \n", + " max_pooling2d_35 (MaxPooli (None, 47, 7, 32) 0 ['conv2d_36[0][0]'] \n", + " ng2D) \n", + " \n", + " conv2d_37 (Conv2D) (None, 46, 6, 64) 8256 ['max_pooling2d_35[0][0]'] \n", + " \n", + " max_pooling2d_36 (MaxPooli (None, 23, 3, 64) 0 ['conv2d_37[0][0]'] \n", + " ng2D) \n", + " \n", + " conv2d_38 (Conv2D) (None, 22, 2, 128) 32896 ['max_pooling2d_36[0][0]'] \n", + " \n", + " input_27 (InputLayer) [(None, 4, 1)] 0 [] \n", + " \n", + " max_pooling2d_37 (MaxPooli (None, 11, 1, 128) 0 ['conv2d_38[0][0]'] \n", + " ng2D) \n", + " \n", + " reshape_50 (Reshape) (None, 48, 256) 0 ['input_28[0][0]'] \n", + " \n", + " tf.compat.v1.shape_11 (TFO (5,) 0 ['input_28[0][0]'] \n", + " pLambda) \n", + " \n", + " dense_54 (Dense) (None, 4, 32) 64 ['input_27[0][0]'] \n", + " \n", + " flatten_11 (Flatten) (None, 1408) 0 ['max_pooling2d_37[0][0]'] \n", + " \n", + " lstm_13 (LSTM) (None, 512) 1574912 ['reshape_50[0][0]'] \n", + " \n", + " tf.__operators__.getitem_1 () 0 ['tf.compat.v1.shape_11[0][0]'\n", + " 1 (SlicingOpLambda) ] \n", + " \n", + " reshape_49 (Reshape) (None, 128) 0 ['dense_54[0][0]'] \n", + " \n", + " dense_56 (Dense) (None, 128) 180352 ['flatten_11[0][0]'] \n", + " \n", + " dense_55 (Dense) (None, 128) 65664 ['lstm_13[0][0]'] \n", + " \n", + " tf.tile_11 (TFOpLambda) (None, 128) 0 ['tf.__operators__.getitem_11[\n", + " 0][0]'] \n", + " \n", + " concatenate_11 (Concatenat (None, 512) 0 ['reshape_49[0][0]', \n", + " e) 'dense_56[0][0]', \n", + " 'dense_55[0][0]', \n", + " 'tf.tile_11[0][0]'] \n", + " \n", + " dense_57 (Dense) (None, 512) 262656 ['concatenate_11[0][0]'] \n", + " \n", + " dense_58 (Dense) (None, 256) 131328 ['dense_57[0][0]'] \n", + " \n", + " reshape_52 (Reshape) (None, 2, 16, 8) 0 ['dense_58[0][0]'] \n", + " \n", + "==================================================================================================\n", + "Total params: 2257184 (8.61 MB)\n", + "Trainable params: 2257184 (8.61 MB)\n", "Non-trainable params: 0 (0.00 Byte)\n", - "_________________________________________________________________\n" + "__________________________________________________________________________________________________\n" ] } ], @@ -82,7 +186,22 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 85, + "metadata": {}, + "outputs": [], + "source": [ + "model_name = \"lstm_cnn_v6.h5\"\n", + "model.compile(optimizer='adam', loss='mse')\n", + "# model.fit([X_train,X_train],y_train,epochs=50, batch_size=10, validation_data=([X_test,X_test], y_test))\n", + "# model.fit(ds,epochs=50, batch_size=10, validation_data=(test_ds),shuffle=False)\n", + "early_stopping_cb = keras.callbacks.EarlyStopping(patience=10,restore_best_weights=True)\n", + "checkpoint_cb = keras.callbacks.ModelCheckpoint(model_name,save_best_only= True)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 86, "metadata": {}, "outputs": [ { @@ -96,49 +215,87 @@ "name": "stdout", "output_type": "stream", "text": [ - "38/38 [==============================] - 24s 592ms/step - loss: 0.5819 - val_loss: 0.4353\n", + "6/6 [==============================] - 3s 367ms/step - loss: 0.6491 - val_loss: 0.4664\n", "Epoch 2/50\n", - "38/38 [==============================] - 23s 608ms/step - loss: 0.4770 - val_loss: 0.4164\n", + "6/6 [==============================] - 2s 329ms/step - loss: 0.4766 - val_loss: 0.3443\n", "Epoch 3/50\n", - "38/38 [==============================] - 21s 565ms/step - loss: 0.4479 - val_loss: 0.4052\n", + "6/6 [==============================] - 2s 344ms/step - loss: 0.3397 - val_loss: 0.3076\n", "Epoch 4/50\n", - "38/38 [==============================] - 24s 628ms/step - loss: 0.4374 - val_loss: 0.3989\n", + "6/6 [==============================] - 2s 335ms/step - loss: 0.2987 - val_loss: 0.3018\n", "Epoch 5/50\n", - "38/38 [==============================] - 24s 636ms/step - loss: 0.4282 - val_loss: 0.3942\n", + "6/6 [==============================] - 2s 349ms/step - loss: 0.2762 - val_loss: 0.2593\n", "Epoch 6/50\n", - "23/38 [=================>............] - ETA: 9s - loss: 0.4247 " + "6/6 [==============================] - 2s 336ms/step - loss: 0.2515 - val_loss: 0.2506\n", + "Epoch 7/50\n", + "6/6 [==============================] - 2s 351ms/step - loss: 0.2375 - val_loss: 0.2453\n", + "Epoch 8/50\n", + "6/6 [==============================] - 2s 342ms/step - loss: 0.2216 - val_loss: 0.2385\n", + "Epoch 9/50\n", + "6/6 [==============================] - 2s 345ms/step - loss: 0.2092 - val_loss: 0.2343\n", + "Epoch 10/50\n", + "6/6 [==============================] - 2s 334ms/step - loss: 0.1973 - val_loss: 0.2327\n", + "Epoch 11/50\n", + "6/6 [==============================] - 2s 347ms/step - loss: 0.1887 - val_loss: 0.2324\n", + "Epoch 12/50\n", + "6/6 [==============================] - 2s 335ms/step - loss: 0.1816 - val_loss: 0.2290\n", + "Epoch 13/50\n", + "6/6 [==============================] - 2s 337ms/step - loss: 0.1778 - val_loss: 0.2293\n", + "Epoch 14/50\n", + "6/6 [==============================] - 2s 342ms/step - loss: 0.1724 - val_loss: 0.2328\n", + "Epoch 15/50\n", + "6/6 [==============================] - 2s 341ms/step - loss: 0.1740 - val_loss: 0.2344\n", + "Epoch 16/50\n", + "6/6 [==============================] - 2s 335ms/step - loss: 0.1663 - val_loss: 0.2314\n", + "Epoch 17/50\n", + "6/6 [==============================] - 2s 338ms/step - loss: 0.1634 - val_loss: 0.2291\n", + "Epoch 18/50\n", + "6/6 [==============================] - 2s 335ms/step - loss: 0.1586 - val_loss: 0.2328\n", + "Epoch 19/50\n", + "6/6 [==============================] - 2s 331ms/step - loss: 0.1565 - val_loss: 0.2408\n", + "Epoch 20/50\n", + "6/6 [==============================] - 2s 336ms/step - loss: 0.1623 - val_loss: 0.2310\n", + "Epoch 21/50\n", + "6/6 [==============================] - 2s 334ms/step - loss: 0.1594 - val_loss: 0.2395\n", + "Epoch 22/50\n", + "6/6 [==============================] - 2s 328ms/step - loss: 0.1578 - val_loss: 0.2404\n" ] }, { - "ename": "KeyboardInterrupt", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[12], line 5\u001b[0m\n\u001b[0;32m 1\u001b[0m model\u001b[38;5;241m.\u001b[39mcompile(optimizer\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124madam\u001b[39m\u001b[38;5;124m'\u001b[39m, loss\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmse\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m 2\u001b[0m \u001b[38;5;66;03m# model.fit([X_train,X_train],y_train,epochs=50, batch_size=10, validation_data=([X_test,X_test], y_test))\u001b[39;00m\n\u001b[0;32m 3\u001b[0m \u001b[38;5;66;03m# model.fit(ds,epochs=50, batch_size=10, validation_data=(test_ds),shuffle=False)\u001b[39;00m\n\u001b[1;32m----> 5\u001b[0m \u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtrain_ds\u001b[49m\u001b[43m,\u001b[49m\u001b[43mepochs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m50\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43mshuffle\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43mvalidation_data\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtest_ds\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 6\u001b[0m model\u001b[38;5;241m.\u001b[39msave(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mbase.h5\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "File \u001b[1;32mc:\\Users\\yuyao\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\keras\\src\\utils\\traceback_utils.py:65\u001b[0m, in \u001b[0;36mfilter_traceback..error_handler\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 63\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 64\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m---> 65\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 66\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m 67\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m _process_traceback_frames(e\u001b[38;5;241m.\u001b[39m__traceback__)\n", - "File \u001b[1;32mc:\\Users\\yuyao\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\keras\\src\\engine\\training.py:1783\u001b[0m, in \u001b[0;36mModel.fit\u001b[1;34m(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)\u001b[0m\n\u001b[0;32m 1775\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m tf\u001b[38;5;241m.\u001b[39mprofiler\u001b[38;5;241m.\u001b[39mexperimental\u001b[38;5;241m.\u001b[39mTrace(\n\u001b[0;32m 1776\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtrain\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m 1777\u001b[0m epoch_num\u001b[38;5;241m=\u001b[39mepoch,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 1780\u001b[0m _r\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m,\n\u001b[0;32m 1781\u001b[0m ):\n\u001b[0;32m 1782\u001b[0m callbacks\u001b[38;5;241m.\u001b[39mon_train_batch_begin(step)\n\u001b[1;32m-> 1783\u001b[0m tmp_logs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtrain_function\u001b[49m\u001b[43m(\u001b[49m\u001b[43miterator\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1784\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m data_handler\u001b[38;5;241m.\u001b[39mshould_sync:\n\u001b[0;32m 1785\u001b[0m context\u001b[38;5;241m.\u001b[39masync_wait()\n", - "File \u001b[1;32mc:\\Users\\yuyao\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\tensorflow\\python\\util\\traceback_utils.py:150\u001b[0m, in \u001b[0;36mfilter_traceback..error_handler\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 148\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 149\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 150\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 151\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m 152\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m _process_traceback_frames(e\u001b[38;5;241m.\u001b[39m__traceback__)\n", - "File \u001b[1;32mc:\\Users\\yuyao\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\polymorphic_function.py:831\u001b[0m, in \u001b[0;36mFunction.__call__\u001b[1;34m(self, *args, **kwds)\u001b[0m\n\u001b[0;32m 828\u001b[0m compiler \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mxla\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_jit_compile \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnonXla\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 830\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m OptionalXlaContext(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_jit_compile):\n\u001b[1;32m--> 831\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwds\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 833\u001b[0m new_tracing_count \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexperimental_get_tracing_count()\n\u001b[0;32m 834\u001b[0m without_tracing \u001b[38;5;241m=\u001b[39m (tracing_count \u001b[38;5;241m==\u001b[39m new_tracing_count)\n", - "File \u001b[1;32mc:\\Users\\yuyao\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\polymorphic_function.py:867\u001b[0m, in \u001b[0;36mFunction._call\u001b[1;34m(self, *args, **kwds)\u001b[0m\n\u001b[0;32m 864\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_lock\u001b[38;5;241m.\u001b[39mrelease()\n\u001b[0;32m 865\u001b[0m \u001b[38;5;66;03m# In this case we have created variables on the first call, so we run the\u001b[39;00m\n\u001b[0;32m 866\u001b[0m \u001b[38;5;66;03m# defunned version which is guaranteed to never create variables.\u001b[39;00m\n\u001b[1;32m--> 867\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mtracing_compilation\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcall_function\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 868\u001b[0m \u001b[43m \u001b[49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkwds\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_no_variable_creation_config\u001b[49m\n\u001b[0;32m 869\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 870\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_variable_creation_config \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m 871\u001b[0m \u001b[38;5;66;03m# Release the lock early so that multiple threads can perform the call\u001b[39;00m\n\u001b[0;32m 872\u001b[0m \u001b[38;5;66;03m# in parallel.\u001b[39;00m\n\u001b[0;32m 873\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_lock\u001b[38;5;241m.\u001b[39mrelease()\n", - "File \u001b[1;32mc:\\Users\\yuyao\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\tracing_compilation.py:139\u001b[0m, in \u001b[0;36mcall_function\u001b[1;34m(args, kwargs, tracing_options)\u001b[0m\n\u001b[0;32m 137\u001b[0m bound_args \u001b[38;5;241m=\u001b[39m function\u001b[38;5;241m.\u001b[39mfunction_type\u001b[38;5;241m.\u001b[39mbind(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m 138\u001b[0m flat_inputs \u001b[38;5;241m=\u001b[39m function\u001b[38;5;241m.\u001b[39mfunction_type\u001b[38;5;241m.\u001b[39munpack_inputs(bound_args)\n\u001b[1;32m--> 139\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunction\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_flat\u001b[49m\u001b[43m(\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# pylint: disable=protected-access\u001b[39;49;00m\n\u001b[0;32m 140\u001b[0m \u001b[43m \u001b[49m\u001b[43mflat_inputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcaptured_inputs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfunction\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcaptured_inputs\u001b[49m\n\u001b[0;32m 141\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32mc:\\Users\\yuyao\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\concrete_function.py:1264\u001b[0m, in \u001b[0;36mConcreteFunction._call_flat\u001b[1;34m(self, tensor_inputs, captured_inputs)\u001b[0m\n\u001b[0;32m 1260\u001b[0m possible_gradient_type \u001b[38;5;241m=\u001b[39m gradients_util\u001b[38;5;241m.\u001b[39mPossibleTapeGradientTypes(args)\n\u001b[0;32m 1261\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (possible_gradient_type \u001b[38;5;241m==\u001b[39m gradients_util\u001b[38;5;241m.\u001b[39mPOSSIBLE_GRADIENT_TYPES_NONE\n\u001b[0;32m 1262\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m executing_eagerly):\n\u001b[0;32m 1263\u001b[0m \u001b[38;5;66;03m# No tape is watching; skip to running the function.\u001b[39;00m\n\u001b[1;32m-> 1264\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_inference_function\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mflat_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1265\u001b[0m forward_backward \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_select_forward_and_backward_functions(\n\u001b[0;32m 1266\u001b[0m args,\n\u001b[0;32m 1267\u001b[0m possible_gradient_type,\n\u001b[0;32m 1268\u001b[0m executing_eagerly)\n\u001b[0;32m 1269\u001b[0m forward_function, args_with_tangents \u001b[38;5;241m=\u001b[39m forward_backward\u001b[38;5;241m.\u001b[39mforward()\n", - "File \u001b[1;32mc:\\Users\\yuyao\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\atomic_function.py:217\u001b[0m, in \u001b[0;36mAtomicFunction.flat_call\u001b[1;34m(self, args)\u001b[0m\n\u001b[0;32m 215\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mflat_call\u001b[39m(\u001b[38;5;28mself\u001b[39m, args: Sequence[core\u001b[38;5;241m.\u001b[39mTensor]) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any:\n\u001b[0;32m 216\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Calls with tensor inputs and returns the structured output.\"\"\"\u001b[39;00m\n\u001b[1;32m--> 217\u001b[0m flat_outputs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 218\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfunction_type\u001b[38;5;241m.\u001b[39mpack_output(flat_outputs)\n", - "File \u001b[1;32mc:\\Users\\yuyao\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\atomic_function.py:252\u001b[0m, in \u001b[0;36mAtomicFunction.__call__\u001b[1;34m(self, *args)\u001b[0m\n\u001b[0;32m 250\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m record\u001b[38;5;241m.\u001b[39mstop_recording():\n\u001b[0;32m 251\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_bound_context\u001b[38;5;241m.\u001b[39mexecuting_eagerly():\n\u001b[1;32m--> 252\u001b[0m outputs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_bound_context\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcall_function\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 253\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mname\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 254\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mlist\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 255\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfunction_type\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mflat_outputs\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 256\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 257\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 258\u001b[0m outputs \u001b[38;5;241m=\u001b[39m make_call_op_in_graph(\n\u001b[0;32m 259\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m 260\u001b[0m \u001b[38;5;28mlist\u001b[39m(args),\n\u001b[0;32m 261\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_bound_context\u001b[38;5;241m.\u001b[39mfunction_call_options\u001b[38;5;241m.\u001b[39mas_attrs(),\n\u001b[0;32m 262\u001b[0m )\n", - "File \u001b[1;32mc:\\Users\\yuyao\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\tensorflow\\python\\eager\\context.py:1479\u001b[0m, in \u001b[0;36mContext.call_function\u001b[1;34m(self, name, tensor_inputs, num_outputs)\u001b[0m\n\u001b[0;32m 1477\u001b[0m cancellation_context \u001b[38;5;241m=\u001b[39m cancellation\u001b[38;5;241m.\u001b[39mcontext()\n\u001b[0;32m 1478\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m cancellation_context \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m-> 1479\u001b[0m outputs \u001b[38;5;241m=\u001b[39m \u001b[43mexecute\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mexecute\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 1480\u001b[0m \u001b[43m \u001b[49m\u001b[43mname\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mutf-8\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1481\u001b[0m \u001b[43m \u001b[49m\u001b[43mnum_outputs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnum_outputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1482\u001b[0m \u001b[43m \u001b[49m\u001b[43minputs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtensor_inputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1483\u001b[0m \u001b[43m \u001b[49m\u001b[43mattrs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mattrs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1484\u001b[0m \u001b[43m \u001b[49m\u001b[43mctx\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1485\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1486\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 1487\u001b[0m outputs \u001b[38;5;241m=\u001b[39m execute\u001b[38;5;241m.\u001b[39mexecute_with_cancellation(\n\u001b[0;32m 1488\u001b[0m name\u001b[38;5;241m.\u001b[39mdecode(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mutf-8\u001b[39m\u001b[38;5;124m\"\u001b[39m),\n\u001b[0;32m 1489\u001b[0m num_outputs\u001b[38;5;241m=\u001b[39mnum_outputs,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 1493\u001b[0m cancellation_manager\u001b[38;5;241m=\u001b[39mcancellation_context,\n\u001b[0;32m 1494\u001b[0m )\n", - "File \u001b[1;32mc:\\Users\\yuyao\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\tensorflow\\python\\eager\\execute.py:60\u001b[0m, in \u001b[0;36mquick_execute\u001b[1;34m(op_name, num_outputs, inputs, attrs, ctx, name)\u001b[0m\n\u001b[0;32m 53\u001b[0m \u001b[38;5;66;03m# Convert any objects of type core_types.Tensor to Tensor.\u001b[39;00m\n\u001b[0;32m 54\u001b[0m inputs \u001b[38;5;241m=\u001b[39m [\n\u001b[0;32m 55\u001b[0m tensor_conversion_registry\u001b[38;5;241m.\u001b[39mconvert(t)\n\u001b[0;32m 56\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(t, core_types\u001b[38;5;241m.\u001b[39mTensor)\n\u001b[0;32m 57\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m t\n\u001b[0;32m 58\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m t \u001b[38;5;129;01min\u001b[39;00m inputs\n\u001b[0;32m 59\u001b[0m ]\n\u001b[1;32m---> 60\u001b[0m tensors \u001b[38;5;241m=\u001b[39m \u001b[43mpywrap_tfe\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mTFE_Py_Execute\u001b[49m\u001b[43m(\u001b[49m\u001b[43mctx\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_handle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdevice_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mop_name\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 61\u001b[0m \u001b[43m \u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mattrs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnum_outputs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 62\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m core\u001b[38;5;241m.\u001b[39m_NotOkStatusException \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m 63\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m name \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", - "\u001b[1;31mKeyboardInterrupt\u001b[0m: " + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 86, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.fit(train_ds,epochs=50,shuffle=False,validation_data=test_ds,callbacks=[checkpoint_cb,early_stopping_cb])" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(TensorShape([32, 4, 1]), TensorShape([32, 48, 2, 16, 8])) (32, 2, 16, 8)\n", + "(TensorShape([32, 4, 1]), TensorShape([32, 48, 2, 16, 8])) (32, 2, 16, 8)\n", + "(TensorShape([32, 4, 1]), TensorShape([32, 48, 2, 16, 8])) (32, 2, 16, 8)\n", + "(TensorShape([32, 4, 1]), TensorShape([32, 48, 2, 16, 8])) (32, 2, 16, 8)\n", + "(TensorShape([32, 4, 1]), TensorShape([32, 48, 2, 16, 8])) (32, 2, 16, 8)\n", + "(TensorShape([32, 4, 1]), TensorShape([32, 48, 2, 16, 8])) (32, 2, 16, 8)\n" ] } ], "source": [ - "model.compile(optimizer='adam', loss='mse')\n", - "# model.fit([X_train,X_train],y_train,epochs=50, batch_size=10, validation_data=([X_test,X_test], y_test))\n", - "# model.fit(ds,epochs=50, batch_size=10, validation_data=(test_ds),shuffle=False)\n", - "\n", - "model.fit(train_ds,epochs=50,shuffle=False,validation_data=test_ds)\n", - "model.save(\"base.h5\")" + "for (i,j),k in test_ds:\n", + " print((i.shape,j.shape),k.shape)" ] }, { diff --git a/model_performance.ipynb b/model_performance.ipynb index 0c1846f..40d3d89 100644 --- a/model_performance.ipynb +++ b/model_performance.ipynb @@ -2,32 +2,37 @@ "cells": [ { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - } - ], + "outputs": [], "source": [ "%load_ext autoreload\n", - "%autoreload 2\n", - "from GenDs import GenDs\n", + "%reload_ext autoreload\n", + "from GenDs2 import GenDs\n", "from ModelPerformance import std_inverse,plot_result,compare_result\n", "import keras\n", "from keras import layers\n", "from keras import models\n", - "import numpy as np\n" + "import numpy as np\n", + "import pandas as pd" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# test base behavior\n", + "# X_train = pd.read_pickle(\"./data/X_train.pkl\")\n", + "# y_train = pd.read_pickle(\"./data/y_train.pkl\")\n", + "# X_test = pd.read_pickle(\"./data/X_test.pkl\")\n", + "# y_test = pd.read_pickle(\"./data/y_test.pkl\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -38,205 +43,104 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Model: \"model\"\n", - "_________________________________________________________________\n", - " Layer (type) Output Shape Param # \n", - "=================================================================\n", - " input_1 (InputLayer) [(None, 48, 2, 16, 8)] 0 \n", - " \n", - " reshape (Reshape) (None, 48, 256) 0 \n", - " \n", - " lstm (LSTM) (None, 100) 142800 \n", - " \n", - " dense (Dense) (None, 256) 25856 \n", - " \n", - " reshape_1 (Reshape) (None, 2, 16, 8) 0 \n", - " \n", - "=================================================================\n", - "Total params: 168656 (658.81 KB)\n", - "Trainable params: 168656 (658.81 KB)\n", - "Non-trainable params: 0 (0.00 Byte)\n", - "_________________________________________________________________\n", - "None\n", - "6/6 [==============================] - 0s 12ms/step - loss: 0.3826\n" - ] - }, - { - "data": { - "text/plain": [ - "0.38258907198905945" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "model = models.load_model(\"base.h5\")\n", + "import pickle\n", + "with open(\"std_scaler.pkl\",\"wb\") as file:\n", + " pickle.dump(std,file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for (i,k),j in test_ds:\n", + " print(i.shape,j.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = models.load_model(\"lstm_cnn_v5.h5\")\n", "print(model.summary())\n", + "# model.evaluate(test_ds)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "model.evaluate(test_ds)" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def recursive_predict(model,initial_input,steps):\n", + " current_input = init_input\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for (X,y) in test_ds:\n", + " inverse_result = std_inverse(std,y)\n", + " for i in range(31):\n", + " plot_result(inverse_result[:-1],inverse_result[1:],i,0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1/1 [==============================] - 0s 140ms/step\n", - "50.180029113849734\n", - "1/1 [==============================] - 0s 34ms/step\n", - "56.82033128532766\n", - "1/1 [==============================] - 0s 24ms/step\n", - "23.381881222715727\n", - "1/1 [==============================] - 0s 21ms/step\n", - "47.64655154910395\n", - "1/1 [==============================] - 0s 19ms/step\n", - "56.868088637474486\n", - "1/1 [==============================] - 0s 19ms/step\n", - "27.372569103597968\n" - ] - } - ], + "outputs": [], "source": [ "# print original mse\n", "for X,y in test_ds:\n", - " result = model.predict (X)\n", + " result = model.predict(X)\n", " inverse_result = std_inverse(std,result)\n", " inverse_y = std_inverse(std,y)\n", " \n", " # print(inverse_result.shape,inverse_y.shape)\n", " compare_result(inverse_result,inverse_y)\n", - "\n", "\n" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1/1 [==============================] - 0s 18ms/step\n" - ] - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1/1 [==============================] - 0s 19ms/step\n" - ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAh8AAAFlCAYAAABLDIrrAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAp9UlEQVR4nO3dfXRU5b3+/2tnApMQkvAQSIiGBxFFELGiUh9qYZkjphbLaoVqrSJVOFUQFWst33MU+FpIbc/yoMiC6m9ZqNUqHip19VT4KYJoCypELR4qBhshQsODQgIB8jT39w+PU1JAE+Yz92SH92utWYvM7Fz7Zrgy+bBnZk/gnHMCAADwJC3VCwAAACcXhg8AAOAVwwcAAPCK4QMAAHjF8AEAALxi+AAAAF4xfAAAAK8YPgAAgFcMHwAAwCuGj3Zk9erVCoJAq1evjl930003qW/fvilbE5ComTNnKgiCVC8DJ5l/7l3fvn110003NdumvLxcV1xxhXJzcxUEgZYtWyZJeuutt3TxxRcrKytLQRDonXfe8bfwkEhP9QLQNs2ZM0eDBg3SmDFjUr0UAGiTxo8fr4qKCs2ePVtdunTR+eefr4aGBo0dO1YZGRn6z//8T3Xq1El9+vRJ9VLbHIaPdu7xxx9XLBZr9ffNmTNH11xzDcMHAEjavHmz0tL+8WTBoUOHtHbtWv3bv/2bpkyZEr/+/fff19atW/X444/rlltuScVSQ4GnXdqAWCymw4cPJyW7Q4cOikajSckG/lltbW2qlwAkRTQaVYcOHeJf7969W5LUpUuXZtvt2rXrmNejOYYPQ58/R/j+++9r3LhxysnJUffu3XXHHXc0Gy6CINCUKVP01FNPafDgwYpGo1q+fLkkafv27frBD36g/Px8RaNRDR48WE888cRR+/r44481ZswYZWVlqWfPnrrrrrtUV1d31HbHes1HLBbTww8/rCFDhigjI0M9evTQlVdeqfXr18fXV1tbq8WLFysIAgVBcNRzncDnfd+0aZO+973vqWvXrrr00kslSb/5zW80bNgwZWZmqlu3brr22mtVWVnZ7Ptfe+01jR07Vr1791Y0GlVRUZHuuusuHTp0KBV/HZzEXn/9dV1wwQXKyMhQ//799ctf/vKobY58zcfMmTPjT6Xcc889CoIgfvvXv/51SdLYsWMVBIFGjBjh668RKjztkgTjxo1T3759VVpaqnXr1umRRx7R3r179etf/zq+zSuvvKIlS5ZoypQpysvLU9++fbVz50599atfjQ8nPXr00Isvvqibb75ZNTU1uvPOOyV9drjv8ssv17Zt2zR16lQVFhbqySef1CuvvNKi9d18881atGiRSkpKdMstt6ixsVGvvfaa1q1bp/PPP19PPvmkbrnlFl144YWaNGmSJKl///7m9xPah7Fjx2rAgAGaM2eOnHOaPXu27rvvPo0bN0633HKLdu/erXnz5umyyy7T22+/Hf8f4XPPPaeDBw/q1ltvVffu3fXmm29q3rx5+vjjj/Xcc8+l9i+Fk8bGjRt1xRVXqEePHpo5c6YaGxs1Y8YM5efnH/d7vv3tb6tLly666667dN111+kb3/iGOnfurPz8fJ1yyimaM2eOpk6dqgsuuOALc05qDmZmzJjhJLmrr7662fW33Xabk+Teffdd55xzklxaWpr7n//5n2bb3Xzzza5Xr15uz549za6/9tprXW5urjt48KBzzrm5c+c6SW7JkiXxbWpra93pp5/uJLlVq1bFrx8/frzr06dP/OtXXnnFSXJTp049av2xWCz+56ysLDd+/PhW/f1xcvm879ddd138uo8++shFIhE3e/bsZttu3LjRpaenN7v+8z4fqbS01AVB4LZu3XrUfoBkGDNmjMvIyGjWuU2bNrlIJNKsd3369Gn2mFhRUeEkuV/84hfN8latWuUkueeeey7paw8znnZJgsmTJzf7+vbbb5ck/fGPf4xf9/Wvf12DBg2Kf+2c09KlSzV69Gg557Rnz574ZdSoUaqurlZZWVk8p1evXrrmmmvi39+pU6f4UYovsnTpUgVBoBkzZhx1G29nxIn44Q9/GP/z7373O8ViMY0bN65ZhwsKCjRgwACtWrUqvm1mZmb8z7W1tdqzZ48uvvhiOef09ttve/074OTU1NSkFStWaMyYMerdu3f8+rPOOkujRo1K4craP552SYIBAwY0+7p///5KS0vTRx99FL+uX79+zbbZvXu39u3bp8cee0yPPfbYMXM/fyHT1q1bdfrppx81LJx55plfurYPP/xQhYWF6tatW0v+KsCXOrLL5eXlcs4d9TPwuSNfsLdt2zbdf//9euGFF7R3795m21VXVydnscARdu/erUOHDh2zr2eeeWaz/zDCFsOHB8c6onDk//okxd8O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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1/1 [==============================] - 0s 20ms/step\n" - ] - }, - { - "data": { - "image/png": "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7He/+11NmTLloHNOPPFE+8UBKfp0lhOJhIIg0DPPPKNIJHLAvt27d5f0yU+cX/va1/TRRx/p5ptv1vDhw1VQUKAtW7boiiuuOKy3hwMID8pHGlRXV7f5aXDjxo1KJBKfe6XRPn36qLCwUPF4XBUVFZ87f9CgQXrzzTflnGtTbDZs2PCFaxs6dKieffZZffTRR5979oOnYHA4hg4dKuechgwZomOOOeaQ+73xxht65513tHjxYl1++eXJ7c8995yPZQKSPvm+m5eXp+rq6gPua8/3Uxw+XvORBgsWLGjz8b333itJqqysPOTnRCIRfetb39KSJUv05ptvHnD//veUS9L555+vrVu36n/+53+S23bv3n3Ip2s+7Vvf+pacc5o3b94B9znnkn8uKCjQjh07vnAe8Gnf/OY3FYlENG/evDZ5kj7J14cffihJybMin97HOae7777b32JxxItEIho/fryWLl2qzZs3J7f/4x//0LPPPpvBlXV9nPlIg5qaGl144YU677zztGrVKv3mN7/Rd77zHY0aNepzP+/nP/+5VqxYoTFjxujqq6/WiBEj9NFHH2ndunX605/+pI8++kiSdPXVV+u+++7T5ZdfrrVr16p///56+OGHlZ+f/4VrGzdunC677DLdc889qq6u1nnnnadEIqEXX3xR48aNS16pb/To0frTn/6ku+66S2VlZRoyZIjGjBmT+oODLm3o0KG67bbbNGvWLL333nuaOHGiCgsLVVNTo6eeekrXXHONfvzjH2v48OEaOnSofvzjH2vLli0qKirSkiVLDnjtB5Bu8+bN07Jly/TVr35V1157rVpbW3Xvvfdq5MiR+vvf/57p5XVdmXmTTde0/y2B69evdxdddJErLCx0PXv2dNOnT3d79uxJ7ifJTZs27aAz6uvr3bRp01x5ebnr1q2b69evnzvnnHPcAw880Ga/TZs2uQsvvNDl5+e7kpISd/3117tly5Z94VttnXOutbXV/eIXv3DDhw93OTk5rk+fPq6ystKtXbs2uc/bb7/tzjrrLJeXl+ck8bZbHGB/3rdt23bAfUuWLHFnnnmmKygocAUFBW748OFu2rRpbsOGDcl91q9f7yoqKlz37t1dSUmJu/rqq93rr7/uJLlf/epXBxwHSJc///nPbvTo0S4nJ8cdddRR7v777z8gd7zV1lbg3GfOjeKwzZ07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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1/1 [==============================] - 0s 20ms/step\n" - ] - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1/1 [==============================] - 0s 22ms/step\n" - ] - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1/1 [==============================] - 0s 21ms/step\n" - ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAh8AAAFlCAYAAABLDIrrAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAqLElEQVR4nO3de3RU5b3/8c+eSTK5kIRLICGaAFIUQcUWlHqpws9UjBbl1wr1UkVUPK0gKq3Hss7hpoVo7fKgyMHq+lmo1Xo5VOpyVVgWQbCC3NRiqRg0QAADQSCBBIZk5vn94WFKBCRhnnkmO7xfa81aZmbns59MPhm/7JnZ4xljjAAAABwJJHsBAADg1MLwAQAAnGL4AAAATjF8AAAApxg+AACAUwwfAADAKYYPAADgFMMHAABwiuEDAAA4xfDRhixZskSe52nJkiWx62677TZ17949aWsC4jVlyhR5npfsZeAU8/Xede/eXbfddluTbcrLy3XllVcqNzdXnudp/vz5kqRVq1bp4osvVlZWljzP04cffuhu4T6RkuwFoHWaPn26+vTpo2HDhiV7KQDQKo0cOVIVFRWaNm2a2rdvrwEDBqihoUHDhw9Xenq6/uu//kuZmZnq1q1bspfa6jB8tHHPPvusotFoi79v+vTpuv766xk+AEDShg0bFAj868mCAwcOaPny5fqP//gPjR07Nnb9J598os2bN+vZZ5/VnXfemYyl+gJPu7QC0WhUBw8eTEh2amqqQqFQQrKBr6urq0v2EoCECIVCSk1NjX1dXV0tSWrfvn2T7Xbu3HnM69EUw4dFh58j/OSTTzRixAjl5OSoU6dOuvfee5sMF57naezYsXrhhRfUt29fhUIhLViwQJK0bds23X777crPz1coFFLfvn313HPPHbWvrVu3atiwYcrKylKXLl10//33KxwOH7XdsV7zEY1G9cQTT+jcc89Venq6OnfurKuuukqrV6+Ora+urk5z586V53nyPO+o5zqBw31fv369brrpJnXo0EGXXnqpJOkPf/iD+vfvr4yMDHXs2FE33HCDKisrm3z/smXLNHz4cBUXFysUCqmoqEj333+/Dhw4kIwfB6ewd999VxdccIHS09PVs2dP/fa3vz1qmyNf8zFlypTYUykPPPCAPM+L3X755ZdLkoYPHy7P8zRo0CBXP4av8LRLAowYMULdu3dXWVmZVqxYoSeffFJ79uzR73//+9g2b7/9tl555RWNHTtWeXl56t69u3bs2KHvfve7seGkc+fOevPNN3XHHXeotrZW9913n6SvDvddccUV2rJli8aNG6fCwkI9//zzevvtt5u1vjvuuENz5sxRaWmp7rzzTjU2NmrZsmVasWKFBgwYoOeff1533nmnLrzwQt11112SpJ49e1q/n9A2DB8+XL169dL06dNljNG0adM0ceJEjRgxQnfeeaeqq6s1c+ZMXXbZZfrggw9i/yJ89dVXVV9fr5/97Gfq1KmTVq5cqZkzZ2rr1q169dVXk/tD4ZSxbt06XXnllercubOmTJmixsZGTZ48Wfn5+cf9nh/+8Idq37697r//ft144426+uqr1a5dO+Xn5+u0007T9OnTNW7cOF1wwQXfmHNKM7Bm8uTJRpK59tprm1x/9913G0nmo48+MsYYI8kEAgHzj3/8o8l2d9xxh+natavZtWtXk+tvuOEGk5uba+rr640xxsyYMcNIMq+88kpsm7q6OvOtb33LSDKLFy+OXT9y5EjTrVu32Ndvv/22kWTGjRt31Pqj0Wjsv7OysszIkSNb9PPj1HK47zfeeGPsuk2bNplgMGimTZvWZNt169aZlJSUJtcf7vORysrKjOd5ZvPmzUftB0iEYcOGmfT09CadW79+vQkGg016161btyaPiRUVFUaSeeyxx5rkLV682Egyr776asLX7mc87ZIAY8aMafL1PffcI0n6y1/+Ervu8ssvV58+fWJfG2M0b948DR06VMYY7dq1K3YZMmSIampqtHbt2lhO165ddf3118e+PzMzM3aU4pvMmzdPnudp8uTJR93G2xlxMn7605/G/vtPf/qTotGoRowY0aTDBQUF6tWrlxYvXhzbNiMjI/bfdXV12rVrly6++GIZY/TBBx84/RlwaopEIlq4cKGGDRum4uLi2PVnn322hgwZksSVtX087ZIAvXr1avJ1z549FQgEtGnTpth1PXr0aLJNdXW19u7dq2eeeUbPPPPMMXMPv5Bp8+bN+ta3vnXUsHDWWWedcG2fffaZCgsL1bFjx+b8KMAJHdnl8vJyGWOO+hs47MgX7G3ZskWTJk3S66+/rj179jTZrqamJjGLBY5QXV2tAwcOHLOvZ511VpN/MMIuhg8HjnVE4ch/9UmKvR32Jz/5iUaOHHnMnPPOO8/+4oA4HdnlaDQqz/P05ptvKhgMHrVtu3btJH31L87vf//72r17tx588EH17t1bWVlZ2rZtm2677baTens4AP9g+EiA8vLyJv8a3Lhxo6LR6DeeabRz587Kzs5WJBJRSUnJN+Z369ZNH3/8sYwxTQabDRs2nHBtPXv21MKFC7V79+5vPPrBUzA4GT179pQxRj169NCZZ5553O3WrVunTz/9VHPnztWtt94au/6tt95ysUxA0lePuxkZGSovLz/qtuY8nuLk8ZqPBJg1a1aTr2fOnClJKi0tPe73BINB/ehHP9K8efP08ccfH3X74feUS9LVV1+t7du363/+539i19XX1x/36Zoj/ehHP5IxRlOnTj3qNmNM7L+zsrK0d+/eE+YBR/rhD3+oYDCoqVOnNumT9FW/vvzyS0mKHRU5chtjjJ544gl3i8UpLxgMasiQIZo/f762bNkSu/6f//ynFi5cmMSVtX0c+UiAiooKXXvttbrqqqu0fPly/eEPf9BNN92kfv36feP3PfLII1q8eLEGDhyo0aNHq0+fPtq9e7fWrl2rv/71r9q9e7ckafTo0Xrqqad06623as2aNeratauef/55ZWZmnnBtgwcP1i233KInn3xS5eXluuqqqxSNRrVs2TINHjw4dqa+/v37669//asef/xxFRYWqkePHho4cGD8dw7atJ49e+pXv/qVJkyYoE2bNmnYsGHKzs5WRUWFXnvtNd111136xS9+od69e6tnz576xS9+oW3btiknJ0fz5s076rUfQKJNnTpVCxYs0Pe+9z3dfffdamxs1MyZM9W3b1/9/e9/T/by2q7kvMmmbTr8lsD169eb66+/3mRnZ5sOHTqYsWPHmgMHDsS2k2TGjBlzzIwdO3aYMWPGmKKiIpOammoKCgrMFVdcYZ555pkm223evNlce+21JjMz0+Tl5Zl7773XLFiw4IRvtTXGmMbGRvPYY4+Z3r17m7S0NNO5c2dTWlpq1qxZE9vmk08+MZdddpnJyMgwknjbLY5yuO/V1dVH3TZv3jxz6aWXmqysLJOVlWV69+5txowZYzZs2BDbZv369aakpMS0a9fO5OXlmdGjR5uPPvrISDK/+93vjtoPkCjvvPOO6d+/v0lLSzNnnHGGefrpp4/qHW+1tcsz5mvHRnHSpkyZoqlTp6q6ulp5eXnJXg4AAK0Sr/kA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laitd9fY6q6lNdn6WzImYiXnqyy62zrZeXwK2HqcM0ErMVFLj9+SJAt9a0l3W93wsW/fPknSu/pLkldyhK3JXsAx1CV7AV9j8W/Apn379ik3N9fZvqRW1t0tyV7AMdQmewH+cMp31yZbA9VBSzltXHO66xmX43UzRKNRbd++XdnZ2fK8Y0+ZtbW1KioqUmVlpXJychyv8NTjx/vbGKN9+/apsLBQgYCbZxeb013Jn/enX/nxvqa7kPx5X7eku63uyEcgENDpp5/erG1zcnJ880tpC/x2f7v6V+NhLemu5L/708/8dl/TXRzmt/u6ud3lBacAAMAphg8AAOCUL4ePUCikyZMnKxQKJXsppwTub7u4P93hvraL+9Odtn5ft7oXnAIAgLbNl0c+AACAfzF8AAAApxg+AACAUwwfAADAKYYPAADglC+Hj1mzZql79+5KT0/XwIEDtXLlymQvqc2ZMmWKPM9rcundu3eyl+V7dDfx6G5i0N3EO5W667vh4+WXX9b48eM1efJkrV27Vv369dOQIUO0c+fOZC+tzenbt6+++OKL2OXdd99N9pJ8je66Q3ftorvunCrd9d3w8fjjj2v06NEaNWqU+vTpo6efflqZmZl67rnnkr20NiclJUUFBQWxS15eXrKX5Gt01x26axfddedU6a6vho9Dhw5pzZo1KikpiV0XCARUUlKi5cuXJ3FlbVN5ebkKCwt1xhln6Oabb9aWLa3x89n9ge66RXftobtunSrd9dXwsWvXLkUiEeXn5ze5Pj8/X1VVVUlaVds0cOBAzZkzRwsWLNDs2bNVUVGh733ve9q3b1+yl+ZLdNcdumsX3XXnVOpuSrIXgNaptLQ09t/nnXeeBg4cqG7duumVV17RHXfckcSVAd+M7sKvTqXu+urIR15enoLBoHbs2NHk+h07dqigoCBJqzo1tG/fXmeeeaY2btyY7KX4Et1NHrobH7qbPG25u74aPtLS0tS/f38tWrQodl00GtWiRYt00UUXJXFlbd/+/fv12WefqWvXrsleii/R3eShu/Ghu8nTprtrfOall14yoVDIzJkzx6xfv97cddddpn379qaqqirZS2tTfv7zn5slS5aYiooK87e//c2UlJSYvLw8s3PnzmQvzbforht01z6668ap1F3fvebjxz/+saqrqzVp0iRVVVXp/PPP14IFC456MRTis3XrVt1444368ssv1blzZ1166aVasWKFOnfunOyl+RbddYPu2kd33TiVuusZY0yyFwEAAE4dvnrNBwAA8D+GDwAA4BTDBwAAcIrhAwAAOMXwAQAAnGL4AAAATjF8AAAApxg+AACAUwwfAADAKYYPAADgFMMHAABw6v8DeWnSw3qDLYYAAAAASUVORK5CYII=", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "for X,y in test_ds:\n", " result = model.predict (X)\n", " inverse_result = std_inverse(std,result)\n", " inverse_y = std_inverse(std,y)\n", - " for i in range(1):\n", - " plot_result(inverse_y,inverse_result,i,0)" + " for i in range(32):\n", + " plot_result(inverse_result,inverse_y,i,0)" ] }, { diff --git a/model_v1.ipynb b/model_v1.ipynb deleted file mode 100644 index 6e84e8c..0000000 --- a/model_v1.ipynb +++ /dev/null @@ -1,482 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import h5py\n", - "import numpy as np\n", - "from datetime import datetime\n" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "with h5py.File('./data/TrainingData.h5', 'r') as f:\n", - " # Access the trip dataset and their corresponding timestamps\n", - " traffic_data = f['trip'][()]\n", - " dates = f['timeslot'][()]" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "formatted_dates = []\n", - "\n", - "for date_string in dates:\n", - " formatted_date = datetime.strptime(date_string.decode(), '%Y%m%d%H%M')\n", - "\n", - " year = formatted_date.year\n", - " month = formatted_date.month\n", - " day = formatted_date.day\n", - " hour = formatted_date.hour\n", - " minute = formatted_date.minute\n", - "\n", - " formatted_dates.append(np.array([year, month, day, hour, minute]))\n", - "\n", - "formatted_dates = np.array(formatted_dates).reshape(1488, 5, 1)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "test_size = 240\n", - "\n", - "train_traffic_data = traffic_data[:-test_size]\n", - "test_traffic_data = traffic_data[-test_size:]\n", - "\n", - "train_formatted_dates = formatted_dates[:-test_size]\n", - "test_formatted_dates = formatted_dates[-test_size:]" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "X_train, X_test = train_formatted_dates, test_formatted_dates\n", - "y_train, y_test = train_traffic_data, test_traffic_data" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "import numpy as np\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Join_CountTARGET_FIDBlockIDBikeLane_milesAADTSpeedLimitAvgSpeedPop2019Pop_DensityShape_LengthShape_AreaStationNum
0011NaN32638.666667NaNNaN0.00.0000007840.4902883.787844e+060
1022NaNNaNNaNNaN0.00.0000007840.6864483.787843e+060
23330.80705521234.74193525.015.01049.00.0295947840.8829703.787843e+063
33442.0962215915.12500025.019.01816.00.0302527841.0804773.787844e+063
43550.98432023940.078947NaNNaN1892.00.0226477841.2773273.787843e+063
.......................................
12331241241.9557079050.487805NaNNaN1986.00.0460457840.2809373.787843e+063
12431251251.4404499121.500000NaNNaN1198.00.0397267840.0850723.787843e+063
12521261260.9857048770.901961NaNNaN555.00.0151257839.8905183.787843e+062
12641271270.22859312266.08571425.016.0814.00.0311257839.6966213.787844e+064
12741281281.61994011077.03703725.016.01385.00.0596717839.5019803.787843e+064
\n", - "

128 rows × 12 columns

\n", - "
" - ], - "text/plain": [ - " Join_Count TARGET_FID BlockID BikeLane_miles AADT \\\n", - "0 0 1 1 NaN 32638.666667 \n", - "1 0 2 2 NaN NaN \n", - "2 3 3 3 0.807055 21234.741935 \n", - "3 3 4 4 2.096221 5915.125000 \n", - "4 3 5 5 0.984320 23940.078947 \n", - ".. ... ... ... ... ... \n", - "123 3 124 124 1.955707 9050.487805 \n", - "124 3 125 125 1.440449 9121.500000 \n", - "125 2 126 126 0.985704 8770.901961 \n", - "126 4 127 127 0.228593 12266.085714 \n", - "127 4 128 128 1.619940 11077.037037 \n", - "\n", - " SpeedLimit AvgSpeed Pop2019 Pop_Density Shape_Length Shape_Area \\\n", - "0 NaN NaN 0.0 0.000000 7840.490288 3.787844e+06 \n", - "1 NaN NaN 0.0 0.000000 7840.686448 3.787843e+06 \n", - "2 25.0 15.0 1049.0 0.029594 7840.882970 3.787843e+06 \n", - "3 25.0 19.0 1816.0 0.030252 7841.080477 3.787844e+06 \n", - "4 NaN NaN 1892.0 0.022647 7841.277327 3.787843e+06 \n", - ".. ... ... ... ... ... ... \n", - "123 NaN NaN 1986.0 0.046045 7840.280937 3.787843e+06 \n", - "124 NaN NaN 1198.0 0.039726 7840.085072 3.787843e+06 \n", - "125 NaN NaN 555.0 0.015125 7839.890518 3.787843e+06 \n", - "126 25.0 16.0 814.0 0.031125 7839.696621 3.787844e+06 \n", - "127 25.0 16.0 1385.0 0.059671 7839.501980 3.787843e+06 \n", - "\n", - " StationNum \n", - "0 0 \n", - "1 0 \n", - "2 3 \n", - "3 3 \n", - "4 3 \n", - ".. ... \n", - "123 3 \n", - "124 3 \n", - "125 2 \n", - "126 4 \n", - "127 4 \n", - "\n", - "[128 rows x 12 columns]" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "spatio_data_file = \"./data/SpatialFeatures.csv\"\n", - "raw_spatio_feature = pd.read_csv(spatio_data_file)\n", - "raw_spatio_feature" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [], - "source": [ - "bikeLane_matrix = raw_spatio_feature[\"BikeLane_miles\"]\n", - "bikeLane_matrix = bikeLane_matrix.fillna(0).to_numpy()\n", - "bikeLane_matrix = bikeLane_matrix/bikeLane_matrix.max()\n", - "bikeLane_matrix_board = bikeLane_matrix[np.newaxis,:] * np.ones((1248,1))" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [], - "source": [ - "import keras\n", - "from keras import layers\n", - "from keras import models\n", - "\n", - "spatio_feature = None\n", - "\n", - "input_shape = (5,1)\n", - "\n", - "static_features = 128\n", - "\n", - "left_inputs = layers.Input(shape = input_shape)\n", - "\n", - "static_input = layers.Input(shape = static_features,)\n", - "\n", - "x = layers.LSTM(50, activation = \"tanh\")(left_inputs)\n", - "\n", - "# x = layers.Dense(128,activation= \"relu\")(x)\n", - "\n", - "\n", - "x = layers.concatenate([x,static_input])\n", - "\n", - "x = layers.Dense(2*16*8, activation = \"relu\")(x)\n", - "\n", - "output = layers.Reshape((2,16,8))(x)\n", - "\n", - "model = models.Model([left_inputs,static_input],outputs = output)\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Epoch 1/50\n", - " 1/39 [..............................] - ETA: 23s - loss: 131.9053" - ] - }, - { - "ename": "ValueError", - "evalue": "in user code:\n\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1972, in test_function *\n return step_function(self, iterator)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1956, in step_function **\n outputs = model.distribute_strategy.run(run_step, args=(data,))\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1944, in run_step **\n outputs = model.test_step(data)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1850, in test_step\n y_pred = self(x, training=False)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\utils\\traceback_utils.py\", line 70, in error_handler\n raise e.with_traceback(filtered_tb) from None\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\input_spec.py\", line 219, in assert_input_compatibility\n raise ValueError(\n\n ValueError: Layer \"model_6\" expects 2 input(s), but it received 1 input tensors. Inputs received: []\n", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[47], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m model\u001b[38;5;241m.\u001b[39mcompile(optimizer\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124madam\u001b[39m\u001b[38;5;124m'\u001b[39m, loss\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmse\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m----> 2\u001b[0m \u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43mX_train\u001b[49m\u001b[43m,\u001b[49m\u001b[43mbikeLane_matrix_board\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43my_train\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mepochs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m50\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbatch_size\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m32\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mvalidation_data\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43mX_test\u001b[49m\u001b[43m,\u001b[49m\u001b[43mbikeLane_matrix_board\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43my_test\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32md:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\utils\\traceback_utils.py:70\u001b[0m, in \u001b[0;36mfilter_traceback..error_handler\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 67\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m _process_traceback_frames(e\u001b[38;5;241m.\u001b[39m__traceback__)\n\u001b[0;32m 68\u001b[0m \u001b[38;5;66;03m# To get the full stack trace, call:\u001b[39;00m\n\u001b[0;32m 69\u001b[0m \u001b[38;5;66;03m# `tf.debugging.disable_traceback_filtering()`\u001b[39;00m\n\u001b[1;32m---> 70\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\u001b[38;5;241m.\u001b[39mwith_traceback(filtered_tb) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 71\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[0;32m 72\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m filtered_tb\n", - "File \u001b[1;32m~\\AppData\\Local\\Temp\\__autograph_generated_file8nzlr_ef.py:15\u001b[0m, in \u001b[0;36mouter_factory..inner_factory..tf__test_function\u001b[1;34m(iterator)\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m 14\u001b[0m do_return \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m---> 15\u001b[0m retval_ \u001b[38;5;241m=\u001b[39m ag__\u001b[38;5;241m.\u001b[39mconverted_call(ag__\u001b[38;5;241m.\u001b[39mld(step_function), (ag__\u001b[38;5;241m.\u001b[39mld(\u001b[38;5;28mself\u001b[39m), ag__\u001b[38;5;241m.\u001b[39mld(iterator)), \u001b[38;5;28;01mNone\u001b[39;00m, fscope)\n\u001b[0;32m 16\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m:\n\u001b[0;32m 17\u001b[0m do_return \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n", - "\u001b[1;31mValueError\u001b[0m: in user code:\n\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1972, in test_function *\n return step_function(self, iterator)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1956, in step_function **\n outputs = model.distribute_strategy.run(run_step, args=(data,))\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1944, in run_step **\n outputs = model.test_step(data)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1850, in test_step\n y_pred = self(x, training=False)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\utils\\traceback_utils.py\", line 70, in error_handler\n raise e.with_traceback(filtered_tb) from None\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\input_spec.py\", line 219, in assert_input_compatibility\n raise ValueError(\n\n ValueError: Layer \"model_6\" expects 2 input(s), but it received 1 input tensors. Inputs received: []\n" - ] - } - ], - "source": [ - "model.compile(optimizer='adam', loss='mse')\n", - "model.fit([X_train,bikeLane_matrix_board], y_train, epochs=50, batch_size=32, validation_data=([X_test,bikeLane_matrix_board], y_test))" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "8/8 [==============================] - 0s 714us/step - loss: 50.3341\n", - "Root Mean Squared Error: 7.094656058773051\n" - ] - } - ], - "source": [ - "mse = model.evaluate(X_test, y_test)\n", - "\n", - "# Show rmse to see how model performs on the test set\n", - "rmse = np.sqrt(mse)\n", - "print(f'Root Mean Squared Error: {rmse}')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py38", - "language": "python", - "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.8.18" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/model_v2.ipynb b/model_v2.ipynb deleted file mode 100644 index 6c61c70..0000000 --- a/model_v2.ipynb +++ /dev/null @@ -1,533 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import h5py\n", - "import numpy as np\n", - "from datetime import datetime\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "with h5py.File('./data/TrainingData.h5', 'r') as f:\n", - " # Access the trip dataset and their corresponding timestamps\n", - " traffic_data = f['trip'][()]\n", - " dates = f['timeslot'][()]" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "formatted_dates = []\n", - "\n", - "for date_string in dates:\n", - " formatted_date = datetime.strptime(date_string.decode(), '%Y%m%d%H%M')\n", - "\n", - " year = formatted_date.year\n", - " month = formatted_date.month\n", - " day = formatted_date.day\n", - " hour = formatted_date.hour\n", - " minute = formatted_date.minute\n", - "\n", - " formatted_dates.append(np.array([year, month, day, hour, minute]))\n", - "\n", - "formatted_dates = np.array(formatted_dates).reshape(1488, 5, 1)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "test_size = 240\n", - "\n", - "train_traffic_data = traffic_data[:-test_size]\n", - "test_traffic_data = traffic_data[-test_size:]\n", - "\n", - "train_formatted_dates = formatted_dates[:-test_size]\n", - "test_formatted_dates = formatted_dates[-test_size:]" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [], - "source": [ - "X_train, X_test = train_formatted_dates, test_formatted_dates\n", - "y_train, y_test = train_traffic_data, test_traffic_data" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "import numpy as np\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Join_CountTARGET_FIDBlockIDBikeLane_milesAADTSpeedLimitAvgSpeedPop2019Pop_DensityShape_LengthShape_AreaStationNum
0011NaN32638.666667NaNNaN0.00.0000007840.4902883.787844e+060
1022NaNNaNNaNNaN0.00.0000007840.6864483.787843e+060
23330.80705521234.74193525.015.01049.00.0295947840.8829703.787843e+063
33442.0962215915.12500025.019.01816.00.0302527841.0804773.787844e+063
43550.98432023940.078947NaNNaN1892.00.0226477841.2773273.787843e+063
.......................................
12331241241.9557079050.487805NaNNaN1986.00.0460457840.2809373.787843e+063
12431251251.4404499121.500000NaNNaN1198.00.0397267840.0850723.787843e+063
12521261260.9857048770.901961NaNNaN555.00.0151257839.8905183.787843e+062
12641271270.22859312266.08571425.016.0814.00.0311257839.6966213.787844e+064
12741281281.61994011077.03703725.016.01385.00.0596717839.5019803.787843e+064
\n", - "

128 rows × 12 columns

\n", - "
" - ], - "text/plain": [ - " Join_Count TARGET_FID BlockID BikeLane_miles AADT \\\n", - "0 0 1 1 NaN 32638.666667 \n", - "1 0 2 2 NaN NaN \n", - "2 3 3 3 0.807055 21234.741935 \n", - "3 3 4 4 2.096221 5915.125000 \n", - "4 3 5 5 0.984320 23940.078947 \n", - ".. ... ... ... ... ... \n", - "123 3 124 124 1.955707 9050.487805 \n", - "124 3 125 125 1.440449 9121.500000 \n", - "125 2 126 126 0.985704 8770.901961 \n", - "126 4 127 127 0.228593 12266.085714 \n", - "127 4 128 128 1.619940 11077.037037 \n", - "\n", - " SpeedLimit AvgSpeed Pop2019 Pop_Density Shape_Length Shape_Area \\\n", - "0 NaN NaN 0.0 0.000000 7840.490288 3.787844e+06 \n", - "1 NaN NaN 0.0 0.000000 7840.686448 3.787843e+06 \n", - "2 25.0 15.0 1049.0 0.029594 7840.882970 3.787843e+06 \n", - "3 25.0 19.0 1816.0 0.030252 7841.080477 3.787844e+06 \n", - "4 NaN NaN 1892.0 0.022647 7841.277327 3.787843e+06 \n", - ".. ... ... ... ... ... ... \n", - "123 NaN NaN 1986.0 0.046045 7840.280937 3.787843e+06 \n", - "124 NaN NaN 1198.0 0.039726 7840.085072 3.787843e+06 \n", - "125 NaN NaN 555.0 0.015125 7839.890518 3.787843e+06 \n", - "126 25.0 16.0 814.0 0.031125 7839.696621 3.787844e+06 \n", - "127 25.0 16.0 1385.0 0.059671 7839.501980 3.787843e+06 \n", - "\n", - " StationNum \n", - "0 0 \n", - "1 0 \n", - "2 3 \n", - "3 3 \n", - "4 3 \n", - ".. ... \n", - "123 3 \n", - "124 3 \n", - "125 2 \n", - "126 4 \n", - "127 4 \n", - "\n", - "[128 rows x 12 columns]" - ] - }, - "execution_count": 48, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "spatio_data_file = \"./data/SpatialFeatures.csv\"\n", - "raw_spatio_feature = pd.read_csv(spatio_data_file)\n", - "raw_spatio_feature" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [], - "source": [ - "bikeLane_matrix = raw_spatio_feature[\"BikeLane_miles\"]\n", - "bikeLane_matrix = bikeLane_matrix.fillna(0).to_numpy()\n", - "bikeLane_matrix = bikeLane_matrix/bikeLane_matrix.max()\n", - "bikeLane_matrix_board = bikeLane_matrix[np.newaxis,:] * np.ones((1248,1))" - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "metadata": {}, - "outputs": [ - { - "ename": "ValueError", - "evalue": "Graph disconnected: cannot obtain value for tensor KerasTensor(type_spec=TensorSpec(shape=(None, 128), dtype=tf.float32, name='input_31'), name='input_31', description=\"created by layer 'input_31'\") at layer \"concatenate_16\". The following previous layers were accessed without issue: ['lstm_25', 'dense_23']", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[60], line 24\u001b[0m\n\u001b[0;32m 20\u001b[0m x \u001b[38;5;241m=\u001b[39m layers\u001b[38;5;241m.\u001b[39mDense(\u001b[38;5;241m2\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m16\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m8\u001b[39m,activation\u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrelu\u001b[39m\u001b[38;5;124m\"\u001b[39m) (x)\n\u001b[0;32m 22\u001b[0m output \u001b[38;5;241m=\u001b[39m layers\u001b[38;5;241m.\u001b[39mReshape((\u001b[38;5;241m2\u001b[39m,\u001b[38;5;241m16\u001b[39m,\u001b[38;5;241m8\u001b[39m))(x)\n\u001b[1;32m---> 24\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[43mmodels\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mModel\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43mleft_inputs\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43moutputs\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[43moutput\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32md:\\Anoconda\\envs\\py38\\lib\\site-packages\\tensorflow\\python\\trackable\\base.py:204\u001b[0m, in \u001b[0;36mno_automatic_dependency_tracking.._method_wrapper\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 202\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_self_setattr_tracking \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m \u001b[38;5;66;03m# pylint: disable=protected-access\u001b[39;00m\n\u001b[0;32m 203\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 204\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mmethod\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 205\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[0;32m 206\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_self_setattr_tracking \u001b[38;5;241m=\u001b[39m previous_value \u001b[38;5;66;03m# pylint: disable=protected-access\u001b[39;00m\n", - "File \u001b[1;32md:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\functional.py:167\u001b[0m, in \u001b[0;36mFunctional.__init__\u001b[1;34m(self, inputs, outputs, name, trainable, **kwargs)\u001b[0m\n\u001b[0;32m 158\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mall\u001b[39m(\n\u001b[0;32m 159\u001b[0m [\n\u001b[0;32m 160\u001b[0m functional_utils\u001b[38;5;241m.\u001b[39mis_input_keras_tensor(t)\n\u001b[0;32m 161\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m t \u001b[38;5;129;01min\u001b[39;00m tf\u001b[38;5;241m.\u001b[39mnest\u001b[38;5;241m.\u001b[39mflatten(inputs)\n\u001b[0;32m 162\u001b[0m ]\n\u001b[0;32m 163\u001b[0m ):\n\u001b[0;32m 164\u001b[0m inputs, outputs \u001b[38;5;241m=\u001b[39m functional_utils\u001b[38;5;241m.\u001b[39mclone_graph_nodes(\n\u001b[0;32m 165\u001b[0m inputs, outputs\n\u001b[0;32m 166\u001b[0m )\n\u001b[1;32m--> 167\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_init_graph_network\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43moutputs\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32md:\\Anoconda\\envs\\py38\\lib\\site-packages\\tensorflow\\python\\trackable\\base.py:204\u001b[0m, in \u001b[0;36mno_automatic_dependency_tracking.._method_wrapper\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 202\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_self_setattr_tracking \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m \u001b[38;5;66;03m# pylint: disable=protected-access\u001b[39;00m\n\u001b[0;32m 203\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 204\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mmethod\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 205\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[0;32m 206\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_self_setattr_tracking \u001b[38;5;241m=\u001b[39m previous_value \u001b[38;5;66;03m# pylint: disable=protected-access\u001b[39;00m\n", - "File \u001b[1;32md:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\functional.py:266\u001b[0m, in \u001b[0;36mFunctional._init_graph_network\u001b[1;34m(self, inputs, outputs)\u001b[0m\n\u001b[0;32m 263\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_input_coordinates\u001b[38;5;241m.\u001b[39mappend((layer, node_index, tensor_index))\n\u001b[0;32m 265\u001b[0m \u001b[38;5;66;03m# Keep track of the network's nodes and layers.\u001b[39;00m\n\u001b[1;32m--> 266\u001b[0m nodes, nodes_by_depth, layers, _ \u001b[38;5;241m=\u001b[39m \u001b[43m_map_graph_network\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 267\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43moutputs\u001b[49m\n\u001b[0;32m 268\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 269\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_network_nodes \u001b[38;5;241m=\u001b[39m nodes\n\u001b[0;32m 270\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_nodes_by_depth \u001b[38;5;241m=\u001b[39m nodes_by_depth\n", - "File \u001b[1;32md:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\functional.py:1142\u001b[0m, in \u001b[0;36m_map_graph_network\u001b[1;34m(inputs, outputs)\u001b[0m\n\u001b[0;32m 1140\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m x \u001b[38;5;129;01min\u001b[39;00m tf\u001b[38;5;241m.\u001b[39mnest\u001b[38;5;241m.\u001b[39mflatten(node\u001b[38;5;241m.\u001b[39mkeras_inputs):\n\u001b[0;32m 1141\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mid\u001b[39m(x) \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m computable_tensors:\n\u001b[1;32m-> 1142\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m 1143\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mGraph disconnected: cannot obtain value for \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1144\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtensor \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mx\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m at layer \u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mlayer\u001b[38;5;241m.\u001b[39mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m. \u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[0;32m 1145\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThe following previous layers were accessed \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1146\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwithout issue: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mlayers_with_complete_input\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1147\u001b[0m )\n\u001b[0;32m 1148\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m x \u001b[38;5;129;01min\u001b[39;00m tf\u001b[38;5;241m.\u001b[39mnest\u001b[38;5;241m.\u001b[39mflatten(node\u001b[38;5;241m.\u001b[39moutputs):\n\u001b[0;32m 1149\u001b[0m computable_tensors\u001b[38;5;241m.\u001b[39madd(\u001b[38;5;28mid\u001b[39m(x))\n", - "\u001b[1;31mValueError\u001b[0m: Graph disconnected: cannot obtain value for tensor KerasTensor(type_spec=TensorSpec(shape=(None, 128), dtype=tf.float32, name='input_31'), name='input_31', description=\"created by layer 'input_31'\") at layer \"concatenate_16\". The following previous layers were accessed without issue: ['lstm_25', 'dense_23']" - ] - } - ], - "source": [ - "import keras\n", - "from keras import layers\n", - "from keras import models\n", - "\n", - "spatio_feature = None\n", - "\n", - "input_shape = (5,1)\n", - "\n", - "left_inputs = layers.Input(shape = (input_shape))\n", - "\n", - "right_inputs = layers.Input(shape = (128))\n", - "\n", - "x = layers.LSTM(128, activation = \"tanh\")(left_inputs)\n", - "\n", - "x = layers.Dense(2*16*8, activation = \"linear\")(x)\n", - "\n", - "\n", - "x = layers.concatenate([x,right_inputs])\n", - "\n", - "x = layers.Dense(2*16*8,activation= \"relu\") (x)\n", - "\n", - "output = layers.Reshape((2,16,8))(x)\n", - "\n", - "model = models.Model([left_inputs],outputs = output)\n", - "\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Model: \"model_7\"\n", - "_________________________________________________________________\n", - " Layer (type) Output Shape Param # \n", - "=================================================================\n", - " input_24 (InputLayer) [(None, 5, 1)] 0 \n", - " \n", - " lstm_22 (LSTM) (None, 128) 66560 \n", - " \n", - " dense_17 (Dense) (None, 256) 33024 \n", - " \n", - " concatenate_13 (Concatenat (2, 384) 0 \n", - " e) \n", - " \n", - " dense_18 (Dense) (2, 256) 98560 \n", - " \n", - " reshape_8 (Reshape) (2, 2, 16, 8) 0 \n", - " \n", - "=================================================================\n", - "Total params: 198144 (774.00 KB)\n", - "Trainable params: 198144 (774.00 KB)\n", - "Non-trainable params: 0 (0.00 Byte)\n", - "_________________________________________________________________\n" - ] - } - ], - "source": [ - "model.summary()" - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Epoch 1/50\n" - ] - }, - { - "ename": "ValueError", - "evalue": "in user code:\n\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1338, in train_function *\n return step_function(self, iterator)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1322, in step_function **\n outputs = model.distribute_strategy.run(run_step, args=(data,))\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1303, in run_step **\n outputs = model.train_step(data)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1080, in train_step\n y_pred = self(x, training=True)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\utils\\traceback_utils.py\", line 70, in error_handler\n raise e.with_traceback(filtered_tb) from None\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\backend.py\", line 3582, in concatenate\n return tf.concat([to_dense(x) for x in tensors], axis)\n\n ValueError: Exception encountered when calling layer 'concatenate_13' (type Concatenate).\n \n Dimension 0 in both shapes must be equal, but are 32 and 2. Shapes are [32] and [2]. for '{{node model_7/concatenate_13/concat}} = ConcatV2[N=2, T=DT_FLOAT, Tidx=DT_INT32](model_7/dense_17/BiasAdd, model_7/concatenate_13/Cast, model_7/concatenate_13/concat/axis)' with input shapes: [32,256], [2,128], [] and with computed input tensors: input[2] = <1>.\n \n Call arguments received by layer 'concatenate_13' (type Concatenate):\n • inputs=['tf.Tensor(shape=(32, 256), dtype=float32)', 'tf.Tensor(shape=(2, 128), dtype=float32)']\n", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[55], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m model\u001b[38;5;241m.\u001b[39mcompile(optimizer\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124madam\u001b[39m\u001b[38;5;124m'\u001b[39m, loss\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmse\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m----> 2\u001b[0m \u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43mX_train\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43my_train\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mepochs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m50\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbatch_size\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m32\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mvalidation_data\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43mX_test\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43my_test\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32md:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\utils\\traceback_utils.py:70\u001b[0m, in \u001b[0;36mfilter_traceback..error_handler\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 67\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m _process_traceback_frames(e\u001b[38;5;241m.\u001b[39m__traceback__)\n\u001b[0;32m 68\u001b[0m \u001b[38;5;66;03m# To get the full stack trace, call:\u001b[39;00m\n\u001b[0;32m 69\u001b[0m \u001b[38;5;66;03m# `tf.debugging.disable_traceback_filtering()`\u001b[39;00m\n\u001b[1;32m---> 70\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\u001b[38;5;241m.\u001b[39mwith_traceback(filtered_tb) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 71\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[0;32m 72\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m filtered_tb\n", - "File \u001b[1;32m~\\AppData\\Local\\Temp\\__autograph_generated_fileootg_h1c.py:15\u001b[0m, in \u001b[0;36mouter_factory..inner_factory..tf__train_function\u001b[1;34m(iterator)\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m 14\u001b[0m do_return \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m---> 15\u001b[0m retval_ \u001b[38;5;241m=\u001b[39m ag__\u001b[38;5;241m.\u001b[39mconverted_call(ag__\u001b[38;5;241m.\u001b[39mld(step_function), (ag__\u001b[38;5;241m.\u001b[39mld(\u001b[38;5;28mself\u001b[39m), ag__\u001b[38;5;241m.\u001b[39mld(iterator)), \u001b[38;5;28;01mNone\u001b[39;00m, fscope)\n\u001b[0;32m 16\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m:\n\u001b[0;32m 17\u001b[0m do_return \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n", - "\u001b[1;31mValueError\u001b[0m: in user code:\n\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1338, in train_function *\n return step_function(self, iterator)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1322, in step_function **\n outputs = model.distribute_strategy.run(run_step, args=(data,))\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1303, in run_step **\n outputs = model.train_step(data)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\engine\\training.py\", line 1080, in train_step\n y_pred = self(x, training=True)\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\utils\\traceback_utils.py\", line 70, in error_handler\n raise e.with_traceback(filtered_tb) from None\n File \"d:\\Anoconda\\envs\\py38\\lib\\site-packages\\keras\\src\\backend.py\", line 3582, in concatenate\n return tf.concat([to_dense(x) for x in tensors], axis)\n\n ValueError: Exception encountered when calling layer 'concatenate_13' (type Concatenate).\n \n Dimension 0 in both shapes must be equal, but are 32 and 2. Shapes are [32] and [2]. for '{{node model_7/concatenate_13/concat}} = ConcatV2[N=2, T=DT_FLOAT, Tidx=DT_INT32](model_7/dense_17/BiasAdd, model_7/concatenate_13/Cast, model_7/concatenate_13/concat/axis)' with input shapes: [32,256], [2,128], [] and with computed input tensors: input[2] = <1>.\n \n Call arguments received by layer 'concatenate_13' (type Concatenate):\n • inputs=['tf.Tensor(shape=(32, 256), dtype=float32)', 'tf.Tensor(shape=(2, 128), dtype=float32)']\n" - ] - } - ], - "source": [ - "model.compile(optimizer='adam', loss='mse')\n", - "model.fit([X_train], y_train, epochs=50, batch_size=32, validation_data=([X_test], y_test))" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "8/8 [==============================] - 0s 1ms/step - loss: 56.9645\n", - "Root Mean Squared Error: 7.5474830524649805\n" - ] - } - ], - "source": [ - "mse = model.evaluate(X_test, y_test)\n", - "\n", - "# Show rmse to see how model performs on the test set\n", - "rmse = np.sqrt(mse)\n", - "print(f'Root Mean Squared Error: {rmse}')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py38", - "language": "python", - "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.8.18" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/model_v3_yshape.ipynb b/model_v3_yshape.ipynb deleted file mode 100644 index e901e48..0000000 --- a/model_v3_yshape.ipynb +++ /dev/null @@ -1,628 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import h5py\n", - "import numpy as np\n", - "from datetime import datetime\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "with h5py.File('./data/TrainingData.h5', 'r') as f:\n", - " # Access the trip dataset and their corresponding timestamps\n", - " traffic_data = f['trip'][()]\n", - " dates = f['timeslot'][()]" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "formatted_dates = []\n", - "\n", - "for date_string in dates:\n", - " formatted_date = datetime.strptime(date_string.decode(), '%Y%m%d%H%M')\n", - "\n", - " year = formatted_date.year\n", - " month = formatted_date.month\n", - " day = formatted_date.day\n", - " hour = formatted_date.hour\n", - " minute = formatted_date.minute\n", - "\n", - " formatted_dates.append(np.array([year, month, day, hour, minute]))\n", - "\n", - "formatted_dates = np.array(formatted_dates).reshape(1488, 5, 1)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "test_size = 240\n", - "\n", - "train_traffic_data = traffic_data[:-test_size]\n", - "test_traffic_data = traffic_data[-test_size:]\n", - "\n", - "train_formatted_dates = formatted_dates[:-test_size]\n", - "test_formatted_dates = formatted_dates[-test_size:]" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "X_train, X_test = train_formatted_dates, test_formatted_dates\n", - "y_train, y_test = train_traffic_data, test_traffic_data" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "import numpy as np\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Join_CountTARGET_FIDBlockIDBikeLane_milesAADTSpeedLimitAvgSpeedPop2019Pop_DensityShape_LengthShape_AreaStationNum
0011NaN32638.666667NaNNaN0.00.0000007840.4902883.787844e+060
1022NaNNaNNaNNaN0.00.0000007840.6864483.787843e+060
23330.80705521234.74193525.015.01049.00.0295947840.8829703.787843e+063
33442.0962215915.12500025.019.01816.00.0302527841.0804773.787844e+063
43550.98432023940.078947NaNNaN1892.00.0226477841.2773273.787843e+063
.......................................
12331241241.9557079050.487805NaNNaN1986.00.0460457840.2809373.787843e+063
12431251251.4404499121.500000NaNNaN1198.00.0397267840.0850723.787843e+063
12521261260.9857048770.901961NaNNaN555.00.0151257839.8905183.787843e+062
12641271270.22859312266.08571425.016.0814.00.0311257839.6966213.787844e+064
12741281281.61994011077.03703725.016.01385.00.0596717839.5019803.787843e+064
\n", - "

128 rows × 12 columns

\n", - "
" - ], - "text/plain": [ - " Join_Count TARGET_FID BlockID BikeLane_miles AADT \\\n", - "0 0 1 1 NaN 32638.666667 \n", - "1 0 2 2 NaN NaN \n", - "2 3 3 3 0.807055 21234.741935 \n", - "3 3 4 4 2.096221 5915.125000 \n", - "4 3 5 5 0.984320 23940.078947 \n", - ".. ... ... ... ... ... \n", - "123 3 124 124 1.955707 9050.487805 \n", - "124 3 125 125 1.440449 9121.500000 \n", - "125 2 126 126 0.985704 8770.901961 \n", - "126 4 127 127 0.228593 12266.085714 \n", - "127 4 128 128 1.619940 11077.037037 \n", - "\n", - " SpeedLimit AvgSpeed Pop2019 Pop_Density Shape_Length Shape_Area \\\n", - "0 NaN NaN 0.0 0.000000 7840.490288 3.787844e+06 \n", - "1 NaN NaN 0.0 0.000000 7840.686448 3.787843e+06 \n", - "2 25.0 15.0 1049.0 0.029594 7840.882970 3.787843e+06 \n", - "3 25.0 19.0 1816.0 0.030252 7841.080477 3.787844e+06 \n", - "4 NaN NaN 1892.0 0.022647 7841.277327 3.787843e+06 \n", - ".. ... ... ... ... ... ... \n", - "123 NaN NaN 1986.0 0.046045 7840.280937 3.787843e+06 \n", - "124 NaN NaN 1198.0 0.039726 7840.085072 3.787843e+06 \n", - "125 NaN NaN 555.0 0.015125 7839.890518 3.787843e+06 \n", - "126 25.0 16.0 814.0 0.031125 7839.696621 3.787844e+06 \n", - "127 25.0 16.0 1385.0 0.059671 7839.501980 3.787843e+06 \n", - "\n", - " StationNum \n", - "0 0 \n", - "1 0 \n", - "2 3 \n", - "3 3 \n", - "4 3 \n", - ".. ... \n", - "123 3 \n", - "124 3 \n", - "125 2 \n", - "126 4 \n", - "127 4 \n", - "\n", - "[128 rows x 12 columns]" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "spatio_data_file = \"./data/SpatialFeatures.csv\"\n", - "raw_spatio_feature = pd.read_csv(spatio_data_file)\n", - "raw_spatio_feature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "bikeLane_matrix = raw_spatio_feature[\"BikeLane_miles\"]\n", - "bikeLane_matrix = bikeLane_matrix.fillna(0).to_numpy()\n", - "bikeLane_matrix = bikeLane_matrix/bikeLane_matrix.max()\n", - "bikeLane_matrix_board = bikeLane_matrix[np.newaxis,:] * np.ones((1248,1))" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "import keras\n", - "from keras import layers\n", - "from keras import models\n", - "\n", - "spatio_feature = None\n", - "\n", - "input_shape = (5,1)\n", - "\n", - "left_inputs = layers.Input(shape = (input_shape))\n", - "\n", - "x = layers.LSTM(128, activation = \"tanh\")(left_inputs)\n", - "\n", - "x = layers.Dense(2*16*8, activation = \"linear\")(x)\n", - "\n", - "right_inputs = layers.Input(shape = (input_shape))\n", - "\n", - "y = layers.LSTM(128,activation= \"tanh\")(right_inputs)\n", - "\n", - "y = layers.Dense(2*16*8,activation= \"relu\")(y)\n", - "\n", - "x = layers.concatenate([x,y])\n", - "\n", - "x = layers.Dense(2*16*8,activation= \"relu\") (x)\n", - "\n", - "output = layers.Reshape((2,16,8))(x)\n", - "\n", - "model = models.Model([left_inputs,right_inputs],outputs = output)\n", - "\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Model: \"model_2\"\n", - "__________________________________________________________________________________________________\n", - " Layer (type) Output Shape Param # Connected to \n", - "==================================================================================================\n", - " input_5 (InputLayer) [(None, 5, 1)] 0 [] \n", - " \n", - " input_6 (InputLayer) [(None, 5, 1)] 0 [] \n", - " \n", - " lstm_4 (LSTM) (None, 128) 66560 ['input_5[0][0]'] \n", - " \n", - " lstm_5 (LSTM) (None, 128) 66560 ['input_6[0][0]'] \n", - " \n", - " dense_6 (Dense) (None, 256) 33024 ['lstm_4[0][0]'] \n", - " \n", - " dense_7 (Dense) (None, 256) 33024 ['lstm_5[0][0]'] \n", - " \n", - " concatenate_2 (Concatenate (None, 512) 0 ['dense_6[0][0]', \n", - " ) 'dense_7[0][0]'] \n", - " \n", - " dense_8 (Dense) (None, 256) 131328 ['concatenate_2[0][0]'] \n", - " \n", - " reshape_2 (Reshape) (None, 2, 16, 8) 0 ['dense_8[0][0]'] \n", - " \n", - "==================================================================================================\n", - "Total params: 330496 (1.26 MB)\n", - "Trainable params: 330496 (1.26 MB)\n", - "Non-trainable params: 0 (0.00 Byte)\n", - "__________________________________________________________________________________________________\n" - ] - } - ], - "source": [ - "model.summary()" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Epoch 1/50\n", - "39/39 [==============================] - 2s 15ms/step - loss: 54.8777 - val_loss: 51.2985\n", - "Epoch 2/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 55.1405 - val_loss: 54.7360\n", - "Epoch 3/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 55.2071 - val_loss: 52.4979\n", - "Epoch 4/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 53.2430 - val_loss: 64.0301\n", - "Epoch 5/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 53.3346 - val_loss: 49.7368\n", - "Epoch 6/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 53.5821 - val_loss: 53.5882\n", - "Epoch 7/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 54.0866 - val_loss: 57.8746\n", - "Epoch 8/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 55.6869 - val_loss: 64.1826\n", - "Epoch 9/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 53.7663 - val_loss: 61.7465\n", - "Epoch 10/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 54.7494 - val_loss: 65.6936\n", - "Epoch 11/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 53.1544 - val_loss: 52.5802\n", - "Epoch 12/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 55.2133 - val_loss: 56.6710\n", - "Epoch 13/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 54.6228 - val_loss: 55.5211\n", - "Epoch 14/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 52.1401 - val_loss: 58.5715\n", - "Epoch 15/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 52.5612 - val_loss: 58.7202\n", - "Epoch 16/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 53.4948 - val_loss: 59.2302\n", - "Epoch 17/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 52.5986 - val_loss: 48.9652\n", - "Epoch 18/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 51.9470 - val_loss: 64.2186\n", - "Epoch 19/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 55.1345 - val_loss: 53.9188\n", - "Epoch 20/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 52.8832 - val_loss: 66.7527\n", - "Epoch 21/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 53.5199 - val_loss: 48.4578\n", - "Epoch 22/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 53.8766 - val_loss: 51.3250\n", - "Epoch 23/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 50.4563 - val_loss: 60.5626\n", - "Epoch 24/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 51.8139 - val_loss: 52.1807\n", - "Epoch 25/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 49.4824 - val_loss: 60.1553\n", - "Epoch 26/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 49.2602 - val_loss: 60.9033\n", - "Epoch 27/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 51.0772 - val_loss: 58.1736\n", - "Epoch 28/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 49.2613 - val_loss: 58.5493\n", - "Epoch 29/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 49.6795 - val_loss: 65.7093\n", - "Epoch 30/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 50.2725 - val_loss: 58.2873\n", - "Epoch 31/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 52.4984 - val_loss: 65.8380\n", - "Epoch 32/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 52.5961 - val_loss: 63.5864\n", - "Epoch 33/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 49.4923 - val_loss: 51.8561\n", - "Epoch 34/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 51.5506 - val_loss: 60.6100\n", - "Epoch 35/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 48.5454 - val_loss: 70.8238\n", - "Epoch 36/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 49.0989 - val_loss: 67.8033\n", - "Epoch 37/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 48.3473 - val_loss: 50.0989\n", - "Epoch 38/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 48.2508 - val_loss: 54.6217\n", - "Epoch 39/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 48.6460 - val_loss: 65.7264\n", - "Epoch 40/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 48.6715 - val_loss: 66.6947\n", - "Epoch 41/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 49.4361 - val_loss: 50.9359\n", - "Epoch 42/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 47.1807 - val_loss: 55.0176\n", - "Epoch 43/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 51.3290 - val_loss: 45.2042\n", - "Epoch 44/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 48.1886 - val_loss: 48.6589\n", - "Epoch 45/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 47.7480 - val_loss: 54.7440\n", - "Epoch 46/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 47.5081 - val_loss: 56.8295\n", - "Epoch 47/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 46.0584 - val_loss: 50.8201\n", - "Epoch 48/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 45.7069 - val_loss: 52.5394\n", - "Epoch 49/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 46.6425 - val_loss: 52.1247\n", - "Epoch 50/50\n", - "39/39 [==============================] - 0s 4ms/step - loss: 47.2073 - val_loss: 51.9383\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "model.compile(optimizer='adam', loss='mse')\n", - "model.fit([X_train,X_train], y_train, epochs=50, batch_size=32, validation_data=([X_test,X_test], y_test))" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "8/8 [==============================] - 0s 1ms/step - loss: 51.9383\n", - "Root Mean Squared Error: 7.206825348515386\n" - ] - } - ], - "source": [ - "mse = model.evaluate([X_test,X_test], y_test)\n", - "\n", - "# Show rmse to see how model performs on the test set\n", - "rmse = np.sqrt(mse)\n", - "print(f'Root Mean Squared Error: {rmse}')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py38", - "language": "python", - "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.8.18" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/playground.ipynb b/playground.ipynb new file mode 100644 index 0000000..133847e --- /dev/null +++ b/playground.ipynb @@ -0,0 +1,71 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:tensorflow:From C:\\Users\\yy\\AppData\\Local\\Temp\\ipykernel_54852\\680963630.py:2: is_gpu_available (from tensorflow.python.framework.test_util) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Use `tf.config.list_physical_devices('GPU')` instead.\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Using TensorFlow backend.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GPU 设备名称: /device:GPU:0\n" + ] + } + ], + "source": [ + "import tensorflow as tf\n", + "if tf.test.is_gpu_available():\n", + " # 获取当前 GPU 设备名称\n", + " gpu_name = tf.test.gpu_device_name()\n", + " print(\"GPU 设备名称:\", gpu_name)\n", + "else:\n", + " print(\"未发现可用的 GPU\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "sdp", + "language": "python", + "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.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/spatio_feature.ipynb b/spatio_feature.ipynb new file mode 100644 index 0000000..7bb907a --- /dev/null +++ b/spatio_feature.ipynb @@ -0,0 +1,504 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Join_CountTARGET_FIDBlockIDBikeLane_milesAADTSpeedLimitAvgSpeedPop2019Pop_DensityShape_LengthShape_AreaStationNum
0011NaN32638.666667NaNNaN0.00.0000007840.4902883.787844e+060
1022NaNNaNNaNNaN0.00.0000007840.6864483.787843e+060
23330.80705521234.74193525.015.01049.00.0295947840.8829703.787843e+063
33442.0962215915.12500025.019.01816.00.0302527841.0804773.787844e+063
43550.98432023940.078947NaNNaN1892.00.0226477841.2773273.787843e+063
.......................................
12331241241.9557079050.487805NaNNaN1986.00.0460457840.2809373.787843e+063
12431251251.4404499121.500000NaNNaN1198.00.0397267840.0850723.787843e+063
12521261260.9857048770.901961NaNNaN555.00.0151257839.8905183.787843e+062
12641271270.22859312266.08571425.016.0814.00.0311257839.6966213.787844e+064
12741281281.61994011077.03703725.016.01385.00.0596717839.5019803.787843e+064
\n", + "

128 rows × 12 columns

\n", + "
" + ], + "text/plain": [ + " Join_Count TARGET_FID BlockID BikeLane_miles AADT \\\n", + "0 0 1 1 NaN 32638.666667 \n", + "1 0 2 2 NaN NaN \n", + "2 3 3 3 0.807055 21234.741935 \n", + "3 3 4 4 2.096221 5915.125000 \n", + "4 3 5 5 0.984320 23940.078947 \n", + ".. ... ... ... ... ... \n", + "123 3 124 124 1.955707 9050.487805 \n", + "124 3 125 125 1.440449 9121.500000 \n", + "125 2 126 126 0.985704 8770.901961 \n", + "126 4 127 127 0.228593 12266.085714 \n", + "127 4 128 128 1.619940 11077.037037 \n", + "\n", + " SpeedLimit AvgSpeed Pop2019 Pop_Density Shape_Length Shape_Area \\\n", + "0 NaN NaN 0.0 0.000000 7840.490288 3.787844e+06 \n", + "1 NaN NaN 0.0 0.000000 7840.686448 3.787843e+06 \n", + "2 25.0 15.0 1049.0 0.029594 7840.882970 3.787843e+06 \n", + "3 25.0 19.0 1816.0 0.030252 7841.080477 3.787844e+06 \n", + "4 NaN NaN 1892.0 0.022647 7841.277327 3.787843e+06 \n", + ".. ... ... ... ... ... ... \n", + "123 NaN NaN 1986.0 0.046045 7840.280937 3.787843e+06 \n", + "124 NaN NaN 1198.0 0.039726 7840.085072 3.787843e+06 \n", + "125 NaN NaN 555.0 0.015125 7839.890518 3.787843e+06 \n", + "126 25.0 16.0 814.0 0.031125 7839.696621 3.787844e+06 \n", + "127 25.0 16.0 1385.0 0.059671 7839.501980 3.787843e+06 \n", + "\n", + " StationNum \n", + "0 0 \n", + "1 0 \n", + "2 3 \n", + "3 3 \n", + "4 3 \n", + ".. ... \n", + "123 3 \n", + "124 3 \n", + "125 2 \n", + "126 4 \n", + "127 4 \n", + "\n", + "[128 rows x 12 columns]" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spatio_data_file = \"./data/SpatialFeatures.csv\"\n", + "raw_spatio_feature = pd.read_csv(spatio_data_file)\n", + "raw_spatio_feature" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "bikeLane_matrix = raw_spatio_feature[\"BikeLane_miles\"]\n", + "bikeLane_matrix = bikeLane_matrix.fillna(0).to_numpy()\n", + "bikeLane_matrix = bikeLane_matrix/bikeLane_matrix.max()\n", + "bikeLane_matrix_board = bikeLane_matrix[np.newaxis,:] * np.ones((1248,1))\n", + "\n", + "\n", + "static_input = bikeLane_matrix_board\n", + "static_input_test = bikeLane_matrix[np.newaxis,:] * np.ones((240,1))" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [], + "source": [ + "def get_feauture_by_name(data,name):\n", + " feature = data[name]\n", + " feature = feature.fillna(0).to_numpy()\n", + " feature = feature/feature.max()\n", + " feature = feature.reshape(16,8)\n", + " feature = feature[::-1,:]\n", + " return feature\n", + "\n", + "def get_feature_list(data,name_list):\n", + " result_array = np.empty((len(name_list),16,8))\n", + " for i in range(len(name_list)):\n", + " result_array[i] = get_feauture_by_name(data,name_list[i])\n", + "\n", + " return result_array" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = get_feauture_by_name(raw_spatio_feature,\"BikeLane_miles\")\n", + "b = get_feature_list(raw_spatio_feature,[\"BikeLane_miles\"])\n", + "np.array_equal(a,b[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "feature_list = [\"BikeLane_miles\",\"AADT\",\"Pop_Density\",\"StationNum\"]\n", + "feature_array = get_feature_list(raw_spatio_feature,feature_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "for i in range(len(feature_array)):\n", + " plt.figure()\n", + " plt.imshow(feature_array[i])" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOgAAAGdCAYAAAAYMT++AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAX7klEQVR4nO3dfWxU973n8c/YY48JmAGTYuzFDr653BIeQiA8XOqoBcUK6yU07KppUxFq0VVoqQlQVynxqkCbFCZUbS4lRZAgNVAVAv2jUIoUEHJ4aFQI2C7dcLPiQaEwhdpObskYTBjMzNk/UiZyY8Am55f5jv1+SecPzxy+5yeHN2c8OXMc8DzPEwCTstK9AAA3R6CAYQQKGEaggGEEChhGoIBhBAoYRqCAYcF0L+CfJZNJXbhwQfn5+QoEAuleDuA7z/N06dIlFRcXKyvr1udIc4FeuHBBJSUl6V4G4Fw0GtXQoUNvuY+5QPPz8yVJD+l/KKicNK+me67+9wedze57ttXZbOccXk16vX+es9lZ1xNO5l5PxPWHP/9H6u/6rZgL9MbL2qByFAxkVqDBHHd/WYLZcWeznXN5uXfQYaCem0Bv6MqPcLxJBBhGoIBhBAoYRqCAYc4CXbt2rYYNG6a8vDxNnjxZR44ccXUooMdyEui2bdtUU1Oj5cuXq7GxUWPHjtX06dPV0tLi4nBAj+Uk0BdffFFPPfWU5s6dq5EjR2r9+vW666679Mtf/tLF4YAey/dAr127poaGBlVUVHx8kKwsVVRU6NChQ5/YPx6Pq7W1tcMG4CO+B/r+++8rkUiosLCww+OFhYVqamr6xP6RSEThcDi1cZkf8LG0v4tbW1urWCyW2qLRaLqXBJjh+6V+d999t7Kzs9Xc3Nzh8ebmZg0ZMuQT+4dCIYVCIb+XAfQIvp9Bc3Nz9eCDD6quri71WDKZVF1dnaZMmeL34YAezcnF8jU1NaqqqtKECRM0adIkrV69Wm1tbZo7d66LwwE9lpNAv/a1r+m9997TsmXL1NTUpAceeEC7d+/+xBtHAG7N2cfNFixYoAULFrgaD/QKaX8XF8DNEShgGIEChhEoYJi5exLdsP3k2+qf7/+/H/+6eb7vM28o+92HzmY7va/PtXZ3syUlB/ZzNvvDInf3JGrv4+a2r4lrQamxa/tyBgUMI1DAMAIFDCNQwDACBQwjUMAwAgUMI1DAMAIFDCNQwDACBQwjUMAwAgUMI1DAMAIFDCNQwDACBQwjUMAwAgUMI1DAMAIFDCNQwDCzt938n/82RsFAju9z+y52cytFScqOJ5zNdnrbzexsd7MdCyTdfV/aitx8XxLxrp8XOYMChhEoYBiBAoYRKGAYgQKGEShgGIEChvkeaCQS0cSJE5Wfn6/Bgwdr1qxZOnHihN+HAXoF3wM9cOCAqqurdfjwYe3du1ft7e165JFH1NbW5vehgB7P9yuJdu/e3eHrjRs3avDgwWpoaNAXv/hFvw8H9GjOL/WLxWKSpIKCgk6fj8fjisfjqa9bW1tdLwnIGE7fJEomk1q8eLHKy8s1evToTveJRCIKh8OpraSkxOWSgIziNNDq6modP35cW7duvek+tbW1isViqS0ajbpcEpBRnL3EXbBggXbt2qWDBw9q6NChN90vFAopFAq5WgaQ0XwP1PM8Pf3009q+fbv279+vsrIyvw8B9Bq+B1pdXa0tW7bod7/7nfLz89XU1CRJCofD6tOnj9+HA3o0338GXbdunWKxmKZOnaqioqLUtm3bNr8PBfR4Tl7iAvAH1+IChhEoYBiBAoYRKGCY2dtuuhI+c93ZbM/dHT3l5WTurTFdyo25++9Z/NMjTuZe99rV1Q9gcgYFDCNQwDACBQwjUMAwAgUMI1DAMAIFDCNQwDACBQwjUMAwAgUMI1DAMAIFDCNQwDACBQwjUMAwAgUMI1DAMAIFDCNQwDACBQwjUMCwXnfbzax2d787JvuDK85mu5QYcJfT+bF/6+ts9nsTnI3W8D+6+b21AS9LindtX86ggGEEChhGoIBhBAoYRqCAYQQKGEaggGHOA33hhRcUCAS0ePFi14cCehyngR49elQvv/yy7r//fpeHAXosZ4FevnxZs2fP1oYNGzRw4EBXhwF6NGeBVldXa8aMGaqoqHB1CKDHc3It7tatW9XY2KijR4/edt94PK54/OMLE1tbW10sCchIvp9Bo9GoFi1apM2bNysvL++2+0ciEYXD4dRWUlLi95KAjOV7oA0NDWppadH48eMVDAYVDAZ14MABrVmzRsFgUIlEosP+tbW1isViqS0ajfq9JCBj+f4S9+GHH9bbb7/d4bG5c+dqxIgRWrJkibKzszs8FwqFFAq5+VgPkOl8DzQ/P1+jR4/u8Fjfvn01aNCgTzwO4Na4kggw7DO5o8L+/fs/i8MAPQ5nUMAwAgUMI1DAMAIFDCNQwDCz98UdsHegcvrm+j63+Tl398VVjrtvZ6DtQ2ezs9uuOZstSdf69XM2e+LEE85mNzw33snc5NWr0rLfdGlfzqCAYQQKGEaggGEEChhGoIBhBAoYRqCAYQQKGEaggGEEChhGoIBhBAoYRqCAYQQKGEaggGEEChhGoIBhBAoYRqCAYQQKGEaggGEEChhm9rabF166V8Gc2/+G7u7KP/O+7zNvCLRfdzZbiaSz0V4g4Gy2JCX6uJt/sfzvzmb/a9//62Tude+a/tLFfTmDAoYRKGAYgQKGEShgGIEChhEoYBiBAoY5CfT8+fN68sknNWjQIPXp00djxoxRfX29i0MBPZrvFypcvHhR5eXlmjZtml5//XV97nOf06lTpzRw4EC/DwX0eL4HumrVKpWUlOjVV19NPVZWVub3YYBewfeXuDt37tSECRP0+OOPa/DgwRo3bpw2bNhw0/3j8bhaW1s7bAA+4nug7777rtatW6fhw4drz549mj9/vhYuXKhNmzZ1un8kElE4HE5tJSUlfi8JyFi+B5pMJjV+/HitXLlS48aN07x58/TUU09p/fr1ne5fW1urWCyW2qLRqN9LAjKW74EWFRVp5MiRHR677777dO7cuU73D4VC6t+/f4cNwEd8D7S8vFwnTpzo8NjJkyd1zz33+H0ooMfzPdDvfve7Onz4sFauXKnTp09ry5YteuWVV1RdXe33oYAez/dAJ06cqO3bt+u1117T6NGj9fzzz2v16tWaPXu234cCejwnd1R49NFH9eijj7oYDfQqXIsLGEaggGEEChhGoIBhZm+7GbrYrmAw2//Bf//A/5n/4AUc/nsX7udsdCB+zdlsSWrv63S8M4HcXDdzPUltXduXMyhgGIEChhEoYBiBAoYRKGAYgQKGEShgGIEChhEoYBiBAoYRKGAYgQKGEShgGIEChhEoYBiBAoYRKGAYgQKGEShgGIEChhEoYBiBAoaZve1m0+Q8ZYfyfJ877FTI95kpyaSz0V6Wu39LA5e6eA/IO9T3vOd0vjNZATdzk12fyxkUMIxAAcMIFDCMQAHDCBQwjEABwwgUMMz3QBOJhJYuXaqysjL16dNH9957r55//nl5Xob+vzAgjXy/UGHVqlVat26dNm3apFGjRqm+vl5z585VOBzWwoUL/T4c0KP5Hugf//hHPfbYY5oxY4YkadiwYXrttdd05MgRvw8F9Hi+v8T9whe+oLq6Op08eVKS9Oc//1lvvvmmKisrO90/Ho+rtbW1wwbgI76fQZ999lm1trZqxIgRys7OViKR0IoVKzR79uxO949EIvrRj37k9zKAHsH3M+hvfvMbbd68WVu2bFFjY6M2bdqkn/70p9q0aVOn+9fW1ioWi6W2aDTq95KAjOX7GfSZZ57Rs88+qyeeeEKSNGbMGJ09e1aRSERVVVWf2D8UCikUcvgJEyCD+X4GvXLlirL+6aNR2dnZSjr8KBbQU/l+Bp05c6ZWrFih0tJSjRo1Sn/605/04osv6pvf/KbfhwJ6PN8Dfemll7R06VJ95zvfUUtLi4qLi/Wtb31Ly5Yt8/tQQI/ne6D5+flavXq1Vq9e7fdooNfhWlzAMAIFDCNQwDACBQwze9vNvL97ys71/yNqiaIC32fekN100dnswJWrzmZ71xPOZkvSwBNXnM53xbvW7mau1/W5nEEBwwgUMIxAAcMIFDCMQAHDCBQwjEABwwgUMIxAAcMIFDCMQAHDCBQwjEABwwgUMIxAAcMIFDCMQAHDCBQwjEABwwgUMIxAAcMIFDDM7G03B/6/DxUM+n/bzezmD3yfmRLMdjY6OaCfs9mBD685my1JZ2fc5Wz2v7yd72x2IDfHzdxk1/9ecwYFDCNQwDACBQwjUMAwAgUMI1DAMAIFDOt2oAcPHtTMmTNVXFysQCCgHTt2dHje8zwtW7ZMRUVF6tOnjyoqKnTq1Cm/1gv0Kt0OtK2tTWPHjtXatWs7ff4nP/mJ1qxZo/Xr1+utt95S3759NX36dF296u73WwI9VbevJKqsrFRlZWWnz3mep9WrV+sHP/iBHnvsMUnSr371KxUWFmrHjh164oknPt1qgV7G159Bz5w5o6amJlVUVKQeC4fDmjx5sg4dOtTpn4nH42ptbe2wAfiIr4E2NTVJkgoLCzs8XlhYmHrun0UiEYXD4dRWUlLi55KAjJb2d3Fra2sVi8VSWzQaTfeSADN8DXTIkCGSpObm5g6PNzc3p577Z6FQSP379++wAfiIr4GWlZVpyJAhqqurSz3W2tqqt956S1OmTPHzUECv0O13cS9fvqzTp0+nvj5z5oyOHTumgoIClZaWavHixfrxj3+s4cOHq6ysTEuXLlVxcbFmzZrl57qBXqHbgdbX12vatGmpr2tqaiRJVVVV2rhxo77//e+rra1N8+bN0wcffKCHHnpIu3fvVl5enn+rBnqJbgc6depUed7NPxEeCAT03HPP6bnnnvtUCwNg4F1cADdHoIBhBAoYRqCAYWZvu+lK+9BBzmbnnHvP2eysDy47m534XNjZbElKDHP3Sab3nhjtbHYiFHAz99pV6eWu7csZFDCMQAHDCBQwjEABwwgUMIxAAcMIFDCMQAHDCBQwjEABwwgUMIxAAcMIFDCMQAHDCBQwjEABwwgUMIxAAcMIFDCMQAHDCBQwjEABw8zedjP76nVlZ7f7Pzjp/8gbPhxV7G72IHf/qfpdiDubLUn3zv6Ts9lZD4x0NvtvXxzgZK7Xjbt5cgYFDCNQwDACBQwjUMAwAgUMI1DAMAIFDOt2oAcPHtTMmTNVXFysQCCgHTt2pJ5rb2/XkiVLNGbMGPXt21fFxcX6xje+oQsXLvi5ZqDX6HagbW1tGjt2rNauXfuJ565cuaLGxkYtXbpUjY2N+u1vf6sTJ07oy1/+si+LBXqbbl+eUllZqcrKyk6fC4fD2rt3b4fHfvGLX2jSpEk6d+6cSktL72yVQC/l/FK/WCymQCCgAQMGdPp8PB5XPP7xpWatra2ulwRkDKdvEl29elVLlizR17/+dfXv37/TfSKRiMLhcGorKSlxuSQgozgLtL29XV/96lfleZ7WrVt30/1qa2sVi8VSWzQadbUkIOM4eYl7I86zZ8/qjTfeuOnZU5JCoZBCoZCLZQAZz/dAb8R56tQp7du3T4MGDfL7EECv0e1AL1++rNOnT6e+PnPmjI4dO6aCggIVFRXpK1/5ihobG7Vr1y4lEgk1NTVJkgoKCpSbm+vfyoFeoNuB1tfXa9q0aamva2pqJElVVVX64Q9/qJ07d0qSHnjggQ5/bt++fZo6deqdrxTohbod6NSpU+V53k2fv9VzALqHa3EBwwgUMIxAAcMIFDCMQAHDzN4XN+vqdWVlZ/s+N/D3mO8zb7gw61+czQ6Ocbfu/v/rP53Ndi0QbXI2u9+FfCdzr7cnurwvZ1DAMAIFDCNQwDACBQwjUMAwAgUMI1DAMAIFDCNQwDACBQwjUMAwAgUMI1DAMAIFDCNQwDACBQwjUMAwAgUMI1DAMAIFDCNQwDACBQwze9vND/9bPwWDeb7PvTp2oO8zb2gPJ53N9v7z5r8E+dP6r/89xdlsSRp86L+czT7xf/o6m11Q5+b8lbjW9bmcQQHDCBQwjEABwwgUMIxAAcMIFDCs24EePHhQM2fOVHFxsQKBgHbs2HHTfb/97W8rEAho9erVn2KJQO/V7UDb2to0duxYrV279pb7bd++XYcPH1ZxcfEdLw7o7bp9oUJlZaUqKytvuc/58+f19NNPa8+ePZoxY8YdLw7o7Xz/GTSZTGrOnDl65plnNGrUKL/HA72K75f6rVq1SsFgUAsXLuzS/vF4XPF4PPV1a2ur30sCMpavZ9CGhgb9/Oc/18aNGxUIBLr0ZyKRiMLhcGorKSnxc0lARvM10D/84Q9qaWlRaWmpgsGggsGgzp49q+9973saNmxYp3+mtrZWsVgstUWjUT+XBGQ0X1/izpkzRxUVFR0emz59uubMmaO5c+d2+mdCoZBCoZCfywB6jG4HevnyZZ0+fTr19ZkzZ3Ts2DEVFBSotLRUgwYN6rB/Tk6OhgwZos9//vOffrVAL9PtQOvr6zVt2rTU1zU1NZKkqqoqbdy40beFAbiDQKdOnSrP87q8/1/+8pfuHgLAP3AtLmAYgQKGEShgGIEChhEoYJjZ2242/XuOsvJyfJ87bOkh32fe4GX9u7PZgw64u8KqqdLt5ZUf3F/gbHa/enfnmMEHLjiZez0Zv/1O/8AZFDCMQAHDCBQwjEABwwgUMIxAAcMIFDCMQAHDCBQwjEABwwgUMIxAAcMIFDCMQAHDCBQwjEABwwgUMIxAAcMIFDCMQAHDCBQwzNxd/W783pdk/KqT+de9didzJSlxzc2ape7dCa67XK5bkq63d/13+XRXIu7uHOPqe349eU2SuvQ7jgJed34T0mfgr3/9K79lG71CNBrV0KFDb7mPuUCTyaQuXLig/Px8BQKB2+7f2tqqkpISRaNR9e/f/zNYoT9Y92fL0ro9z9OlS5dUXFysrKxbvwIw9xI3Kyvrtv+qdKZ///5p/8bfCdb92bKy7nA43KX9eJMIMIxAAcMyPtBQKKTly5crFAqleyndwro/W5m6bnNvEgH4WMafQYGejEABwwgUMIxAAcMyOtC1a9dq2LBhysvL0+TJk3XkyJF0L+m2IpGIJk6cqPz8fA0ePFizZs3SiRMn0r2sbnvhhRcUCAS0ePHidC/lts6fP68nn3xSgwYNUp8+fTRmzBjV19ene1ldkrGBbtu2TTU1NVq+fLkaGxs1duxYTZ8+XS0tLele2i0dOHBA1dXVOnz4sPbu3av29nY98sgjamtrS/fSuuzo0aN6+eWXdf/996d7Kbd18eJFlZeXKycnR6+//rreeecd/exnP9PAgQPTvbSu8TLUpEmTvOrq6tTXiUTCKy4u9iKRSBpX1X0tLS2eJO/AgQPpXkqXXLp0yRs+fLi3d+9e70tf+pK3aNGidC/plpYsWeI99NBD6V7GHcvIM+i1a9fU0NCgioqK1GNZWVmqqKjQoUOH0riy7ovFYpKkgoKCNK+ka6qrqzVjxowO33vLdu7cqQkTJujxxx/X4MGDNW7cOG3YsCHdy+qyjAz0/fffVyKRUGFhYYfHCwsL1dTUlKZVdV8ymdTixYtVXl6u0aNHp3s5t7V161Y1NjYqEomkeyld9u6772rdunUaPny49uzZo/nz52vhwoXatGlTupfWJeY+zdKbVFdX6/jx43rzzTfTvZTbikajWrRokfbu3au8vLx0L6fLksmkJkyYoJUrV0qSxo0bp+PHj2v9+vWqqqpK8+puLyPPoHfffbeys7PV3Nzc4fHm5mYNGTIkTavqngULFmjXrl3at2/fHX287rPW0NCglpYWjR8/XsFgUMFgUAcOHNCaNWsUDAaVSCTSvcROFRUVaeTIkR0eu++++3Tu3Lk0rah7MjLQ3NxcPfjgg6qrq0s9lkwmVVdXpylTpqRxZbfneZ4WLFig7du364033lBZWVm6l9QlDz/8sN5++20dO3YstU2YMEGzZ8/WsWPHlJ2dne4ldqq8vPwT/xvr5MmTuueee9K0om5K97tUd2rr1q1eKBTyNm7c6L3zzjvevHnzvAEDBnhNTU3pXtotzZ8/3wuHw97+/fu9v/3tb6ntypUr6V5at2XCu7hHjhzxgsGgt2LFCu/UqVPe5s2bvbvuusv79a9/ne6ldUnGBup5nvfSSy95paWlXm5urjdp0iTv8OHD6V7SbUnqdHv11VfTvbRuy4RAPc/zfv/733ujR4/2QqGQN2LECO+VV15J95K6jI+bAYZl5M+gQG9BoIBhBAoYRqCAYQQKGEaggGEEChhGoIBhBAoYRqCAYQQKGEaggGH/H0gwOEkXpfavAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from GenFeature import gen_features\n", + "feature_array = gen_features()\n", + "for i in range(len(feature_array)):\n", + " plt.figure()\n", + " plt.imshow(feature_array[i])" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(4, 16, 8)" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_array.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "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.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/std_scaler.pkl b/std_scaler.pkl new file mode 100644 index 0000000..3f8a66d Binary files /dev/null and b/std_scaler.pkl differ diff --git a/testing_example.ipynb b/testing_example.ipynb new file mode 100644 index 0000000..eac075e --- /dev/null +++ b/testing_example.ipynb @@ -0,0 +1,433 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# **Sample Tutorial: Testing your Models**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hello teams! In order to help streamline the judging process for each of your models, this notebook will walk through how to format your models for easy and fair evaluation.\n", + "\n", + "This sample tutorial will be using the previous sample LSTM model given in the training notebook to show how models will be tested. We hope this transparency will allow for teams to understand exactly how models will be judged. \n", + "\n", + "Let's first begin by importing some basic libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import h5py\n", + "import numpy as np\n", + "from datetime import datetime\n", + "from tensorflow.keras.models import Sequential, load_model\n", + "from tensorflow.keras.layers import LSTM, Dense, Reshape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We'll be using the first week of our original training dataset for testing. Let's go ahead and open and access that data now\n", + "\n", + "Note: this will not be the actual dataset being used the for final model judging." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "with h5py.File('TrainingData.h5', 'r') as f:\n", + " # Access the trip dataset and their corresponding timestamps\n", + " traffic_data = f['trip'][()]\n", + " dates = f['timeslot'][()]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "test_set_size = 48 * 7\n", + "\n", + "test_traffic_data = traffic_data[:test_set_size]\n", + "test_dates = dates[:test_set_size]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the data open, we can go ahead and do any preprocessing needed for it to run in our models. If teams reshaped or adjusted their model's data in any way this code should be changed to reflect those adjustments\n", + "\n", + "The code below handles some of the basic data handling we did in the model training tutorial. We'll need to use this formatted data for our model to accept it as input. The bottom code snippet does just that" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "formatted_dates = []\n", + "\n", + "for date_string in test_dates:\n", + " formatted_date = datetime.strptime(date_string.decode(), '%Y%m%d%H%M')\n", + "\n", + " year = formatted_date.year\n", + " month = formatted_date.month\n", + " day = formatted_date.day\n", + " hour = formatted_date.hour\n", + " minute = formatted_date.minute\n", + "\n", + " formatted_dates.append(np.array([year, month, day, hour, minute]))\n", + "\n", + "test_dates = np.array(formatted_dates).reshape(test_set_size, 5, 1)\n", + "\n", + "# generate test dataset\n", + "import pandas as pd\n", + "import numpy as np\n", + "import tensorflow as tf\n", + "import pickle\n", + "from sklearn.preprocessing import StandardScaler,MinMaxScaler\n", + "from keras import models\n", + "from GenFeature import gen_features\n", + "def apply_sin(X,axis,range):\n", + " \"\"\"Apply sin function on some time features\"\"\"\n", + " X = X.copy()\n", + " X[:,axis,:] = np.sin(X[:,axis,:]*2*np.pi/range)\n", + " return X\n", + "def apply_cos(X,axis,range):\n", + " \"\"\"same for cos\"\"\"\n", + " X = X.copy()\n", + " X[:,axis,:] = np.cos(X[:,axis,:]*2*np.pi/range)\n", + " return X\n", + "def create_rolling_window(matrix,t):\n", + " \"\"\"This function is used for create X for lstm\"\"\"\n", + " matrix_shape = matrix.shape\n", + " return_length = matrix_shape[0] - t \n", + " dataset = tf.data.Dataset.from_tensor_slices(matrix)\n", + " windows = dataset.window(t,shift = 1,drop_remainder=True)\n", + " windows = windows.take(return_length)\n", + " windows = windows.flat_map(lambda window: window.batch(t))\n", + "\n", + " return windows\n", + "def create_result_ds(matrix,delay):\n", + " \"\"\"Creat Y target \"\"\"\n", + " dataset = tf.data.Dataset.from_tensor_slices(matrix)\n", + " dataset = dataset.skip(delay)\n", + " return dataset\n", + "\n", + "def combine_ds(X_train,ds1,ds2):\n", + " \"\"\"zip two dataset and returns a batch dataset\"\"\"\n", + " combined_ds = tf.data.Dataset.zip(((X_train,ds1),ds2))\n", + " combined_ds = combined_ds.batch(batch_size=32)\n", + " return combined_ds\n", + "def gen_test_ds(X_test,y_test,step_len):\n", + "\n", + " X = create_rolling_window(y_test,step_len)\n", + " y = create_result_ds(y_test,step_len)\n", + " X_test_ds = create_result_ds(X_test,step_len)\n", + "\n", + " test_ds = combine_ds(X_test_ds,X,y)\n", + " return test_ds\n", + "with open(\"std_scaler.pkl\",\"rb\") as file:\n", + " std_scaler = pickle.load(file)\n", + "\n", + "\"\"\" create a batch dataset thus the lstm could be able to learn from the \"time steps\"\"\"\n", + "y_test = test_traffic_data\n", + "# use std_scaler to normalize some of the input data\n", + "test_shape = y_test.shape\n", + "y_test = std_scaler.transform(np.reshape(y_test,(-1,y_test.shape[-2]*y_test.shape[-1])))\n", + "y_test = y_test.reshape(test_shape)\n", + "\n", + "X_test = test_dates[:,1:,:].astype(np.float64)\n", + "X_test = apply_sin(X_test,2,24)\n", + "X_test = X_test/X_test.max()\n", + "\n", + "model_input = X_test\n", + "time_step = 48\n", + "test_ds = gen_test_ds(X_test,y_test,time_step)\n", + "feature_array = gen_features()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we'll define our model architecture. This is necessary in order to load the previously trained model. If you have any questions on how we obtained the *lstm_model.h5* file please review the previous LSTM model training tutorial where we covered this in more depth\n", + "\n", + "Teams should replace the bottom code snippet to load their custom built models. " + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model: \"model_10\"\n", + "__________________________________________________________________________________________________\n", + " Layer (type) Output Shape Param # Connected to \n", + "==================================================================================================\n", + " input_28 (InputLayer) [(None, 48, 2, 16, 8)] 0 [] \n", + " \n", + " reshape_51 (Reshape) (None, 96, 16, 8) 0 ['input_28[0][0]'] \n", + " \n", + " conv2d_36 (Conv2D) (None, 95, 15, 32) 1056 ['reshape_51[0][0]'] \n", + " \n", + " max_pooling2d_35 (MaxPooli (None, 47, 7, 32) 0 ['conv2d_36[0][0]'] \n", + " ng2D) \n", + " \n", + " conv2d_37 (Conv2D) (None, 46, 6, 64) 8256 ['max_pooling2d_35[0][0]'] \n", + " \n", + " max_pooling2d_36 (MaxPooli (None, 23, 3, 64) 0 ['conv2d_37[0][0]'] \n", + " ng2D) \n", + " \n", + " conv2d_38 (Conv2D) (None, 22, 2, 128) 32896 ['max_pooling2d_36[0][0]'] \n", + " \n", + " input_27 (InputLayer) [(None, 4, 1)] 0 [] \n", + " \n", + " max_pooling2d_37 (MaxPooli (None, 11, 1, 128) 0 ['conv2d_38[0][0]'] \n", + " ng2D) \n", + " \n", + " reshape_50 (Reshape) (None, 48, 256) 0 ['input_28[0][0]'] \n", + " \n", + " tf.compat.v1.shape_11 (TFO (5,) 0 ['input_28[0][0]'] \n", + " pLambda) \n", + " \n", + " dense_54 (Dense) (None, 4, 32) 64 ['input_27[0][0]'] \n", + " \n", + " flatten_11 (Flatten) (None, 1408) 0 ['max_pooling2d_37[0][0]'] \n", + " \n", + " lstm_13 (LSTM) (None, 512) 1574912 ['reshape_50[0][0]'] \n", + " \n", + " tf.__operators__.getitem_1 () 0 ['tf.compat.v1.shape_11[0][0]'\n", + " 1 (SlicingOpLambda) ] \n", + " \n", + " reshape_49 (Reshape) (None, 128) 0 ['dense_54[0][0]'] \n", + " \n", + " dense_56 (Dense) (None, 128) 180352 ['flatten_11[0][0]'] \n", + " \n", + " dense_55 (Dense) (None, 128) 65664 ['lstm_13[0][0]'] \n", + " \n", + " tf.tile_11 (TFOpLambda) (None, 128) 0 ['tf.__operators__.getitem_11[\n", + " 0][0]'] \n", + " \n", + " concatenate_11 (Concatenat (None, 512) 0 ['reshape_49[0][0]', \n", + " e) 'dense_56[0][0]', \n", + " 'dense_55[0][0]', \n", + " 'tf.tile_11[0][0]'] \n", + " \n", + " dense_57 (Dense) (None, 512) 262656 ['concatenate_11[0][0]'] \n", + " \n", + " dense_58 (Dense) (None, 256) 131328 ['dense_57[0][0]'] \n", + " \n", + " reshape_52 (Reshape) (None, 2, 16, 8) 0 ['dense_58[0][0]'] \n", + " \n", + "==================================================================================================\n", + "Total params: 2257184 (8.61 MB)\n", + "Trainable params: 2257184 (8.61 MB)\n", + "Non-trainable params: 0 (0.00 Byte)\n", + "__________________________________________________________________________________________________\n", + "None\n" + ] + } + ], + "source": [ + "# load model\n", + "model = models.load_model(\"lstm_cnn_v6.h5\")\n", + "print(model.summary())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the model's correctly loaded in, we can simply evaluate it's performance on our \"test set\". Examining it's RMSE we can get a quick idea how the model performed on the test set" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "9/9 [==============================] - 1s 96ms/step - loss: 0.2001\n", + "Root Mean Squared Error: StandardScaler()\n" + ] + } + ], + "source": [ + "\n", + "mse = model.evaluate(test_ds)\n", + "\n", + "# Show rmse to see how model performs on the test set\n", + "rmse = np.sqrt(mse)\n", + "print(f'Root Mean Squared Error: {std_scaler}')" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1/1 [==============================] - 0s 303ms/step\n", + "11.248793599595093\n", + "1/1 [==============================] - 0s 78ms/step\n", + "10.365546264488305\n", + "1/1 [==============================] - 0s 73ms/step\n", + "10.23328950075086\n", + "1/1 [==============================] - 0s 76ms/step\n", + "11.116244210247057\n", + "1/1 [==============================] - 0s 73ms/step\n", + "9.62333573014892\n", + "1/1 [==============================] - 0s 70ms/step\n", + "15.534290603441073\n", + "1/1 [==============================] - 0s 72ms/step\n", + "11.153009478693466\n", + "1/1 [==============================] - 0s 75ms/step\n", + "12.661326560881609\n", + "1/1 [==============================] - 0s 73ms/step\n", + "31.319326890297543\n" + ] + } + ], + "source": [ + "# return the normalized result in to original scalar\n", + "# details for model performance are in the attached file \"model performance\"\n", + "from ModelPerformance import std_inverse,plot_result,compare_result\n", + "# iter trhough the dataset and pring out the mse for each batch\n", + "for X,y in test_ds:\n", + " result = model.predict(X)\n", + " inverse_result = std_inverse(std_scaler,result)\n", + " inverse_y = std_inverse(std_scaler,y)\n", + " \n", + " # print(inverse_result.shape,inverse_y.shape)\n", + " compare_result(inverse_result,inverse_y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1/1 [==============================] - 0s 74ms/step\n", + "(32, 2, 16, 8)\n", + "11.248793599595093\n", + "1/1 [==============================] - 0s 71ms/step\n", + "(32, 2, 16, 8)\n", + "10.365546264488305\n", + "1/1 [==============================] - 0s 73ms/step\n", + "(32, 2, 16, 8)\n", + "10.23328950075086\n", + "1/1 [==============================] - 0s 73ms/step\n", + "(32, 2, 16, 8)\n", + "11.116244210247057\n", + "1/1 [==============================] - 0s 70ms/step\n", + "(32, 2, 16, 8)\n", + "9.62333573014892\n", + "1/1 [==============================] - 0s 68ms/step\n", + "(32, 2, 16, 8)\n", + "15.534290603441073\n", + "1/1 [==============================] - 0s 66ms/step\n", + "(32, 2, 16, 8)\n", + "11.153009478693466\n", + "1/1 [==============================] - 0s 69ms/step\n", + "(32, 2, 16, 8)\n", + "12.661326560881609\n", + "1/1 [==============================] - 0s 69ms/step\n", + "(32, 2, 16, 8)\n", + "31.319326890297543\n", + "The MSE is13.695018093171548\n" + ] + } + ], + "source": [ + "# to sum up the batch mse and take a square root:\n", + "result_list= []\n", + "for X,y in test_ds:\n", + " result = model.predict(X)\n", + " inverse_result = std_inverse(std_scaler,result)\n", + " inverse_y = std_inverse(std_scaler,y)\n", + " print(y.shape)\n", + " # print(inverse_result.shape,inverse_y.shape)\n", + " result_list.append(compare_result(inverse_result,inverse_y))\n", + "print(f\"The MSE is{np.mean(result_list)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we see our model's achieved RMSE, it's important for teams to remember that model performance will not be the sole judging criteria for this competition. Team presentations will also play a large role in determining overall placing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This concludes this sample notebook. Teams are encouraged to send in their testing notebooks by Friday, February 2nd by 5pm EST\n", + "\n", + "If any teams have follow up questions or need any help relating to this notebook, please feel free to drop a question in the hackathon teams chat. We are all more than happy to help answer any questions you might have!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# **Thank you and best of luck!**" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "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.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/time_feature.ipynb b/time_feature.ipynb new file mode 100644 index 0000000..2f9e998 --- /dev/null +++ b/time_feature.ipynb @@ -0,0 +1,341 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
stationdateair_tempdew_tempsea_level_pressurewind_directionwind_speed_ratesky_conditionprecip_1hourprecip_6hour
0725053947282019-01-01T01:00Z6.75.61017.8NaNNaNNaN4.1NaN
1725053947282019-01-01T02:00Z7.26.11016.3NaNNaNNaN3.8NaN
2725053947282019-01-01T03:00Z7.26.11013.3NaNNaNNaN4.8NaN
3725053947282019-01-01T04:00Z7.86.71011.6NaNNaNNaN2.5NaN
4725053947282019-01-01T05:00Z8.37.81009.0NaNNaNNaN4.3NaN
.................................
8747725053947282019-12-31T19:00Z6.12.81002.7NaN2.6NaN0.0NaN
8748725053947282019-12-31T20:00Z6.12.21002.3220.03.1NaN0.0NaN
8749725053947282019-12-31T21:00Z6.71.11002.6NaN2.14.00.0NaN
8750725053947282019-12-31T22:00Z6.71.11003.0NaN2.6NaN0.0NaN
8751725053947282019-12-31T23:00Z6.11.71003.4240.01.5NaN0.0NaN
\n", + "

8752 rows × 10 columns

\n", + "
" + ], + "text/plain": [ + " station date air_temp dew_temp sea_level_pressure \\\n", + "0 72505394728 2019-01-01T01:00Z 6.7 5.6 1017.8 \n", + "1 72505394728 2019-01-01T02:00Z 7.2 6.1 1016.3 \n", + "2 72505394728 2019-01-01T03:00Z 7.2 6.1 1013.3 \n", + "3 72505394728 2019-01-01T04:00Z 7.8 6.7 1011.6 \n", + "4 72505394728 2019-01-01T05:00Z 8.3 7.8 1009.0 \n", + "... ... ... ... ... ... \n", + "8747 72505394728 2019-12-31T19:00Z 6.1 2.8 1002.7 \n", + "8748 72505394728 2019-12-31T20:00Z 6.1 2.2 1002.3 \n", + "8749 72505394728 2019-12-31T21:00Z 6.7 1.1 1002.6 \n", + "8750 72505394728 2019-12-31T22:00Z 6.7 1.1 1003.0 \n", + "8751 72505394728 2019-12-31T23:00Z 6.1 1.7 1003.4 \n", + "\n", + " wind_direction wind_speed_rate sky_condition precip_1hour \\\n", + "0 NaN NaN NaN 4.1 \n", + "1 NaN NaN NaN 3.8 \n", + "2 NaN NaN NaN 4.8 \n", + "3 NaN NaN NaN 2.5 \n", + "4 NaN NaN NaN 4.3 \n", + "... ... ... ... ... \n", + "8747 NaN 2.6 NaN 0.0 \n", + "8748 220.0 3.1 NaN 0.0 \n", + "8749 NaN 2.1 4.0 0.0 \n", + "8750 NaN 2.6 NaN 0.0 \n", + "8751 240.0 1.5 NaN 0.0 \n", + "\n", + " precip_6hour \n", + "0 NaN \n", + "1 NaN \n", + "2 NaN \n", + "3 NaN \n", + "4 NaN \n", + "... ... \n", + "8747 NaN \n", + "8748 NaN \n", + "8749 NaN \n", + "8750 NaN \n", + "8751 NaN \n", + "\n", + "[8752 rows x 10 columns]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "weather_raw_data = pd.read_csv(\"./data/NY_weather2019.csv\")\n", + "weather_raw_data" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [], + "source": [ + "def preprocess_weather(X):\n", + " X = X.copy()\n", + " selected_columns = [\"date\",\"air_temp\",\"dew_temp\",\"precip_1hour\"]\n", + " X = X[selected_columns]\n", + " X[\"date\"] = pd.to_datetime(X[\"date\"],format = '%Y-%m-%dT%H:%MZ',errors= 'ignore')\n", + " X[\"date\"] = pd.to_datetime(X[\"date\"],format = \"%Y-%m-%d\",errors=\"ignore\")\n", + " return X" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [], + "source": [ + "X_train = pd.read_pickle(\"./data/X_train.pkl\")\n", + "\n", + "weather_feature = preprocess_weather(weather_raw_data)" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [], + "source": [ + "X_train = pd.DataFrame(X_train.reshape((-1,5)))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [ + { + "ename": "MergeError", + "evalue": "No common columns to perform merge on. Merge options: left_on=None, right_on=None, left_index=False, right_index=False", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mMergeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[67], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mpd\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmerge\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX_train\u001b[49m\u001b[43m,\u001b[49m\u001b[43mweather_feature\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32mc:\\Users\\yy\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\pandas\\core\\reshape\\merge.py:169\u001b[0m, in \u001b[0;36mmerge\u001b[1;34m(left, right, how, on, left_on, right_on, left_index, right_index, sort, suffixes, copy, indicator, validate)\u001b[0m\n\u001b[0;32m 154\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m _cross_merge(\n\u001b[0;32m 155\u001b[0m left_df,\n\u001b[0;32m 156\u001b[0m right_df,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 166\u001b[0m copy\u001b[38;5;241m=\u001b[39mcopy,\n\u001b[0;32m 167\u001b[0m )\n\u001b[0;32m 168\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m--> 169\u001b[0m op \u001b[38;5;241m=\u001b[39m \u001b[43m_MergeOperation\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 170\u001b[0m \u001b[43m \u001b[49m\u001b[43mleft_df\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 171\u001b[0m \u001b[43m \u001b[49m\u001b[43mright_df\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 172\u001b[0m \u001b[43m \u001b[49m\u001b[43mhow\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mhow\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 173\u001b[0m \u001b[43m \u001b[49m\u001b[43mon\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mon\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 174\u001b[0m \u001b[43m \u001b[49m\u001b[43mleft_on\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mleft_on\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 175\u001b[0m \u001b[43m \u001b[49m\u001b[43mright_on\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mright_on\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 176\u001b[0m \u001b[43m \u001b[49m\u001b[43mleft_index\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mleft_index\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 177\u001b[0m \u001b[43m \u001b[49m\u001b[43mright_index\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mright_index\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 178\u001b[0m \u001b[43m \u001b[49m\u001b[43msort\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msort\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 179\u001b[0m \u001b[43m \u001b[49m\u001b[43msuffixes\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msuffixes\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 180\u001b[0m \u001b[43m \u001b[49m\u001b[43mindicator\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mindicator\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 181\u001b[0m \u001b[43m \u001b[49m\u001b[43mvalidate\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mvalidate\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 182\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 183\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m op\u001b[38;5;241m.\u001b[39mget_result(copy\u001b[38;5;241m=\u001b[39mcopy)\n", + "File \u001b[1;32mc:\\Users\\yy\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\pandas\\core\\reshape\\merge.py:783\u001b[0m, in \u001b[0;36m_MergeOperation.__init__\u001b[1;34m(self, left, right, how, on, left_on, right_on, left_index, right_index, sort, suffixes, indicator, validate)\u001b[0m\n\u001b[0;32m 776\u001b[0m msg \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m 777\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNot allowed to merge between different levels. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 778\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m(\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m_left\u001b[38;5;241m.\u001b[39mcolumns\u001b[38;5;241m.\u001b[39mnlevels\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m levels on the left, \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 779\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m_right\u001b[38;5;241m.\u001b[39mcolumns\u001b[38;5;241m.\u001b[39mnlevels\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m on the right)\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 780\u001b[0m )\n\u001b[0;32m 781\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m MergeError(msg)\n\u001b[1;32m--> 783\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mleft_on, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mright_on \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_validate_left_right_on\u001b[49m\u001b[43m(\u001b[49m\u001b[43mleft_on\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mright_on\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 785\u001b[0m (\n\u001b[0;32m 786\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mleft_join_keys,\n\u001b[0;32m 787\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mright_join_keys,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 790\u001b[0m right_drop,\n\u001b[0;32m 791\u001b[0m ) \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_get_merge_keys()\n\u001b[0;32m 793\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m left_drop:\n", + "File \u001b[1;32mc:\\Users\\yy\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\pandas\\core\\reshape\\merge.py:1538\u001b[0m, in \u001b[0;36m_MergeOperation._validate_left_right_on\u001b[1;34m(self, left_on, right_on)\u001b[0m\n\u001b[0;32m 1536\u001b[0m common_cols \u001b[38;5;241m=\u001b[39m left_cols\u001b[38;5;241m.\u001b[39mintersection(right_cols)\n\u001b[0;32m 1537\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(common_cols) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m-> 1538\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m MergeError(\n\u001b[0;32m 1539\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNo common columns to perform merge on. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1540\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mMerge options: left_on=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mleft_on\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m, \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1541\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mright_on=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mright_on\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m, \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1542\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mleft_index=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mleft_index\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m, \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1543\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mright_index=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mright_index\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1544\u001b[0m )\n\u001b[0;32m 1545\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[0;32m 1546\u001b[0m \u001b[38;5;129;01mnot\u001b[39;00m left_cols\u001b[38;5;241m.\u001b[39mjoin(common_cols, how\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minner\u001b[39m\u001b[38;5;124m\"\u001b[39m)\u001b[38;5;241m.\u001b[39mis_unique\n\u001b[0;32m 1547\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m right_cols\u001b[38;5;241m.\u001b[39mjoin(common_cols, how\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minner\u001b[39m\u001b[38;5;124m\"\u001b[39m)\u001b[38;5;241m.\u001b[39mis_unique\n\u001b[0;32m 1548\u001b[0m ):\n\u001b[0;32m 1549\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m MergeError(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mData columns not unique: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mrepr\u001b[39m(common_cols)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[1;31mMergeError\u001b[0m: No common columns to perform merge on. Merge options: left_on=None, right_on=None, left_index=False, right_index=False" + ] + } + ], + "source": [ + "pd.merge(X_train,weather_feature)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "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.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}