Tin Theethawat Savastham commited on
Commit ·
d4c7aae
1
Parent(s): 92dbef5
✨ Add Model Code
Browse files- Readme.md +19 -0
- model/.gitignore +2 -0
- model/display_input_variation.py +167 -0
- model/extractor/.gitignore +1 -0
- model/extractor/adjust_data.py +15 -0
- model/extractor/emanufac_tdabc_extractor_class.py +389 -0
- model/extractor/shaker_augmentation.py +134 -0
- model/matrix_generator/.gitignore +1 -0
- model/matrix_generator/cost_matrix_class.py +550 -0
- model/matrix_generator/cost_matrix_generator.py +297 -0
- model/model/.gitignore +1 -0
- model/model/activation.py +20 -0
- model/model/captial_fc_layer.py +111 -0
- model/model/employee_fc_layer.py +121 -0
- model/model/generate_data_set.py +78 -0
- model/model/layer.py +17 -0
- model/model/loss.py +21 -0
- model/model/material_fc_layer.py +94 -0
- model/model/material_network.py +113 -0
- model/model/matrix_normalization.py +153 -0
- model/model/network.py +105 -0
- model/model/normalize.py +70 -0
- model/model/sample_payload_adjustment.py +152 -0
- model/model/tdce_model.py +541 -0
- model/model/time_driven_network.py +109 -0
- model/model/weight_activation.py +10 -0
- model/plot_input_variation.py +12 -0
- model/result_display.py +114 -0
- model/viyacrab_augmentation.py +78 -0
- requirement.txt +11 -0
Readme.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Time Driven Cost Estimation Learning Model (TDCE)
|
| 2 |
+
|
| 3 |
+
This is the open-source part of Time-Driven Cost Estimation Learning Model under the research titled "Artificial Neural Network like for Manufacturing Cost Estimation" wish to create neural network like system by using the core equation of time-driven activity-based costing.
|
| 4 |
+
|
| 5 |
+
## Starting
|
| 6 |
+
|
| 7 |
+
Creating ENV followed by `.env.example` and then Creating your virtual environment
|
| 8 |
+
|
| 9 |
+
```
|
| 10 |
+
python -m venv venv
|
| 11 |
+
```
|
| 12 |
+
|
| 13 |
+
Install all requirements
|
| 14 |
+
|
| 15 |
+
```
|
| 16 |
+
pip install -r requirement.txt
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
© 2024, Prince of Songkla University under Inteligent Automation Engineering Center
|
model/.gitignore
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__pycache__
|
| 2 |
+
generated/
|
model/display_input_variation.py
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
from scipy.stats import variation, iqr
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def display_input_variation(
|
| 6 |
+
process_df,
|
| 7 |
+
material_usage_df,
|
| 8 |
+
employee_usage,
|
| 9 |
+
capital_cost_df,
|
| 10 |
+
):
|
| 11 |
+
process_des = process_df.describe()
|
| 12 |
+
|
| 13 |
+
cost_dict = {
|
| 14 |
+
"data": "Total Cost",
|
| 15 |
+
"records": process_des["cost"]["count"],
|
| 16 |
+
"types": len(process_df["process_id"].unique()),
|
| 17 |
+
"min": process_des["cost"]["min"],
|
| 18 |
+
"mean": round(process_des["cost"]["mean"], 2),
|
| 19 |
+
"max": process_des["cost"]["max"],
|
| 20 |
+
"sd": process_des["cost"]["std"],
|
| 21 |
+
"variation": variation(process_df["cost"]),
|
| 22 |
+
"iqr": iqr(process_df["cost"]),
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
material_des = material_usage_df.describe()
|
| 26 |
+
|
| 27 |
+
material_amount = {
|
| 28 |
+
"data": "Material Amount",
|
| 29 |
+
"records": material_des["amount"]["count"],
|
| 30 |
+
"types": len(material_usage_df["name"].unique()),
|
| 31 |
+
"min": material_des["amount"]["min"],
|
| 32 |
+
"mean": round(material_des["amount"]["mean"], 2),
|
| 33 |
+
"max": material_des["amount"]["max"],
|
| 34 |
+
"sd": material_des["amount"]["std"],
|
| 35 |
+
"variation": variation(material_usage_df["amount"]),
|
| 36 |
+
"iqr": iqr(material_usage_df["amount"]),
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
material_unit_cost = {
|
| 40 |
+
"data": "Material Unit Cost",
|
| 41 |
+
"records": material_des["unit_cost"]["count"],
|
| 42 |
+
"types": len(material_usage_df["name"].unique()),
|
| 43 |
+
"min": material_des["unit_cost"]["min"],
|
| 44 |
+
"mean": round(material_des["unit_cost"]["mean"], 2),
|
| 45 |
+
"max": material_des["unit_cost"]["max"],
|
| 46 |
+
"sd": material_des["unit_cost"]["std"],
|
| 47 |
+
"variation": variation(material_usage_df["unit_cost"]),
|
| 48 |
+
"iqr": iqr(material_usage_df["unit_cost"]),
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
employee_usage["duration"] = (
|
| 52 |
+
employee_usage["duration"] * employee_usage["amount"]
|
| 53 |
+
)
|
| 54 |
+
ec_des = employee_usage.describe()
|
| 55 |
+
|
| 56 |
+
ec_unit_cost = {
|
| 57 |
+
"data": "Labor Unit Cost",
|
| 58 |
+
"records": ec_des["cost"]["count"],
|
| 59 |
+
"types": len(employee_usage["employee_name"].unique()),
|
| 60 |
+
"min": ec_des["cost"]["min"],
|
| 61 |
+
"mean": round(ec_des["cost"]["mean"], 2),
|
| 62 |
+
"max": ec_des["cost"]["max"],
|
| 63 |
+
"sd": ec_des["cost"]["std"],
|
| 64 |
+
"variation": variation(employee_usage["cost"]),
|
| 65 |
+
"iqr": iqr(employee_usage["cost"]),
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
ec_duration = {
|
| 69 |
+
"data": "Labor Duration",
|
| 70 |
+
"records": ec_des["duration"]["count"],
|
| 71 |
+
"types": len(employee_usage["employee_name"].unique()),
|
| 72 |
+
"min": ec_des["duration"]["min"],
|
| 73 |
+
"mean": round(ec_des["duration"]["mean"], 2),
|
| 74 |
+
"max": ec_des["duration"]["max"],
|
| 75 |
+
"sd": ec_des["duration"]["std"],
|
| 76 |
+
"variation": variation(employee_usage["duration"]),
|
| 77 |
+
"iqr": iqr(employee_usage["duration"]),
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
ec_day_amount = {
|
| 81 |
+
"data": "Labor Day Amount",
|
| 82 |
+
"records": ec_des["day_amount"]["count"],
|
| 83 |
+
"types": len(employee_usage["employee_name"].unique()),
|
| 84 |
+
"min": ec_des["day_amount"]["min"],
|
| 85 |
+
"mean": round(ec_des["day_amount"]["mean"], 2),
|
| 86 |
+
"max": ec_des["day_amount"]["max"],
|
| 87 |
+
"sd": ec_des["day_amount"]["std"],
|
| 88 |
+
"variation": variation(employee_usage["day_amount"]),
|
| 89 |
+
"iqr": iqr(employee_usage["day_amount"]),
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
capital_des = capital_cost_df.describe()
|
| 93 |
+
|
| 94 |
+
cc_unit_cost = {
|
| 95 |
+
"data": "Capital Cost",
|
| 96 |
+
"records": capital_des["cost"]["count"],
|
| 97 |
+
"types": len(capital_cost_df["name"].unique()),
|
| 98 |
+
"min": capital_des["cost"]["min"],
|
| 99 |
+
"mean": round(capital_des["cost"]["mean"], 2),
|
| 100 |
+
"max": capital_des["cost"]["max"],
|
| 101 |
+
"sd": capital_des["cost"]["std"],
|
| 102 |
+
"variation": variation(capital_cost_df["cost"]),
|
| 103 |
+
"iqr": iqr(capital_cost_df["cost"])
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
cc_dayamount = {
|
| 107 |
+
"data": "Capital Cost Day Amount",
|
| 108 |
+
"records": capital_des["day_amount"]["count"],
|
| 109 |
+
"types": len(capital_cost_df["name"].unique()),
|
| 110 |
+
"min": capital_des["day_amount"]["min"],
|
| 111 |
+
"mean": round(capital_des["day_amount"]["mean"], 2),
|
| 112 |
+
"max": capital_des["day_amount"]["max"],
|
| 113 |
+
"sd": capital_des["day_amount"]["std"],
|
| 114 |
+
"variation": variation(capital_cost_df["day_amount"]),
|
| 115 |
+
"iqr": iqr(capital_cost_df["day_amount"])
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
cc_duration = {
|
| 119 |
+
"data": "Capital Cost Duration",
|
| 120 |
+
"records": capital_des["duration"]["count"],
|
| 121 |
+
"types": len(capital_cost_df["name"].unique()),
|
| 122 |
+
"min": capital_des["duration"]["min"],
|
| 123 |
+
"mean": round(capital_des["duration"]["mean"], 2),
|
| 124 |
+
"max": capital_des["duration"]["max"],
|
| 125 |
+
"sd": capital_des["duration"]["std"],
|
| 126 |
+
"variation": variation(capital_cost_df["duration"]),
|
| 127 |
+
"iqr": iqr(capital_cost_df["duration"])
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
data_variation = pd.DataFrame(
|
| 131 |
+
[
|
| 132 |
+
cost_dict,
|
| 133 |
+
material_unit_cost,
|
| 134 |
+
material_amount,
|
| 135 |
+
ec_unit_cost,
|
| 136 |
+
ec_duration,
|
| 137 |
+
ec_day_amount,
|
| 138 |
+
cc_unit_cost,
|
| 139 |
+
cc_dayamount,
|
| 140 |
+
cc_duration,
|
| 141 |
+
]
|
| 142 |
+
)
|
| 143 |
+
|
| 144 |
+
# try:
|
| 145 |
+
# display(data_variation)
|
| 146 |
+
# except:
|
| 147 |
+
# print("Not Run in Jupyter Notebook")
|
| 148 |
+
# print(data_variation)
|
| 149 |
+
return data_variation
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
def display_input_variation_by_directory(folder_name):
|
| 153 |
+
process_df = pd.read_csv(f"{folder_name}/generated_process_data.csv")
|
| 154 |
+
material_usage_df = pd.read_csv(
|
| 155 |
+
f"{folder_name}/generated_material_usage.csv")
|
| 156 |
+
employee_usage_df = pd.read_csv(
|
| 157 |
+
f"{folder_name}/generated_employee_usage.csv")
|
| 158 |
+
capital_cost_df = pd.read_csv(f"{folder_name}/generated_captial_cost.csv")
|
| 159 |
+
|
| 160 |
+
result_variation = display_input_variation(
|
| 161 |
+
process_df,
|
| 162 |
+
material_usage_df,
|
| 163 |
+
employee_usage_df,
|
| 164 |
+
capital_cost_df,
|
| 165 |
+
)
|
| 166 |
+
|
| 167 |
+
return result_variation
|
model/extractor/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
__pycache__
|
model/extractor/adjust_data.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
def adjust_to_match_process(capital_cost_usage,
|
| 3 |
+
employee_usage,
|
| 4 |
+
material_usage,
|
| 5 |
+
new_process_df):
|
| 6 |
+
new_capital_cost = capital_cost_usage.copy()
|
| 7 |
+
new_capital_cost = new_capital_cost[new_capital_cost['process_id'].isin(
|
| 8 |
+
new_process_df['process_id'])]
|
| 9 |
+
new_employee_usage = employee_usage.copy()
|
| 10 |
+
new_employee_usage = new_employee_usage[
|
| 11 |
+
new_employee_usage['process_id'].isin(new_process_df['process_id'])]
|
| 12 |
+
new_material_usage = material_usage.copy()
|
| 13 |
+
new_material_usage = new_material_usage[
|
| 14 |
+
new_material_usage['process_id'].isin(new_process_df['process_id'])]
|
| 15 |
+
return new_capital_cost, new_employee_usage, new_material_usage
|
model/extractor/emanufac_tdabc_extractor_class.py
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import requests
|
| 3 |
+
import numpy as np
|
| 4 |
+
import pickle
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class EManufacTDABCExtractor:
|
| 8 |
+
def __init__(self, api_url, api_key, profile_id, costed_place):
|
| 9 |
+
self.api_url = api_url
|
| 10 |
+
self.api_key = api_key
|
| 11 |
+
self.process_df = pd.DataFrame()
|
| 12 |
+
self.material_usage_df = pd.DataFrame()
|
| 13 |
+
self.original_material_usage_df = pd.DataFrame()
|
| 14 |
+
self.original_employee_usage_df = pd.DataFrame()
|
| 15 |
+
self.original_process_df = pd.DataFrame()
|
| 16 |
+
self.capital_cost_df = pd.DataFrame()
|
| 17 |
+
self.employee_usage_df = pd.DataFrame()
|
| 18 |
+
self.original_capital_cost_df = pd.DataFrame()
|
| 19 |
+
self.profile_id = profile_id # Profile For TDABC
|
| 20 |
+
self.original_procedure_profile_id = "" # Profile For Factory Current Method
|
| 21 |
+
self.profile_element_name_for_material = "ต้นทุนวัตถุดิบ"
|
| 22 |
+
self.costed_place = costed_place
|
| 23 |
+
self.running_no_start = ""
|
| 24 |
+
self.running_no_end = ""
|
| 25 |
+
|
| 26 |
+
def set_running_no_margin(self, start, end):
|
| 27 |
+
self.running_no_start = start
|
| 28 |
+
self.running_no_end = end
|
| 29 |
+
print("Setting Successfully")
|
| 30 |
+
|
| 31 |
+
def fetch_material_usage(self, start_date, end_date, limit, page=1):
|
| 32 |
+
url = f"{self.api_url}/cost-estimation/on-type"
|
| 33 |
+
headers = {
|
| 34 |
+
"Accept": "application/json",
|
| 35 |
+
"Authorization": f"Bearer {self.api_key}",
|
| 36 |
+
}
|
| 37 |
+
querystring = {
|
| 38 |
+
"startDate": start_date,
|
| 39 |
+
"endDate": end_date,
|
| 40 |
+
"size": limit,
|
| 41 |
+
"page": page,
|
| 42 |
+
"profile": self.profile_id,
|
| 43 |
+
"elementType": "MATERIAL",
|
| 44 |
+
"placeRestricNotify": "true",
|
| 45 |
+
"correctPlaceOnly": "true",
|
| 46 |
+
"extractOriginalLot": "true",
|
| 47 |
+
"place": self.costed_place,
|
| 48 |
+
"specifyProfileElement": self.profile_element_name_for_material,
|
| 49 |
+
"runningNoStart": self.running_no_start,
|
| 50 |
+
"runningNoEnd": self.running_no_end,
|
| 51 |
+
}
|
| 52 |
+
response = requests.get(url, headers=headers, params=querystring)
|
| 53 |
+
try:
|
| 54 |
+
material_data = response.json()["rows"]
|
| 55 |
+
except Exception as e:
|
| 56 |
+
print("Error in fetch material", e)
|
| 57 |
+
material_data = []
|
| 58 |
+
|
| 59 |
+
self.material_usage_df = pd.DataFrame(material_data)
|
| 60 |
+
self.original_material_usage_df = pd.DataFrame(material_data)
|
| 61 |
+
|
| 62 |
+
with open("material.pickle", "wb") as handle:
|
| 63 |
+
pickle.dump(self.material_usage_df, handle)
|
| 64 |
+
|
| 65 |
+
return (self.material_usage_df,)
|
| 66 |
+
|
| 67 |
+
def fetch_employee_usage(self, start_date, end_date, limit, page=1):
|
| 68 |
+
url = f"{self.api_url}/cost-estimation/on-type"
|
| 69 |
+
headers = {
|
| 70 |
+
"Accept": "application/json",
|
| 71 |
+
"Authorization": f"Bearer {self.api_key}",
|
| 72 |
+
}
|
| 73 |
+
querystring = {
|
| 74 |
+
"startDate": start_date,
|
| 75 |
+
"endDate": end_date,
|
| 76 |
+
"size": limit,
|
| 77 |
+
"page": page,
|
| 78 |
+
"profile": self.profile_id,
|
| 79 |
+
"elementType": "LABOR",
|
| 80 |
+
"placeRestricNotify": "true",
|
| 81 |
+
"correctPlaceOnly": "true",
|
| 82 |
+
"place": self.costed_place,
|
| 83 |
+
"merged": "true",
|
| 84 |
+
"runningNoStart": self.running_no_start,
|
| 85 |
+
"runningNoEnd": self.running_no_end,
|
| 86 |
+
}
|
| 87 |
+
response = requests.get(url, headers=headers, params=querystring)
|
| 88 |
+
try:
|
| 89 |
+
employee_data = response.json()["rows"]
|
| 90 |
+
except Exception as e:
|
| 91 |
+
print("Error in fetch employee", e)
|
| 92 |
+
employee_data = []
|
| 93 |
+
|
| 94 |
+
self.employee_usage_df = pd.DataFrame(employee_data)
|
| 95 |
+
self.original_employee_usage_df = pd.DataFrame(employee_data)
|
| 96 |
+
|
| 97 |
+
with open("employee.pickle", "wb") as handle:
|
| 98 |
+
pickle.dump(self.employee_usage_df, handle)
|
| 99 |
+
|
| 100 |
+
return (self.employee_usage_df,)
|
| 101 |
+
|
| 102 |
+
def fetch_capital_cost_usage(self, start_date, end_date, limit, page=1):
|
| 103 |
+
url = f"{self.api_url}/cost-estimation/on-type"
|
| 104 |
+
headers = {
|
| 105 |
+
"Accept": "application/json",
|
| 106 |
+
"Authorization": f"Bearer {self.api_key}",
|
| 107 |
+
}
|
| 108 |
+
querystring = {
|
| 109 |
+
"startDate": start_date,
|
| 110 |
+
"endDate": end_date,
|
| 111 |
+
"size": limit,
|
| 112 |
+
"page": page,
|
| 113 |
+
"profile": self.profile_id,
|
| 114 |
+
"elementType": "CAPITAL_COST",
|
| 115 |
+
"placeRestricNotify": "true",
|
| 116 |
+
"correctPlaceOnly": "true",
|
| 117 |
+
"place": self.costed_place,
|
| 118 |
+
"merged": "true",
|
| 119 |
+
"splitCostDriver": "true",
|
| 120 |
+
"runningNoStart": self.running_no_start,
|
| 121 |
+
"runningNoEnd": self.running_no_end,
|
| 122 |
+
}
|
| 123 |
+
response = requests.get(url, headers=headers, params=querystring)
|
| 124 |
+
try:
|
| 125 |
+
capital_cost_data = response.json()["rows"]
|
| 126 |
+
except Exception as e:
|
| 127 |
+
print("Error in fetch capital cost", e)
|
| 128 |
+
capital_cost_data = []
|
| 129 |
+
|
| 130 |
+
self.capital_cost_df = pd.DataFrame(capital_cost_data)
|
| 131 |
+
self.original_capital_cost_df = pd.DataFrame(capital_cost_data)
|
| 132 |
+
|
| 133 |
+
with open("capital.pickle", "wb") as handle:
|
| 134 |
+
pickle.dump(self.capital_cost_df, handle)
|
| 135 |
+
|
| 136 |
+
return (self.capital_cost_df,)
|
| 137 |
+
|
| 138 |
+
def change_profile_element_for_material(self, new_element_name):
|
| 139 |
+
self.profile_element_name_for_material = new_element_name
|
| 140 |
+
print("Success Changing")
|
| 141 |
+
|
| 142 |
+
# Profile For Current Factory Cost Estimation Method
|
| 143 |
+
def change_profile_for_original_procedure(self, profile_id):
|
| 144 |
+
self.original_procedure_profile_id = profile_id
|
| 145 |
+
print("Success Changing")
|
| 146 |
+
|
| 147 |
+
# Get Data From Current Factory Cost Estimation Method as a Reference or Result
|
| 148 |
+
# Of our new Profile using TDABC
|
| 149 |
+
def fetch_process_data(self, start_date, end_date, limit, page=1):
|
| 150 |
+
url = f"{self.api_url}/cost-estimation"
|
| 151 |
+
headers = {
|
| 152 |
+
"Accept": "application/json",
|
| 153 |
+
"Authorization": f"Bearer {self.api_key}",
|
| 154 |
+
}
|
| 155 |
+
querystring = {
|
| 156 |
+
"startDate": start_date,
|
| 157 |
+
"endDate": end_date,
|
| 158 |
+
"size": limit,
|
| 159 |
+
"page": page,
|
| 160 |
+
"profile": self.original_procedure_profile_id,
|
| 161 |
+
"hideResultList": "true",
|
| 162 |
+
"placeRestricNotify": "true",
|
| 163 |
+
"correctPlaceOnly": "true",
|
| 164 |
+
"runningNoStart": self.running_no_start,
|
| 165 |
+
"runningNoEnd": self.running_no_end,
|
| 166 |
+
"place": self.costed_place,
|
| 167 |
+
}
|
| 168 |
+
response = requests.get(url, headers=headers, params=querystring)
|
| 169 |
+
process_data = response.json()["rows"]
|
| 170 |
+
|
| 171 |
+
self.process_df = pd.DataFrame(process_data)
|
| 172 |
+
self.original_process_df = pd.DataFrame(process_data)
|
| 173 |
+
|
| 174 |
+
with open("process.pickle", "wb") as handle:
|
| 175 |
+
pickle.dump(self.process_df, handle)
|
| 176 |
+
|
| 177 |
+
return (self.process_df,)
|
| 178 |
+
|
| 179 |
+
def load_from_pickle(self):
|
| 180 |
+
|
| 181 |
+
try:
|
| 182 |
+
with open("material.pickle", "rb") as handle:
|
| 183 |
+
material_usage_df = pickle.load(handle)
|
| 184 |
+
self.material_usage_df = material_usage_df
|
| 185 |
+
self.original_material_usage_df = material_usage_df
|
| 186 |
+
except:
|
| 187 |
+
print("Error loading material Pickle")
|
| 188 |
+
|
| 189 |
+
try:
|
| 190 |
+
with open("employee.pickle", "rb") as handle:
|
| 191 |
+
employee_usage_df = pickle.load(handle)
|
| 192 |
+
self.employee_usage_df = employee_usage_df
|
| 193 |
+
self.original_employee_usage_df = employee_usage_df
|
| 194 |
+
except:
|
| 195 |
+
print("Error loading employee Pickle")
|
| 196 |
+
|
| 197 |
+
try:
|
| 198 |
+
with open("capital.pickle", "rb") as handle:
|
| 199 |
+
capital_cost_df = pickle.load(handle)
|
| 200 |
+
self.capital_cost_df = capital_cost_df
|
| 201 |
+
self.original_capital_cost_df = capital_cost_df
|
| 202 |
+
except:
|
| 203 |
+
print("Error loading capital Pickle")
|
| 204 |
+
|
| 205 |
+
try:
|
| 206 |
+
with open("process.pickle", "rb") as handle:
|
| 207 |
+
process_df = pickle.load(handle)
|
| 208 |
+
self.process_df = process_df
|
| 209 |
+
self.original_process_df = process_df
|
| 210 |
+
except:
|
| 211 |
+
print("Error loading Process Pickle")
|
| 212 |
+
|
| 213 |
+
# self.capital_cost_df = capital_cost_df
|
| 214 |
+
print("Loaded from pickle Successfully")
|
| 215 |
+
|
| 216 |
+
def get_process_list(self):
|
| 217 |
+
return self.process_df
|
| 218 |
+
|
| 219 |
+
def get_material_usage(self):
|
| 220 |
+
return self.material_usage_df
|
| 221 |
+
|
| 222 |
+
def get_employee_usage(self):
|
| 223 |
+
return self.employee_usage_df
|
| 224 |
+
|
| 225 |
+
def get_capital_cost(self):
|
| 226 |
+
return self.capital_cost_df
|
| 227 |
+
|
| 228 |
+
def load_material_usage(self, material_usage_df):
|
| 229 |
+
self.material_usage_df = material_usage_df
|
| 230 |
+
|
| 231 |
+
def load_employee_usage(self, employee_usage_df):
|
| 232 |
+
self.employee_usage_df = employee_usage_df
|
| 233 |
+
|
| 234 |
+
def load_capital_cost(self, capital_cost_df):
|
| 235 |
+
self.capital_cost_df = capital_cost_df
|
| 236 |
+
|
| 237 |
+
def load_process(self, process_df):
|
| 238 |
+
self.process_df = process_df
|
| 239 |
+
|
| 240 |
+
def load_original_process(self, process_df):
|
| 241 |
+
self.original_process_df = process_df
|
| 242 |
+
|
| 243 |
+
def load_original_material_usage(self, material_usage_df):
|
| 244 |
+
self.original_material_usage_df = material_usage_df
|
| 245 |
+
|
| 246 |
+
def load_original_employee_usage(self, employee_usage_df):
|
| 247 |
+
self.original_employee_usage_df = employee_usage_df
|
| 248 |
+
|
| 249 |
+
def load_original_capital_cost(self, capital_cost_df):
|
| 250 |
+
self.original_capital_cost_df = capital_cost_df
|
| 251 |
+
|
| 252 |
+
def adjust_material_usage(self):
|
| 253 |
+
new_material_usage_df = pd.DataFrame() # self.material_usage_df.copy()
|
| 254 |
+
new_material_usage_df["_id"] = self.original_material_usage_df["material_id"]
|
| 255 |
+
new_material_usage_df["process_id"] = self.original_material_usage_df[
|
| 256 |
+
"process_id"
|
| 257 |
+
]
|
| 258 |
+
new_material_usage_df["name"] = self.original_material_usage_df["material_name"]
|
| 259 |
+
new_material_usage_df["amount"] = self.original_material_usage_df[
|
| 260 |
+
"used_quantity"
|
| 261 |
+
]
|
| 262 |
+
new_material_usage_df["unit_cost"] = self.original_material_usage_df[
|
| 263 |
+
"unit_cost"
|
| 264 |
+
]
|
| 265 |
+
# TODO: Update in EManufac Code to pick the purchase date instead
|
| 266 |
+
new_material_usage_df["date"] = self.original_material_usage_df["used_date"]
|
| 267 |
+
self.material_usage_df = new_material_usage_df
|
| 268 |
+
|
| 269 |
+
def adjust_employee_usage(self):
|
| 270 |
+
new_employee_usage_df = pd.DataFrame()
|
| 271 |
+
new_employee_usage_df["_id"] = self.original_employee_usage_df[
|
| 272 |
+
"artifact_employee_id"
|
| 273 |
+
]
|
| 274 |
+
new_employee_usage_df["employee_id"] = self.original_employee_usage_df[
|
| 275 |
+
"artifact_employee_id"
|
| 276 |
+
]
|
| 277 |
+
new_employee_usage_df["process_id"] = self.original_employee_usage_df[
|
| 278 |
+
"process_id"
|
| 279 |
+
]
|
| 280 |
+
new_employee_usage_df["employee_name"] = self.original_employee_usage_df[
|
| 281 |
+
"artifact_employee_name"
|
| 282 |
+
]
|
| 283 |
+
new_employee_usage_df["amount"] = self.original_employee_usage_df[
|
| 284 |
+
"average_labor_amount"
|
| 285 |
+
]
|
| 286 |
+
new_employee_usage_df["date"] = self.original_employee_usage_df["receipt_date"]
|
| 287 |
+
|
| 288 |
+
# If more than 1 employee (unit cost is same) we group to one, and sum the duration
|
| 289 |
+
new_employee_usage_df["duration"] = (
|
| 290 |
+
self.original_employee_usage_df["artifact_minute_use"]
|
| 291 |
+
* self.original_employee_usage_df["average_labor_amount"]
|
| 292 |
+
)
|
| 293 |
+
|
| 294 |
+
# new_employee_usage_df["type"]
|
| 295 |
+
new_employee_usage_df["type"] = "daily"
|
| 296 |
+
new_employee_usage_df['day_amount'] = 1
|
| 297 |
+
try:
|
| 298 |
+
new_employee_usage_df["cost"] = self.original_employee_usage_df[
|
| 299 |
+
"average_daily_labor_cost"
|
| 300 |
+
]
|
| 301 |
+
except:
|
| 302 |
+
new_employee_usage_df["cost"] = 0
|
| 303 |
+
|
| 304 |
+
new_employee_usage_df = new_employee_usage_df.dropna(subset=["cost"])
|
| 305 |
+
|
| 306 |
+
self.employee_usage_df = new_employee_usage_df
|
| 307 |
+
|
| 308 |
+
def adjust_capital_cost(self):
|
| 309 |
+
new_capital_cost_df = pd.DataFrame()
|
| 310 |
+
try:
|
| 311 |
+
new_capital_cost_df["_id"] = self.original_capital_cost_df[
|
| 312 |
+
"artifact_cost_title"
|
| 313 |
+
]
|
| 314 |
+
new_capital_cost_df["process_id"] = self.original_capital_cost_df[
|
| 315 |
+
"process_id"
|
| 316 |
+
]
|
| 317 |
+
new_capital_cost_df["name"] = self.original_capital_cost_df[
|
| 318 |
+
"artifact_cost_title"
|
| 319 |
+
]
|
| 320 |
+
new_capital_cost_df["cost"] = self.original_capital_cost_df[
|
| 321 |
+
"artifact_capital_cost"
|
| 322 |
+
]
|
| 323 |
+
new_capital_cost_df["day_amount"] = self.original_capital_cost_df[
|
| 324 |
+
"average_day_amount"
|
| 325 |
+
]
|
| 326 |
+
new_capital_cost_df["hour_amount"] = self.original_capital_cost_df[
|
| 327 |
+
"average_hour_amount"
|
| 328 |
+
]
|
| 329 |
+
new_capital_cost_df["unit_cost"] = self.original_capital_cost_df[
|
| 330 |
+
"artifact_unit_cost"
|
| 331 |
+
]
|
| 332 |
+
new_capital_cost_df["duration"] = self.original_capital_cost_df[
|
| 333 |
+
"artifact_used_time"
|
| 334 |
+
]
|
| 335 |
+
new_capital_cost_df["date"] = self.original_capital_cost_df["receipt_date"]
|
| 336 |
+
|
| 337 |
+
# new_capital_cost_df["machine_hour"] = new_capital_cost_df["machineHour"]
|
| 338 |
+
# new_capital_cost_df["life_time"] = new_capital_cost_df["lifeTime"]
|
| 339 |
+
# new_capital_cost_df["day_per_month"] = new_capital_cost_df["dayPerMonth"]
|
| 340 |
+
|
| 341 |
+
zero_cost = new_capital_cost_df[new_capital_cost_df["cost"] == 0]
|
| 342 |
+
# Remove None machine usage
|
| 343 |
+
new_capital_cost_df = new_capital_cost_df.drop(zero_cost.index)
|
| 344 |
+
self.capital_cost_df = new_capital_cost_df
|
| 345 |
+
except Exception as e:
|
| 346 |
+
print("Error in adjust capital cost", e)
|
| 347 |
+
|
| 348 |
+
def adjust_process_df(self):
|
| 349 |
+
temp_process_df = self.original_process_df.copy()
|
| 350 |
+
temp_process_df = temp_process_df[temp_process_df["cost"] > 0]
|
| 351 |
+
|
| 352 |
+
self.process_df = temp_process_df
|
| 353 |
+
|
| 354 |
+
def save_material_csv(self, destination_folder_path="generated"):
|
| 355 |
+
self.material_usage_df.to_csv(
|
| 356 |
+
f"{destination_folder_path}/generated_material_usage.csv"
|
| 357 |
+
)
|
| 358 |
+
self.original_material_usage_df.to_csv(
|
| 359 |
+
f"{destination_folder_path}/original_material_usage.csv"
|
| 360 |
+
)
|
| 361 |
+
|
| 362 |
+
def save_process_csv(self, destination_folder_path="generated"):
|
| 363 |
+
self.process_df.to_csv(
|
| 364 |
+
f"{destination_folder_path}/generated_process_data.csv")
|
| 365 |
+
self.original_process_df.to_csv(
|
| 366 |
+
f"{destination_folder_path}/original_process_data.csv"
|
| 367 |
+
)
|
| 368 |
+
|
| 369 |
+
def save_employee_csv(self, destination_folder_path="generated"):
|
| 370 |
+
self.employee_usage_df.to_csv(
|
| 371 |
+
f"{destination_folder_path}/generated_employee_usage.csv"
|
| 372 |
+
)
|
| 373 |
+
self.original_employee_usage_df.to_csv(
|
| 374 |
+
f"{destination_folder_path}/original_employee_usage.csv"
|
| 375 |
+
)
|
| 376 |
+
|
| 377 |
+
def save_capital_csv(self, destination_folder_path="generated"):
|
| 378 |
+
self.capital_cost_df.to_csv(
|
| 379 |
+
f"{destination_folder_path}/generated_captial_cost.csv"
|
| 380 |
+
)
|
| 381 |
+
self.original_capital_cost_df.to_csv(
|
| 382 |
+
f"{destination_folder_path}/original_captial_cost.csv"
|
| 383 |
+
)
|
| 384 |
+
|
| 385 |
+
def save_csv(self, destination_folder_path="generated"):
|
| 386 |
+
self.save_process_csv(destination_folder_path)
|
| 387 |
+
self.save_material_csv(destination_folder_path)
|
| 388 |
+
self.save_employee_csv(destination_folder_path)
|
| 389 |
+
self.save_capital_csv(destination_folder_path)
|
model/extractor/shaker_augmentation.py
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This find provide the shaker function
|
| 2 |
+
# for make data into more variation
|
| 3 |
+
# and augment the data for training the model
|
| 4 |
+
# In first case study we will shake the data from dataset 1
|
| 5 |
+
# And Create the dataset 4
|
| 6 |
+
|
| 7 |
+
import pandas as pd
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def dataset_shake(dataset_name, new_dataset_name, random_rate=10):
|
| 11 |
+
# import data from dataset
|
| 12 |
+
process_df = pd.read_csv(f'data/{dataset_name}/generated_process_data.csv')
|
| 13 |
+
employee_df = pd.read_csv(
|
| 14 |
+
f'data/{dataset_name}/generated_employee_usage.csv')
|
| 15 |
+
material_df = pd.read_csv(
|
| 16 |
+
f'data/{dataset_name}/generated_material_usage.csv')
|
| 17 |
+
capitalcost_df = pd.read_csv(
|
| 18 |
+
f'data/{dataset_name}/generated_captial_cost.csv')
|
| 19 |
+
|
| 20 |
+
# Adjust Employee Cost
|
| 21 |
+
# Picking Cost
|
| 22 |
+
example_employee_ids = range(0, 12)
|
| 23 |
+
example_employee_name = ['A', 'B', "C", "D",
|
| 24 |
+
"E", "F", "G", "H", "I", "J", "K", "L"]
|
| 25 |
+
example_cost = [27769.652, 20508.323, 811.6214, 547.8455,
|
| 26 |
+
392.4559, 372.7312, 354.8132, 2682.522,
|
| 27 |
+
2451.125, 24071.33, 22683.42, 22683.42]
|
| 28 |
+
example_day_amount = [26, 26, 1, 1, 1, 1, 1, 7, 7, 7, 7, 7]
|
| 29 |
+
|
| 30 |
+
picking_df = employee_df[employee_df['employee_name']
|
| 31 |
+
== "ตัวแทนพนักงานเฉลี่ยคลังที่ 2 (ดองน้ำแข็ง)"]
|
| 32 |
+
example_picking_df = pd.DataFrame({
|
| 33 |
+
'employee_id': example_employee_ids,
|
| 34 |
+
'employee_name': example_employee_name,
|
| 35 |
+
'cost': example_cost,
|
| 36 |
+
'day_amount': example_day_amount
|
| 37 |
+
})
|
| 38 |
+
|
| 39 |
+
example_picking_df['cost'] = example_picking_df['cost'].astype(float)
|
| 40 |
+
example_picking_df['day_amount'] = example_picking_df['day_amount'].astype(
|
| 41 |
+
int)
|
| 42 |
+
|
| 43 |
+
# Update the picking_df based on the condition
|
| 44 |
+
for i in range(len(picking_df)):
|
| 45 |
+
cost_mod_index = i % 12
|
| 46 |
+
coefficient = random_rate / 2
|
| 47 |
+
if cost_mod_index % 2 == 0:
|
| 48 |
+
coefficient = -random_rate / 2
|
| 49 |
+
picking_df.loc[i, ['employee_id', 'employee_name', 'cost', 'day_amount']
|
| 50 |
+
] = example_picking_df.loc[cost_mod_index, ['employee_id', 'employee_name', 'cost', 'day_amount']]
|
| 51 |
+
# Update Duration +- 5%
|
| 52 |
+
picking_df.loc[i, 'duration'] = picking_df.loc[i, 'duration'] + \
|
| 53 |
+
(coefficient * picking_df.loc[i, 'duration'] / 100)
|
| 54 |
+
|
| 55 |
+
# Packing Cost
|
| 56 |
+
packing_df = employee_df[employee_df['employee_name']
|
| 57 |
+
== "ตัวแทนพนักงานเฉลี่ยคลังที่ 3 (ปูเข้าเป็นกระป๋อง)"]
|
| 58 |
+
packing_df.reset_index(drop=True, inplace=True)
|
| 59 |
+
example_employee_ids = range(12, 24)
|
| 60 |
+
example_employee_name = ['M', 'N', "O", "P",
|
| 61 |
+
"Q", "R", "S", "T", "U", "V", "W", "X"]
|
| 62 |
+
example_cost = [37769.652, 30508.323, 311.6214, 647.8455,
|
| 63 |
+
492.4559, 472.7312, 454.8132, 3682.522,
|
| 64 |
+
3451.125, 34071.33, 22683.42, 32683.42]
|
| 65 |
+
example_day_amount = [26, 26, 1, 1, 1, 1, 1, 7, 7, 7, 7, 7]
|
| 66 |
+
|
| 67 |
+
example_packing_df = pd.DataFrame({
|
| 68 |
+
'employee_id': example_employee_ids,
|
| 69 |
+
'employee_name': example_employee_name,
|
| 70 |
+
'cost': example_cost,
|
| 71 |
+
'day_amount': example_day_amount
|
| 72 |
+
})
|
| 73 |
+
example_packing_df['cost'] = example_packing_df['cost'].astype(float)
|
| 74 |
+
example_packing_df['day_amount'] = example_packing_df['day_amount'].astype(
|
| 75 |
+
int)
|
| 76 |
+
|
| 77 |
+
# Update the picking_df based on the condition
|
| 78 |
+
for i in range(len(packing_df)):
|
| 79 |
+
cost_mod_index = i % 12
|
| 80 |
+
coefficient = random_rate / 2
|
| 81 |
+
if cost_mod_index % 2 == 0:
|
| 82 |
+
coefficient = -random_rate / 2
|
| 83 |
+
packing_df.loc[i, ['employee_id', 'employee_name', 'cost', 'day_amount']
|
| 84 |
+
] = example_packing_df.loc[cost_mod_index, ['employee_id', 'employee_name', 'cost', 'day_amount']]
|
| 85 |
+
# Update Duration +- random_rate %
|
| 86 |
+
packing_df.loc[i, 'duration'] = packing_df.loc[i, 'duration'] + \
|
| 87 |
+
(coefficient * packing_df.loc[i, 'duration'] / 100)
|
| 88 |
+
|
| 89 |
+
# Combining
|
| 90 |
+
new_employee_df = pd.concat([picking_df, packing_df], ignore_index=True)
|
| 91 |
+
|
| 92 |
+
# Adjust Capital Cost
|
| 93 |
+
new_capital_cost = capitalcost_df.copy()
|
| 94 |
+
for i in range(len(new_capital_cost)):
|
| 95 |
+
cost_mod_index = i % random_rate
|
| 96 |
+
amout_mod_index = i % random_rate / 2
|
| 97 |
+
coefficient = 1
|
| 98 |
+
if cost_mod_index % 2 == 0:
|
| 99 |
+
coefficient = -1
|
| 100 |
+
|
| 101 |
+
# Update Cost +- 1 - 10%
|
| 102 |
+
new_capital_cost.loc[i, 'cost'] = new_capital_cost.loc[i, 'cost'] + \
|
| 103 |
+
(coefficient * cost_mod_index *
|
| 104 |
+
new_capital_cost.loc[i, 'cost'] / 100)
|
| 105 |
+
new_capital_cost.loc[i, 'duration'] = new_capital_cost.loc[i, 'duration'] + (
|
| 106 |
+
coefficient * amout_mod_index * new_capital_cost.loc[i, 'duration'] / 100)
|
| 107 |
+
|
| 108 |
+
# Adjust Material Cost
|
| 109 |
+
new_material_cost = material_df.copy()
|
| 110 |
+
for i in range(len(new_material_cost)):
|
| 111 |
+
cost_mod_index = i % random_rate
|
| 112 |
+
amout_mod_index = i % random_rate / 2
|
| 113 |
+
coefficient = 1
|
| 114 |
+
if cost_mod_index % 2 == 0:
|
| 115 |
+
coefficient = -1
|
| 116 |
+
|
| 117 |
+
# Update Cost +- 1 - 10%
|
| 118 |
+
new_material_cost.loc[i, 'unit_cost'] = new_material_cost.loc[i, 'unit_cost'] + (
|
| 119 |
+
coefficient * cost_mod_index * new_material_cost.loc[i, 'unit_cost'] / 100)
|
| 120 |
+
new_material_cost.loc[i, 'amount'] = new_material_cost.loc[i, 'amount'] + (
|
| 121 |
+
coefficient * amout_mod_index * new_material_cost.loc[i, 'amount'] / 100)
|
| 122 |
+
|
| 123 |
+
# Save data
|
| 124 |
+
process_df.to_csv(
|
| 125 |
+
f'data/{new_dataset_name}/generated_process_data.csv', index=False)
|
| 126 |
+
new_employee_df.to_csv(
|
| 127 |
+
f'data/{new_dataset_name}/generated_employee_usage.csv', index=False)
|
| 128 |
+
new_material_cost.to_csv(
|
| 129 |
+
f'data/{new_dataset_name}/generated_material_usage.csv', index=False)
|
| 130 |
+
new_capital_cost.to_csv(
|
| 131 |
+
f'data/{new_dataset_name}/generated_captial_cost.csv', index=False)
|
| 132 |
+
# Print the result
|
| 133 |
+
print(
|
| 134 |
+
f"Data from {dataset_name} has been shaken and saved as {new_dataset_name}.")
|
model/matrix_generator/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
__pycache__
|
model/matrix_generator/cost_matrix_class.py
ADDED
|
@@ -0,0 +1,550 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import numpy as np
|
| 3 |
+
import importlib
|
| 4 |
+
|
| 5 |
+
# fmt:off
|
| 6 |
+
import cost_matrix_generator as cmg
|
| 7 |
+
importlib.reload(cmg)
|
| 8 |
+
# fmt:on
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class CostMatrixGenerator:
|
| 12 |
+
def __init__(self):
|
| 13 |
+
self.process_df = pd.DataFrame()
|
| 14 |
+
self.employee_usage = pd.DataFrame()
|
| 15 |
+
self.material_usage = pd.DataFrame()
|
| 16 |
+
self.capital_cost_usage = pd.DataFrame()
|
| 17 |
+
self.data_directory = "example"
|
| 18 |
+
|
| 19 |
+
def change_data_directory(self, new_directory):
|
| 20 |
+
self.data_directory = new_directory
|
| 21 |
+
|
| 22 |
+
def load_data(self):
|
| 23 |
+
self.process_df = pd.read_csv(
|
| 24 |
+
f"{self.data_directory}/generated_process_data.csv"
|
| 25 |
+
)
|
| 26 |
+
self.employee_usage = pd.read_csv(
|
| 27 |
+
f"{self.data_directory}/generated_employee_usage.csv"
|
| 28 |
+
)
|
| 29 |
+
self.material_usage = pd.read_csv(
|
| 30 |
+
f"{self.data_directory}/generated_material_usage.csv"
|
| 31 |
+
)
|
| 32 |
+
self.capital_cost_usage = pd.read_csv(
|
| 33 |
+
f"{self.data_directory}/generated_captial_cost.csv"
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
def remove_outlier_iqr(self, iqr_index=1.5):
|
| 37 |
+
process_df = self.process_df
|
| 38 |
+
q1 = np.percentile(process_df["cost"], 25)
|
| 39 |
+
q3 = np.percentile(process_df["cost"], 75)
|
| 40 |
+
iqr = q3 - q1
|
| 41 |
+
lower_bound = q1 - (iqr_index * iqr)
|
| 42 |
+
upper_bound = q3 + (iqr_index * iqr)
|
| 43 |
+
process_df = process_df[
|
| 44 |
+
(process_df["cost"] > lower_bound) & (
|
| 45 |
+
process_df["cost"] < upper_bound)
|
| 46 |
+
]
|
| 47 |
+
removed_data = self.process_df[
|
| 48 |
+
~self.process_df["process_id"].isin(process_df["process_id"])
|
| 49 |
+
]
|
| 50 |
+
self.process_df = process_df
|
| 51 |
+
print("Outliers removed")
|
| 52 |
+
print(f"Amount of process to remove {len(removed_data)}")
|
| 53 |
+
return process_df
|
| 54 |
+
|
| 55 |
+
def generate_data(self):
|
| 56 |
+
# Material
|
| 57 |
+
material_cost_matrix, material_amount_matrix = (
|
| 58 |
+
cmg.generate_material_usage_cost_matrix(
|
| 59 |
+
self.process_df, self.material_usage
|
| 60 |
+
)
|
| 61 |
+
)
|
| 62 |
+
material_cost_matrix = material_cost_matrix.values
|
| 63 |
+
material_amount_matrix = material_amount_matrix.values
|
| 64 |
+
|
| 65 |
+
row, col = material_cost_matrix.shape
|
| 66 |
+
material_cost_matrix = material_cost_matrix.reshape(row, 1, col)
|
| 67 |
+
material_amount_matrix = material_amount_matrix.reshape(row, 1, col)
|
| 68 |
+
|
| 69 |
+
# Employee
|
| 70 |
+
(
|
| 71 |
+
employee_cost_matrix,
|
| 72 |
+
employee_duration_matrix,
|
| 73 |
+
employee_day_amount_matrix,
|
| 74 |
+
) = cmg.generate_employee_usage_cost_matrix(
|
| 75 |
+
self.process_df, self.employee_usage
|
| 76 |
+
)
|
| 77 |
+
employee_cost_matrix = employee_cost_matrix.values
|
| 78 |
+
employee_duration_matrix = employee_duration_matrix.values
|
| 79 |
+
employee_day_amount_matrix = employee_day_amount_matrix.values
|
| 80 |
+
|
| 81 |
+
# Reshape Matrix
|
| 82 |
+
# Employee Cost
|
| 83 |
+
row, col = employee_cost_matrix.shape
|
| 84 |
+
employee_cost_matrix = employee_cost_matrix.reshape(
|
| 85 |
+
row, 1, col)
|
| 86 |
+
|
| 87 |
+
# Employee Duration
|
| 88 |
+
row, col = employee_duration_matrix.shape
|
| 89 |
+
employee_duration_matrix = employee_duration_matrix.reshape(
|
| 90 |
+
row, 1, col
|
| 91 |
+
)
|
| 92 |
+
|
| 93 |
+
# Employee Day Amount
|
| 94 |
+
row, col = employee_day_amount_matrix.shape
|
| 95 |
+
employee_day_amount_matrix = employee_day_amount_matrix.reshape(
|
| 96 |
+
row, 1, col
|
| 97 |
+
)
|
| 98 |
+
|
| 99 |
+
print(
|
| 100 |
+
f" Employee Cost matrix shape {employee_cost_matrix.shape}"
|
| 101 |
+
)
|
| 102 |
+
|
| 103 |
+
# Capital Cost
|
| 104 |
+
(
|
| 105 |
+
capital_cost_matrix,
|
| 106 |
+
day_amount_matrix,
|
| 107 |
+
capital_cost_duration_matrix,
|
| 108 |
+
) = cmg.generate_capital_cost_matrix(
|
| 109 |
+
self.process_df, capital_cost_df=self.capital_cost_usage
|
| 110 |
+
)
|
| 111 |
+
|
| 112 |
+
# Get Values
|
| 113 |
+
capital_cost_matrix = capital_cost_matrix.values
|
| 114 |
+
day_amount_matrix = day_amount_matrix.values
|
| 115 |
+
capital_cost_duration_matrix = capital_cost_duration_matrix.values
|
| 116 |
+
|
| 117 |
+
# Reshape Matrix
|
| 118 |
+
row, col = capital_cost_matrix.shape
|
| 119 |
+
capital_cost_matrix = capital_cost_matrix.reshape(row, 1, col)
|
| 120 |
+
|
| 121 |
+
row, col = day_amount_matrix.shape
|
| 122 |
+
day_amount_matrix = day_amount_matrix.reshape(row, 1, col)
|
| 123 |
+
|
| 124 |
+
row, col = capital_cost_duration_matrix.shape
|
| 125 |
+
capital_cost_duration_matrix = capital_cost_duration_matrix.reshape(
|
| 126 |
+
row, 1, col)
|
| 127 |
+
|
| 128 |
+
result_matrix = cmg.generate_price_matrix(
|
| 129 |
+
process_df=self.process_df, use_3d=True
|
| 130 |
+
)
|
| 131 |
+
|
| 132 |
+
return (
|
| 133 |
+
material_cost_matrix,
|
| 134 |
+
material_amount_matrix,
|
| 135 |
+
employee_cost_matrix,
|
| 136 |
+
employee_duration_matrix,
|
| 137 |
+
employee_day_amount_matrix,
|
| 138 |
+
capital_cost_matrix,
|
| 139 |
+
day_amount_matrix,
|
| 140 |
+
capital_cost_duration_matrix, # New On Finetuning
|
| 141 |
+
result_matrix,
|
| 142 |
+
)
|
| 143 |
+
|
| 144 |
+
def train_test_split(self, train_rate):
|
| 145 |
+
process_df_size = len(self.process_df)
|
| 146 |
+
trained_size = train_rate * process_df_size
|
| 147 |
+
train_process_df = self.process_df.sample(int(trained_size))
|
| 148 |
+
validate_process_df = self.process_df.drop(train_process_df.index)
|
| 149 |
+
# Ensure at least one record per original_material_name in train_process_df
|
| 150 |
+
unique_materials = self.process_df['original_material_name'].unique()
|
| 151 |
+
for material in unique_materials:
|
| 152 |
+
if material not in train_process_df['original_material_name'].values:
|
| 153 |
+
sample_record = self.process_df[self.process_df['original_material_name'] == material].sample(
|
| 154 |
+
1)
|
| 155 |
+
train_process_df = pd.concat([train_process_df, sample_record])
|
| 156 |
+
validate_process_df = validate_process_df.drop(
|
| 157 |
+
sample_record.index)
|
| 158 |
+
|
| 159 |
+
# Result Matrix
|
| 160 |
+
result_matrix = cmg.generate_price_matrix(
|
| 161 |
+
process_df=train_process_df, use_3d=True
|
| 162 |
+
)
|
| 163 |
+
|
| 164 |
+
validate_result_matrix = cmg.generate_price_matrix(
|
| 165 |
+
process_df=validate_process_df, use_3d=True
|
| 166 |
+
)
|
| 167 |
+
|
| 168 |
+
# Material
|
| 169 |
+
material_cost_matrix, material_amount_matrix = (
|
| 170 |
+
cmg.generate_material_usage_cost_matrix(
|
| 171 |
+
train_process_df, self.material_usage
|
| 172 |
+
)
|
| 173 |
+
)
|
| 174 |
+
material_cost_matrix = material_cost_matrix.values
|
| 175 |
+
material_amount_matrix = material_amount_matrix.values
|
| 176 |
+
|
| 177 |
+
# Material Validate
|
| 178 |
+
validate_material_cost_matrix, validate_material_amount_matrix = (
|
| 179 |
+
cmg.generate_material_usage_cost_matrix(
|
| 180 |
+
validate_process_df, self.material_usage
|
| 181 |
+
)
|
| 182 |
+
)
|
| 183 |
+
|
| 184 |
+
validate_material_cost_matrix = validate_material_cost_matrix.values
|
| 185 |
+
validate_material_amount_matrix = validate_material_amount_matrix.values
|
| 186 |
+
|
| 187 |
+
row, col = material_cost_matrix.shape
|
| 188 |
+
material_cost_matrix = material_cost_matrix.reshape(row, 1, col)
|
| 189 |
+
material_amount_matrix = material_amount_matrix.reshape(row, 1, col)
|
| 190 |
+
|
| 191 |
+
# Employee
|
| 192 |
+
(
|
| 193 |
+
employee_cost_matrix,
|
| 194 |
+
employee_duration_matrix,
|
| 195 |
+
employee_day_amount_matrix,
|
| 196 |
+
) = cmg.generate_employee_usage_cost_matrix(
|
| 197 |
+
train_process_df, self.employee_usage
|
| 198 |
+
)
|
| 199 |
+
# Employee Extract Value
|
| 200 |
+
employee_cost_matrix = employee_cost_matrix.values
|
| 201 |
+
employee_duration_matrix = employee_duration_matrix.values
|
| 202 |
+
employee_day_amount_matrix = employee_day_amount_matrix.values
|
| 203 |
+
|
| 204 |
+
# Employee Reshape
|
| 205 |
+
row, col = employee_cost_matrix.shape
|
| 206 |
+
employee_cost_matrix = employee_cost_matrix.reshape(
|
| 207 |
+
row, 1, col)
|
| 208 |
+
row, col = employee_duration_matrix.shape
|
| 209 |
+
employee_duration_matrix = employee_duration_matrix.reshape(
|
| 210 |
+
row, 1, col)
|
| 211 |
+
row, col = employee_day_amount_matrix.shape
|
| 212 |
+
employee_day_amount_matrix = employee_day_amount_matrix.reshape(
|
| 213 |
+
row, 1, col)
|
| 214 |
+
|
| 215 |
+
print(
|
| 216 |
+
f" Employee Cost matrix shape {employee_duration_matrix.shape} "
|
| 217 |
+
)
|
| 218 |
+
|
| 219 |
+
# Employee validate
|
| 220 |
+
(
|
| 221 |
+
validate_emp_cost_matrix,
|
| 222 |
+
validate_emp_duration_matrix,
|
| 223 |
+
validate_emp_day_amount_matrix,
|
| 224 |
+
) = cmg.generate_employee_usage_cost_matrix(
|
| 225 |
+
validate_process_df, self.employee_usage
|
| 226 |
+
)
|
| 227 |
+
# Employee Validate Extract Value
|
| 228 |
+
validate_emp_cost_matrix = validate_emp_cost_matrix.values
|
| 229 |
+
validate_emp_duration_matrix = validate_emp_duration_matrix.values
|
| 230 |
+
validate_emp_day_amount_matrix = validate_emp_day_amount_matrix.values
|
| 231 |
+
|
| 232 |
+
# Employee Validate Reshape
|
| 233 |
+
row, col = validate_emp_cost_matrix.shape
|
| 234 |
+
validate_emp_cost_matrix = validate_emp_cost_matrix.reshape(
|
| 235 |
+
row, 1, col
|
| 236 |
+
)
|
| 237 |
+
row, col = validate_emp_duration_matrix.shape
|
| 238 |
+
validate_emp_duration_matrix = validate_emp_duration_matrix.reshape(
|
| 239 |
+
row, 1, col
|
| 240 |
+
)
|
| 241 |
+
row, col = validate_emp_day_amount_matrix.shape
|
| 242 |
+
validate_emp_day_amount_matrix = validate_emp_day_amount_matrix.reshape(
|
| 243 |
+
row, 1, col
|
| 244 |
+
)
|
| 245 |
+
|
| 246 |
+
# Capital Cost
|
| 247 |
+
capital_cost_matrix, day_amount_matrix, capital_duration_matrix = (
|
| 248 |
+
cmg.generate_capital_cost_matrix(
|
| 249 |
+
train_process_df, capital_cost_df=self.capital_cost_usage
|
| 250 |
+
)
|
| 251 |
+
)
|
| 252 |
+
|
| 253 |
+
# Capital Cost Extract Value
|
| 254 |
+
capital_cost_matrix = capital_cost_matrix.values
|
| 255 |
+
day_amount_matrix = day_amount_matrix.values
|
| 256 |
+
capital_duration_matrix = capital_duration_matrix.values
|
| 257 |
+
|
| 258 |
+
# Capital Cost Reshape for 3D
|
| 259 |
+
row, col = capital_cost_matrix.shape
|
| 260 |
+
capital_cost_matrix = capital_cost_matrix.reshape(row, 1, col)
|
| 261 |
+
row, col = day_amount_matrix.shape
|
| 262 |
+
day_amount_matrix = day_amount_matrix.reshape(row, 1, col)
|
| 263 |
+
row, col = capital_duration_matrix.shape
|
| 264 |
+
capital_duration_matrix = capital_duration_matrix.reshape(row, 1, col)
|
| 265 |
+
|
| 266 |
+
# Capital Cost validate
|
| 267 |
+
(
|
| 268 |
+
valdiate_capital_cost_matrix,
|
| 269 |
+
validate_dayamount_matrix,
|
| 270 |
+
validate_capital_duration_matrix,
|
| 271 |
+
) = cmg.generate_capital_cost_matrix(
|
| 272 |
+
validate_process_df, capital_cost_df=self.capital_cost_usage
|
| 273 |
+
)
|
| 274 |
+
|
| 275 |
+
# Capital Cost Validate Value Extraction
|
| 276 |
+
valdiate_capital_cost_matrix = valdiate_capital_cost_matrix.values
|
| 277 |
+
validate_dayamount_matrix = validate_dayamount_matrix.values
|
| 278 |
+
validate_capital_duration_matrix = validate_capital_duration_matrix.values
|
| 279 |
+
|
| 280 |
+
# Capital Cost Validate Reshape
|
| 281 |
+
row, col = valdiate_capital_cost_matrix.shape
|
| 282 |
+
valdiate_capital_cost_matrix = valdiate_capital_cost_matrix.reshape(
|
| 283 |
+
row, 1, col)
|
| 284 |
+
|
| 285 |
+
row, col = validate_dayamount_matrix.shape
|
| 286 |
+
validate_dayamount_matrix = validate_dayamount_matrix.reshape(
|
| 287 |
+
row, 1, col)
|
| 288 |
+
|
| 289 |
+
row, col = validate_capital_duration_matrix.shape
|
| 290 |
+
validate_capital_duration_matrix = validate_capital_duration_matrix.reshape(
|
| 291 |
+
row, 1, col
|
| 292 |
+
)
|
| 293 |
+
|
| 294 |
+
validate_payload = {
|
| 295 |
+
"validate_process_df": validate_process_df,
|
| 296 |
+
"validate_result_matrix": validate_result_matrix,
|
| 297 |
+
"validate_material_cost_matrix": validate_material_cost_matrix,
|
| 298 |
+
"validate_material_amount_matrix": validate_material_amount_matrix,
|
| 299 |
+
"validate_capital_cost_matrix": valdiate_capital_cost_matrix,
|
| 300 |
+
"validate_day_amount_matrix": validate_dayamount_matrix,
|
| 301 |
+
"validate_capital_duration_matrix": validate_capital_duration_matrix,
|
| 302 |
+
"validate_employee_cost_matrix": validate_emp_cost_matrix,
|
| 303 |
+
"validate_employee_duration_matrix": validate_emp_duration_matrix,
|
| 304 |
+
"validate_employee_day_amount_matrix": validate_emp_day_amount_matrix,
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
return (
|
| 308 |
+
material_cost_matrix,
|
| 309 |
+
material_amount_matrix,
|
| 310 |
+
employee_cost_matrix,
|
| 311 |
+
employee_duration_matrix,
|
| 312 |
+
employee_day_amount_matrix,
|
| 313 |
+
capital_cost_matrix,
|
| 314 |
+
day_amount_matrix,
|
| 315 |
+
capital_duration_matrix,
|
| 316 |
+
result_matrix,
|
| 317 |
+
validate_payload,
|
| 318 |
+
)
|
| 319 |
+
|
| 320 |
+
def train_test_split_without_matrix(self, train_rate):
|
| 321 |
+
process_df_size = len(self.process_df)
|
| 322 |
+
trained_size = train_rate * process_df_size
|
| 323 |
+
train_process_df = self.process_df.sample(int(trained_size))
|
| 324 |
+
validate_process_df = self.process_df.drop(train_process_df.index)
|
| 325 |
+
|
| 326 |
+
# Adjust to match new Process dataset
|
| 327 |
+
train_capital_cost = self.capital_cost_usage.copy()
|
| 328 |
+
train_capital_cost = train_capital_cost[
|
| 329 |
+
train_capital_cost["process_id"].isin(
|
| 330 |
+
train_process_df["process_id"])
|
| 331 |
+
]
|
| 332 |
+
|
| 333 |
+
train_employee_usage = self.employee_usage.copy()
|
| 334 |
+
train_employee_usage = train_employee_usage[
|
| 335 |
+
train_employee_usage["process_id"].isin(
|
| 336 |
+
train_process_df["process_id"])
|
| 337 |
+
]
|
| 338 |
+
|
| 339 |
+
train_material_usage = self.material_usage.copy()
|
| 340 |
+
train_material_usage = train_material_usage[
|
| 341 |
+
train_material_usage["process_id"].isin(
|
| 342 |
+
train_process_df["process_id"])
|
| 343 |
+
]
|
| 344 |
+
|
| 345 |
+
# Adjust to match new Process dataset for validation set
|
| 346 |
+
validate_capital_cost = self.capital_cost_usage.copy()
|
| 347 |
+
validate_capital_cost = validate_capital_cost[
|
| 348 |
+
validate_capital_cost["process_id"].isin(
|
| 349 |
+
validate_process_df["process_id"])
|
| 350 |
+
]
|
| 351 |
+
|
| 352 |
+
validate_employee_usage = self.employee_usage.copy()
|
| 353 |
+
validate_employee_usage = validate_employee_usage[
|
| 354 |
+
validate_employee_usage["process_id"].isin(
|
| 355 |
+
validate_process_df["process_id"]
|
| 356 |
+
)
|
| 357 |
+
]
|
| 358 |
+
|
| 359 |
+
validate_material_usage = self.material_usage.copy()
|
| 360 |
+
validate_material_usage = validate_material_usage[
|
| 361 |
+
validate_material_usage["process_id"].isin(
|
| 362 |
+
validate_process_df["process_id"]
|
| 363 |
+
)
|
| 364 |
+
]
|
| 365 |
+
|
| 366 |
+
return (
|
| 367 |
+
train_process_df,
|
| 368 |
+
train_employee_usage,
|
| 369 |
+
train_material_usage,
|
| 370 |
+
train_capital_cost,
|
| 371 |
+
validate_process_df,
|
| 372 |
+
validate_employee_usage,
|
| 373 |
+
validate_material_usage,
|
| 374 |
+
validate_capital_cost,
|
| 375 |
+
)
|
| 376 |
+
|
| 377 |
+
def generate_data_from_input(
|
| 378 |
+
self, process_df, material_usage, employee_usage, capital_cost_usage
|
| 379 |
+
):
|
| 380 |
+
# Material
|
| 381 |
+
material_cost_matrix, material_amount_matrix = (
|
| 382 |
+
cmg.generate_material_usage_cost_matrix(process_df, material_usage)
|
| 383 |
+
)
|
| 384 |
+
material_cost_matrix = material_cost_matrix.values
|
| 385 |
+
material_amount_matrix = material_amount_matrix.values
|
| 386 |
+
|
| 387 |
+
row, col = material_cost_matrix.shape
|
| 388 |
+
material_cost_matrix = material_cost_matrix.reshape(row, 1, col)
|
| 389 |
+
material_amount_matrix = material_amount_matrix.reshape(row, 1, col)
|
| 390 |
+
|
| 391 |
+
# Employee
|
| 392 |
+
(employee_cost_matrix,
|
| 393 |
+
employee_duration_matrix,
|
| 394 |
+
employee_day_amount_matrix,
|
| 395 |
+
) = cmg.generate_employee_usage_cost_matrix(process_df, employee_usage)
|
| 396 |
+
employee_cost_matrix = employee_cost_matrix.values
|
| 397 |
+
employee_duration_matrix = employee_duration_matrix.values
|
| 398 |
+
employee_day_amount_matrix = employee_day_amount_matrix.values
|
| 399 |
+
|
| 400 |
+
# Reshape Matrix
|
| 401 |
+
# Employee Cost
|
| 402 |
+
row, col = employee_cost_matrix.shape
|
| 403 |
+
employee_cost_matrix = employee_cost_matrix.reshape(
|
| 404 |
+
row, 1, col)
|
| 405 |
+
# Employee Duration
|
| 406 |
+
row, col = employee_duration_matrix.shape
|
| 407 |
+
employee_duration_matrix = employee_duration_matrix.reshape(
|
| 408 |
+
row, 1, col)
|
| 409 |
+
# Employee Day Amount
|
| 410 |
+
row, col = employee_day_amount_matrix.shape
|
| 411 |
+
employee_day_amount_matrix = employee_day_amount_matrix.reshape(
|
| 412 |
+
row, 1, col
|
| 413 |
+
)
|
| 414 |
+
|
| 415 |
+
print(
|
| 416 |
+
f" Employee Cost matrix shape {employee_cost_matrix.shape} "
|
| 417 |
+
)
|
| 418 |
+
|
| 419 |
+
# Capital Cost
|
| 420 |
+
(
|
| 421 |
+
capital_cost_matrix,
|
| 422 |
+
day_amount_matrix,
|
| 423 |
+
capital_cost_duration_matrix,
|
| 424 |
+
) = cmg.generate_capital_cost_matrix(
|
| 425 |
+
process_df, capital_cost_df=capital_cost_usage
|
| 426 |
+
)
|
| 427 |
+
|
| 428 |
+
# Get Values
|
| 429 |
+
capital_cost_matrix = capital_cost_matrix.values
|
| 430 |
+
day_amount_matrix = day_amount_matrix.values
|
| 431 |
+
capital_cost_duration_matrix = capital_cost_duration_matrix.values
|
| 432 |
+
|
| 433 |
+
# Reshape Matrix
|
| 434 |
+
row, col = capital_cost_matrix.shape
|
| 435 |
+
capital_cost_matrix = capital_cost_matrix.reshape(row, 1, col)
|
| 436 |
+
|
| 437 |
+
row, col = day_amount_matrix.shape
|
| 438 |
+
day_amount_matrix = day_amount_matrix.reshape(row, 1, col)
|
| 439 |
+
|
| 440 |
+
row, col = capital_cost_duration_matrix.shape
|
| 441 |
+
capital_cost_duration_matrix = capital_cost_duration_matrix.reshape(
|
| 442 |
+
row, 1, col)
|
| 443 |
+
|
| 444 |
+
result_matrix = cmg.generate_price_matrix(
|
| 445 |
+
process_df=process_df, use_3d=True)
|
| 446 |
+
|
| 447 |
+
return (
|
| 448 |
+
material_cost_matrix,
|
| 449 |
+
material_amount_matrix,
|
| 450 |
+
employee_cost_matrix,
|
| 451 |
+
employee_duration_matrix,
|
| 452 |
+
employee_day_amount_matrix,
|
| 453 |
+
capital_cost_matrix,
|
| 454 |
+
day_amount_matrix,
|
| 455 |
+
capital_cost_duration_matrix, # New On Finetuning
|
| 456 |
+
result_matrix,
|
| 457 |
+
)
|
| 458 |
+
|
| 459 |
+
def get_validation_payload(self, validate_process_df):
|
| 460 |
+
validate_result_matrix = cmg.generate_price_matrix(
|
| 461 |
+
process_df=validate_process_df, use_3d=True
|
| 462 |
+
)
|
| 463 |
+
|
| 464 |
+
# Material Validate
|
| 465 |
+
validate_material_cost_matrix, validate_material_amount_matrix = (
|
| 466 |
+
cmg.generate_material_usage_cost_matrix(
|
| 467 |
+
validate_process_df, self.material_usage
|
| 468 |
+
)
|
| 469 |
+
)
|
| 470 |
+
|
| 471 |
+
validate_material_cost_matrix = validate_material_cost_matrix.values
|
| 472 |
+
validate_material_amount_matrix = validate_material_amount_matrix.values
|
| 473 |
+
|
| 474 |
+
# Employee validate
|
| 475 |
+
(
|
| 476 |
+
validate_employee_cost_matrix,
|
| 477 |
+
validate_employee_duration_matrix,
|
| 478 |
+
validate_employee_day_amount_matrix,
|
| 479 |
+
) = cmg.generate_employee_usage_cost_matrix(
|
| 480 |
+
validate_process_df, self.employee_usage
|
| 481 |
+
)
|
| 482 |
+
# Employee Validate Extract Value
|
| 483 |
+
validate_employee_cost_matrix = validate_employee_cost_matrix.values
|
| 484 |
+
validate_employee_duration_matrix = validate_employee_duration_matrix.values
|
| 485 |
+
validate_employee_day_amount_matrix = validate_employee_day_amount_matrix.values
|
| 486 |
+
|
| 487 |
+
# Employee Validate Reshape
|
| 488 |
+
row, col = validate_employee_cost_matrix.shape
|
| 489 |
+
validate_employee_cost_matrix = validate_employee_cost_matrix.reshape(
|
| 490 |
+
row, 1, col
|
| 491 |
+
)
|
| 492 |
+
row, col = validate_employee_duration_matrix.shape
|
| 493 |
+
validate_employee_duration_matrix = validate_employee_duration_matrix.reshape(
|
| 494 |
+
row, 1, col
|
| 495 |
+
)
|
| 496 |
+
row, col = validate_employee_day_amount_matrix.shape
|
| 497 |
+
validate_employee_day_amount_matrix = validate_employee_day_amount_matrix.reshape(
|
| 498 |
+
row, 1, col
|
| 499 |
+
)
|
| 500 |
+
|
| 501 |
+
# Capital Cost validate
|
| 502 |
+
(
|
| 503 |
+
valdiate_capital_cost_matrix,
|
| 504 |
+
validate_dayamount_matrix,
|
| 505 |
+
validate_capital_duration_matrix,
|
| 506 |
+
) = cmg.generate_capital_cost_matrix(
|
| 507 |
+
validate_process_df, capital_cost_df=self.capital_cost_usage
|
| 508 |
+
)
|
| 509 |
+
|
| 510 |
+
# Capital Cost Validate Value Extraction
|
| 511 |
+
valdiate_capital_cost_matrix = valdiate_capital_cost_matrix.values
|
| 512 |
+
validate_dayamount_matrix = validate_dayamount_matrix.values
|
| 513 |
+
validate_capital_duration_matrix = validate_capital_duration_matrix.values
|
| 514 |
+
|
| 515 |
+
# Capital Cost Validate Reshape
|
| 516 |
+
row, col = valdiate_capital_cost_matrix.shape
|
| 517 |
+
valdiate_capital_cost_matrix = valdiate_capital_cost_matrix.reshape(
|
| 518 |
+
row, 1, col)
|
| 519 |
+
|
| 520 |
+
row, col = validate_dayamount_matrix.shape
|
| 521 |
+
validate_dayamount_matrix = validate_dayamount_matrix.reshape(
|
| 522 |
+
row, 1, col)
|
| 523 |
+
|
| 524 |
+
row, col = validate_capital_duration_matrix.shape
|
| 525 |
+
validate_capital_duration_matrix = validate_capital_duration_matrix.reshape(
|
| 526 |
+
row, 1, col
|
| 527 |
+
)
|
| 528 |
+
|
| 529 |
+
validate_payload = {
|
| 530 |
+
"validate_process_df": validate_process_df,
|
| 531 |
+
"validate_result_matrix": validate_result_matrix,
|
| 532 |
+
"validate_material_cost_matrix": validate_material_cost_matrix,
|
| 533 |
+
"validate_material_amount_matrix": validate_material_amount_matrix,
|
| 534 |
+
"validate_capital_cost_matrix": valdiate_capital_cost_matrix,
|
| 535 |
+
"validate_day_amount_matrix": validate_dayamount_matrix,
|
| 536 |
+
"validate_capital_duration_matrix": validate_capital_duration_matrix,
|
| 537 |
+
"validate_employee_cost_matrix": validate_employee_cost_matrix,
|
| 538 |
+
"validate_employee_duration_matrix": validate_employee_duration_matrix,
|
| 539 |
+
"validate_employee_day_amount_matrix": validate_employee_day_amount_matrix,
|
| 540 |
+
}
|
| 541 |
+
|
| 542 |
+
return validate_payload
|
| 543 |
+
|
| 544 |
+
def get_data(self):
|
| 545 |
+
return (
|
| 546 |
+
self.process_df,
|
| 547 |
+
self.employee_usage,
|
| 548 |
+
self.material_usage,
|
| 549 |
+
self.capital_cost_usage,
|
| 550 |
+
)
|
model/matrix_generator/cost_matrix_generator.py
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import numpy as np
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def generate_material_usage_cost_matrix(process_df, material_usage_df):
|
| 6 |
+
overall_cost_matrix = pd.DataFrame()
|
| 7 |
+
overall_amount_matrix = pd.DataFrame()
|
| 8 |
+
process_df = process_df.reset_index()
|
| 9 |
+
|
| 10 |
+
# Find Unique for fixed the column of dataframe and Matrix
|
| 11 |
+
unique_material_id = material_usage_df["_id"].unique()
|
| 12 |
+
|
| 13 |
+
for index in process_df.index:
|
| 14 |
+
selected_process = process_df.iloc[index]
|
| 15 |
+
|
| 16 |
+
# Find Unique Material
|
| 17 |
+
# Find All Material Usage
|
| 18 |
+
selected_process_material = material_usage_df[
|
| 19 |
+
material_usage_df["process_id"] == selected_process["process_id"]
|
| 20 |
+
]
|
| 21 |
+
cost_dict = {}
|
| 22 |
+
amount_dict = {}
|
| 23 |
+
|
| 24 |
+
# Iteration Over Material
|
| 25 |
+
for idx in range(len(selected_process_material)):
|
| 26 |
+
selected_data = selected_process_material.iloc[idx]
|
| 27 |
+
material_id = selected_data["_id"]
|
| 28 |
+
cost = selected_data["unit_cost"]
|
| 29 |
+
amount = selected_data["amount"]
|
| 30 |
+
cost_dict[material_id] = cost
|
| 31 |
+
amount_dict[material_id] = amount
|
| 32 |
+
|
| 33 |
+
# Iteration Over Rest of Material
|
| 34 |
+
for material_id in unique_material_id:
|
| 35 |
+
if material_id not in cost_dict:
|
| 36 |
+
cost_dict[material_id] = 0
|
| 37 |
+
amount_dict[material_id] = 0
|
| 38 |
+
|
| 39 |
+
cost_df = pd.DataFrame(
|
| 40 |
+
cost_dict, index=[selected_process["process_id"]])
|
| 41 |
+
amount_df = pd.DataFrame(
|
| 42 |
+
amount_dict, index=[selected_process["process_id"]])
|
| 43 |
+
|
| 44 |
+
overall_cost_matrix = pd.concat([overall_cost_matrix, cost_df], axis=0)
|
| 45 |
+
overall_amount_matrix = pd.concat(
|
| 46 |
+
[overall_amount_matrix, amount_df], axis=0)
|
| 47 |
+
|
| 48 |
+
# Reorder Column to be same normal and validation
|
| 49 |
+
column_list = unique_material_id.tolist()
|
| 50 |
+
ordered_columns = sorted(column_list)
|
| 51 |
+
overall_cost_matrix = overall_cost_matrix[ordered_columns]
|
| 52 |
+
overall_amount_matrix = overall_amount_matrix[ordered_columns]
|
| 53 |
+
|
| 54 |
+
overall_cost_matrix.fillna(0, inplace=True)
|
| 55 |
+
overall_amount_matrix.fillna(0, inplace=True)
|
| 56 |
+
|
| 57 |
+
return (overall_cost_matrix, overall_amount_matrix)
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def generate_employee_usage_cost_matrix(process_df, employee_usage_df):
|
| 61 |
+
overall_cost_matrix = pd.DataFrame()
|
| 62 |
+
overall_duration_matrix = pd.DataFrame()
|
| 63 |
+
overall_day_amount_matrix = pd.DataFrame()
|
| 64 |
+
|
| 65 |
+
employee_usage_df["duration"] = (
|
| 66 |
+
employee_usage_df["duration"] * employee_usage_df["amount"]
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
unique_emp_id = employee_usage_df["employee_id"].unique()
|
| 70 |
+
|
| 71 |
+
process_df = process_df.reset_index()
|
| 72 |
+
|
| 73 |
+
# Iteration Over each process
|
| 74 |
+
for index in process_df.index:
|
| 75 |
+
selected_process = process_df.iloc[index]
|
| 76 |
+
selected_process_employee = employee_usage_df[
|
| 77 |
+
employee_usage_df["process_id"] == selected_process["process_id"]
|
| 78 |
+
]
|
| 79 |
+
|
| 80 |
+
ec_cost_dict = {}
|
| 81 |
+
ec_duration_dict = {}
|
| 82 |
+
ec_day_amount_dict = {}
|
| 83 |
+
|
| 84 |
+
unique_process_employee = selected_process_employee["employee_id"].unique(
|
| 85 |
+
)
|
| 86 |
+
unique_pe_df = pd.DataFrame(
|
| 87 |
+
unique_process_employee, columns=["employee_id"])
|
| 88 |
+
|
| 89 |
+
# Adust Employee
|
| 90 |
+
# Converse many employee record to one record for each employee in one process
|
| 91 |
+
# Process will can contain many of employee but 1 employee only 1 record
|
| 92 |
+
for idx in range(len(unique_pe_df)):
|
| 93 |
+
selected_data = unique_pe_df.iloc[idx]
|
| 94 |
+
all_record = selected_process_employee[
|
| 95 |
+
selected_process_employee["employee_id"] == selected_data["employee_id"]
|
| 96 |
+
]
|
| 97 |
+
first_record = all_record.iloc[0]
|
| 98 |
+
# Cost also the same pick from the first record
|
| 99 |
+
cost = first_record["cost"]
|
| 100 |
+
day_amount = first_record["day_amount"]
|
| 101 |
+
# Duration is the sum of all duration of employee in the process
|
| 102 |
+
duration = all_record["duration"].sum()
|
| 103 |
+
# Update the record of unique_pe_df add cost and duration
|
| 104 |
+
unique_pe_df.loc[idx, "cost"] = cost
|
| 105 |
+
unique_pe_df.loc[idx, "duration"] = duration
|
| 106 |
+
unique_pe_df.loc[idx, "day_amount"] = day_amount
|
| 107 |
+
unique_pe_df.loc[idx, "process_id"] = first_record["process_id"]
|
| 108 |
+
|
| 109 |
+
for idx in range(len(unique_pe_df)):
|
| 110 |
+
selected_data = unique_pe_df.iloc[idx]
|
| 111 |
+
cost = selected_data["cost"]
|
| 112 |
+
employee_id = selected_data["employee_id"]
|
| 113 |
+
duration = selected_data["duration"]
|
| 114 |
+
day_amount = selected_data["day_amount"]
|
| 115 |
+
|
| 116 |
+
ec_cost_dict[employee_id] = cost
|
| 117 |
+
ec_duration_dict[employee_id] = duration
|
| 118 |
+
ec_day_amount_dict[employee_id] = day_amount
|
| 119 |
+
|
| 120 |
+
# Iteration Over Rest of Employee
|
| 121 |
+
|
| 122 |
+
for employee_id in unique_emp_id:
|
| 123 |
+
if employee_id not in ec_cost_dict:
|
| 124 |
+
ec_cost_dict[employee_id] = 0
|
| 125 |
+
ec_duration_dict[employee_id] = 0
|
| 126 |
+
ec_day_amount_dict[employee_id] = 1
|
| 127 |
+
|
| 128 |
+
employee_cost_df = pd.DataFrame(
|
| 129 |
+
ec_cost_dict, index=[selected_process["process_id"]]
|
| 130 |
+
)
|
| 131 |
+
|
| 132 |
+
employee_duration_df = pd.DataFrame(
|
| 133 |
+
ec_duration_dict, index=[selected_process["process_id"]]
|
| 134 |
+
)
|
| 135 |
+
|
| 136 |
+
employee_dayamount_df = pd.DataFrame(
|
| 137 |
+
ec_day_amount_dict, index=[selected_process["process_id"]]
|
| 138 |
+
)
|
| 139 |
+
|
| 140 |
+
overall_cost_matrix = pd.concat(
|
| 141 |
+
[overall_cost_matrix, employee_cost_df], axis=0
|
| 142 |
+
)
|
| 143 |
+
|
| 144 |
+
overall_duration_matrix = pd.concat(
|
| 145 |
+
[overall_duration_matrix, employee_duration_df], axis=0
|
| 146 |
+
)
|
| 147 |
+
|
| 148 |
+
overall_day_amount_matrix = pd.concat(
|
| 149 |
+
[overall_day_amount_matrix, employee_dayamount_df], axis=0
|
| 150 |
+
)
|
| 151 |
+
|
| 152 |
+
# Reorder Column to be same normal and validation
|
| 153 |
+
|
| 154 |
+
# Reorder for Emploee
|
| 155 |
+
column_list = unique_emp_id.tolist()
|
| 156 |
+
ordered_columns = sorted(column_list)
|
| 157 |
+
overall_cost_matrix = overall_cost_matrix[ordered_columns]
|
| 158 |
+
overall_duration_matrix = overall_duration_matrix[ordered_columns]
|
| 159 |
+
overall_day_amount_matrix = overall_day_amount_matrix[ordered_columns]
|
| 160 |
+
|
| 161 |
+
overall_cost_matrix.fillna(0, inplace=True)
|
| 162 |
+
overall_duration_matrix.fillna(0, inplace=True)
|
| 163 |
+
overall_day_amount_matrix.fillna(1, inplace=True)
|
| 164 |
+
|
| 165 |
+
return (
|
| 166 |
+
overall_cost_matrix,
|
| 167 |
+
overall_duration_matrix,
|
| 168 |
+
overall_day_amount_matrix,
|
| 169 |
+
)
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def generate_capital_cost_matrix(process_df, capital_cost_df):
|
| 173 |
+
cost_df = pd.DataFrame()
|
| 174 |
+
day_amount_df = pd.DataFrame()
|
| 175 |
+
duration_df = pd.DataFrame()
|
| 176 |
+
process_df = process_df.reset_index()
|
| 177 |
+
|
| 178 |
+
# Find Unique id to fixed the column of dataframe and Matrix
|
| 179 |
+
unique_capital_cost_id = capital_cost_df["_id"].unique()
|
| 180 |
+
|
| 181 |
+
# Iteration Over each process
|
| 182 |
+
for index in process_df.index:
|
| 183 |
+
selected_process = process_df.iloc[index]
|
| 184 |
+
selected_process_capitalcost = capital_cost_df[
|
| 185 |
+
capital_cost_df["process_id"] == selected_process["process_id"]
|
| 186 |
+
]
|
| 187 |
+
|
| 188 |
+
cost_dict = {}
|
| 189 |
+
day_amount_dict = {}
|
| 190 |
+
duration_dict = {}
|
| 191 |
+
uniq_process_cc = selected_process_capitalcost["_id"].unique()
|
| 192 |
+
|
| 193 |
+
uniq_pcc_df = pd.DataFrame(
|
| 194 |
+
uniq_process_cc, columns=["capital_cost_id"])
|
| 195 |
+
|
| 196 |
+
# Adust Capital Cost
|
| 197 |
+
# Converse many capital Cost record to one record for each capital Cost in one process
|
| 198 |
+
# Process will can contain many of capital cost but 1 capital cost only 1 record
|
| 199 |
+
for idx in range(len(uniq_pcc_df)):
|
| 200 |
+
selected_data = uniq_pcc_df.iloc[idx]
|
| 201 |
+
all_record = selected_process_capitalcost[
|
| 202 |
+
selected_process_capitalcost["_id"] == selected_data["capital_cost_id"]
|
| 203 |
+
]
|
| 204 |
+
first_record = all_record.iloc[0]
|
| 205 |
+
# Cost also the same pick from the first record
|
| 206 |
+
cost = first_record["cost"]
|
| 207 |
+
# Duration is the sum of all duration of employee in the process
|
| 208 |
+
duration = all_record["duration"].sum()
|
| 209 |
+
# Update the record of unique_pe_df add cost and duration
|
| 210 |
+
uniq_pcc_df.loc[idx, "cost"] = cost
|
| 211 |
+
uniq_pcc_df.loc[idx, "duration"] = duration
|
| 212 |
+
uniq_pcc_df.loc[idx, "day_amount"] = first_record["day_amount"]
|
| 213 |
+
uniq_pcc_df.loc[idx, "process_id"] = first_record["process_id"]
|
| 214 |
+
|
| 215 |
+
# Iteration Only for 1 cc per record data
|
| 216 |
+
for idx in range(len(uniq_pcc_df)):
|
| 217 |
+
selected_data = uniq_pcc_df.iloc[idx]
|
| 218 |
+
cost = selected_data["cost"]
|
| 219 |
+
duration = selected_data["duration"]
|
| 220 |
+
captial_cost_id = selected_data["capital_cost_id"]
|
| 221 |
+
cost_dict[captial_cost_id] = cost
|
| 222 |
+
day_amount_dict[captial_cost_id] = selected_data["day_amount"]
|
| 223 |
+
duration_dict[captial_cost_id] = duration
|
| 224 |
+
|
| 225 |
+
# Do for the rest of capital cost object
|
| 226 |
+
for cc_id in unique_capital_cost_id:
|
| 227 |
+
if cc_id not in cost_dict:
|
| 228 |
+
cost_dict[cc_id] = 0
|
| 229 |
+
day_amount_dict[cc_id] = 1
|
| 230 |
+
duration_dict[cc_id] = 0
|
| 231 |
+
|
| 232 |
+
# Dataframe Generation
|
| 233 |
+
sub_cost_df = pd.DataFrame(
|
| 234 |
+
cost_dict, index=[selected_process["process_id"]])
|
| 235 |
+
sub_duration_df = pd.DataFrame(
|
| 236 |
+
duration_dict, index=[selected_process["process_id"]]
|
| 237 |
+
)
|
| 238 |
+
sub_dayamount_df = pd.DataFrame(
|
| 239 |
+
day_amount_dict, index=[selected_process["process_id"]]
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
# Generate Matrix
|
| 243 |
+
cost_df = pd.concat([cost_df, sub_cost_df], axis=0)
|
| 244 |
+
day_amount_df = pd.concat([day_amount_df, sub_dayamount_df], axis=0)
|
| 245 |
+
duration_df = pd.concat([duration_df, sub_duration_df], axis=0)
|
| 246 |
+
|
| 247 |
+
# Reorder the Column to be same on Training and validation
|
| 248 |
+
|
| 249 |
+
column_list = unique_capital_cost_id.tolist()
|
| 250 |
+
sorted_column = sorted(column_list)
|
| 251 |
+
|
| 252 |
+
day_amount_df = day_amount_df[sorted_column]
|
| 253 |
+
cost_df = cost_df[sorted_column]
|
| 254 |
+
duration_df = duration_df[sorted_column]
|
| 255 |
+
|
| 256 |
+
day_amount_df.fillna(1, inplace=True)
|
| 257 |
+
cost_df.fillna(0, inplace=True)
|
| 258 |
+
duration_df.fillna(1, inplace=True)
|
| 259 |
+
|
| 260 |
+
return (cost_df, day_amount_df, duration_df)
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
def generate_price_matrix(process_df, use_3d=False, use_unit_cost=True):
|
| 264 |
+
price_arr = []
|
| 265 |
+
process_df = process_df.reset_index()
|
| 266 |
+
if use_unit_cost:
|
| 267 |
+
for index in process_df.index:
|
| 268 |
+
selected_data = process_df.iloc[index]
|
| 269 |
+
cost = selected_data["cost"]
|
| 270 |
+
if use_3d:
|
| 271 |
+
price_arr.append([[cost]])
|
| 272 |
+
else:
|
| 273 |
+
price_arr.append([cost])
|
| 274 |
+
else:
|
| 275 |
+
for index in process_df.index:
|
| 276 |
+
selected_data = process_df.iloc[index]
|
| 277 |
+
if use_3d:
|
| 278 |
+
price_arr.append([[selected_data["cost"]]])
|
| 279 |
+
else:
|
| 280 |
+
price_arr.append([selected_data["cost"]])
|
| 281 |
+
price_arr = np.array(price_arr)
|
| 282 |
+
return price_arr
|
| 283 |
+
|
| 284 |
+
|
| 285 |
+
def generate_duration_matrix(process_df, use_3d=False):
|
| 286 |
+
duration_array = []
|
| 287 |
+
process_df = process_df.reset_index()
|
| 288 |
+
for index in process_df.index:
|
| 289 |
+
selected_data = process_df.iloc[index]
|
| 290 |
+
duration = selected_data["duration"]
|
| 291 |
+
if use_3d:
|
| 292 |
+
duration_array.append([[duration]])
|
| 293 |
+
else:
|
| 294 |
+
duration_array.append([duration])
|
| 295 |
+
|
| 296 |
+
duration_array = np.array(duration_array)
|
| 297 |
+
return duration_array
|
model/model/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
__pycache__/
|
model/model/activation.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
alpha = 0.1
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def leaky_relu(x):
|
| 5 |
+
shape = x.shape
|
| 6 |
+
x = x.flatten()
|
| 7 |
+
result = 0
|
| 8 |
+
if x > 0:
|
| 9 |
+
result = x
|
| 10 |
+
else:
|
| 11 |
+
result = alpha * x
|
| 12 |
+
return result.reshape(shape)
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def leaky_relu_prime(x):
|
| 16 |
+
x = x.flatten()
|
| 17 |
+
if x > 0:
|
| 18 |
+
return 1
|
| 19 |
+
else:
|
| 20 |
+
return alpha
|
model/model/captial_fc_layer.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from layer import Layer
|
| 2 |
+
from tsensor import explain as exp
|
| 3 |
+
import numpy as np
|
| 4 |
+
import activation as act
|
| 5 |
+
import importlib
|
| 6 |
+
import weight_activation as wa
|
| 7 |
+
|
| 8 |
+
importlib.reload(act)
|
| 9 |
+
importlib.reload(wa)
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class CapitalCostFCLayer(Layer):
|
| 13 |
+
def __init__(self, input_size, output_size, hour_day):
|
| 14 |
+
self.weights = np.full(
|
| 15 |
+
(input_size, output_size), 1.0
|
| 16 |
+
) # np.random.rand(input_size, output_size) - 0.5
|
| 17 |
+
self.bias = np.full(
|
| 18 |
+
(1, output_size), 0.0
|
| 19 |
+
) # np.random.rand(1, output_size) - 0.5
|
| 20 |
+
print(f"weight shape {self.weights.shape}")
|
| 21 |
+
self.second_input = None
|
| 22 |
+
self.day_amount = None
|
| 23 |
+
self.hour_day = hour_day
|
| 24 |
+
self.cost = None
|
| 25 |
+
self.time_usage = None
|
| 26 |
+
self.input = None
|
| 27 |
+
|
| 28 |
+
def annotate(self, cost_rate, day_amount, time_usage):
|
| 29 |
+
with exp() as c:
|
| 30 |
+
# fmt:off
|
| 31 |
+
output = 1/60 * (1/self.hour_day) * cost_rate * time_usage * (1/day_amount) @ self.weights + self.bias
|
| 32 |
+
|
| 33 |
+
# fmt:on
|
| 34 |
+
|
| 35 |
+
# Predict during use
|
| 36 |
+
def predict(self, cost_data, time_usage, day_amount):
|
| 37 |
+
element_input = np.multiply(cost_data, time_usage)
|
| 38 |
+
element_input = np.divide(element_input, day_amount)
|
| 39 |
+
output = (1 / 60) * (1 / self.hour_day) * np.dot(
|
| 40 |
+
element_input, self.weights
|
| 41 |
+
) + self.bias
|
| 42 |
+
self.input = output
|
| 43 |
+
return act.leaky_relu(output)
|
| 44 |
+
|
| 45 |
+
# Predict During Train
|
| 46 |
+
def forward_propagation(self, cost_data, time_usage, day_amount):
|
| 47 |
+
self.cost = cost_data
|
| 48 |
+
self.time_usage = time_usage
|
| 49 |
+
self.day_amount = day_amount
|
| 50 |
+
if np.all(cost_data == 0) and np.all(time_usage == 0):
|
| 51 |
+
self.output = np.zeros((1, 1))
|
| 52 |
+
return self.output
|
| 53 |
+
|
| 54 |
+
element_input = np.multiply(self.cost, self.time_usage)
|
| 55 |
+
element_input = np.divide(element_input, self.day_amount)
|
| 56 |
+
self.output = (1 / 60) * (1 / self.hour_day) * np.dot(
|
| 57 |
+
element_input, self.weights
|
| 58 |
+
) # + self.bias
|
| 59 |
+
self.output = np.nan_to_num(self.output)
|
| 60 |
+
return act.leaky_relu(self.output)
|
| 61 |
+
|
| 62 |
+
def predict(self, cost_data, time_usage, day_amount):
|
| 63 |
+
element_input = np.multiply(cost_data, time_usage)
|
| 64 |
+
element_input = np.divide(element_input, day_amount)
|
| 65 |
+
output = (1 / 60) * (1 / self.hour_day) * np.dot(
|
| 66 |
+
element_input, self.weights
|
| 67 |
+
) # + self.bias
|
| 68 |
+
self.input = output
|
| 69 |
+
return act.leaky_relu(output)
|
| 70 |
+
|
| 71 |
+
# output error is dE/dY
|
| 72 |
+
def backward_propagation(self, output_error, learning_rate):
|
| 73 |
+
# dE/dX = dE/dY * df(x)/dx
|
| 74 |
+
# dE/dX = dE/dY * W^T
|
| 75 |
+
input_error = np.dot(output_error, self.weights.T)
|
| 76 |
+
# print(f'Output Error {output_error}')
|
| 77 |
+
# dE/dW = dE/dY * dY/dW
|
| 78 |
+
# dE/dwi = dE/dyi * xi
|
| 79 |
+
# dE/dW = dE/dY * X^T
|
| 80 |
+
|
| 81 |
+
activation_input = self.input
|
| 82 |
+
activation_prime = act.leaky_relu_prime(activation_input)
|
| 83 |
+
input = self.time_usage * (1 / 60) * (1 / self.hour_day)
|
| 84 |
+
input = np.multiply(input, self.cost)
|
| 85 |
+
input = np.divide(input, self.day_amount)
|
| 86 |
+
|
| 87 |
+
weight_error = np.dot(output_error, input)
|
| 88 |
+
weight_error = np.multiply(weight_error, activation_prime)
|
| 89 |
+
|
| 90 |
+
row, col = self.weights.shape
|
| 91 |
+
weight_error = weight_error.reshape(row, col)
|
| 92 |
+
|
| 93 |
+
# dE/dB = dE/dY
|
| 94 |
+
bias_error = output_error * activation_prime
|
| 95 |
+
# bias_error = output_error
|
| 96 |
+
# print(f"Capital Cost Acutal Input{activation_input}")
|
| 97 |
+
# print(f"Capital Cost Activation Prime {activation_prime}")
|
| 98 |
+
# print(f"Capital Cost Output Error {output_error}")
|
| 99 |
+
|
| 100 |
+
# Update Parameter
|
| 101 |
+
self.weights -= learning_rate * weight_error
|
| 102 |
+
self.weights = wa.un_zero_weight(self.weights)
|
| 103 |
+
self.bias -= learning_rate * bias_error
|
| 104 |
+
# print("Update weight to ", self.weights)
|
| 105 |
+
return input_error # dE/dX
|
| 106 |
+
|
| 107 |
+
def get_weight(self):
|
| 108 |
+
return self.weights
|
| 109 |
+
|
| 110 |
+
def get_bias(self):
|
| 111 |
+
return self.bias
|
model/model/employee_fc_layer.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from layer import Layer
|
| 2 |
+
import numpy as np
|
| 3 |
+
from tsensor import explain as exp
|
| 4 |
+
|
| 5 |
+
import activation as act
|
| 6 |
+
import weight_activation as wa
|
| 7 |
+
import importlib
|
| 8 |
+
|
| 9 |
+
importlib.reload(act)
|
| 10 |
+
importlib.reload(wa)
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class EmployeeFCLayer(Layer):
|
| 14 |
+
def __init__(self, input_size, output_size, hour_day):
|
| 15 |
+
self.weights = np.full(
|
| 16 |
+
(input_size, output_size), 1.0
|
| 17 |
+
) # np.random.rand(input_size, output_size) - 0.5
|
| 18 |
+
self.bias = np.full(
|
| 19 |
+
(1, output_size), 0.0
|
| 20 |
+
) # np.random.rand(1, output_size) - 0.5
|
| 21 |
+
print(f"weight shape {self.weights.shape}")
|
| 22 |
+
self.time_usage = None
|
| 23 |
+
self.hour_day = hour_day
|
| 24 |
+
self.cost = None
|
| 25 |
+
self.input = None
|
| 26 |
+
|
| 27 |
+
def annotate(self, cost_rate, time_usage, day_amount):
|
| 28 |
+
with exp() as c:
|
| 29 |
+
# fmt: off
|
| 30 |
+
output = 1/75 * 1/self.hour_day * time_usage *1/day_amount * cost_rate @ self.weights + self.bias
|
| 31 |
+
|
| 32 |
+
# fmt: on
|
| 33 |
+
|
| 34 |
+
# Predict the result during use
|
| 35 |
+
def predict(self, cost_data, time_usage, day_amount):
|
| 36 |
+
cost_time = np.multiply(cost_data, time_usage)
|
| 37 |
+
day_amount = np.divide(1, day_amount)
|
| 38 |
+
output = (1 / 75) * (1 / self.hour_day) * np.dot(
|
| 39 |
+
cost_time, self.weights
|
| 40 |
+
) + self.bias
|
| 41 |
+
# print(f"Weight For Daily Employee: {self.weights}")
|
| 42 |
+
self.input = output
|
| 43 |
+
return act.leaky_relu(output)
|
| 44 |
+
|
| 45 |
+
# Predict During Train
|
| 46 |
+
def forward_propagation(self, cost_data, time_usage, day_amount):
|
| 47 |
+
self.cost = cost_data
|
| 48 |
+
self.time_usage = time_usage
|
| 49 |
+
self.day_amount = day_amount
|
| 50 |
+
|
| 51 |
+
if (
|
| 52 |
+
np.all(cost_data == 0)
|
| 53 |
+
and np.all(time_usage == 0)
|
| 54 |
+
and np.all(day_amount == 0)
|
| 55 |
+
):
|
| 56 |
+
self.output = np.zeros((1, 1))
|
| 57 |
+
return self.output
|
| 58 |
+
|
| 59 |
+
cost_time = np.multiply(self.cost, self.time_usage)
|
| 60 |
+
cost_time = np.divide(cost_time, day_amount)
|
| 61 |
+
self.output = (
|
| 62 |
+
(1 / 75) * (1 / self.hour_day) * np.dot(cost_time, self.weights)
|
| 63 |
+
) # + self.bias
|
| 64 |
+
return act.leaky_relu(self.output)
|
| 65 |
+
|
| 66 |
+
def predict(self, cost_data, time_usage, day_amount):
|
| 67 |
+
cost_time = np.multiply(cost_data, time_usage)
|
| 68 |
+
cost_time = np.divide(cost_time, day_amount)
|
| 69 |
+
output = (
|
| 70 |
+
(1 / 75) * (1 / self.hour_day) * np.dot(cost_time, self.weights)
|
| 71 |
+
) # + self.bias
|
| 72 |
+
# print(f"Weight For Daily Employee: {self.weights}")
|
| 73 |
+
self.input = output
|
| 74 |
+
return act.leaky_relu(output)
|
| 75 |
+
|
| 76 |
+
# output error is dE/dY
|
| 77 |
+
def backward_propagation(self, output_error, learning_rate):
|
| 78 |
+
# print(f"DE: Weight {self.weights}")
|
| 79 |
+
input_error = np.dot(output_error, self.weights.T)
|
| 80 |
+
# print(f"DE: Weight.T {self.weights.T}")
|
| 81 |
+
# print(f"DE: Input Error {input_error}")
|
| 82 |
+
# print(f"DE: Output Error {output_error}")
|
| 83 |
+
# print(f"DE: Time Usage {self.time_usage}")
|
| 84 |
+
input = self.time_usage * (1 / 75) * (1 / self.hour_day)
|
| 85 |
+
# print(f"DE: input Before Multiply {input}")
|
| 86 |
+
# print(f"DE: Cost {self.cost} and Cost Transpose {self.cost.T}")
|
| 87 |
+
input = np.multiply(input, self.cost)
|
| 88 |
+
input = np.multiply(input, 1 / self.day_amount)
|
| 89 |
+
# print(f"DE: input After Multiply {gradient}")
|
| 90 |
+
# print(f"DE: Output Error {output_error}")
|
| 91 |
+
weight_error = np.dot(output_error, input)
|
| 92 |
+
|
| 93 |
+
activation_input = self.input
|
| 94 |
+
activation_prime = act.leaky_relu_prime(activation_input)
|
| 95 |
+
|
| 96 |
+
weight_error = np.multiply(weight_error, activation_prime)
|
| 97 |
+
|
| 98 |
+
row, col = self.weights.shape
|
| 99 |
+
# dE/dB = dE/dY
|
| 100 |
+
bias_error = output_error * activation_prime
|
| 101 |
+
# bias_error = output_error
|
| 102 |
+
# print(f"Daily Employee Acutal Input{activation_input}")
|
| 103 |
+
# print(f"Daily Employee Activation Prime {activation_prime}")
|
| 104 |
+
# print(f"Daily Employee Output Error {output_error}")
|
| 105 |
+
|
| 106 |
+
weight_error = weight_error.reshape(row, col)
|
| 107 |
+
# Update Parameter
|
| 108 |
+
# print(f"DE: Weight Error {weight_error}")
|
| 109 |
+
# print(f"DE: New Weight {self.weights}")
|
| 110 |
+
self.weights -= learning_rate * weight_error
|
| 111 |
+
self.weights = wa.un_zero_weight(self.weights)
|
| 112 |
+
# print('DE: New Bias', self.bias)
|
| 113 |
+
self.bias -= learning_rate * bias_error
|
| 114 |
+
# print("Update weight to ", self.weights)
|
| 115 |
+
return input_error # dE/dX
|
| 116 |
+
|
| 117 |
+
def get_weight(self):
|
| 118 |
+
return self.weights
|
| 119 |
+
|
| 120 |
+
def get_bias(self):
|
| 121 |
+
return self.bias
|
model/model/generate_data_set.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import numpy as np
|
| 3 |
+
import importlib
|
| 4 |
+
import sys
|
| 5 |
+
|
| 6 |
+
# fmt:off
|
| 7 |
+
sys.path.append('../matrix_generator')
|
| 8 |
+
|
| 9 |
+
import cost_matrix_generator as cmg
|
| 10 |
+
importlib.reload(cmg)
|
| 11 |
+
# fmt:on
|
| 12 |
+
|
| 13 |
+
# Import Data
|
| 14 |
+
process_df = pd.read_csv('example/generated_process_data.csv')
|
| 15 |
+
employee_usage = pd.read_csv("example/generated_employee_usage.csv")
|
| 16 |
+
material_usage = pd.read_csv("example/generated_material_usage.csv")
|
| 17 |
+
capital_cost_usage = pd.read_csv("example/generated_captial_cost.csv")
|
| 18 |
+
|
| 19 |
+
# Data Extract and Shaping (Pre Processing)
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def generate_data():
|
| 23 |
+
# Material
|
| 24 |
+
material_cost_matrix, material_amount_matrix = cmg.generate_material_usage_cost_matrix(
|
| 25 |
+
process_df, material_usage)
|
| 26 |
+
material_cost_matrix = material_cost_matrix.values
|
| 27 |
+
material_amount_matrix = material_amount_matrix.values
|
| 28 |
+
|
| 29 |
+
row, col = material_cost_matrix.shape
|
| 30 |
+
material_cost_matrix = material_cost_matrix.reshape(row, 1, col)
|
| 31 |
+
material_amount_matrix = material_amount_matrix.reshape(row, 1, col)
|
| 32 |
+
|
| 33 |
+
# Employee
|
| 34 |
+
monthy_employee_cost_matrix, daily_employee_cost_matrix = cmg.generate_employee_usage_cost_matrix(
|
| 35 |
+
process_df, employee_usage)
|
| 36 |
+
monthy_employee_cost_matrix = monthy_employee_cost_matrix.values
|
| 37 |
+
daily_employee_cost_matrix = daily_employee_cost_matrix.values
|
| 38 |
+
|
| 39 |
+
row, col = monthy_employee_cost_matrix.shape
|
| 40 |
+
monthy_employee_cost_matrix = monthy_employee_cost_matrix.reshape(
|
| 41 |
+
row, 1, col)
|
| 42 |
+
row, col = daily_employee_cost_matrix.shape
|
| 43 |
+
daily_employee_cost_matrix = daily_employee_cost_matrix.reshape(
|
| 44 |
+
row, 1, col)
|
| 45 |
+
print(
|
| 46 |
+
f'Monthy Employee Cost matrix shape {monthy_employee_cost_matrix.shape} & Daily Employee Cost Matrix Shape {daily_employee_cost_matrix.shape}')
|
| 47 |
+
|
| 48 |
+
# Capital Cost
|
| 49 |
+
unit_cost_matrix, machine_hour_matrix, life_time_matrix = cmg.generate_capital_cost_matrix(
|
| 50 |
+
process_df, capital_cost_df=capital_cost_usage)
|
| 51 |
+
|
| 52 |
+
capital_cost_matrix = unit_cost_matrix.values
|
| 53 |
+
|
| 54 |
+
machine_hour_matrix = machine_hour_matrix.values
|
| 55 |
+
|
| 56 |
+
life_time_matrix = life_time_matrix.values
|
| 57 |
+
|
| 58 |
+
row, col = capital_cost_matrix.shape
|
| 59 |
+
|
| 60 |
+
capital_cost_matrix = capital_cost_matrix.reshape(row, 1, col)
|
| 61 |
+
|
| 62 |
+
row, col = machine_hour_matrix.shape
|
| 63 |
+
|
| 64 |
+
machine_hour_matrix = machine_hour_matrix.reshape(row, 1, col)
|
| 65 |
+
|
| 66 |
+
row, col = life_time_matrix.shape
|
| 67 |
+
|
| 68 |
+
life_time_matrix = life_time_matrix.reshape(row, 1, col)
|
| 69 |
+
|
| 70 |
+
# Time Usage
|
| 71 |
+
duration_matrix = cmg.generate_duration_matrix(
|
| 72 |
+
process_df=process_df, use_3d=True)
|
| 73 |
+
|
| 74 |
+
result_matrix = cmg.generate_price_matrix(
|
| 75 |
+
process_df=process_df, use_3d=True
|
| 76 |
+
)
|
| 77 |
+
|
| 78 |
+
return material_cost_matrix, material_amount_matrix, monthy_employee_cost_matrix, daily_employee_cost_matrix, capital_cost_matrix, machine_hour_matrix, life_time_matrix, duration_matrix, result_matrix
|
model/model/layer.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Base Class Layer
|
| 2 |
+
class Layer:
|
| 3 |
+
def __init__(self):
|
| 4 |
+
self.input = None
|
| 5 |
+
self.output = None
|
| 6 |
+
self.time_usage = None
|
| 7 |
+
|
| 8 |
+
# compute the output of a layer for a given input
|
| 9 |
+
def forward_propagation(self, input):
|
| 10 |
+
raise NotImplementedError
|
| 11 |
+
|
| 12 |
+
# conpute dE/dX for a given dE/dY (and update parameters if any)
|
| 13 |
+
def backward_propagation(self, output_error, learning_rate):
|
| 14 |
+
raise NotImplementedError
|
| 15 |
+
|
| 16 |
+
def predict(self):
|
| 17 |
+
raise NotImplementedError
|
model/model/loss.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
# lost function and its derivatives
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def mse(y_true, y_pred):
|
| 7 |
+
# print(f'y-true = {y_true} & y-predict = {y_pred}')
|
| 8 |
+
return np.mean(np.power(y_true-y_pred, 2))
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def mse_prime(y_true, y_pred):
|
| 12 |
+
# dE/dY = d(ERROR ROOT MEAN SQUARE)/dY
|
| 13 |
+
# dE/dY = d/dy (y-y_predict)^2
|
| 14 |
+
# dE/dY = 2(y-y_predict)
|
| 15 |
+
# dE/dY = 2*error
|
| 16 |
+
return 2*(y_pred-y_true)/y_true.size
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def rmspe(y_true, y_pred):
|
| 20 |
+
rmspe = (np.sqrt(np.mean(np.square((y_true - y_pred) / y_true)))) * 100
|
| 21 |
+
return rmspe
|
model/model/material_fc_layer.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from layer import Layer
|
| 2 |
+
from tsensor import explain as exp
|
| 3 |
+
import numpy as np
|
| 4 |
+
|
| 5 |
+
import activation as act
|
| 6 |
+
import weight_activation as wa
|
| 7 |
+
import importlib
|
| 8 |
+
|
| 9 |
+
importlib.reload(act)
|
| 10 |
+
importlib.reload(wa)
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class MaterialFCLayer(Layer):
|
| 14 |
+
def __init__(self, input_size, output_size):
|
| 15 |
+
self.weights = np.full((input_size, output_size), 1.0)
|
| 16 |
+
self.bias = np.full((1, output_size), 0.0)
|
| 17 |
+
print(f"weight shape {self.weights.shape}")
|
| 18 |
+
self.cost = None
|
| 19 |
+
self.amount = None
|
| 20 |
+
self.input = None
|
| 21 |
+
|
| 22 |
+
def annotate(self, cost_data, amount_data):
|
| 23 |
+
with exp() as c:
|
| 24 |
+
output = cost_data * amount_data @ self.weights + self.bias
|
| 25 |
+
|
| 26 |
+
# For Predict the result during use
|
| 27 |
+
def predict(self, cost_data, amount_data):
|
| 28 |
+
cost_amount = np.multiply(cost_data, amount_data)
|
| 29 |
+
output = np.dot(cost_amount, self.weights) + self.bias
|
| 30 |
+
self.input = output
|
| 31 |
+
return act.leaky_relu(output)
|
| 32 |
+
|
| 33 |
+
# For Predict the result during training
|
| 34 |
+
def forward_propagation(self, cost_data, amount_data):
|
| 35 |
+
self.cost = cost_data
|
| 36 |
+
self.amount = amount_data
|
| 37 |
+
if np.all(cost_data == 0) and np.all(amount_data == 0):
|
| 38 |
+
self.output = np.zeros((1, 1))
|
| 39 |
+
return self.output
|
| 40 |
+
cost_amount = np.multiply(self.cost, self.amount)
|
| 41 |
+
self.output = np.dot(cost_amount, self.weights) # + self.bias
|
| 42 |
+
return act.leaky_relu(self.output)
|
| 43 |
+
|
| 44 |
+
def predict(self, cost_data, amount_data):
|
| 45 |
+
cost_amount = np.multiply(cost_data, amount_data)
|
| 46 |
+
output = np.dot(cost_amount, self.weights) # + self.bias
|
| 47 |
+
# print(f"Weight For Material: {self.weights}")
|
| 48 |
+
self.input = output
|
| 49 |
+
# print(f"Material Acutal Input On Predict {self.input}")
|
| 50 |
+
|
| 51 |
+
return act.leaky_relu(output)
|
| 52 |
+
|
| 53 |
+
# output error is dE/dY
|
| 54 |
+
# dE/dX = dE/dY * df(x)/dx
|
| 55 |
+
# dE/dX = dE/dY * W^T
|
| 56 |
+
# dE/dW = dE/dY * dY/dW
|
| 57 |
+
# dE/dwi = dE/dyi * xi
|
| 58 |
+
# dE/dW = dE/dY * X^T
|
| 59 |
+
def backward_propagation(self, output_error, learning_rate):
|
| 60 |
+
row, col = self.weights.shape
|
| 61 |
+
input_error = np.dot(output_error, self.weights.T)
|
| 62 |
+
gradient = np.multiply(self.cost, self.amount)
|
| 63 |
+
|
| 64 |
+
weight_error = np.dot(output_error, gradient)
|
| 65 |
+
|
| 66 |
+
weight_error = weight_error.reshape(row, col)
|
| 67 |
+
activation_input = self.input
|
| 68 |
+
activation_prime = act.leaky_relu_prime(activation_input)
|
| 69 |
+
weight_error = np.multiply(weight_error, activation_prime)
|
| 70 |
+
bias_error = output_error * activation_prime
|
| 71 |
+
|
| 72 |
+
self.weights -= learning_rate * weight_error
|
| 73 |
+
self.weights = wa.un_zero_weight(self.weights)
|
| 74 |
+
self.bias -= learning_rate * bias_error
|
| 75 |
+
# dE/dB = dE/dY
|
| 76 |
+
# print(f"M: Input Error {input_error}")
|
| 77 |
+
# print(f"M: Gradient {gradient}")
|
| 78 |
+
# print(f"M: Output Error {output_error}")
|
| 79 |
+
# print(f"In Material, output error {output_error} gradient {gradient}")
|
| 80 |
+
# print(f"Material Acutal Input{activation_input}")
|
| 81 |
+
# print(f"Material Activation Prime {activation_prime}")
|
| 82 |
+
# print(f"Material Output Error {output_error}")
|
| 83 |
+
|
| 84 |
+
# Update Parameter
|
| 85 |
+
# print(f"M: Learning Rate {learning_rate} Weight Error {weight_error}")
|
| 86 |
+
# print(f"M: New Weight {self.weights} ")
|
| 87 |
+
# print("Update weight to ", self.weights)
|
| 88 |
+
return input_error # dE/dX
|
| 89 |
+
|
| 90 |
+
def get_weight(self):
|
| 91 |
+
return self.weights
|
| 92 |
+
|
| 93 |
+
def get_bias(self):
|
| 94 |
+
return self.bias
|
model/model/material_network.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import network as nw
|
| 2 |
+
import importlib
|
| 3 |
+
import numpy as np
|
| 4 |
+
|
| 5 |
+
importlib.reload(nw)
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class MaterialNetwork(nw.Network):
|
| 9 |
+
def __init__(self):
|
| 10 |
+
super().__init__()
|
| 11 |
+
|
| 12 |
+
def fit(self, cost_train, y_train, epochs, learning_rate, amount_train):
|
| 13 |
+
result = []
|
| 14 |
+
samples = len(cost_train)
|
| 15 |
+
|
| 16 |
+
# Train epoch times
|
| 17 |
+
for i in range(epochs):
|
| 18 |
+
err = 0
|
| 19 |
+
|
| 20 |
+
# train for all samples
|
| 21 |
+
for j in range(samples):
|
| 22 |
+
cost_input = cost_train[j]
|
| 23 |
+
amount_input = amount_train[j]
|
| 24 |
+
output = None
|
| 25 |
+
|
| 26 |
+
# predict data at all layer
|
| 27 |
+
for layer in self.layers:
|
| 28 |
+
output = layer.forward_propagation(cost_input, amount_input)
|
| 29 |
+
# output as input of next layer
|
| 30 |
+
cost_input = output
|
| 31 |
+
|
| 32 |
+
# Find loss for display
|
| 33 |
+
err += self.loss(y_train[j], output)
|
| 34 |
+
|
| 35 |
+
# Find Error of output dE/dY using derivation of MSE
|
| 36 |
+
error = self.loss_prime(y_train[j], output)
|
| 37 |
+
# Update Weight for next data
|
| 38 |
+
# By find gradient of weight in each layer and update
|
| 39 |
+
weight = []
|
| 40 |
+
|
| 41 |
+
for layer in reversed(self.layers):
|
| 42 |
+
error = layer.backward_propagation(error, learning_rate)
|
| 43 |
+
weight.append(layer.get_weight())
|
| 44 |
+
|
| 45 |
+
# Find Average Error per sample
|
| 46 |
+
err /= samples
|
| 47 |
+
print("Epoch %d/%d calculate with error = %f" % (i + 1, epochs, err))
|
| 48 |
+
result.append({"epoch": i + 1, "error": err})
|
| 49 |
+
self.weight_list = np.append(self.weight_list, [weight])
|
| 50 |
+
|
| 51 |
+
return result
|
| 52 |
+
|
| 53 |
+
def fit_on_sample(self, cost_input, y_train, learning_rate, amount_input):
|
| 54 |
+
err = 0
|
| 55 |
+
output = None
|
| 56 |
+
|
| 57 |
+
# predict data at all layer
|
| 58 |
+
for layer in self.layers:
|
| 59 |
+
output = layer.forward_propagation(cost_input, amount_input)
|
| 60 |
+
# output as input of next layer
|
| 61 |
+
cost_input = output
|
| 62 |
+
|
| 63 |
+
# Find loss for display
|
| 64 |
+
err += self.loss(y_train, output)
|
| 65 |
+
|
| 66 |
+
# Find Error of output dE/dY using derivation of MSE
|
| 67 |
+
error = self.loss_prime(y_train, output)
|
| 68 |
+
|
| 69 |
+
# Update Weight for next data
|
| 70 |
+
# By find gradient of weight in each layer and update
|
| 71 |
+
weight = []
|
| 72 |
+
for layer in reversed(self.layers):
|
| 73 |
+
error = layer.backward_propagation(error, learning_rate)
|
| 74 |
+
weight.append(layer.get_weight())
|
| 75 |
+
# print(f'Epoch calculate with error = {err}')
|
| 76 |
+
|
| 77 |
+
self.weight_list = np.append(self.weight_list, [weight])
|
| 78 |
+
return (output, err)
|
| 79 |
+
|
| 80 |
+
def get_weights(self):
|
| 81 |
+
result = []
|
| 82 |
+
for layer in self.layers:
|
| 83 |
+
result.append(layer.get_weight())
|
| 84 |
+
return result
|
| 85 |
+
|
| 86 |
+
def predict_sample(self, cost_input, amount_input):
|
| 87 |
+
output = None
|
| 88 |
+
|
| 89 |
+
# predict data at all layer
|
| 90 |
+
for layer in self.layers:
|
| 91 |
+
output = layer.forward_propagation(cost_input, amount_input)
|
| 92 |
+
# output as input of next layer
|
| 93 |
+
first_input = output
|
| 94 |
+
weight = layer.get_weight()
|
| 95 |
+
self.weight_list = np.append(self.weight_list, [weight])
|
| 96 |
+
|
| 97 |
+
return output
|
| 98 |
+
|
| 99 |
+
def predict(self, cost_input, amount_input):
|
| 100 |
+
output = None
|
| 101 |
+
|
| 102 |
+
# predict data at all layer
|
| 103 |
+
for layer in self.layers:
|
| 104 |
+
output = layer.predict(cost_input, amount_input)
|
| 105 |
+
# output as input of next layer
|
| 106 |
+
first_input = output
|
| 107 |
+
return output
|
| 108 |
+
|
| 109 |
+
def check_type(self, input_name):
|
| 110 |
+
if input_name == "material":
|
| 111 |
+
return True
|
| 112 |
+
print(f"You go to wrong class this is Material not {input_name}")
|
| 113 |
+
return False
|
model/model/matrix_normalization.py
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import normalize as norm
|
| 2 |
+
import importlib
|
| 3 |
+
|
| 4 |
+
importlib.reload(norm)
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def normalize_payload(
|
| 8 |
+
material_cost_matrix,
|
| 9 |
+
material_amount_matrix,
|
| 10 |
+
employee_cost_matrix,
|
| 11 |
+
employee_duration_matrix,
|
| 12 |
+
employee_day_amount_matrix,
|
| 13 |
+
capital_cost_matrix,
|
| 14 |
+
day_amount_matrix,
|
| 15 |
+
capital_cost_duration_matrix,
|
| 16 |
+
validation_payload,
|
| 17 |
+
display_log=False,
|
| 18 |
+
):
|
| 19 |
+
max_data = {}
|
| 20 |
+
min_data = {}
|
| 21 |
+
# Normalized Material Matrix
|
| 22 |
+
max_arr, min_arr = norm.find_max_min(material_cost_matrix)
|
| 23 |
+
normalized_material_cost = norm.normalized(
|
| 24 |
+
material_cost_matrix, max_arr, min_arr)
|
| 25 |
+
validate_material_cost_matrix = validation_payload["validate_material_cost_matrix"]
|
| 26 |
+
|
| 27 |
+
# Normalize Validate Material Cost Matrix
|
| 28 |
+
normalized_validate_material_cost = norm.normalized_2d(
|
| 29 |
+
validate_material_cost_matrix, material_cost_matrix, max_arr, min_arr
|
| 30 |
+
)
|
| 31 |
+
max_data["material_cost"] = max_arr
|
| 32 |
+
min_data["material_cost"] = min_arr
|
| 33 |
+
|
| 34 |
+
# Normalized Material Amount Matrix
|
| 35 |
+
max_arr, min_arr = norm.find_max_min(material_amount_matrix)
|
| 36 |
+
normalized_material_amount = norm.normalized(
|
| 37 |
+
material_amount_matrix, max_arr, min_arr
|
| 38 |
+
)
|
| 39 |
+
validate_material_amount_matrix = validation_payload[
|
| 40 |
+
"validate_material_amount_matrix"
|
| 41 |
+
]
|
| 42 |
+
|
| 43 |
+
if display_log:
|
| 44 |
+
print("normalized_material_amount", normalized_material_amount)
|
| 45 |
+
print("------------")
|
| 46 |
+
print("normalized_material_cost", normalized_material_cost)
|
| 47 |
+
print("------------")
|
| 48 |
+
|
| 49 |
+
normalized_validate_material_amount = norm.normalized_2d(
|
| 50 |
+
validate_material_amount_matrix, material_amount_matrix, max_arr, min_arr
|
| 51 |
+
)
|
| 52 |
+
max_data["material_amount"] = max_arr
|
| 53 |
+
min_data["material_amount"] = min_arr
|
| 54 |
+
|
| 55 |
+
# Normalized Employee Cost Matrix
|
| 56 |
+
max_arr, min_arr = norm.find_max_min(employee_cost_matrix)
|
| 57 |
+
normalized_employee_cost = norm.normalized(
|
| 58 |
+
employee_cost_matrix, max_arr, min_arr)
|
| 59 |
+
validate_employee_cost_matrix = validation_payload["validate_employee_cost_matrix"]
|
| 60 |
+
normalized_validate_employee_cost = norm.normalized(
|
| 61 |
+
validate_employee_cost_matrix, max_arr, min_arr
|
| 62 |
+
)
|
| 63 |
+
max_data["employee_cost"] = max_arr
|
| 64 |
+
min_data["employee_cost"] = min_arr
|
| 65 |
+
|
| 66 |
+
# Normalized Employee Duration Matrix
|
| 67 |
+
max_arr, min_arr = norm.find_max_min(employee_duration_matrix)
|
| 68 |
+
normalized_employee_duration = norm.normalized(
|
| 69 |
+
employee_duration_matrix, max_arr, min_arr
|
| 70 |
+
)
|
| 71 |
+
validate_employee_duration_matrix = validation_payload[
|
| 72 |
+
"validate_employee_duration_matrix"
|
| 73 |
+
]
|
| 74 |
+
normalized_validate_employee_duration = norm.normalized(
|
| 75 |
+
validate_employee_duration_matrix,
|
| 76 |
+
max_arr,
|
| 77 |
+
min_arr,
|
| 78 |
+
)
|
| 79 |
+
max_data["employee_duration"] = max_arr
|
| 80 |
+
min_data["employee_duration"] = min_arr
|
| 81 |
+
|
| 82 |
+
# Normalized Employee Day Amount
|
| 83 |
+
max_arr, min_arr = norm.find_max_min(employee_day_amount_matrix)
|
| 84 |
+
normalized_employee_day_amount = norm.normalized(
|
| 85 |
+
employee_day_amount_matrix, max_arr, min_arr
|
| 86 |
+
)
|
| 87 |
+
validate_employee_day_amount_matrix = validation_payload[
|
| 88 |
+
"validate_employee_day_amount_matrix"
|
| 89 |
+
]
|
| 90 |
+
normalized_validate_employee_day_amount = norm.normalized(
|
| 91 |
+
validate_employee_day_amount_matrix,
|
| 92 |
+
max_arr,
|
| 93 |
+
min_arr,
|
| 94 |
+
)
|
| 95 |
+
max_data["employee_day_amount"] = max_arr
|
| 96 |
+
min_data["employee_day_amount"] = min_arr
|
| 97 |
+
|
| 98 |
+
# Normalized Capital Cost Matrix
|
| 99 |
+
max_arr, min_arr = norm.find_max_min(capital_cost_matrix)
|
| 100 |
+
normalized_capital_cost = norm.normalized(
|
| 101 |
+
capital_cost_matrix, max_arr, min_arr)
|
| 102 |
+
validate_capital_cost_matrix = validation_payload["validate_capital_cost_matrix"]
|
| 103 |
+
normalized_validate_capital_cost = norm.normalized(
|
| 104 |
+
validate_capital_cost_matrix, max_arr, min_arr
|
| 105 |
+
)
|
| 106 |
+
max_data["capital_cost"] = max_arr
|
| 107 |
+
min_data["capital_cost"] = min_arr
|
| 108 |
+
|
| 109 |
+
# Normalized Day Amount Matrix
|
| 110 |
+
max_arr, min_arr = norm.find_max_min(day_amount_matrix)
|
| 111 |
+
normalized_day_amount = norm.normalized(
|
| 112 |
+
day_amount_matrix, max_arr, min_arr)
|
| 113 |
+
validate_day_amount_matrix = validation_payload["validate_day_amount_matrix"]
|
| 114 |
+
normalized_validate_day_amount = norm.normalized(
|
| 115 |
+
validate_day_amount_matrix, max_arr, min_arr
|
| 116 |
+
)
|
| 117 |
+
max_data["day_amount"] = max_arr
|
| 118 |
+
min_data["day_amount"] = min_arr
|
| 119 |
+
|
| 120 |
+
# Normalized Capital Cost Duration Matrix
|
| 121 |
+
validate_capital_duration_matrix = validation_payload[
|
| 122 |
+
"validate_capital_duration_matrix"
|
| 123 |
+
]
|
| 124 |
+
max_arr, min_arr = norm.find_max_min(capital_cost_duration_matrix)
|
| 125 |
+
normalized_capital_cost_duration = norm.normalized(
|
| 126 |
+
capital_cost_duration_matrix, max_arr, min_arr
|
| 127 |
+
)
|
| 128 |
+
normalized_validate_capital_duration = norm.normalized(
|
| 129 |
+
validate_capital_duration_matrix, max_arr, min_arr
|
| 130 |
+
)
|
| 131 |
+
max_data["capital_cost_duration"] = max_arr
|
| 132 |
+
min_data["capital_cost_duration"] = min_arr
|
| 133 |
+
|
| 134 |
+
return (
|
| 135 |
+
normalized_material_cost,
|
| 136 |
+
normalized_material_amount,
|
| 137 |
+
normalized_validate_material_cost,
|
| 138 |
+
normalized_validate_material_amount,
|
| 139 |
+
normalized_employee_cost,
|
| 140 |
+
normalized_employee_duration,
|
| 141 |
+
normalized_employee_day_amount,
|
| 142 |
+
normalized_validate_employee_cost,
|
| 143 |
+
normalized_validate_employee_duration,
|
| 144 |
+
normalized_validate_employee_day_amount,
|
| 145 |
+
normalized_capital_cost,
|
| 146 |
+
normalized_capital_cost_duration,
|
| 147 |
+
normalized_day_amount,
|
| 148 |
+
normalized_validate_capital_cost,
|
| 149 |
+
normalized_validate_capital_duration,
|
| 150 |
+
normalized_validate_day_amount,
|
| 151 |
+
max_data,
|
| 152 |
+
min_data,
|
| 153 |
+
)
|
model/model/network.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
# https://medium.com/towards-data-science/math-neural-network-from-scratch-in-python-d6da9f29ce65
|
| 5 |
+
class Network:
|
| 6 |
+
def __init__(self):
|
| 7 |
+
self.layers = []
|
| 8 |
+
self.loss = None
|
| 9 |
+
self.loss_prime = None
|
| 10 |
+
self.weight_list = []
|
| 11 |
+
|
| 12 |
+
def add(self, layer):
|
| 13 |
+
self.layers.append(layer)
|
| 14 |
+
|
| 15 |
+
def use(self, loss, loss_prime):
|
| 16 |
+
self.loss = loss
|
| 17 |
+
self.loss_prime = loss_prime
|
| 18 |
+
|
| 19 |
+
def fit(self, x_train, y_train, epochs, learning_rate):
|
| 20 |
+
samples = len(x_train)
|
| 21 |
+
|
| 22 |
+
# Train epoch times
|
| 23 |
+
for i in range(epochs):
|
| 24 |
+
err = 0
|
| 25 |
+
|
| 26 |
+
# train for all samples
|
| 27 |
+
for j in range(samples):
|
| 28 |
+
input = x_train[j]
|
| 29 |
+
output = None
|
| 30 |
+
|
| 31 |
+
# predict data at all layer
|
| 32 |
+
for layer in self.layers:
|
| 33 |
+
output = layer.forward_propagation(input)
|
| 34 |
+
# output as input of next layer
|
| 35 |
+
input = output
|
| 36 |
+
|
| 37 |
+
# Find loss for display
|
| 38 |
+
err += self.loss(y_train[j], output)
|
| 39 |
+
|
| 40 |
+
# Find Error of output dE/dY using derivation of MSE
|
| 41 |
+
error = self.loss_prime(y_train[j], output)
|
| 42 |
+
# Update Weight for next data
|
| 43 |
+
# By find gradient of weight in each layer and update
|
| 44 |
+
for layer in reversed(self.layers):
|
| 45 |
+
error = layer.backward_propagation(error, learning_rate)
|
| 46 |
+
|
| 47 |
+
# Find Average Error per sample
|
| 48 |
+
err /= samples
|
| 49 |
+
print("Epoch %d/%d calculate with error = %f" %
|
| 50 |
+
(i + 1, epochs, err))
|
| 51 |
+
print(f"Update weight to {layer.get_weight()} ")
|
| 52 |
+
print(f"Update Bias to {layer.get_bias()}")
|
| 53 |
+
print("")
|
| 54 |
+
|
| 55 |
+
def fit_on_sample(self):
|
| 56 |
+
raise NotImplementedError
|
| 57 |
+
|
| 58 |
+
def get_weight_list(self):
|
| 59 |
+
return self.weight_list
|
| 60 |
+
|
| 61 |
+
def get_weights(self):
|
| 62 |
+
raise NotImplementedError
|
| 63 |
+
|
| 64 |
+
def get_biases(self):
|
| 65 |
+
result = []
|
| 66 |
+
for layer in self.layers:
|
| 67 |
+
result.append(layer.get_bias())
|
| 68 |
+
return result
|
| 69 |
+
|
| 70 |
+
def predict_sample(self, first_input, second_input):
|
| 71 |
+
output = None
|
| 72 |
+
|
| 73 |
+
# predict data at all layer
|
| 74 |
+
for layer in self.layers:
|
| 75 |
+
output = layer.forward_propagation(first_input, second_input)
|
| 76 |
+
# output as input of next layer
|
| 77 |
+
first_input = output
|
| 78 |
+
|
| 79 |
+
return output
|
| 80 |
+
|
| 81 |
+
def back_propagate(self, error, learning_rate):
|
| 82 |
+
# weight = []
|
| 83 |
+
for layer in reversed(self.layers):
|
| 84 |
+
error = layer.backward_propagation(error, learning_rate)
|
| 85 |
+
# weight.append(layer.get_weight())
|
| 86 |
+
# print(f'Epoch calculate with error = {err}')
|
| 87 |
+
|
| 88 |
+
# self.weight_list = np.append(self.weight_list, [weight])
|
| 89 |
+
|
| 90 |
+
def predict(self, first_input, second_input):
|
| 91 |
+
output = None
|
| 92 |
+
|
| 93 |
+
# predict data at all layer
|
| 94 |
+
for layer in self.layers:
|
| 95 |
+
output = layer.predict(first_input, second_input)
|
| 96 |
+
# output as input of next layer
|
| 97 |
+
first_input = output
|
| 98 |
+
|
| 99 |
+
return output
|
| 100 |
+
|
| 101 |
+
def check_type(self):
|
| 102 |
+
print(
|
| 103 |
+
"It is in the Initial Class Network Please call this function on the child class"
|
| 104 |
+
)
|
| 105 |
+
return False
|
model/model/normalize.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def find_max_min(input_array):
|
| 5 |
+
input_np_arr = np.array(input_array)
|
| 6 |
+
x, y, z = input_np_arr.shape
|
| 7 |
+
if z == 0:
|
| 8 |
+
return None, None
|
| 9 |
+
input_np_arr = input_np_arr.reshape(-y, z)
|
| 10 |
+
# Find Max
|
| 11 |
+
max_array = np.max(input_np_arr, axis=0)
|
| 12 |
+
min_array = np.min(input_np_arr, axis=0)
|
| 13 |
+
data_amount = max_array - min_array
|
| 14 |
+
data_margin = np.multiply(data_amount, 0.15)
|
| 15 |
+
max_with_added = np.add(max_array, data_margin)
|
| 16 |
+
# Find Min
|
| 17 |
+
min_with_added = np.subtract(min_array, data_margin)
|
| 18 |
+
min_with_added[min_with_added < 0] = 0
|
| 19 |
+
|
| 20 |
+
return max_with_added, min_with_added
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def normalized(input_array, max_arr, min_arr):
|
| 24 |
+
input_np_arr = np.array(input_array, dtype=np.float32)
|
| 25 |
+
x, y, z = input_np_arr.shape
|
| 26 |
+
if z == 0:
|
| 27 |
+
return input_np_arr
|
| 28 |
+
input_np_arr = input_np_arr.reshape(-y, z)
|
| 29 |
+
normalized_array = input_np_arr.copy()
|
| 30 |
+
for i in range(0, len(input_np_arr)):
|
| 31 |
+
for j in range(0, len(input_np_arr[i])):
|
| 32 |
+
max = max_arr[j]
|
| 33 |
+
min = min_arr[j]
|
| 34 |
+
if max == min:
|
| 35 |
+
new_data = 1
|
| 36 |
+
else:
|
| 37 |
+
new_data = (input_np_arr[i][j] - min) / (max - min)
|
| 38 |
+
normalized_array[i][j] = new_data
|
| 39 |
+
|
| 40 |
+
normalized_array = normalized_array.reshape(x, y, z)
|
| 41 |
+
return normalized_array
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def normalized_2d(validate_payload, train_payload, max_arr, min_arr):
|
| 45 |
+
x, y, z = train_payload.shape
|
| 46 |
+
|
| 47 |
+
if z == 0:
|
| 48 |
+
return validate_payload
|
| 49 |
+
print('----')
|
| 50 |
+
print("Validate Payload size", validate_payload.shape)
|
| 51 |
+
print("Train Payload size", train_payload.shape)
|
| 52 |
+
x, y = np.array(validate_payload).shape
|
| 53 |
+
validate_payload = validate_payload.reshape(x, 1, z)
|
| 54 |
+
result = normalized(validate_payload, max_arr, min_arr)
|
| 55 |
+
return result
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def denormalize(value, max, min):
|
| 59 |
+
data_amount = max - min
|
| 60 |
+
data_margin = np.multiply(data_amount, 0.15)
|
| 61 |
+
max_with_added = max + data_margin
|
| 62 |
+
# Find Min
|
| 63 |
+
min_with_added = min - data_margin
|
| 64 |
+
if min_with_added < 0:
|
| 65 |
+
min_with_added = 0
|
| 66 |
+
|
| 67 |
+
denormalized_vaule = (
|
| 68 |
+
value * (max_with_added - min_with_added)) + min_with_added
|
| 69 |
+
|
| 70 |
+
return denormalized_vaule
|
model/model/sample_payload_adjustment.py
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def get_sample_payload(
|
| 5 |
+
sample_payload,
|
| 6 |
+
material_element,
|
| 7 |
+
employee_element,
|
| 8 |
+
capital_cost_element,
|
| 9 |
+
material_cost_input,
|
| 10 |
+
material_amount_input,
|
| 11 |
+
employee_input,
|
| 12 |
+
emp_dur_input,
|
| 13 |
+
employee_dayamount_input,
|
| 14 |
+
capital_cost_input,
|
| 15 |
+
day_amount_input,
|
| 16 |
+
capital_cost_dur_input,
|
| 17 |
+
predicted_mc,
|
| 18 |
+
predicted_ec,
|
| 19 |
+
predicted_cc,
|
| 20 |
+
bias,
|
| 21 |
+
result_input,
|
| 22 |
+
result,
|
| 23 |
+
error,
|
| 24 |
+
percent_loss,
|
| 25 |
+
epoch_number,
|
| 26 |
+
sample_number,
|
| 27 |
+
model_weights,
|
| 28 |
+
):
|
| 29 |
+
# Sample Payload for Debugging
|
| 30 |
+
# Reshape weight to 2D
|
| 31 |
+
# Material Weight
|
| 32 |
+
i = epoch_number
|
| 33 |
+
j = sample_number
|
| 34 |
+
model_bias = bias
|
| 35 |
+
|
| 36 |
+
material_element.check_type("material")
|
| 37 |
+
material_elem_weight = material_element.get_weights()
|
| 38 |
+
x, y, z = np.array(material_elem_weight).shape
|
| 39 |
+
material_elem_weight = np.array(material_elem_weight).reshape(x, y)
|
| 40 |
+
# Material Bias
|
| 41 |
+
material_elem_bias = material_element.get_biases()
|
| 42 |
+
x, y, z = np.array(material_elem_bias).shape
|
| 43 |
+
material_elem_bias = np.array(material_elem_bias).reshape(x, y)
|
| 44 |
+
employee_element.check_type("employee")
|
| 45 |
+
# Employee Weight
|
| 46 |
+
employee_elem_weight = employee_element.get_weights()
|
| 47 |
+
x, y, z = np.array(employee_elem_weight).shape
|
| 48 |
+
employee_elem_weight = np.array(employee_elem_weight).reshape(x, y)
|
| 49 |
+
# Employee Bias
|
| 50 |
+
employee_elem_bias = employee_element.get_biases()
|
| 51 |
+
x, y, z = np.array(employee_elem_bias).shape
|
| 52 |
+
employee_elem_bias = np.array(employee_elem_bias).reshape(x, y)
|
| 53 |
+
# Capital Cost Weight
|
| 54 |
+
capital_cost_element.check_type("capital")
|
| 55 |
+
capital_elem_weight = capital_cost_element.get_weights()
|
| 56 |
+
x, y, z = np.array(capital_elem_weight).shape
|
| 57 |
+
capital_elem_weight = np.array(capital_elem_weight).reshape(x, y)
|
| 58 |
+
# Capital Cost Bias
|
| 59 |
+
capital_elem_bias = capital_cost_element.get_biases()
|
| 60 |
+
x, y, z = np.array(capital_elem_bias).shape
|
| 61 |
+
capital_elem_bias = np.array(capital_elem_bias).reshape(x, y)
|
| 62 |
+
sample_payload.append(
|
| 63 |
+
{
|
| 64 |
+
"epoch": (i - 1),
|
| 65 |
+
"sample": j,
|
| 66 |
+
"material_cost": material_cost_input,
|
| 67 |
+
"material_amount": material_amount_input,
|
| 68 |
+
"material_weight": material_elem_weight,
|
| 69 |
+
"material_bias": material_elem_bias,
|
| 70 |
+
"employee_cost": employee_input,
|
| 71 |
+
"employee_duration": emp_dur_input,
|
| 72 |
+
"employee_dayamount": employee_dayamount_input,
|
| 73 |
+
"employee_weight": employee_elem_weight,
|
| 74 |
+
"employee_bias": employee_elem_bias,
|
| 75 |
+
"capital_cost": capital_cost_input,
|
| 76 |
+
"day_amount": day_amount_input,
|
| 77 |
+
"capital_cost_duration": capital_cost_dur_input,
|
| 78 |
+
"capital_cost_weight": capital_elem_weight,
|
| 79 |
+
"capital_cost_bias": capital_elem_bias,
|
| 80 |
+
"result": result_input,
|
| 81 |
+
"result_predict": result,
|
| 82 |
+
}
|
| 83 |
+
)
|
| 84 |
+
material_costs = material_cost_input.flatten()
|
| 85 |
+
for idx, cost in enumerate(material_costs):
|
| 86 |
+
sample_payload[-1][f"material_cost_{idx + 1}"] = cost
|
| 87 |
+
material_amounts = material_amount_input.flatten()
|
| 88 |
+
for idx, amount in enumerate(material_amounts):
|
| 89 |
+
sample_payload[-1][f"material_amount_{idx + 1}"] = amount
|
| 90 |
+
material_weights = material_elem_weight.flatten()
|
| 91 |
+
for idx, weight in enumerate(material_weights):
|
| 92 |
+
sample_payload[-1][f"material_weight_{idx + 1}"] = weight
|
| 93 |
+
material_biases = material_elem_bias.flatten()
|
| 94 |
+
for idx, bias in enumerate(material_biases):
|
| 95 |
+
sample_payload[-1][f"material_bias_{idx + 1}"] = bias
|
| 96 |
+
employee_costs = employee_input.flatten()
|
| 97 |
+
for idx, cost in enumerate(employee_costs):
|
| 98 |
+
sample_payload[-1][f"employee_cost_{idx + 1}"] = cost
|
| 99 |
+
employee_durations = emp_dur_input.flatten()
|
| 100 |
+
for idx, duration in enumerate(employee_durations):
|
| 101 |
+
sample_payload[-1][f"employee_duration_{idx + 1}"] = duration
|
| 102 |
+
employee_dayamounts = employee_dayamount_input.flatten()
|
| 103 |
+
for idx, amount in enumerate(employee_dayamounts):
|
| 104 |
+
sample_payload[-1][f"employee_dayamount_{idx + 1}"] = amount
|
| 105 |
+
employee_weights = employee_elem_weight.flatten()
|
| 106 |
+
for idx, weight in enumerate(employee_weights):
|
| 107 |
+
sample_payload[-1][f"employee_weight_{idx + 1}"] = weight
|
| 108 |
+
employee_biases = employee_elem_bias.flatten()
|
| 109 |
+
for idx, bias in enumerate(employee_biases):
|
| 110 |
+
sample_payload[-1][f"employee_bias_{idx + 1}"] = bias
|
| 111 |
+
capital_costs = capital_cost_input.flatten()
|
| 112 |
+
for idx, cost in enumerate(capital_costs):
|
| 113 |
+
sample_payload[-1][f"capital_cost_{idx + 1}"] = cost
|
| 114 |
+
day_amounts = day_amount_input.flatten()
|
| 115 |
+
for idx, amount in enumerate(day_amounts):
|
| 116 |
+
sample_payload[-1][f"day_amount_{idx + 1}"] = amount
|
| 117 |
+
capital_cost_durations = capital_cost_dur_input.flatten()
|
| 118 |
+
for idx, duration in enumerate(capital_cost_durations):
|
| 119 |
+
sample_payload[-1][f"capital_cost_duration_{idx + 1}"] = duration
|
| 120 |
+
capital_cost_weights = capital_elem_weight.flatten()
|
| 121 |
+
for idx, weight in enumerate(capital_cost_weights):
|
| 122 |
+
sample_payload[-1][f"capital_cost_weight_{idx + 1}"] = weight
|
| 123 |
+
capital_cost_bias = capital_elem_bias.flatten()
|
| 124 |
+
for idx, bias in enumerate(capital_cost_bias):
|
| 125 |
+
sample_payload[-1][f"capital_cost_bias_{idx + 1}"] = bias
|
| 126 |
+
predicted_mc_reshape = np.array(predicted_mc).flatten()
|
| 127 |
+
for idx, res in enumerate(predicted_mc_reshape):
|
| 128 |
+
sample_payload[-1]["total_material"] = res
|
| 129 |
+
predicted_ec_reshape = np.array(predicted_ec).flatten()
|
| 130 |
+
for idx, res in enumerate(predicted_ec_reshape):
|
| 131 |
+
sample_payload[-1]["total_daily_employee"] = res
|
| 132 |
+
predicted_cc_reshape = np.array(predicted_cc).flatten()
|
| 133 |
+
for idx, res in enumerate(predicted_cc_reshape):
|
| 134 |
+
sample_payload[-1]["total_capital_cost"] = res
|
| 135 |
+
|
| 136 |
+
model_bias_reshape = np.array(model_bias).flatten()
|
| 137 |
+
for idx, res in enumerate(model_bias_reshape):
|
| 138 |
+
sample_payload[-1]["model_bias"] = res
|
| 139 |
+
|
| 140 |
+
model_weights_reshape = np.array(model_weights).flatten()
|
| 141 |
+
for idx, res in enumerate(model_weights_reshape):
|
| 142 |
+
sample_payload[-1][f"model_weight_{idx + 1}"] = res
|
| 143 |
+
result_reshape = np.array(result_input).flatten()
|
| 144 |
+
for idx, res in enumerate(result_reshape):
|
| 145 |
+
sample_payload[-1]["result"] = res
|
| 146 |
+
result_predict_reshape = np.array(result).flatten()
|
| 147 |
+
for idx, res in enumerate(result_predict_reshape):
|
| 148 |
+
sample_payload[-1]["result_predict"] = res
|
| 149 |
+
sample_payload[-1]["error"] = error
|
| 150 |
+
sample_payload[-1]["error_percent"] = percent_loss
|
| 151 |
+
|
| 152 |
+
return sample_payload
|
model/model/tdce_model.py
ADDED
|
@@ -0,0 +1,541 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import random
|
| 3 |
+
import pandas as pd
|
| 4 |
+
import importlib
|
| 5 |
+
import time
|
| 6 |
+
|
| 7 |
+
import material_network as mn
|
| 8 |
+
import time_driven_network as tdn
|
| 9 |
+
import loss
|
| 10 |
+
import normalize as norm
|
| 11 |
+
import matrix_normalization as mnorm
|
| 12 |
+
import sample_payload_adjustment as spa
|
| 13 |
+
import weight_activation as wa
|
| 14 |
+
|
| 15 |
+
importlib.reload(mn)
|
| 16 |
+
importlib.reload(tdn)
|
| 17 |
+
importlib.reload(loss)
|
| 18 |
+
importlib.reload(norm)
|
| 19 |
+
importlib.reload(mnorm)
|
| 20 |
+
importlib.reload(spa)
|
| 21 |
+
importlib.reload(wa)
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
# Generated from Gemini
|
| 25 |
+
def generate_random_numbers():
|
| 26 |
+
# Generate a random number between 0 and 1 (exclusive)
|
| 27 |
+
random_val = random.random()
|
| 28 |
+
number1 = random_val
|
| 29 |
+
# The second number is another random value between 0 and (1 - number1)
|
| 30 |
+
number2 = random.random() * (1 - number1)
|
| 31 |
+
# The third number is simply 1 minus the sum of the first two
|
| 32 |
+
number3 = 1 - number1 - number2
|
| 33 |
+
|
| 34 |
+
return np.array([number1, number2, number3]).reshape(3, 1)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
# Model Reference
|
| 38 |
+
# Early Stopping https://medium.com/@juanc.olamendy/understanding-early-stopping-a-key-to-preventing-overfitting-in-machine-learning-17554fc321ff
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
class TDCEModel:
|
| 42 |
+
def __init__(self):
|
| 43 |
+
self.material_element = mn.MaterialNetwork()
|
| 44 |
+
self.employee_element = tdn.TimeDrivenNetwork()
|
| 45 |
+
self.capital_cost_element = tdn.TimeDrivenNetwork()
|
| 46 |
+
random_weight = np.array([1.0, 1.0, 1.0]).reshape(
|
| 47 |
+
3, 1
|
| 48 |
+
) # generate_random_numbers()
|
| 49 |
+
self.weights = random_weight
|
| 50 |
+
self.bias = np.full((1, 1), 0.0)
|
| 51 |
+
self.loss = loss.mse
|
| 52 |
+
self.loss_prime = loss.mse_prime
|
| 53 |
+
self.loss_percent = loss.rmspe
|
| 54 |
+
self.gradient = np.array([[0, 0, 0]])
|
| 55 |
+
self.prediction_error = np.array([[0, 0, 0]])
|
| 56 |
+
self.weight_list = np.array([[[0], [0], [0]]])
|
| 57 |
+
self.epoch_error = []
|
| 58 |
+
self.sample_errors = []
|
| 59 |
+
self.material_learning_rate = 0.001
|
| 60 |
+
self.employee_learning_rate = 0.001
|
| 61 |
+
self.capital_cost_learning_rate = 0.001
|
| 62 |
+
self.max_data = {}
|
| 63 |
+
self.min_data = {}
|
| 64 |
+
self.sample_payload = []
|
| 65 |
+
self.use_early_stopping = False
|
| 66 |
+
self.patience = 10
|
| 67 |
+
self.use_model_weight = False
|
| 68 |
+
|
| 69 |
+
def inital_inside_element(
|
| 70 |
+
self,
|
| 71 |
+
material_layer,
|
| 72 |
+
employee_layer,
|
| 73 |
+
capital_cost_layer,
|
| 74 |
+
):
|
| 75 |
+
self.material_element.add(material_layer)
|
| 76 |
+
self.material_element.use(loss.mse, loss.mse_prime)
|
| 77 |
+
self.employee_element.add(employee_layer)
|
| 78 |
+
self.employee_element.use(loss.mse, loss.mse_prime)
|
| 79 |
+
self.capital_cost_element.add(capital_cost_layer)
|
| 80 |
+
self.capital_cost_element.use(loss.mse, loss.mse_prime)
|
| 81 |
+
print("Initial Successfully")
|
| 82 |
+
|
| 83 |
+
# For Setting New Network Element
|
| 84 |
+
|
| 85 |
+
def set_material_element(self, material_network):
|
| 86 |
+
self.material_element = material_network
|
| 87 |
+
|
| 88 |
+
def set_employee_element(self, employee_element):
|
| 89 |
+
self.employee_element = employee_element
|
| 90 |
+
|
| 91 |
+
def set_capital_cost_element(self, capital_cost_element):
|
| 92 |
+
self.capital_cost_element = capital_cost_element
|
| 93 |
+
|
| 94 |
+
def use(self, loss, loss_prime, loss_percent):
|
| 95 |
+
self.loss = loss
|
| 96 |
+
self.loss_prime = loss_prime
|
| 97 |
+
self.loss_percent = loss_percent
|
| 98 |
+
|
| 99 |
+
def set_learning_rate(self, material_lr, employee_lr, cc_lr):
|
| 100 |
+
self.material_learning_rate = material_lr
|
| 101 |
+
self.employee_learning_rate = employee_lr
|
| 102 |
+
self.capital_cost_learning_rate = cc_lr
|
| 103 |
+
print("Learning Rate Set Successfully")
|
| 104 |
+
print(
|
| 105 |
+
f"Material LL {material_lr}, Employee LL {employee_lr}, Capital Cost LL {cc_lr}"
|
| 106 |
+
)
|
| 107 |
+
|
| 108 |
+
def activate_early_stopping(self):
|
| 109 |
+
self.use_early_stopping = True
|
| 110 |
+
print("Activate Early Stopping Successfully")
|
| 111 |
+
|
| 112 |
+
def deactivate_early_stopping(self):
|
| 113 |
+
self.use_early_stopping = False
|
| 114 |
+
print("Deactivate Early Stopping Successfully")
|
| 115 |
+
|
| 116 |
+
def activete_model_weight(self):
|
| 117 |
+
self.use_model_weight = True
|
| 118 |
+
print("Activate Model Weight Successfully")
|
| 119 |
+
|
| 120 |
+
def deactivate_model_weight(self):
|
| 121 |
+
self.use_model_weight = False
|
| 122 |
+
print("Deactivate Model Weight Successfully")
|
| 123 |
+
|
| 124 |
+
# For Early Stopping
|
| 125 |
+
def edit_patience_round(self, patience_round):
|
| 126 |
+
self.patience = patience_round
|
| 127 |
+
|
| 128 |
+
def fit_with_validation(
|
| 129 |
+
self,
|
| 130 |
+
material_cost_matrix,
|
| 131 |
+
material_amount_matrix,
|
| 132 |
+
employee_cost_matrix,
|
| 133 |
+
employee_duration_matrix,
|
| 134 |
+
employee_day_amount_matrix,
|
| 135 |
+
capital_cost_matrix,
|
| 136 |
+
day_amount_matrix,
|
| 137 |
+
capital_cost_duration_matrix,
|
| 138 |
+
result_matrix,
|
| 139 |
+
epoch,
|
| 140 |
+
learning_rate,
|
| 141 |
+
validation_payload,
|
| 142 |
+
display_round_log=False,
|
| 143 |
+
):
|
| 144 |
+
results = []
|
| 145 |
+
epoch_errors = []
|
| 146 |
+
sample_errors = []
|
| 147 |
+
sample_payload = []
|
| 148 |
+
|
| 149 |
+
# For Early Stopping
|
| 150 |
+
patience_counter = 0
|
| 151 |
+
best_validation_error = np.inf
|
| 152 |
+
|
| 153 |
+
# print('Material Cost Matrix')
|
| 154 |
+
# print(material_cost_matrix)
|
| 155 |
+
# print('-----------------------------------')
|
| 156 |
+
# print('Material Amount Matrix')
|
| 157 |
+
# print(material_amount_matrix)
|
| 158 |
+
# print('------------------------------')
|
| 159 |
+
# print('Daily Employee Matrix')
|
| 160 |
+
# print(daily_employee_cost_matrix)
|
| 161 |
+
# print('------------------------------')
|
| 162 |
+
# print('Monthly Employee Matrix')
|
| 163 |
+
# print(monthly_employee_cost_matrix)
|
| 164 |
+
# print('------------------------------')
|
| 165 |
+
print(f"W: Initial Weight {self.weights}")
|
| 166 |
+
|
| 167 |
+
# Duration Represent the amount of process
|
| 168 |
+
samples = len(result_matrix)
|
| 169 |
+
validate_result_matrix = validation_payload["validate_result_matrix"]
|
| 170 |
+
|
| 171 |
+
# Some of validate payload use normalized_validate because size is not
|
| 172 |
+
# same as train payload if they are in 3D it will use only normalized function
|
| 173 |
+
|
| 174 |
+
(
|
| 175 |
+
normalized_material_cost,
|
| 176 |
+
normalized_material_amount,
|
| 177 |
+
normalized_validate_material_cost,
|
| 178 |
+
normalized_validate_material_amount,
|
| 179 |
+
normalized_employee_cost,
|
| 180 |
+
normalized_employee_duration,
|
| 181 |
+
normalized_employee_day_amount,
|
| 182 |
+
normalized_validate_employee_cost,
|
| 183 |
+
normalized_validate_employee_duration,
|
| 184 |
+
normalized_validate_employee_day_amount,
|
| 185 |
+
normalized_capital_cost,
|
| 186 |
+
normalized_capital_cost_duration,
|
| 187 |
+
normalized_day_amount,
|
| 188 |
+
normalized_validate_capital_cost,
|
| 189 |
+
normalized_validate_capital_duration,
|
| 190 |
+
normalized_validate_day_amount,
|
| 191 |
+
max_data,
|
| 192 |
+
min_data,
|
| 193 |
+
) = mnorm.normalize_payload(
|
| 194 |
+
material_cost_matrix=material_cost_matrix,
|
| 195 |
+
material_amount_matrix=material_amount_matrix,
|
| 196 |
+
employee_cost_matrix=employee_cost_matrix,
|
| 197 |
+
employee_duration_matrix=employee_duration_matrix,
|
| 198 |
+
employee_day_amount_matrix=employee_day_amount_matrix,
|
| 199 |
+
capital_cost_matrix=capital_cost_matrix,
|
| 200 |
+
day_amount_matrix=day_amount_matrix,
|
| 201 |
+
capital_cost_duration_matrix=capital_cost_duration_matrix,
|
| 202 |
+
validation_payload=validation_payload,
|
| 203 |
+
display_log=False,
|
| 204 |
+
)
|
| 205 |
+
|
| 206 |
+
self.min_data = min_data
|
| 207 |
+
self.max_data = max_data
|
| 208 |
+
|
| 209 |
+
for i in range(epoch):
|
| 210 |
+
error = 0
|
| 211 |
+
sum_error = 0
|
| 212 |
+
sum_error_percent = 0
|
| 213 |
+
sum_validation_error = 0
|
| 214 |
+
sum_validation_error_percent = 0
|
| 215 |
+
start_time = time.time()
|
| 216 |
+
validate_sample_amount = 0
|
| 217 |
+
|
| 218 |
+
for j in range(samples):
|
| 219 |
+
# Result
|
| 220 |
+
result_input = result_matrix[j]
|
| 221 |
+
# Material
|
| 222 |
+
# material_cost_input = material_cost_matrix[j]
|
| 223 |
+
material_cost_input = normalized_material_cost[j]
|
| 224 |
+
|
| 225 |
+
# material_amount_input = material_amount_matrix[j]
|
| 226 |
+
material_amount_input = normalized_material_amount[j]
|
| 227 |
+
|
| 228 |
+
# Employee / Labor
|
| 229 |
+
employee_cost_input = normalized_employee_cost[j]
|
| 230 |
+
employee_duration_input = normalized_employee_duration[j]
|
| 231 |
+
employee_day_amount_input = normalized_employee_day_amount[j]
|
| 232 |
+
# Capital Cost
|
| 233 |
+
capital_cost_input = normalized_capital_cost[j]
|
| 234 |
+
day_amount_input = normalized_day_amount[j]
|
| 235 |
+
capital_cost_dur_input = normalized_capital_cost_duration[j]
|
| 236 |
+
|
| 237 |
+
if j < len(normalized_validate_material_cost):
|
| 238 |
+
# VALIDATION INPUT
|
| 239 |
+
validate_material_cost_input = normalized_validate_material_cost[j]
|
| 240 |
+
validate_material_amount_input = (
|
| 241 |
+
normalized_validate_material_amount[j]
|
| 242 |
+
)
|
| 243 |
+
validate_employee_input = (
|
| 244 |
+
normalized_validate_employee_cost[j]
|
| 245 |
+
)
|
| 246 |
+
validate_emp_dur_input = (
|
| 247 |
+
normalized_validate_employee_duration[j]
|
| 248 |
+
)
|
| 249 |
+
validate_emp_dayamount_input = (
|
| 250 |
+
normalized_validate_employee_day_amount[j]
|
| 251 |
+
)
|
| 252 |
+
validate_capital_cost_input = normalized_validate_capital_cost[j]
|
| 253 |
+
validate_dayamount_input = normalized_validate_day_amount[j]
|
| 254 |
+
validate_capital_cost_dur_input = (
|
| 255 |
+
normalized_validate_capital_duration[j]
|
| 256 |
+
)
|
| 257 |
+
validate_result_input = validate_result_matrix[j]
|
| 258 |
+
|
| 259 |
+
# Train Material ELE
|
| 260 |
+
predicted_mc = self.material_element.predict_sample(
|
| 261 |
+
cost_input=material_cost_input, amount_input=material_amount_input
|
| 262 |
+
)
|
| 263 |
+
|
| 264 |
+
# Employee Cost ELE
|
| 265 |
+
predicted_ec = self.employee_element.predict_sample(
|
| 266 |
+
cost_input=employee_cost_input,
|
| 267 |
+
time_input=employee_duration_input,
|
| 268 |
+
day_amount=employee_day_amount_input
|
| 269 |
+
)
|
| 270 |
+
|
| 271 |
+
# Capital Cost ELE
|
| 272 |
+
predicted_cc = self.capital_cost_element.predict_sample(
|
| 273 |
+
cost_input=capital_cost_input,
|
| 274 |
+
time_input=capital_cost_dur_input,
|
| 275 |
+
day_amount=day_amount_input,
|
| 276 |
+
)
|
| 277 |
+
|
| 278 |
+
# For Validation
|
| 279 |
+
# Predict will not update class vairable while predict_sample
|
| 280 |
+
# which will be update their variable for train
|
| 281 |
+
|
| 282 |
+
if j < len(normalized_validate_material_cost):
|
| 283 |
+
# Test Material ELE
|
| 284 |
+
validate_predicted_mc = self.material_element.predict(
|
| 285 |
+
cost_input=validate_material_cost_input,
|
| 286 |
+
amount_input=validate_material_amount_input,
|
| 287 |
+
)
|
| 288 |
+
|
| 289 |
+
# Test Monthly Employee Cost ELE
|
| 290 |
+
validate_predicted_ec = self.employee_element.predict(
|
| 291 |
+
cost_input=validate_employee_input,
|
| 292 |
+
time_input=validate_emp_dur_input,
|
| 293 |
+
day_amount=validate_emp_dayamount_input
|
| 294 |
+
)
|
| 295 |
+
|
| 296 |
+
# Test Capital Cost ELE
|
| 297 |
+
validate_predicted_cc = self.capital_cost_element.predict(
|
| 298 |
+
cost_input=validate_capital_cost_input,
|
| 299 |
+
time_input=validate_capital_cost_dur_input,
|
| 300 |
+
day_amount=validate_dayamount_input,
|
| 301 |
+
)
|
| 302 |
+
|
| 303 |
+
validate_result = (
|
| 304 |
+
validate_predicted_mc * self.weights[0]
|
| 305 |
+
+ validate_predicted_ec * self.weights[1]
|
| 306 |
+
+ validate_predicted_cc * self.weights[2]
|
| 307 |
+
) + self.bias
|
| 308 |
+
|
| 309 |
+
# Result Combination and Find Error
|
| 310 |
+
result = (
|
| 311 |
+
predicted_mc * self.weights[0]
|
| 312 |
+
+ predicted_ec * self.weights[1]
|
| 313 |
+
+ predicted_cc * self.weights[2]
|
| 314 |
+
) + self.bias
|
| 315 |
+
|
| 316 |
+
# if result < 0:
|
| 317 |
+
# result = [[0]]
|
| 318 |
+
|
| 319 |
+
# print(
|
| 320 |
+
# f"predicted_mc {predicted_mc} predicted_dmc {predicted_dmc} predicted_mec{predicted_mec} predicted_cc{predicted_cc}")
|
| 321 |
+
|
| 322 |
+
# Find MSE both Result and validation
|
| 323 |
+
error = self.loss(result_input, result)
|
| 324 |
+
|
| 325 |
+
# Find RMSPE both Result and Validate
|
| 326 |
+
percent_loss = self.loss_percent(result_input, result)
|
| 327 |
+
|
| 328 |
+
# Find Derivative of Loss
|
| 329 |
+
loss_prime = self.loss_prime(result_input, result)
|
| 330 |
+
bias_error = loss_prime
|
| 331 |
+
|
| 332 |
+
if display_round_log:
|
| 333 |
+
print(
|
| 334 |
+
f"Epoch {i} Sample {j} : Model level weight {self.weights}")
|
| 335 |
+
print(f"Epoch {i} Sample {j} : Bias {self.bias}")
|
| 336 |
+
print(
|
| 337 |
+
f"Epoch {i} Sample {j} : Result {result}, Validate Result {validate_result}"
|
| 338 |
+
)
|
| 339 |
+
print(
|
| 340 |
+
f"Epoch {i} Sample {j} : Material Result {predicted_mc} Employee {predicted_ec} Capital Cost {predicted_cc}"
|
| 341 |
+
)
|
| 342 |
+
print(
|
| 343 |
+
f"Epoch {i} Sample {j} : Actual Result {result_input}")
|
| 344 |
+
print(
|
| 345 |
+
f"Epoch {i} Sample {j} : Error (MSE) {error}, Error To Adjust(Loss Prime) {loss_prime} "
|
| 346 |
+
)
|
| 347 |
+
print(
|
| 348 |
+
f"Epoch {i} Sample {j} : Error Percent {percent_loss} ")
|
| 349 |
+
print("-----------------")
|
| 350 |
+
|
| 351 |
+
# Find Gradient of each weight
|
| 352 |
+
# mse_prime dot Leaky_relu(input)
|
| 353 |
+
# For Adjust Grdient in Model Level
|
| 354 |
+
material_weight_error = np.dot(predicted_mc, loss_prime)
|
| 355 |
+
ec_weight_error = np.dot(predicted_ec, loss_prime)
|
| 356 |
+
cc_weight_error = np.dot(predicted_cc, loss_prime)
|
| 357 |
+
|
| 358 |
+
# Append For log keeping
|
| 359 |
+
sample_errors.append(
|
| 360 |
+
{
|
| 361 |
+
"epoch": (i - 1),
|
| 362 |
+
"sample": j,
|
| 363 |
+
"error": error,
|
| 364 |
+
"error_percent": percent_loss,
|
| 365 |
+
}
|
| 366 |
+
)
|
| 367 |
+
|
| 368 |
+
# Sample Payload for Debugging
|
| 369 |
+
sample_payload = spa.get_sample_payload(
|
| 370 |
+
sample_payload=sample_payload,
|
| 371 |
+
material_element=self.material_element,
|
| 372 |
+
employee_element=self.employee_element,
|
| 373 |
+
capital_cost_element=self.capital_cost_element,
|
| 374 |
+
material_cost_input=material_cost_input,
|
| 375 |
+
material_amount_input=material_amount_input,
|
| 376 |
+
employee_input=employee_cost_input,
|
| 377 |
+
emp_dur_input=employee_duration_input,
|
| 378 |
+
employee_dayamount_input=employee_day_amount_input,
|
| 379 |
+
capital_cost_input=capital_cost_input,
|
| 380 |
+
day_amount_input=day_amount_input,
|
| 381 |
+
capital_cost_dur_input=capital_cost_dur_input,
|
| 382 |
+
predicted_mc=predicted_mc,
|
| 383 |
+
predicted_ec=predicted_ec,
|
| 384 |
+
predicted_cc=predicted_cc,
|
| 385 |
+
bias=self.bias,
|
| 386 |
+
result_input=result_input,
|
| 387 |
+
result=result,
|
| 388 |
+
error=error,
|
| 389 |
+
percent_loss=percent_loss,
|
| 390 |
+
epoch_number=i,
|
| 391 |
+
sample_number=j,
|
| 392 |
+
model_weights=self.weights,
|
| 393 |
+
)
|
| 394 |
+
|
| 395 |
+
# print(f'Result {result} & Loss {loss_prime}')
|
| 396 |
+
# print(
|
| 397 |
+
# f'Material Gradient {material_weight_error}, DE Gradient {de_weight_error}, ME Gradient {me_weight_error}, CC Gradient {cc_weight_error}')
|
| 398 |
+
|
| 399 |
+
# Back Propagation of Inside Element
|
| 400 |
+
# mse_prime dot w
|
| 401 |
+
sum_material_error = np.dot(loss_prime, self.weights[0])
|
| 402 |
+
self.material_element.back_propagate(
|
| 403 |
+
sum_material_error, self.material_learning_rate
|
| 404 |
+
)
|
| 405 |
+
|
| 406 |
+
sum_ec_error = np.dot(loss_prime, self.weights[1])
|
| 407 |
+
self.employee_element.back_propagate(
|
| 408 |
+
sum_ec_error, self.employee_learning_rate
|
| 409 |
+
)
|
| 410 |
+
|
| 411 |
+
sum_capital_error = np.dot(loss_prime, self.weights[2])
|
| 412 |
+
self.capital_cost_element.back_propagate(
|
| 413 |
+
sum_capital_error, self.capital_cost_learning_rate
|
| 414 |
+
)
|
| 415 |
+
|
| 416 |
+
if self.use_model_weight is True:
|
| 417 |
+
# Update Weight
|
| 418 |
+
overall_gradient = np.array(
|
| 419 |
+
[
|
| 420 |
+
material_weight_error[0],
|
| 421 |
+
ec_weight_error[0],
|
| 422 |
+
cc_weight_error[0],
|
| 423 |
+
]
|
| 424 |
+
)
|
| 425 |
+
self.weights -= learning_rate * overall_gradient
|
| 426 |
+
self.bias -= learning_rate * bias_error
|
| 427 |
+
|
| 428 |
+
result_input_value = result_input.reshape(1)
|
| 429 |
+
result_input_value = result_input_value[0]
|
| 430 |
+
|
| 431 |
+
if j < len(normalized_validate_material_cost):
|
| 432 |
+
validation_error = self.loss(
|
| 433 |
+
validate_result_input, validate_result)
|
| 434 |
+
validation_error_percent = self.loss_percent(
|
| 435 |
+
validate_result_input, validate_result
|
| 436 |
+
)
|
| 437 |
+
sum_validation_error += validation_error
|
| 438 |
+
sum_validation_error_percent += validation_error_percent
|
| 439 |
+
validate_sample_amount += 1
|
| 440 |
+
|
| 441 |
+
sum_error += error
|
| 442 |
+
sum_error_percent += percent_loss
|
| 443 |
+
|
| 444 |
+
end_time = time.time()
|
| 445 |
+
validation_error = sum_validation_error / validate_sample_amount
|
| 446 |
+
print(
|
| 447 |
+
f"{i + 1} /{epoch} Epoch Error = {sum_error / samples} ({sum_error_percent / samples} %), Validate Error = {validation_error} ({sum_validation_error_percent / validate_sample_amount}) estimate time {end_time - start_time}"
|
| 448 |
+
)
|
| 449 |
+
|
| 450 |
+
epoch_errors.append(
|
| 451 |
+
{
|
| 452 |
+
"epoch": (i + 1),
|
| 453 |
+
"error": sum_error / samples,
|
| 454 |
+
"error_percent": sum_error_percent / samples,
|
| 455 |
+
"validate_error": sum_validation_error / validate_sample_amount,
|
| 456 |
+
"validate_error_percent": sum_validation_error_percent / validate_sample_amount,
|
| 457 |
+
}
|
| 458 |
+
)
|
| 459 |
+
|
| 460 |
+
if self.use_early_stopping:
|
| 461 |
+
if validation_error < best_validation_error:
|
| 462 |
+
best_validation_error = validation_error
|
| 463 |
+
patience_counter = 0
|
| 464 |
+
else:
|
| 465 |
+
patience_counter += 1
|
| 466 |
+
if patience_counter == self.patience:
|
| 467 |
+
print(f"Early Stopping at Epoch {i + 1}")
|
| 468 |
+
break
|
| 469 |
+
|
| 470 |
+
sum_error = 0
|
| 471 |
+
sum_error_percent = 0
|
| 472 |
+
sum_validation_error = 0
|
| 473 |
+
sum_validation_error_percent = 0
|
| 474 |
+
|
| 475 |
+
self.epoch_error = epoch_errors
|
| 476 |
+
self.sample_errors = sample_errors
|
| 477 |
+
self.sample_payload = sample_payload
|
| 478 |
+
epoch_error_df = pd.DataFrame(epoch_errors)
|
| 479 |
+
last_sample_payload = sample_payload[-1]
|
| 480 |
+
|
| 481 |
+
print("-------------------")
|
| 482 |
+
print(
|
| 483 |
+
f"Minimum Error = {epoch_error_df['error'].min()} Minimum Error percent {round(epoch_error_df['error_percent'].min(), 4)} Accuracy {100 - epoch_error_df['error_percent'].min()}%"
|
| 484 |
+
)
|
| 485 |
+
print(
|
| 486 |
+
f"Average Error = {epoch_error_df['error'].mean()} Average Error percent {round(epoch_error_df['error_percent'].mean(), 4)} Accuracy {100 - epoch_error_df['error_percent'].mean()}%"
|
| 487 |
+
)
|
| 488 |
+
print(
|
| 489 |
+
f"Maximum Error = {epoch_error_df['error'].max()} Maximum Error percent {round(epoch_error_df['error_percent'].max(), 2)} Accuracy {100 - epoch_error_df['error_percent'].max()}%"
|
| 490 |
+
)
|
| 491 |
+
print(
|
| 492 |
+
f"Minimum Validation Error = {epoch_error_df['validate_error'].min()} Minimum Error percent {round(epoch_error_df['validate_error_percent'].min(), 4)} Accuracy {100 - epoch_error_df['validate_error_percent'].min()}%"
|
| 493 |
+
)
|
| 494 |
+
print(
|
| 495 |
+
f"Average Validation Error = {epoch_error_df['validate_error'].mean()} Average Error percent {round(epoch_error_df['validate_error_percent'].mean(), 4)} Accuracy {100 - epoch_error_df['validate_error_percent'].mean()}%"
|
| 496 |
+
)
|
| 497 |
+
print(
|
| 498 |
+
f"Maximum Validation Error = {epoch_error_df['validate_error'].max()} Maximum Error percent {round(epoch_error_df['validate_error_percent'].max(), 4)} Accuracy {100 - epoch_error_df['validate_error_percent'].max()}%"
|
| 499 |
+
)
|
| 500 |
+
print(
|
| 501 |
+
f"Last Validation Error = {epoch_error_df.iloc[-1]['validate_error']} Last Validate Error percent {round(epoch_error_df.iloc[-1]['validate_error_percent'], 4)} Accuracy {100 - epoch_error_df.iloc[-1]['validate_error_percent']}%"
|
| 502 |
+
)
|
| 503 |
+
print(
|
| 504 |
+
f"Final Model - Material Weight {last_sample_payload['material_weight']} Material Bias {last_sample_payload['material_bias']}"
|
| 505 |
+
)
|
| 506 |
+
print(
|
| 507 |
+
f" - Employee Weight {last_sample_payload['employee_weight']} Monthly Employee Bias {last_sample_payload['employee_bias']}"
|
| 508 |
+
)
|
| 509 |
+
print(
|
| 510 |
+
f" - Capital Cost Weight {last_sample_payload['capital_cost_weight']} Capital Cost Bias {last_sample_payload['capital_cost_bias']}"
|
| 511 |
+
)
|
| 512 |
+
print(f" - Model Bias {last_sample_payload['model_bias']}")
|
| 513 |
+
print("-------------------")
|
| 514 |
+
|
| 515 |
+
return results
|
| 516 |
+
|
| 517 |
+
def get_gradient(self):
|
| 518 |
+
return self.gradient
|
| 519 |
+
|
| 520 |
+
def get_prediction_error(self):
|
| 521 |
+
return self.prediction_error
|
| 522 |
+
|
| 523 |
+
def get_weight_list(self):
|
| 524 |
+
return self.weight_list
|
| 525 |
+
|
| 526 |
+
def get_epoch_error(self):
|
| 527 |
+
return self.epoch_error
|
| 528 |
+
|
| 529 |
+
def get_sample_error(self):
|
| 530 |
+
return self.sample_errors
|
| 531 |
+
|
| 532 |
+
def get_model_element_weights(self):
|
| 533 |
+
return (
|
| 534 |
+
self.material_element.get_weight_list(),
|
| 535 |
+
self.daily_employee_element.get_weight_list(),
|
| 536 |
+
self.monthly_employee_element.get_weight_list(),
|
| 537 |
+
self.capital_cost_element.get_weight_list(),
|
| 538 |
+
)
|
| 539 |
+
|
| 540 |
+
def get_sample_payload(self):
|
| 541 |
+
return self.sample_payload
|
model/model/time_driven_network.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import network as nw
|
| 2 |
+
import importlib
|
| 3 |
+
import numpy as np
|
| 4 |
+
|
| 5 |
+
importlib.reload(nw)
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class TimeDrivenNetwork(nw.Network):
|
| 9 |
+
def __init__(self):
|
| 10 |
+
super().__init__()
|
| 11 |
+
|
| 12 |
+
def fit(self, cost_train, y_train, epochs, learning_rate, time_usage, day_amount):
|
| 13 |
+
result = []
|
| 14 |
+
samples = len(cost_train)
|
| 15 |
+
|
| 16 |
+
# Train epoch times
|
| 17 |
+
for i in range(epochs):
|
| 18 |
+
err = 0
|
| 19 |
+
|
| 20 |
+
# train for all samples
|
| 21 |
+
for j in range(samples):
|
| 22 |
+
cost_input = cost_train[j]
|
| 23 |
+
time_input = time_usage[j]
|
| 24 |
+
da_input = day_amount[j]
|
| 25 |
+
output = None
|
| 26 |
+
|
| 27 |
+
# predict data at all layer
|
| 28 |
+
for layer in self.layers:
|
| 29 |
+
output = layer.forward_propagation(
|
| 30 |
+
cost_input, time_input, da_input)
|
| 31 |
+
# output as input of next layer
|
| 32 |
+
cost_input = output
|
| 33 |
+
|
| 34 |
+
# Find loss for display
|
| 35 |
+
err += self.loss(y_train[j], output)
|
| 36 |
+
|
| 37 |
+
# Find Error of output dE/dY using derivation of MSE
|
| 38 |
+
error = self.loss_prime(y_train[j], output)
|
| 39 |
+
weight = []
|
| 40 |
+
|
| 41 |
+
# Update Weight for next data
|
| 42 |
+
# By find gradient of weight in each layer and update
|
| 43 |
+
for layer in reversed(self.layers):
|
| 44 |
+
error = layer.backward_propagation(error, learning_rate)
|
| 45 |
+
weight.append(layer.get_weight())
|
| 46 |
+
|
| 47 |
+
# Find Average Error per sample
|
| 48 |
+
err /= samples
|
| 49 |
+
print("Epoch %d/%d calculate with error = %f" %
|
| 50 |
+
(i + 1, epochs, err))
|
| 51 |
+
result.append({"epoch": i + 1, "error": err})
|
| 52 |
+
self.weight_list = np.append(self.weight_list, [weight])
|
| 53 |
+
|
| 54 |
+
return result
|
| 55 |
+
|
| 56 |
+
def fit_on_sample(self, cost_input, y_train, learning_rate, time_input, day_amount):
|
| 57 |
+
err = 0
|
| 58 |
+
output = None
|
| 59 |
+
|
| 60 |
+
# predict data at all layer
|
| 61 |
+
for layer in self.layers:
|
| 62 |
+
output = layer.forward_propagation(
|
| 63 |
+
cost_input, time_input, day_amount)
|
| 64 |
+
# output as input of next layer
|
| 65 |
+
cost_input = output
|
| 66 |
+
|
| 67 |
+
# Find loss for display
|
| 68 |
+
err += self.loss(y_train, output)
|
| 69 |
+
|
| 70 |
+
# Find Error of output dE/dY using derivation of MSE
|
| 71 |
+
error = self.loss_prime(y_train, output)
|
| 72 |
+
|
| 73 |
+
# Update Weight for next data
|
| 74 |
+
# By find gradient of weight in each layer and update
|
| 75 |
+
for layer in reversed(self.layers):
|
| 76 |
+
error = layer.backward_propagation(error, learning_rate)
|
| 77 |
+
# print(f'Epoch calculate with error = {err}')
|
| 78 |
+
return (output, err)
|
| 79 |
+
|
| 80 |
+
def get_weights(self):
|
| 81 |
+
result = []
|
| 82 |
+
for layer in self.layers:
|
| 83 |
+
result.append(layer.get_weight())
|
| 84 |
+
return result
|
| 85 |
+
|
| 86 |
+
def predict_sample(self, cost_input, time_input, day_amount):
|
| 87 |
+
output = None
|
| 88 |
+
for layer in self.layers:
|
| 89 |
+
output = layer.forward_propagation(
|
| 90 |
+
cost_input, time_input, day_amount)
|
| 91 |
+
# output as input of next layer
|
| 92 |
+
cost_input = output
|
| 93 |
+
weight = layer.get_weight()
|
| 94 |
+
self.weight_list = np.append(self.weight_list, [weight])
|
| 95 |
+
return output
|
| 96 |
+
|
| 97 |
+
def predict(self, cost_input, time_input, day_amount):
|
| 98 |
+
output = None
|
| 99 |
+
for layer in self.layers:
|
| 100 |
+
output = layer.predict(cost_input, time_input, day_amount)
|
| 101 |
+
# output as input of next layer
|
| 102 |
+
cost_input = output
|
| 103 |
+
return output
|
| 104 |
+
|
| 105 |
+
def check_type(self, input_name):
|
| 106 |
+
if input_name == "capital" or input_name == "employee":
|
| 107 |
+
return True
|
| 108 |
+
print(f"You go to wrong class this is Time Driven not {input_name}")
|
| 109 |
+
return False
|
model/model/weight_activation.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
alpha = 0
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def un_zero_weight(x):
|
| 7 |
+
shape = x.shape
|
| 8 |
+
x = x.flatten()
|
| 9 |
+
result = np.where(x < 0, 0, x)
|
| 10 |
+
return result.reshape(shape)
|
model/plot_input_variation.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
from scipy.stats import variation, iqr
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def get_data(folder_name):
|
| 6 |
+
process_df = pd.read_csv(f"{folder_name}/generated_process_data.csv")
|
| 7 |
+
material_usage_df = pd.read_csv(
|
| 8 |
+
f"{folder_name}/generated_material_usage.csv")
|
| 9 |
+
employee_usage_df = pd.read_csv(
|
| 10 |
+
f"{folder_name}/generated_employee_usage.csv")
|
| 11 |
+
capital_cost_df = pd.read_csv(f"{folder_name}/generated_captial_cost.csv")
|
| 12 |
+
return process_df, material_usage_df, employee_usage_df, capital_cost_df
|
model/result_display.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import pandas as pd
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def create_directory(primary_directory_name):
|
| 6 |
+
result_dir = f"{primary_directory_name}/results"
|
| 7 |
+
try:
|
| 8 |
+
os.mkdir(result_dir)
|
| 9 |
+
except FileExistsError:
|
| 10 |
+
print("Folder is Exist")
|
| 11 |
+
|
| 12 |
+
return result_dir
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def creating_error_csv(
|
| 16 |
+
primary_directory_name,
|
| 17 |
+
learning_rate,
|
| 18 |
+
iteration_number,
|
| 19 |
+
round_number,
|
| 20 |
+
breakpoint_number,
|
| 21 |
+
):
|
| 22 |
+
result_dir = create_directory(primary_directory_name)
|
| 23 |
+
overall_learning_rate_err_ = []
|
| 24 |
+
for lr in learning_rate:
|
| 25 |
+
round_err_list = []
|
| 26 |
+
round_percent_list = []
|
| 27 |
+
round_validate_err_list = []
|
| 28 |
+
round_validate_err_percent_list = []
|
| 29 |
+
round_brakpoint_err_list = []
|
| 30 |
+
round_brakpoint_err_percent_list = []
|
| 31 |
+
round_brakpoint_val_err_list = []
|
| 32 |
+
round_brakpoint_val_err_percent_list = []
|
| 33 |
+
round_errors = []
|
| 34 |
+
learning_rate_err_dict = {"learning_rate": str(lr)}
|
| 35 |
+
for round_no in range(round_number):
|
| 36 |
+
round_err_dict = {"learning_rate": str(lr)}
|
| 37 |
+
directory_name = primary_directory_name + "/round" + str(round_no + 1)
|
| 38 |
+
df = pd.read_csv(f"{directory_name}/{iteration_number}-{lr}.csv")
|
| 39 |
+
round_err_list.append(df["error"].values[-1])
|
| 40 |
+
round_percent_list.append(df["error_percent"].values[-1])
|
| 41 |
+
round_validate_err_list.append(df["validate_error"].values[-1])
|
| 42 |
+
round_validate_err_percent_list.append(
|
| 43 |
+
df["validate_error_percent"].values[-1]
|
| 44 |
+
)
|
| 45 |
+
breakpoint_df = df[df["epoch"] <= breakpoint_number]
|
| 46 |
+
round_brakpoint_err_list.append(breakpoint_df["error"].values[-1])
|
| 47 |
+
round_brakpoint_err_percent_list.append(
|
| 48 |
+
breakpoint_df["error_percent"].values[-1]
|
| 49 |
+
)
|
| 50 |
+
round_brakpoint_val_err_list.append(
|
| 51 |
+
breakpoint_df["validate_error"].values[-1]
|
| 52 |
+
)
|
| 53 |
+
round_brakpoint_val_err_percent_list.append(
|
| 54 |
+
breakpoint_df["validate_error_percent"].values[-1]
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
# Added to the dictionary
|
| 58 |
+
round_err_dict[f"round"] = round_no
|
| 59 |
+
round_err_dict[f"error"] = df["error"].values[-1]
|
| 60 |
+
round_err_dict[f"error_percent"] = df["error_percent"].values[-1]
|
| 61 |
+
round_err_dict[f"validate_error"] = df["validate_error"].values[-1]
|
| 62 |
+
round_err_dict[f"validate_error_percent"] = df[
|
| 63 |
+
"validate_error_percent"
|
| 64 |
+
].values[-1]
|
| 65 |
+
round_err_dict[f"brakpoint_error"] = breakpoint_df["error"].values[-1]
|
| 66 |
+
round_err_dict[f"brakpoint_error_percent"] = breakpoint_df[
|
| 67 |
+
"error_percent"
|
| 68 |
+
].values[-1]
|
| 69 |
+
round_err_dict[f"brakpoint_validate_error"] = breakpoint_df[
|
| 70 |
+
"validate_error"
|
| 71 |
+
].values[-1]
|
| 72 |
+
round_err_dict[f"brakpoint_validate_error_percent"] = breakpoint_df[
|
| 73 |
+
"validate_error_percent"
|
| 74 |
+
].values[-1]
|
| 75 |
+
round_errors.append(round_err_dict)
|
| 76 |
+
|
| 77 |
+
round_err_df = pd.DataFrame(round_errors)
|
| 78 |
+
round_err_df.to_csv(f"{result_dir}/{lr}_round_error.csv", index=False)
|
| 79 |
+
|
| 80 |
+
average_error = round_err_df["error"].mean()
|
| 81 |
+
average_error_percent = round_err_df["error_percent"].mean()
|
| 82 |
+
average_validate_error = round_err_df["validate_error"].mean()
|
| 83 |
+
average_validate_error_percent = round_err_df["validate_error_percent"].mean()
|
| 84 |
+
average_brakpoint_error = round_err_df["brakpoint_error"].mean()
|
| 85 |
+
average_brakpoint_error_percent = round_err_df["brakpoint_error_percent"].mean()
|
| 86 |
+
average_brakpoint_validate_error = round_err_df[
|
| 87 |
+
"brakpoint_validate_error"
|
| 88 |
+
].mean()
|
| 89 |
+
average_brakpoint_validate_error_percent = round_err_df[
|
| 90 |
+
"brakpoint_validate_error_percent"
|
| 91 |
+
].mean()
|
| 92 |
+
learning_rate_err_dict["average_error"] = average_error
|
| 93 |
+
learning_rate_err_dict["average_error_percent"] = average_error_percent
|
| 94 |
+
learning_rate_err_dict["average_validate_error"] = average_validate_error
|
| 95 |
+
learning_rate_err_dict["average_validate_error_percent"] = (
|
| 96 |
+
average_validate_error_percent
|
| 97 |
+
)
|
| 98 |
+
learning_rate_err_dict["average_brakpoint_error"] = average_brakpoint_error
|
| 99 |
+
learning_rate_err_dict["average_brakpoint_error_percent"] = (
|
| 100 |
+
average_brakpoint_error_percent
|
| 101 |
+
)
|
| 102 |
+
learning_rate_err_dict["average_brakpoint_validate_error"] = (
|
| 103 |
+
average_brakpoint_validate_error
|
| 104 |
+
)
|
| 105 |
+
learning_rate_err_dict["average_brakpoint_validate_error_percent"] = (
|
| 106 |
+
average_brakpoint_validate_error_percent
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
overall_learning_rate_err_.append(learning_rate_err_dict)
|
| 110 |
+
|
| 111 |
+
overall_learning_rate_err_df = pd.DataFrame(overall_learning_rate_err_)
|
| 112 |
+
overall_learning_rate_err_df.to_csv(
|
| 113 |
+
f"{result_dir}/overall_learning_rate_err.csv", index=False
|
| 114 |
+
)
|
model/viyacrab_augmentation.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
from sklearn.utils import resample
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def vy_training_augmentation(process_df):
|
| 6 |
+
process_df = process_df.copy()
|
| 7 |
+
a_crab_df = process_df[process_df["original_material_name"]
|
| 8 |
+
== "ปูทั้งตัว A"]
|
| 9 |
+
c_crab_df = process_df[process_df["original_material_name"]
|
| 10 |
+
== "ปูทั้งตัว C"]
|
| 11 |
+
only_small_crab_df = process_df[process_df["original_material_name"]
|
| 12 |
+
== "ปูทั้งตัว จิ๋ว"]
|
| 13 |
+
only_loss_crab_df = process_df[process_df["original_material_name"]
|
| 14 |
+
== "ปูทั้งตัว โพรก"]
|
| 15 |
+
small_crab_df = process_df[process_df["original_material_name"]
|
| 16 |
+
== "ปูจิ๋ว และโพรก"]
|
| 17 |
+
|
| 18 |
+
# Compare the amount of each crab type rows
|
| 19 |
+
a_crab_size = a_crab_df.shape[0]
|
| 20 |
+
c_crab_size = c_crab_df.shape[0]
|
| 21 |
+
small_crab_size = small_crab_df.shape[0]
|
| 22 |
+
only_small_size = only_small_crab_df.shape[0]
|
| 23 |
+
only_loss_size = only_loss_crab_df.shape[0]
|
| 24 |
+
|
| 25 |
+
# Find the maximum size of the crab type
|
| 26 |
+
max_size = max(a_crab_size, c_crab_size, small_crab_size,
|
| 27 |
+
only_small_size, only_loss_size)
|
| 28 |
+
|
| 29 |
+
# Calculate the number of rows to add for each crab type
|
| 30 |
+
a_crab_add = max_size * 2 - a_crab_size
|
| 31 |
+
c_crab_add = max_size * 2 - c_crab_size
|
| 32 |
+
small_crab_add = max_size * 2 - small_crab_size
|
| 33 |
+
only_small_crab_add = max_size * 2 - only_small_size
|
| 34 |
+
only_loss_crab_add = max_size * 2 - only_loss_size
|
| 35 |
+
|
| 36 |
+
# Add rows to each crab type
|
| 37 |
+
if a_crab_size > 0:
|
| 38 |
+
a_crab_augmented = resample(a_crab_df, n_samples=a_crab_add)
|
| 39 |
+
else:
|
| 40 |
+
a_crab_augmented = pd.DataFrame()
|
| 41 |
+
if c_crab_size > 0:
|
| 42 |
+
c_crab_augmented = resample(c_crab_df, n_samples=c_crab_add)
|
| 43 |
+
else:
|
| 44 |
+
c_crab_augmented = pd.DataFrame()
|
| 45 |
+
if small_crab_size > 0:
|
| 46 |
+
small_crab_augmented = resample(
|
| 47 |
+
small_crab_df, n_samples=small_crab_add)
|
| 48 |
+
else:
|
| 49 |
+
small_crab_augmented = pd.DataFrame()
|
| 50 |
+
if only_small_size > 0:
|
| 51 |
+
only_small_crab_augmented = resample(
|
| 52 |
+
only_small_crab_df, n_samples=only_small_crab_add)
|
| 53 |
+
else:
|
| 54 |
+
only_small_crab_augmented = pd.DataFrame()
|
| 55 |
+
if only_loss_size > 0:
|
| 56 |
+
only_loss_crab_augmented = resample(
|
| 57 |
+
only_loss_crab_df, n_samples=only_loss_crab_add)
|
| 58 |
+
else:
|
| 59 |
+
only_loss_crab_augmented = pd.DataFrame()
|
| 60 |
+
|
| 61 |
+
# Concatenate the augmented dataframes
|
| 62 |
+
a_crab_df_combined = pd.concat([a_crab_df, a_crab_augmented])
|
| 63 |
+
c_crab_df_combined = pd.concat([c_crab_df, c_crab_augmented])
|
| 64 |
+
small_crab_df_combined = pd.concat([small_crab_df, small_crab_augmented])
|
| 65 |
+
|
| 66 |
+
only_small_crab_df_combined = pd.concat(
|
| 67 |
+
[only_small_crab_df, only_small_crab_augmented])
|
| 68 |
+
only_loss_crab_df_combined = pd.concat(
|
| 69 |
+
[only_loss_crab_df, only_loss_crab_augmented])
|
| 70 |
+
|
| 71 |
+
# New Process Dataframe
|
| 72 |
+
process_df = pd.concat(
|
| 73 |
+
[a_crab_df_combined, c_crab_df_combined,
|
| 74 |
+
small_crab_df_combined, only_small_crab_df_combined,
|
| 75 |
+
only_loss_crab_df_combined
|
| 76 |
+
])
|
| 77 |
+
|
| 78 |
+
return process_df
|
requirement.txt
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
numpy
|
| 2 |
+
pandas
|
| 3 |
+
matplotlib
|
| 4 |
+
tensor-sensor
|
| 5 |
+
array-to-latex
|
| 6 |
+
scikit-learn
|
| 7 |
+
scipy
|
| 8 |
+
cowsay
|
| 9 |
+
pyfiglet
|
| 10 |
+
seaborn
|
| 11 |
+
statsmodels
|