Tin Theethawat Savastham commited on
Commit
d4c7aae
·
1 Parent(s): 92dbef5

✨ Add Model Code

Browse files
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