From 17daf99c50b255332f4f0ede60418fa7311aa6de Mon Sep 17 00:00:00 2001 From: amilashanaka <dsa.amilashanaka@gmail.com> Date: Sat, 14 Jan 2023 04:36:18 +0000 Subject: [PATCH] update web app --- api/__pycache__/app.cpython-310.pyc | Bin 192 -> 0 bytes api/run.py | 748 ++++++++++++++++------------ dash_board.php | 66 ++- decompose.php | 178 +++++++ forecast_list.php | 120 +++++ inc/function.php | 5 + index.php | 6 - output.png | Bin 0 -> 16131 bytes page_decompose.php | 26 + perforemence_list.php | 132 +++++ settings.php | 63 ++- settings_list.php | 120 +++++ side_bar.php | 27 +- 13 files changed, 1142 insertions(+), 349 deletions(-) delete mode 100644 api/__pycache__/app.cpython-310.pyc create mode 100644 decompose.php create mode 100644 forecast_list.php create mode 100644 output.png create mode 100644 page_decompose.php create mode 100644 perforemence_list.php create mode 100644 settings_list.php diff --git a/api/__pycache__/app.cpython-310.pyc b/api/__pycache__/app.cpython-310.pyc deleted file mode 100644 index a694bd589ce1602823bdfe06ffd3bb86cfc44283..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmd1j<>g{vU|>kMdlqZJz`*br#6iYP3=9ko3=9m#5)2FsDGVu$ISjdsQH+cXsf?*i z&5TjZDNMl(n#?ajdNdhtvAX3X7H9iuvfN@#1F?!g`fqW>$LA&HrpCwLVooe5SjkYt z#=rm}eyKZK#gr%J7MPjDl$V#sBo`-_#HS<{XC&n(7Nx`_7G%aG78K|eRNmsS$<0qG T%}KRm1i6NVfq{XCfrkkIF}*Dg diff --git a/api/run.py b/api/run.py index 78667ab..8a8319d 100644 --- a/api/run.py +++ b/api/run.py @@ -1,72 +1,84 @@ -#==================================================== +# ==================================================== # Written By Don Gunasinha = # Master in Data Science = -#==================================================== +# ==================================================== -# libarary declare +# libarary declare from app import app import pandas as pd -import datetime as dt +import datetime as dt import numpy as np import json import time +import math +import sklearn.metrics from sqlalchemy import create_engine -from sklearn.preprocessing import MinMaxScaler +from sklearn.preprocessing import MinMaxScaler from tensorflow import keras -from keras.models import Sequential +from keras.models import Sequential from keras.layers import Dense, LSTM, Dropout +from statsmodels.tsa.seasonal import seasonal_decompose + from flask import Flask, jsonify, request, make_response from flask import flash, request from datetime import datetime, timedelta -import matplotlib.pyplot as plt import matplotlib.dates as mdates import seaborn as sns +from matplotlib import pyplot +import matplotlib.pyplot as plt +from matplotlib.ticker import (MultipleLocator, FormatStrFormatter, + AutoMinorLocator) +import matplotlib.dates as mdates sns.set_theme(style="darkgrid") -#================================================= +# ================================================= -# Globally Declare data set +# Globally Declare data set -# Data Frames -raw_data_set=pd.DataFrame() -data_set =pd.DataFrame() -index_data_set =pd.DataFrame() -tranning_set=pd.DataFrame() -result=pd.DataFrame() -predictions_set=pd.DataFrame() +# Data Frames +raw_data_set = pd.DataFrame() +data_set = pd.DataFrame() +index_data_set = pd.DataFrame() +tranning_set = pd.DataFrame() +result = pd.DataFrame() +predictions_set = pd.DataFrame() +decompose_set = pd.DataFrame() +model_settings = pd.DataFrame() -# numpy Arrays -data_arr_x=np.array([]) -data_arr_y=np.array([]) +# numpy Arrays +data_arr_x = np.array([]) +data_arr_y = np.array([]) x_train = np.array([]) y_train = np.array([]) x_test = np.array([]) y_test = np.array([]) -predictions = np.array([]) +predictions = np.array([]) # Initialising the LSTM model with training model = Sequential() -feature_length = 100 -testing_records=50 +feature_length =0 +testing_records = 50 batch_size = 5 epochs = 10 -accuracy=0 -execute_time=0 -input_units=100 -hidden_layer_1=50 -hidden_layer_2=25 -output_units=1 +accuracy = 0 +execute_time = 0 +input_units = 100 +hidden_layer_1 = 67 +hidden_layer_2 = 34 +output_units = 1 -# Scaler -scaler = MinMaxScaler() +seetings_id=0 + +# Scaler +scaler = MinMaxScaler() # MySQL database connection @@ -74,412 +86,496 @@ db_connection_str = 'mysql+pymysql://root:@localhost/csct' db_connection = create_engine(db_connection_str) -#============================================ +# mesure perforemence +rmse=0 + + +# ============================================ + +# Support Functions definitions -# Support Functions definitions +def read_model_settings(): + global model_settings + global feature_length + global batch_size + global epochs + global input_units + global hidden_layer_1 + global hidden_layer_2 + global output_units + global seetings_id + model_settings = pd.read_sql('select * from model_settings ORDER BY id DESC LIMIT 1', con=db_connection) + feature_length=model_settings['feature_length'].values[0] + batch_size=model_settings['batch_size'].values[0] + epochs=model_settings['epochs'].values[0] + input_units=model_settings['input_units'].values[0] + hidden_layer_1=model_settings['hidden_layer_1'].values[0] + hidden_layer_2=model_settings['hidden_layer_2'].values[0] + output_units=model_settings['output_units'].values[0] + seetings_id=model_settings['id'].values[0] -# Read data from data base and re arrange data + return model_settings -#--------------------------------------------- + + +# Read data from data base and re arrange data + +# --------------------------------------------- def read_data_set(): - # Declare global variable - global data_set - global raw_data_set - global index_data_set + # Declare global variable + global data_set + global raw_data_set + global index_data_set + global decompose_set - - + # Read data in to Data Frame + raw_data_set = pd.read_sql( + 'SELECT * FROM aw_product_demand', con=db_connection) - # Read data in to Data Frame - raw_data_set = pd.read_sql('SELECT * FROM aw_product_demand', con=db_connection) + # Validate Date + raw_data_set['Date'] = pd.to_datetime(raw_data_set['Date']).dt.date + raw_data_set['Order_Demand'] = raw_data_set['Order_Demand'].astype('int64') - # Validate Date - raw_data_set['Date']= pd.to_datetime(raw_data_set['Date']).dt.date - raw_data_set['Order_Demand'] = raw_data_set['Order_Demand'].astype('int64') + # combine to single date + data_set = raw_data_set.groupby('Date')['Order_Demand'].sum().reset_index() - #combine to single date - data_set = raw_data_set.groupby('Date')['Order_Demand'].sum().reset_index() - - data_set.sort_values('Date', inplace=True) - data_set['Date']=data_set['Date'].astype(str) + data_set.sort_values('Date', inplace=True) + data_set['Date'] = data_set['Date'].astype(str) - # Create index data frame - index_data_set=data_set + # Create index data frame + index_data_set = data_set + index_data_set = index_data_set.set_index(index_data_set['Date']) + index_data_set = index_data_set.drop('Date', axis=1) - index_data_set=index_data_set.set_index(index_data_set['Date']) + #genarate decompose data set using seasonal_decompose - return data_set + result = seasonal_decompose(index_data_set, model='multiplicative', extrapolate_trend='freq', period=100) + + #push data in to pandas dataframe + + decompose_set['Date'] = data_set['Date'] + decompose_set['trend'] = result.trend.values + decompose_set['sesonal'] = result.seasonal.values + decompose_set['resid'] = result.resid.values + decompose_set['observed'] = result.observed.values + + return data_set + + +# ------------------------------------------------------------------------------- +def save_tranning_history(epochs, time_steps, batch_size, execute_time, rmse,mae,mape,accurecy): + global seetings_id + + print(seetings_id) + + id = db_connection.execute("INSERT INTO `trannings` ( `date_time`, `epochs`, `time_steps`, `batch_size`, `execute_time`, `rmse`,`mae`,`mape`,`accurecy`) VALUES ( CURRENT_TIMESTAMP, '" + + str(epochs)+"', '"+str(time_steps)+"', '"+str(batch_size)+"', '"+str(execute_time)+"', '"+str(rmse)+"', '"+str(mae)+"', '"+str(mape)+"','"+str(accurecy)+"')") + + db_connection.execute("INSERT INTO `model_perforemence` ( `date_time`, `trannings_id`, `model_settings_id`) VALUES ( CURRENT_TIMESTAMP, '"+str(seetings_id)+"', '"+str(id.lastrowid)+"')") + print("Row Added = ", id.rowcount) -#------------------------------------------------------------------------------- -def save_tranning_history(epochs,time_steps,batch_size,execute_time,accuracy): - id=db_connection.execute("INSERT INTO `trannings` ( `date_time`, `epochs`, `time_steps`, `batch_size`, `execute_time`, `accurecy`) VALUES ( CURRENT_TIMESTAMP, '"+str(epochs)+"', '"+str(time_steps)+"', '"+str(batch_size)+"', '"+str(execute_time)+"', '"+str(accuracy)+"')") - print("Row Added = ",id.rowcount) #------------------------------------------------------------------------------- # Function to create x and y data -def input_and_targert(data,feature_length): - - # Genarate Samples - x_samples = list() - y_samples = list() - NumerOfRows=len(data) - - for i in range(feature_length , NumerOfRows , 1): - x_sample = data[i-feature_length:i] - y_sample = data[i] - x_samples.append(x_sample) - y_samples.append(y_sample) - - # Reshape the input as a 3D (Number of Samples,time steps,features) - X = np.array(x_samples) - X=X.reshape(X.shape[0],X.shape[1],1) - print("\n____Input Data Shape :____") - print(X.shape) - # Reshape Target - Y=np.array(y_samples) - Y=Y.reshape(Y.shape[0],1) - print("\n ______Target Data Shape :______") - print(Y.shape) - - return X,Y -#---------------------------------------------------------------------------- -# function to calculate prediction + + +def input_and_targert(data, feature_length): + + # Genarate Samples + x_samples = list() + y_samples = list() + NumerOfRows = len(data) + + for i in range(feature_length, NumerOfRows, 1): + x_sample = data[i-feature_length:i] + y_sample = data[i] + x_samples.append(x_sample) + y_samples.append(y_sample) + + # Reshape the input as a 3D (Number of Samples,time steps,features) + X = np.array(x_samples) + X = X.reshape(X.shape[0], X.shape[1], 1) + print("\n____Input Data Shape :____") + print(X.shape) + # Reshape Target + Y = np.array(y_samples) + Y = Y.reshape(Y.shape[0], 1) + print("\n ______Target Data Shape :______") + print(Y.shape) + + return X, Y +# ---------------------------------------------------------------------------- +# function to calculate prediction + def predict_given_date(data, date, feature_length): - if date not in data.index: - last_date=data.tail(1) - data.loc[date]=0 - idx = data.index.get_loc(date) - # close_col = data.iloc[:,1:2] - # close_col = close_col.iloc[idx - feature_length : idx,:].values - # close_col = np.expand_dims(scaler.transform(close_col) , axis = 0) - # Prediction = model.predict(close_col) - # Prediction=np.array(Prediction).reshape(-1, 1) - # Prediction = scaler.inverse_transform(Prediction) - return str(last_date) + if date not in data.index: + last_date = data.tail(1) + data.loc[date] = 0 + idx = data.index.get_loc(date) + # close_col = data.iloc[:,1:2] + # close_col = close_col.iloc[idx - feature_length : idx,:].values + # close_col = np.expand_dims(scaler.transform(close_col) , axis = 0) + # Prediction = model.predict(close_col) + # Prediction=np.array(Prediction).reshape(-1, 1) + # Prediction = scaler.inverse_transform(Prediction) + return str(last_date) -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ def one_step_ahade(): - global data_set - global predictions_set - global model - - last_values=data_set.tail(feature_length)['Order_Demand'].values - last_values=np.array(last_values) - print(last_values) - last_values=scaler.transform(last_values.reshape(-1,1)) + global data_set + global predictions_set + global model - NumSamples=1 - TimeSteps=feature_length - NumFeatures=1 - last_values=last_values.reshape(NumSamples,TimeSteps,NumFeatures) - predicted_order_demand = model.predict(last_values) - predicted_order_demand = scaler.inverse_transform(predicted_order_demand) - predicted_order_demand=round(predicted_order_demand[0][0]) + last_values = data_set.tail(feature_length)['Order_Demand'].values + last_values = np.array(last_values) + print(last_values) + last_values = scaler.transform(last_values.reshape(-1, 1)) - last_date=str(data_set.tail(1)["Date"].values[0]) - last_date = datetime.strptime(last_date, "%Y-%m-%d") - last_date+= timedelta(days=1) - new_date=datetime.strftime(last_date,"%Y-%m-%d") + NumSamples = 1 + TimeSteps = feature_length + NumFeatures = 1 + last_values = last_values.reshape(NumSamples, TimeSteps, NumFeatures) + predicted_order_demand = model.predict(last_values) + predicted_order_demand = scaler.inverse_transform(predicted_order_demand) + predicted_order_demand = round(predicted_order_demand[0][0]) - new_row={'Date':new_date,'Order_Demand':predicted_order_demand} - data_set = data_set.append(new_row, ignore_index=True) - predictions_set= predictions_set.append(new_row, ignore_index=True) - print(predictions_set) + last_date = str(data_set.tail(1)["Date"].values[0]) + last_date = datetime.strptime(last_date, "%Y-%m-%d") + last_date += timedelta(days=1) + new_date = datetime.strftime(last_date, "%Y-%m-%d") + new_row = {'Date': new_date, 'Order_Demand': predicted_order_demand} + data_set = data_set.append(new_row, ignore_index=True) + predictions_set = predictions_set.append(new_row, ignore_index=True) + print(predictions_set) +# ----------------------------------------------------------------------------- -#------------------------------------------------------------------------------ # =========================== End of support Functions ================= -#============================= Main funtion =================== +# ============================= Main funtion =================== def setup(): - # Declare Global variables ================= + # Declare Global variables ================= - global data_set - global predictions - global result - global scaler - global accuracy - global execute_time + global data_set + global predictions + global result + global scaler + global accuracy + global execute_time + global rmse - # Read Data from DataSet - read_data_set() + # Read Data from DataSet + read_data_set() + print(data_set.describe()) - # Filter order Deamands array - data_set["Order_Demand"]=pd.to_numeric(data_set.Order_Demand,errors='coerce') - data = data_set.iloc[:,1:2] - data = data.values + # Filter order Deamands array + data_set["Order_Demand"] = pd.to_numeric( + data_set.Order_Demand, errors='coerce') + data = data_set.iloc[:, 1:2] + print(data) - ds = scaler.fit(data) - scal_data=ds.transform(data) + print("--------------------------------------") + data = data.values + ds = scaler.fit(data) + scal_data = ds.transform(data) - scal_data = scaler.fit_transform(data) + scal_data = scaler.fit_transform(data) - x,y= input_and_targert(scal_data,feature_length) - - # Split the data into training and test - x_train=x[:-testing_records] - x_test=x[-testing_records:] - y_train=y[:-testing_records] - y_test=y[-testing_records:] + x, y = input_and_targert(scal_data, feature_length) + # Split the data into training and test + x_train = x[:-testing_records] + x_test = x[-testing_records:] + y_train = y[:-testing_records] + y_test = y[-testing_records:] - print("\n___Tranning Data Shape___ ") - print(x_train.shape) - print(y_train.shape) - print("\n___Testing Data Shape___ ") - print(x_test.shape) - print(y_test.shape) + print("\n___Tranning Data Shape___ ") + print(x_train.shape) + print(y_train.shape) + print("\n___Testing Data Shape___ ") + print(x_test.shape) + print(y_test.shape) - for inp, out in zip(x_train[0:2], y_train[0:2]): - print(inp,'--', out) + for inp, out in zip(x_train[0:2], y_train[0:2]): + print(inp, '--', out) - - # Defining Input shapes for LSTM - time_steps=x_train.shape[1] - features=x_train.shape[2] - print("Number of TimeSteps:", time_steps) - print("Number of Features:", features) + # Defining Input shapes for LSTM + time_steps = x_train.shape[1] + features = x_train.shape[2] + print("Number of TimeSteps:", time_steps) + print("Number of Features:", features) + # Add First LSTM Layer + model.add(LSTM(units=input_units, activation='relu', input_shape=( + time_steps, features), return_sequences=True)) + # Adding the Second hidden layer and the LSTM layer + model.add(LSTM(units=hidden_layer_1, activation='relu', + input_shape=(time_steps, features), return_sequences=True)) - #Add First LSTM Layer - model.add(LSTM(units = input_units, activation = 'relu', input_shape = (time_steps, features), return_sequences=True)) + # Adding the Third hidden layer and the LSTM layer + model.add(LSTM(units=hidden_layer_2, + activation='relu', return_sequences=False)) - # Adding the Second hidden layer and the LSTM layer - model.add(LSTM(units = hidden_layer_1, activation = 'relu', input_shape = (time_steps, features), return_sequences=True)) + # Adding the output layer + model.add(Dense(units=output_units)) + # Compiling model + model.compile(optimizer='adam', loss='mean_squared_error') - # Adding the Third hidden layer and the LSTM layer - model.add(LSTM(units = hidden_layer_2, activation = 'relu', return_sequences=False )) + print(model.input) + print(model.output) - # Adding the output layer - model.add(Dense(units = output_units)) - # Compiling model - model.compile(optimizer = 'adam', loss = 'mean_squared_error') + print(model.summary()) - print(model.input) - print(model.output) + # Measuring the time taken by the model to train + start_time = time.time() - print(model.summary()) + # Fitting the RNN to the Training set + model_history = model.fit(x_train, y_train, batch_size, epochs) + end_time = time.time() + execute_time = round((end_time-start_time)/60, 2) + print("__Total Time Taken: ", execute_time, ' Minutes___') - # Measuring the time taken by the model to train - start_time=time.time() + # Making predictions on test data + predicted = model.predict(x_test) + predicted = scaler.inverse_transform(predicted) - # Fitting the RNN to the Training set - model_history=model.fit(x_train, y_train, batch_size , epochs) + # Getting the original price values for testing data + orig = y_test + orig = scaler.inverse_transform(y_test) - end_time=time.time() - execute_time=round((end_time-start_time)/60,2) - print("__Total Time Taken: ", execute_time, ' Minutes___') + # Accuracy of the predictions + accuracy = 100 - (100*(abs(orig-predicted)/orig)).mean() + mse = sklearn.metrics.mean_squared_error(orig, predicted) + rmse=math.sqrt(mse) + mae=sklearn.metrics.mean_absolute_error(orig, predicted) + mape=sklearn.metrics.mean_absolute_percentage_error(orig, predicted) + mape=mape + mape=round(mape,2) + + accuracy = round(accuracy, 2) + print('Accuracy:', accuracy) - # Making predictions on test data - predicted_Price = model.predict(x_test) - predicted_Price = scaler.inverse_transform(predicted_Price) + save_tranning_history(epochs, time_steps, batch_size, + execute_time, rmse,mae,mape,accuracy) - # Getting the original price values for testing data - orig=y_test - orig=scaler.inverse_transform(y_test) + # Generating predictions on full data + TrainPredictions = scaler.inverse_transform(model.predict(x_train)) + TestPredictions = scaler.inverse_transform(model.predict(x_test)) + FullDataPredictions = np.append(TrainPredictions, TestPredictions) - # Accuracy of the predictions - accuracy=100 - (100*(abs(orig-predicted_Price)/orig)).mean() - accuracy=round(accuracy,2) - print('Accuracy:',accuracy) + # Save data to result data set + + result["Date"] = data_set.iloc[time_steps:]["Date"] + result["Predictions"] = FullDataPredictions + result["OrderDemand"] = data[time_steps:] + +# ==================================================================== +# main function call - save_tranning_history(epochs,time_steps,batch_size,execute_time,accuracy) +read_model_settings() - # Generating predictions on full data - TrainPredictions=scaler.inverse_transform(model.predict(x_train)) - TestPredictions=scaler.inverse_transform(model.predict(x_test)) - FullDataPredictions=np.append(TrainPredictions, TestPredictions) +setup() - # Save data to result data set - result["Date"]=data_set.iloc[time_steps:]["Date"] - result["Predictions"]=FullDataPredictions - result["OrderDemand"]=data[time_steps:] - # ==================================================================== -# main function call -setup() +# end points declaration + +@app.route("/plot_result", methods=['GET']) +def plot_result(): + + # plotting the full data + plt.plot(result["Predictions"], color='blue', + label='Predicted Order Demand') + plt.plot(result["OrderDemand"], color='lightblue', label='Original Price') + plt.title('Order Demand Predictions') + plt.xlabel(' Date') + plt.ylabel('Order Demand') + plt.legend() + fig = plt.gcf() + fig.set_figwidth(20) + fig.set_figheight(8) + plt.show() + + return "plot complete" -#==================================================================== +@app.route('/decompose', methods=['GET']) +def decompose(): + return decompose_set.to_json(orient='records') -# end points declaration -@app.route("/predict_one_step",methods=['GET']) +@app.route('/decompose_plot_resid', methods=['GET']) +def decompose_plot(): + result = seasonal_decompose( + index_data_set, model='multiplicative', extrapolate_trend='freq', period=100) + + ax = sns.lineplot(data=result.resid) + + ax.xaxis.set_major_locator(mdates.DayLocator(interval=30)) + plt.gcf().autofmt_xdate() + + plt.show() + return decompose_set.to_json(orient='records') + + +@app.route("/predict_one_step", methods=['GET']) def predict_one_step(): - one_step_ahade() - steps=str(len(predictions_set)) - return steps + one_step_ahade() + steps = str(len(predictions_set)) + return steps + -@app.route("/predict_result",methods=['GET']) +@app.route("/predict_result", methods=['GET']) def predicpredict_result(): global predictions_set return predictions_set.to_json(orient='records') - - - -@app.route("/plot_order-demands",methods=['GET']) +@app.route("/plot_order-demands", methods=['GET']) def plot_order_demands_total(): - global raw_data_set - sns.lineplot(x='Date', y='Order_Demand',hue='Warehouse', data=raw_data_set) - plt.figure(figsize=(20, 7)) - plt.xticks(rotation=15) - plt.gcf().autofmt_xdate() + global raw_data_set + sns.lineplot(x='Date', y='Order_Demand', + hue='Warehouse', data=raw_data_set) + plt.figure(figsize=(20, 7)) + plt.xticks(rotation=15) + plt.gcf().autofmt_xdate() - plt.legend() - plt.show() + plt.legend() + plt.show() - return "Order demand" + return "Order demand" -@app.route("/plot_order_demand_total",methods=['GET']) +@app.route("/plot_order_demand_total", methods=['GET']) def plot_order_demands(): - global data_set - import matplotlib.pyplot as plt - from matplotlib.ticker import (MultipleLocator, FormatStrFormatter, - AutoMinorLocator) - import matplotlib.dates as mdates - - dtFmt = mdates.DateFormatter('%Y-%b') # define the formatting + global data_set - sns.lineplot(x='Date', y='Order_Demand', data=data_set) - plt.figure(figsize=(20, 7)) - plt.gca().xaxis.set_major_formatter(dtFmt) - # show every 12th tick on x axes - plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=1)) - plt.xticks(rotation=90, fontweight='light', fontsize='x-small',) - plt.legend() - plt.show() + dtFmt = mdates.DateFormatter('%Y-%b') # define the formatting - return "Order demand" + sns.lineplot(x='Date', y='Order_Demand', data=data_set) + plt.figure(figsize=(20, 7)) + plt.gca().xaxis.set_major_formatter(dtFmt) + # show every 12th tick on x axes + plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=1)) + plt.xticks(rotation=90, fontweight='light', fontsize='x-small',) + plt.legend() + plt.show() + return "Order demand" -@app.route("/products",methods=['GET']) +@app.route("/products", methods=['GET']) def products(): - global raw_data_set - result_array =raw_data_set['Product_code'].unique() - return result_array.tolist() + global raw_data_set + result_array = raw_data_set['Product_code'].unique() + return result_array.tolist() -@app.route("/date_range",methods=['GET']) +@app.route("/date_range", methods=['GET']) def date_range(): - result_array =data_set['Date'].unique() - return result_array.tolist() + result_array = data_set['Date'].unique() + return result_array.tolist() -@app.route("/warehouse",methods=['GET']) - +@app.route("/warehouse", methods=['GET']) def warehouse(): - global raw_data_set - warehouse_array =raw_data_set['Warehouse'].unique() - return warehouse_array.tolist() + global raw_data_set + warehouse_array = raw_data_set['Warehouse'].unique() + return warehouse_array.tolist() -@app.route("/row_data",methods=['GET']) +@app.route("/row_data", methods=['GET']) def row_data(): - global raw_data_set - return raw_data_set.to_json(orient='records') - + global raw_data_set + return raw_data_set.to_json(orient='records') - -@app.route("/validation",methods=['GET']) +@app.route("/forecast_data", methods=['GET']) def validation(): - global result - result=result.set_index(result['Date']) - return result.to_json(orient='records') + global result + result = result.set_index(result['Date']) + return result.to_json(orient='records') + -@app.route("/forecast_to_date",methods=["POST"]) +@app.route("/forecast_to_date", methods=["POST"]) def forecast_to_date(): - global data_set - global scaler - global index_data_set - global model - - # read incomming json data - data=request.get_json() - date=data['date'] - new_date=datetime.strptime(date, "%Y-%m-%d").date() - new_date=new_date - timedelta(days=(feature_length-1)) - new_date=new_date.strftime("%Y-%m-%d") - print(new_date) - - - result=predict_given_date(index_data_set,new_date, feature_length) - # df=pd.DataFrame() - # # df=pd.DataFrame(data=result,columns=["Prediction"]) - # df['Date']=pd.date_range(start=new_date,periods=feature_length) - # df=df.loc[::-1] - # df['Prediction']=result - - - # df['Date']= pd.to_datetime(df['Date']).dt.date - # df.sort_values('Date', inplace=True) - # df['Date']=df['Date'].astype(str) - # df=df.set_index(df['Date']) - # df=df.tail(1) - - return result - -@app.route('/get_accuracy',method=["POST"]) -def get_accuracy(): - # model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) - # history = model.fit(X, Y, epochs=100) - # print(history.history['loss']) - # print(history.history['accuracy']) - return "accuracy" - -@app.route("/forecast_to_range",methods=["POST"]) + global data_set + global scaler + global index_data_set + global model + + # read incomming json data + data = request.get_json() + date = data['date'] + new_date = datetime.strptime(date, "%Y-%m-%d").date() + new_date = new_date - timedelta(days=(feature_length-1)) + new_date = new_date.strftime("%Y-%m-%d") + print(new_date) + + result = predict_given_date(index_data_set, new_date, feature_length) + # df=pd.DataFrame() + # # df=pd.DataFrame(data=result,columns=["Prediction"]) + # df['Date']=pd.date_range(start=new_date,periods=feature_length) + # df=df.loc[::-1] + # df['Prediction']=result + + # df['Date']= pd.to_datetime(df['Date']).dt.date + # df.sort_values('Date', inplace=True) + # df['Date']=df['Date'].astype(str) + # df=df.set_index(df['Date']) + # df=df.tail(1) + + return result + + +@app.route("/forecast_to_range", methods=["POST"]) def forecast_to_range(): - global data_set - global scaler - global index_data_set - global model - - index_data_set=data_set - - index_data_set=index_data_set.set_index(index_data_set['Date']) - - # read incomming json data - data=request.get_json() - date=data['date'] - new_date=datetime.strptime(date, "%Y-%m-%d").date() - new_date=new_date - timedelta(days=(feature_length-1)) - new_date=new_date.strftime("%Y-%m-%d") - - result=predict_given_date(index_data_set,new_date, feature_length) - df=pd.DataFrame() - # df=pd.DataFrame(data=result,columns=["Prediction"]) - df['Date']=pd.date_range(start=new_date,periods=feature_length) - df=df.loc[::-1] - df['Prediction']=result - df['Date']= pd.to_datetime(df['Date']).dt.date - df.sort_values('Date', inplace=True) - df['Date']=df['Date'].astype(str) - df=df.set_index(df['Date']) - return df.to_json(orient='records') + global data_set + global scaler + global index_data_set + global model + + index_data_set = data_set + + index_data_set = index_data_set.set_index(index_data_set['Date']) + + # read incomming json data + data = request.get_json() + date = data['date'] + new_date = datetime.strptime(date, "%Y-%m-%d").date() + new_date = new_date - timedelta(days=(feature_length-1)) + new_date = new_date.strftime("%Y-%m-%d") + + result = predict_given_date(index_data_set, new_date, feature_length) + df = pd.DataFrame() + # df=pd.DataFrame(data=result,columns=["Prediction"]) + df['Date'] = pd.date_range(start=new_date, periods=feature_length) + df = df.loc[::-1] + df['Prediction'] = result + df['Date'] = pd.to_datetime(df['Date']).dt.date + df.sort_values('Date', inplace=True) + df['Date'] = df['Date'].astype(str) + df = df.set_index(df['Date']) + return df.to_json(orient='records') if __name__ == "__main__": - app.run() \ No newline at end of file + app.run() diff --git a/dash_board.php b/dash_board.php index 3942082..f8c22ed 100644 --- a/dash_board.php +++ b/dash_board.php @@ -97,8 +97,70 @@ option && myChart.setOption(option); </script> - - <script src="dist/js/chart2.js" type="text/javascript"> </script> + + <script type="text/javascript"> + var dom = document.getElementById('chart2'); + var myChart = echarts.init(dom, null, { + renderer: 'canvas', + useDirtyRect: false + }); + var app = {}; + + var option2; + + option2 = { + tooltip: { + trigger: 'item' + }, + legend: { + bottom: '5%', + left: 'center' + }, + series: [ + { + name: 'Access From', + type: 'pie', + radius: ['40%', '70%'], + avoidLabelOverlap: false, + itemStyle: { + borderRadius: 10, + borderColor: '#fff', + borderWidth: 2 + }, + label: { + show: false, + position: 'center' + }, + emphasis: { + label: { + show: true, + fontSize: 40, + fontWeight: 'bold' + } + }, + labelLine: { + show: false + }, + data: [ + { value: <?=$total_order_demands?>, name: 'Order demands' }, + { value: <?=$total_predection?>, name: 'Predictions' }, + { value: <?=$total_error?>, name: 'Error' }, + ] + } + ] + }; + + + if (option2 && typeof option2 === 'object') { + myChart.setOption(option2); + } + + window.addEventListener('resize', myChart.resize); + + </script> + + + <script src="dist/js/chart3.js" type="text/javascript"> </script> diff --git a/decompose.php b/decompose.php new file mode 100644 index 0000000..1d8b1c1 --- /dev/null +++ b/decompose.php @@ -0,0 +1,178 @@ +<div class="content-wrapper"> + + <?php + $title = "Analysis Result"; + $t1 = "Home"; + $t2 = "Decomposition"; + + + include_once './page_header.php';?> + <!-- Main content --> + <div class="content"> + <div class="container-fluid"> + + <?php include_once './data/decompose_data.php';?> + + + + <div class="row" style="padding: 10px;"> + + <div class="col-md-12"> + + <div style="width:full; height:400px;" id="chart1"></div> + + </div> + + <div class="col-md-12"> + + <div style="width:full; height:400px;" id="chart2"></div> + + </div> + + <div class="col-md-12"> + + <div style="width:full; height:400px;" id="chart3"></div> + + </div> + + + </div> + + <script> + var chartDom = document.getElementById('chart1'); + var myChart = echarts.init(chartDom); + var option; + + option = { + title: { + text: 'Trend' + }, + tooltip: { + trigger: 'axis' + }, + legend: { + data: ['Trend'] + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + toolbox: { + feature: { + saveAsImage: {} + } + }, + xAxis: { + type: 'category', + data: [<?=$dates?>] + }, + yAxis: { + type: 'value' + }, + series: [{ + data: [<?=$trend?>], + type: 'line', + smooth: true + }] + }; + + option && myChart.setOption(option); + </script> + + <script> + var chartDom = document.getElementById('chart2'); + var myChart2 = echarts.init(chartDom); + var option2; + + option2 = { + title: { + text: 'Sesonal' + }, + tooltip: { + trigger: 'axis' + }, + legend: { + data: ['Sesonal'] + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + toolbox: { + feature: { + saveAsImage: {} + } + }, + xAxis: { + type: 'category', + data: [<?=$dates?>] + }, + yAxis: { + type: 'value' + }, + series: [{ + data: [<?=$sesonal?>], + type: 'line', + smooth: true + }] + }; + + option2 && myChart2.setOption(option2); + </script> + + +<script> + var chartDom = document.getElementById('chart3'); + var myChart3 = echarts.init(chartDom); + var option3; + + option3 = { + title: { + text: 'Resid' + }, + tooltip: { + trigger: 'axis' + }, + legend: { + data: ['Resid'] + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + toolbox: { + feature: { + saveAsImage: {} + } + }, + xAxis: { + type: 'category', + data: [<?=$dates?>] + }, + yAxis: { + type: 'value' + }, + series: [{ + data: [<?=$resid?>], + type: 'line', + smooth: true + }] + }; + + option3 && myChart3.setOption(option3); + </script> + + + <!-- /.row --> + </div> + <!-- /.container-fluid --> + </div> + <!-- /.content --> +</div> +<!-- /.content-wrapper --> \ No newline at end of file diff --git a/forecast_list.php b/forecast_list.php new file mode 100644 index 0000000..a0a7cd3 --- /dev/null +++ b/forecast_list.php @@ -0,0 +1,120 @@ +<?php +include_once './data/forecast_data.php'; +include_once('header.php'); + +?> + + +<body class="hold-transition sidebar-mini"> + <div class="wrapper"> + <!-- Navbar --> + + <?php include_once('./nav_bar.php'); ?> + <!-- Main Sidebar Container --> + <?php include_once('./side_bar.php'); ?> + + + <!-- Content Wrapper. Contains page content --> + <div class="content-wrapper"> + <!-- Content Header (Page header) --> + + <?php + $title = "Model Settings List "; + $t1="Model"; + $t2= " Settings List"; + + + + ?> + + <?php include_once('page_header.php')?> + + <!-- Main content --> + <section class="content"> + <div class="row"> + <div class="col-12"> + + <div class="card"> + + <div class="card-header"> + <h3 class="card-title"> + <button type="button" class="btn btn-block btn-outline-secondary" + onclick="location.href = 'settings.php';">Add New Record</button> + + </h3> + </div> + + <!-- /.card-header --> + <div class="card-body"> + <table id="example23" + class="display nowrap table table-hover table-striped table-bordered" + cellspacing="0" width="100%"> + <thead> + <tr> + <th>#</th> + <th>Date</th> + <th>Forecast Order Demand</th> + <th>Epochs</th> + <th>Input Units</th> + <th>Hidden Layer 1</th> + <th>Hiddden Layer 2</th> + <th>Output Layer</th> + + + + </tr> + </thead> + <tfoot> + <tr> + <th>#</th> + <th>Feture Length</th> + <th>batch size</th> + <th>Epochs</th> + <th>Input Units</th> + <th>Hidden Layer 1</th> + <th>Hiddden Layer 2</th> + <th>Output Layer</th> + </tr> + </tfoot> + <tbody> + <?php + $i = 1; + while ($row = mysqli_fetch_assoc($result)) { + + + ?> + <tr> + <td><?php echo $i++; ?></td> + + <td><?= $row['feature_length'] ?></td> + <td><?= $row['batch_size'] ?></td> + <td><?= $row['epochs'] ?></td> + <td><?= $row['input_units'] ?></td> + <td><?= $row['hidden_layer_1'] ?></td> + <td><?= $row['hidden_layer_2'] ?></td> + <td><?= $row['output_units'] ?></td> + </tr> + <?php } ?> + </tbody> + </table> + </div> + <!-- /.card-body --> + </div> + <!-- /.card --> + </div> + <!-- /.col --> + </div> + <!-- /.row --> + </section> + <!-- /.content --> + </div> + + <?php include_once('control_side_bar.php');?> + <!-- /.content-wrapper --> + <?php include_once('footer.php');?> + + </div> + <?php include_once('footer_script.php');?> +</body> + +</html> \ No newline at end of file diff --git a/inc/function.php b/inc/function.php index e5b8515..e1c54d9 100644 --- a/inc/function.php +++ b/inc/function.php @@ -13,6 +13,11 @@ function get_accurecy($conn){ return $res['accurecy']; +} + +function get_layer_1_nodes(){ + + } function get_epochs($conn){ diff --git a/index.php b/index.php index 457eb67..25cb3b3 100644 --- a/index.php +++ b/index.php @@ -3,12 +3,6 @@ include_once('inc/conn.php'); include_once('header.php'); - - - - - - ?> <body class="hold-transition sidebar-mini"> diff --git a/output.png b/output.png new file mode 100644 index 0000000000000000000000000000000000000000..9f7e2eb4aa8555cc8df98bcee38001670dc8f135 GIT binary patch literal 16131 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 CQr|cL literal 0 HcmV?d00001 diff --git a/page_decompose.php b/page_decompose.php new file mode 100644 index 0000000..c8aa7bf --- /dev/null +++ b/page_decompose.php @@ -0,0 +1,26 @@ +<?php +include_once('inc/conn.php'); +include_once('header.php'); + +?> + +<body class="hold-transition sidebar-mini"> + <div class="wrapper"> + + + + <?php include_once('./nav_bar.php'); ?> + <!-- Main Sidebar Container --> + <?php include_once('./side_bar.php'); ?> + + <?php include_once('decompose.php');?> + + <?php include_once('control_side_bar.php');?> + + <?php include_once('footer.php');?> + </div> + + <?php include_once('footer_script.php');?> +</body> + +</html> \ No newline at end of file diff --git a/perforemence_list.php b/perforemence_list.php new file mode 100644 index 0000000..e3ac5bf --- /dev/null +++ b/perforemence_list.php @@ -0,0 +1,132 @@ +<?php +include_once './data/data_mp.php'; +include_once('header.php'); + + +?> + + + + +<body class="hold-transition sidebar-mini"> + <div class="wrapper"> + <!-- Navbar --> + + <?php include_once('./nav_bar.php'); ?> + <!-- Main Sidebar Container --> + <?php include_once('./side_bar.php'); ?> + + + <!-- Content Wrapper. Contains page content --> + <div class="content-wrapper"> + <!-- Content Header (Page header) --> + + <?php + $title = "Model Settings List "; + $t1="Model"; + $t2= " Settings List"; + + + + ?> + + <?php include_once('page_header.php')?> + + <!-- Main content --> + <section class="content"> + <div class="row"> + <div class="col-12"> + + <div class="card"> + + <div class="card-header"> + <h3 class="card-title"> + <button type="button" class="btn btn-block btn-outline-secondary" + onclick="location.href = 'settings.php';">Add New Record</button> + + </h3> + </div> + + <!-- /.card-header --> + <div class="card-body"> + <table id="example23" + class="display nowrap table table-hover table-striped table-bordered" + cellspacing="0" width="100%"> + <thead> + <tr> + <th>#</th> + <th>Input Nodes</th> + <th>Hidden layer 1 nodes</th> + <th>Hidden layer 2 nodes</th> + <th>output nodes</th> + <th>Epochs</th> + <th>RMSE</th> + <th>MAE</th> + <th>MAPE</th> + <th>Accurecy %</th> + + + + + </tr> + </thead> + <tfoot> + <tr> + <th>#</th> + <th>Input Nodes</th> + <th>Hidden layer 1 nodes</th> + <th>Hidden layer 2 nodes</th> + <th>output nodes</th> + <th>Epochs</th> + <th>RMSE</th> + <th>MAE</th> + <th>MAPE</th> + <th>Accurecy %</th> + + </tr> + </tfoot> + <tbody> + <?php + $i = 1; + while ($row = mysqli_fetch_assoc($result)) { + + + ?> + <tr> + <td><?php echo $i++; ?></td> + + <td><?= $row['input_units'] ?></td> + <td><?= $row['hidden_layer_1'] ?></td> + <td><?= $row['hidden_layer_2'] ?></td> + <td><?= $row['output_units'] ?></td> + <td><?= $row['epochs'] ?></td> + <td><?= round($row['rmse'],3) ?></td> + <td><?= round($row['mae'],3) ?></td> + <td><?= $row['mape'] ?></td> + <td><?= $row['accurecy'] ?></td> + + </tr> + <?php } ?> + </tbody> + </table> + </div> + <!-- /.card-body --> + </div> + <!-- /.card --> + </div> + <!-- /.col --> + </div> + <!-- /.row --> + </section> + <!-- /.content --> + </div> + + <?php include_once('control_side_bar.php');?> + <!-- /.content-wrapper --> + <?php include_once('footer.php');?> + + </div> + <?php include_once('footer_script.php');?> +</body> + +</html> \ No newline at end of file diff --git a/settings.php b/settings.php index b823698..4dbd154 100644 --- a/settings.php +++ b/settings.php @@ -47,22 +47,75 @@ include_once('header.php'); <div class="form-row"> <div class="col-lg-6 col-md-6 form-group"> - <lable>Number of Nodes for Layer 1:</lable> + <lable>Feature Length:</lable> - <input type="text" class="form-control" name="layer1_nodes" + <input type="text" class="form-control" name="feture_length" placeholder="0"> </div> <div class="col-lg-6 col-md-6 form-group"> - <lable>Number of Nodes for Layer 2:</lable> - - <input type="text" class="form-control" name="layer2_nodes" + <lable>Batch Size:</lable> + + <input type="text" class="form-control" name="batch_size" + placeholder="0"> + + </div> + + <div class="col-lg-6 col-md-6 form-group"> + <lable>Epochs:</lable> + + <input type="text" class="form-control" name="epochs" + placeholder="0"> + + </div> + + <div class="col-lg-6 col-md-6 form-group"> + <lable>Input Layer:</lable> + + <input type="text" class="form-control" name="input_units" placeholder="0"> </div> + <div class="col-lg-6 col-md-6 form-group"> + <lable>Hidden Layer 1:</lable> + + <input type="text" class="form-control" name="hidden_layer_1" + placeholder="0"> + </div> + <div class="col-lg-6 col-md-6 form-group"> + <lable>Hidden Layer 2:</lable> + + <input type="text" class="form-control" name="hidden_layer_2" + placeholder="0"> + </div> + + <div class="col-lg-6 col-md-6 form-group"> + <lable>Output Layer:</lable> + + <input type="text" class="form-control" name="output_layer" + placeholder="0"> + + </div> + + + + + + </div> + + <div class="form-row"> + + <div class="col-md-6"> + + </div> + + <div class="col-md-6 "> + <input type="submit" class="btn btn-outline-success float-right" value="Add New"> + </div> + </div> diff --git a/settings_list.php b/settings_list.php new file mode 100644 index 0000000..4692285 --- /dev/null +++ b/settings_list.php @@ -0,0 +1,120 @@ +<?php +include_once './data/model_settings_list.php'; +include_once('header.php'); + +?> + + +<body class="hold-transition sidebar-mini"> + <div class="wrapper"> + <!-- Navbar --> + + <?php include_once('./nav_bar.php'); ?> + <!-- Main Sidebar Container --> + <?php include_once('./side_bar.php'); ?> + + + <!-- Content Wrapper. Contains page content --> + <div class="content-wrapper"> + <!-- Content Header (Page header) --> + + <?php + $title = "Model Settings List "; + $t1="Model"; + $t2= " Settings List"; + + + + ?> + + <?php include_once('page_header.php')?> + + <!-- Main content --> + <section class="content"> + <div class="row"> + <div class="col-12"> + + <div class="card"> + + <div class="card-header"> + <h3 class="card-title"> + <button type="button" class="btn btn-block btn-outline-secondary" + onclick="location.href = 'settings.php';">Add New Record</button> + + </h3> + </div> + + <!-- /.card-header --> + <div class="card-body"> + <table id="example23" + class="display nowrap table table-hover table-striped table-bordered" + cellspacing="0" width="100%"> + <thead> + <tr> + <th>#</th> + <th>Feture Length</th> + <th>batch size</th> + <th>Epochs</th> + <th>Input Units</th> + <th>Hidden Layer 1</th> + <th>Hiddden Layer 2</th> + <th>Output Layer</th> + + + + </tr> + </thead> + <tfoot> + <tr> + <th>#</th> + <th>Feture Length</th> + <th>batch size</th> + <th>Epochs</th> + <th>Input Units</th> + <th>Hidden Layer 1</th> + <th>Hiddden Layer 2</th> + <th>Output Layer</th> + </tr> + </tfoot> + <tbody> + <?php + $i = 1; + while ($row = mysqli_fetch_assoc($result)) { + + + ?> + <tr> + <td><?php echo $i++; ?></td> + + <td><?= $row['feature_length'] ?></td> + <td><?= $row['batch_size'] ?></td> + <td><?= $row['epochs'] ?></td> + <td><?= $row['input_units'] ?></td> + <td><?= $row['hidden_layer_1'] ?></td> + <td><?= $row['hidden_layer_2'] ?></td> + <td><?= $row['output_units'] ?></td> + </tr> + <?php } ?> + </tbody> + </table> + </div> + <!-- /.card-body --> + </div> + <!-- /.card --> + </div> + <!-- /.col --> + </div> + <!-- /.row --> + </section> + <!-- /.content --> + </div> + + <?php include_once('control_side_bar.php');?> + <!-- /.content-wrapper --> + <?php include_once('footer.php');?> + + </div> + <?php include_once('footer_script.php');?> +</body> + +</html> \ No newline at end of file diff --git a/side_bar.php b/side_bar.php index 99520a4..041f873 100644 --- a/side_bar.php +++ b/side_bar.php @@ -46,11 +46,11 @@ <li class="nav-item"> <a href="run.php" class="nav-link"> <i class="fa fa-play nav-icon"></i> - <p>Run Model</p> + <p>Model History</p> </a> </li> <li class="nav-item"> - <a href="settings.php" class="nav-link"> + <a href="settings_list.php" class="nav-link"> <i class="fa fa-cog nav-icon"></i> <p>Model Settings</p> </a> @@ -73,37 +73,44 @@ <p>Get the forecast</p> </a> </li> + + <li class="nav-item"> + <a href="page_forecast.php" class="nav-link"> + <i class="fas fa-list nav-icon"></i> + <p>List Forecast</p> + </a> + </li> </ul> </li> <li class="nav-header">Data Analytics</li> <li class="nav-item"> - <a href="products.php" class="nav-link"> - <i class="nav-icon fas fa-calendar-alt"></i> + <a href="page_decompose.php" class="nav-link"> + <i class="nav-icon far fa-chart-bar"></i> <p> - Products + Time Series </p> </a> </li> <li class="nav-item"> - <a href="pages/gallery.html" class="nav-link"> - <i class="nav-icon far fa-image"></i> + <a href="perforemence_list.php" class="nav-link"> + <i class="nav-icon fa-solid fa-dumbbell"></i> <p> - Warehouse + Model Perforemence </p> </a> </li> - <li class="nav-item"> + <!-- <li class="nav-item"> <a href="category.php" class="nav-link"> <i class="nav-icon far fa-image"></i> <p> Category </p> </a> - </li> + </li> --> </ul> -- GitLab