整线优化第一版论文定稿工程
增加了整线批量测试 修改了现有min-max模型路径 修改了遗传算法整体框架 估计器增加异常数据剔除 封装优化结果类 修改供料器扫描算法中重复吸嘴组的判定
This commit is contained in:
209
estimator.py
209
estimator.py
@ -1,10 +1,58 @@
|
||||
import copy
|
||||
import random
|
||||
|
||||
from generator import *
|
||||
from base_optimizer.optimizer_interface import *
|
||||
|
||||
|
||||
def exact_assembly_time(pcb_data, component_data):
|
||||
component_result, cycle_result, feeder_slot_result = feeder_priority_assignment(component_data, pcb_data,
|
||||
hinter=False)
|
||||
placement_result, head_sequence_result = greedy_placement_route_generation(component_data, pcb_data,
|
||||
component_result, cycle_result,
|
||||
feeder_slot_result, hinter=False)
|
||||
opt_res = OptResult(component_result, cycle_result, feeder_slot_result, placement_result, head_sequence_result)
|
||||
info = placement_info_evaluation(component_data, pcb_data, opt_res)
|
||||
# return info.metric()
|
||||
return info.total_time
|
||||
|
||||
|
||||
def error_info(pred_val, real_val, type='train'):
|
||||
absolute_error = np.array([])
|
||||
for idx, (t1, t2) in enumerate(np.nditer([pred_val, real_val])):
|
||||
absolute_error = np.append(absolute_error, abs(t1 - t2) / (t2 + 1e-10) * 100)
|
||||
if absolute_error[-1] > 15:
|
||||
print(f'\033[0;31;31midx: {idx + 1: d}, net: {t1: .3f}, real: {t2: .3f}, '
|
||||
f'gap: {absolute_error[-1]: .3f}\033[0m')
|
||||
|
||||
print('')
|
||||
print(f'mean absolute prediction error for {type} data : {np.average(absolute_error): .2f}% ')
|
||||
print(f'maximum absolute prediction error for {type} data : {np.max(absolute_error): .2f}% ')
|
||||
|
||||
|
||||
def converter(pcb_data, component_data, assignment):
|
||||
cp_items = defaultdict(list)
|
||||
|
||||
board_width, board_height = pcb_data['x'].max() - pcb_data['x'].min(), pcb_data['y'].max() - pcb_data['y'].min()
|
||||
|
||||
_, partial_component_data = convert_line_assigment(None, component_data, assignment)
|
||||
for machine_index in range(len(assignment)):
|
||||
cp_item_index = 0
|
||||
cp_points, cp_nozzle = defaultdict(int), defaultdict(str)
|
||||
for _, data in partial_component_data[machine_index].iterrows():
|
||||
feeder_limit, total_points = data.fdn, data.points
|
||||
surplus_points = total_points % feeder_limit
|
||||
for _ in range(feeder_limit):
|
||||
div_points = math.floor(total_points / feeder_limit)
|
||||
if surplus_points:
|
||||
div_points += 1
|
||||
surplus_points -= 1
|
||||
|
||||
cp_points[cp_item_index], cp_nozzle[cp_item_index] = div_points, data.nz
|
||||
cp_item_index += 1
|
||||
|
||||
cp_items[machine_index] = [cp_points, cp_nozzle, board_width, board_height]
|
||||
|
||||
return cp_items
|
||||
|
||||
|
||||
class Net(torch.nn.Module):
|
||||
def __init__(self, input_size, hidden_size=1000, output_size=1):
|
||||
super(Net, self).__init__()
|
||||
@ -61,7 +109,10 @@ class NeuralEstimator(Estimator):
|
||||
self.net = Net(input_size=self.data_mgr.get_feature(), output_size=1).to(device)
|
||||
self.net_file = 'model/net_model.pth'
|
||||
if os.path.exists(self.net_file):
|
||||
self.net.load_state_dict(torch.load(self.net_file))
|
||||
try:
|
||||
self.net.load_state_dict(torch.load(self.net_file))
|
||||
except:
|
||||
warnings.warn('the parameters of neural net model load failed', UserWarning)
|
||||
|
||||
def init_weights(self):
|
||||
for m in self.net.modules():
|
||||
@ -71,6 +122,7 @@ class NeuralEstimator(Estimator):
|
||||
|
||||
def training(self, params):
|
||||
self.init_weights() # 初始化参数
|
||||
|
||||
data = data_mgr.loader('opt/' + params.train_file)
|
||||
x_train = np.array(data_mgr.neural_encode(data[0][::data_mgr.get_update_round()]))
|
||||
y_train = np.array(data[1][::data_mgr.get_update_round()])
|
||||
@ -97,57 +149,23 @@ class NeuralEstimator(Estimator):
|
||||
|
||||
net_predict = self.net(x_train).view(-1)
|
||||
pred_time, real_time = net_predict.cpu().detach().numpy(), y_train.view(-1).cpu().detach().numpy()
|
||||
error_info(pred_time, real_time)
|
||||
|
||||
pred_error = np.array([])
|
||||
for t1, t2 in np.nditer([pred_time, real_time]):
|
||||
pred_error = np.append(pred_error, abs(t1 - t2) / (t2 + 1e-10) * 100)
|
||||
|
||||
print('--------------------------------------')
|
||||
print(f'average prediction error for train data : {np.average(pred_error): .2f}% ')
|
||||
print(f'maximum prediction error for train data : {np.max(pred_error): .2f}% ')
|
||||
|
||||
mse = np.linalg.norm((net_predict - y_train.view(-1)).cpu().detach().numpy())
|
||||
print(f'mean square error for training data result : {mse: 2f} ')
|
||||
if params.save:
|
||||
if not os.path.exists('model'):
|
||||
os.mkdir('model')
|
||||
torch.save(self.net.state_dict(), self.net_file)
|
||||
# self.net.load_state_dict(torch.load(self.net_file))
|
||||
|
||||
def testing(self, params):
|
||||
data = data_mgr.loader('opt/' + params.test_file)
|
||||
x_test, y_test = np.array(data_mgr.neural_encode(data[0])), np.array(data[1])
|
||||
|
||||
x_test, y_test = np.array(data_mgr.neural_encode(data[0])), np.array(data[1])
|
||||
x_test = torch.from_numpy(x_test.reshape((-1, np.shape(x_test)[1]))).float().to(device)
|
||||
|
||||
self.net.eval()
|
||||
with torch.no_grad():
|
||||
pred_time = self.net(x_test).view(-1).cpu().detach().numpy()
|
||||
# x_test = x_test.cpu().detach().numpy()
|
||||
|
||||
over_set = []
|
||||
pred_idx, pred_error = 0, np.array([])
|
||||
for t1, t2 in np.nditer([pred_time, y_test.reshape(-1)]):
|
||||
pred_error = np.append(pred_error, abs(t1 - t2) / (t2 + 1e-10) * 100)
|
||||
|
||||
if pred_error[-1] > 5:
|
||||
over_set.append(pred_idx + 1)
|
||||
print(f'\033[0;31;31midx: {pred_idx + 1: d}, net: {t1: .3f}, real: {t2: .3f}, '
|
||||
f'gap: {pred_error[-1]: .3f}\033[0m')
|
||||
# else:
|
||||
# print(f'idx: {pred_idx + 1: d}, net: {t1: .3f}, real: {t2: .3f}, gap: {pred_error[-1]: .3f}')
|
||||
|
||||
pred_idx += 1
|
||||
|
||||
print('over:', over_set)
|
||||
print('size:', len(over_set))
|
||||
|
||||
print('--------------------------------------')
|
||||
print(f'average prediction error for test data : {np.average(pred_error): .3f}% ')
|
||||
print(f'maximum prediction error for test data : {np.max(pred_error): .3f}% ')
|
||||
|
||||
mse = np.linalg.norm(pred_time - y_test.reshape(-1))
|
||||
print(f'mean square error for test data result : {mse: 2f} ')
|
||||
error_info(pred_time, y_test.reshape(-1), 'test')
|
||||
|
||||
def predict(self, cp_points, cp_nozzle, board_width=None, board_height=None):
|
||||
assert board_width is not None and board_height is not None
|
||||
@ -179,13 +197,7 @@ class HeuristicEstimator(Estimator):
|
||||
pickle.dump(self.lr, f)
|
||||
|
||||
y_predict = self.lr.predict(x_fit)
|
||||
pred_error = np.array([])
|
||||
for t1, t2 in np.nditer([y_fit, y_predict]):
|
||||
pred_error = np.append(pred_error, abs(t1 - t2) / (t2 + 1e-10) * 100)
|
||||
|
||||
print('--------------------------------------')
|
||||
print(f'average prediction error for train data : {np.average(pred_error): .2f}% ')
|
||||
print(f'maximum prediction error for train data : {np.max(pred_error): .2f}% ')
|
||||
error_info(y_fit, y_predict)
|
||||
|
||||
def testing(self, params):
|
||||
data = data_mgr.loader('opt/' + params.test_file)
|
||||
@ -193,13 +205,7 @@ class HeuristicEstimator(Estimator):
|
||||
y_fit = np.array([data[1]]).T
|
||||
|
||||
y_predict = self.lr.predict(x_fit)
|
||||
pred_error = np.array([])
|
||||
for t1, t2 in np.nditer([y_fit, y_predict]):
|
||||
pred_error = np.append(pred_error, abs(t1 - t2) / (t2 + 1e-10) * 100)
|
||||
|
||||
print('--------------------------------------')
|
||||
print(f'average prediction error for test data : {np.average(pred_error): .2f}% ')
|
||||
print(f'maximum prediction error for test data : {np.max(pred_error): .2f}% ')
|
||||
error_info(y_fit, y_predict, 'test')
|
||||
|
||||
def predict(self, cp_points, cp_nozzle, board_width=None, board_height=None):
|
||||
return self.lr.predict(np.array(self.heuristic_genetic(cp_points, cp_nozzle)).reshape(1, -1))
|
||||
@ -288,12 +294,12 @@ class HeuristicEstimator(Estimator):
|
||||
return [nl, wl, ul]
|
||||
|
||||
|
||||
class RegressionEstimator(Estimator):
|
||||
class ReconfigEstimator(Estimator):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.lr = LinearRegression()
|
||||
self.pickle_file = 'model/params_lr_model.pkl'
|
||||
self.pickle_file = 'model/reconfig_model.pkl'
|
||||
if os.path.exists(self.pickle_file):
|
||||
with open(self.pickle_file, 'rb') as f:
|
||||
self.lr = pickle.load(f)
|
||||
@ -311,13 +317,7 @@ class RegressionEstimator(Estimator):
|
||||
pickle.dump(self.lr, f)
|
||||
|
||||
y_predict = self.lr.predict(x_fit)
|
||||
pred_error = np.array([])
|
||||
for t1, t2 in np.nditer([y_fit, y_predict]):
|
||||
pred_error = np.append(pred_error, abs(t1 - t2) / (t2 + 1e-10) * 100)
|
||||
|
||||
print('--------------------------------------')
|
||||
print(f'average prediction error for train data : {np.average(pred_error): .2f}% ')
|
||||
print(f'maximum prediction error for train data : {np.max(pred_error): .2f}% ')
|
||||
error_info(y_fit, y_predict)
|
||||
|
||||
def testing(self, params):
|
||||
data = data_mgr.loader('opt/' + params.test_file)
|
||||
@ -325,19 +325,15 @@ class RegressionEstimator(Estimator):
|
||||
y_fit = np.array([data[1]]).T
|
||||
|
||||
y_predict = self.lr.predict(x_fit)
|
||||
pred_error = np.array([])
|
||||
for t1, t2 in np.nditer([y_fit, y_predict]):
|
||||
pred_error = np.append(pred_error, abs(t1 - t2) / (t2 + 1e-10) * 100)
|
||||
|
||||
print('--------------------------------------')
|
||||
print(f'average prediction error for test data : {np.average(pred_error): .2f}% ')
|
||||
print(f'maximum prediction error for test data : {np.max(pred_error): .2f}% ')
|
||||
error_info(y_fit, y_predict, 'test')
|
||||
|
||||
def predict(self, cp_points, cp_nozzle, board_width=None, board_height=None):
|
||||
return self.lr.predict(np.array(self.heuristic_reconfig(cp_points, cp_nozzle)).reshape(1, -1))
|
||||
return self.lr.predict(np.array(self.heuristic_reconfig(cp_points, cp_nozzle)).reshape(1, -1))[0, 0]
|
||||
|
||||
def heuristic_reconfig(self, cp_points, cp_nozzle):
|
||||
task_block_number, total_point_number = 0, sum(cp_points.values())
|
||||
if total_point_number == 0:
|
||||
return [total_point_number, task_block_number]
|
||||
nozzle_points, nozzle_heads = defaultdict(int), defaultdict(int)
|
||||
|
||||
for part, points in cp_points.items():
|
||||
@ -437,13 +433,7 @@ class SVREstimator(Estimator):
|
||||
input = [[np.average(predict_y[i:i + self.num_folds])] for i in range(len(predict_y) // self.num_folds)]
|
||||
predict_val = self.svr_list[-1].predict(input)
|
||||
|
||||
pred_error = np.array([])
|
||||
for t1, t2 in np.nditer([data[1], predict_val]):
|
||||
pred_error = np.append(pred_error, abs(t1 - t2) / (t2 + 1e-10) * 100)
|
||||
|
||||
print('--------------------------------------')
|
||||
print(f'average prediction error for train data : {np.average(pred_error): .2f}% ')
|
||||
print(f'maximum prediction error for train data : {np.max(pred_error): .2f}% ')
|
||||
error_info(data[1], predict_val)
|
||||
|
||||
def sos_svr_training(self, x_train, y_train):
|
||||
population = []
|
||||
@ -533,14 +523,7 @@ class SVREstimator(Estimator):
|
||||
|
||||
input = [[np.average(predict_y[i:i + self.num_folds])] for i in range(len(predict_y) // self.num_folds)]
|
||||
predict_val = self.svr_list[-1].predict(input)
|
||||
|
||||
pred_error = np.array([])
|
||||
for t1, t2 in np.nditer([data[1], predict_val]):
|
||||
pred_error = np.append(pred_error, abs(t1 - t2) / (t2 + 1e-10) * 100)
|
||||
|
||||
print('--------------------------------------')
|
||||
print(f'average prediction error for test data : {np.average(pred_error): .2f}% ')
|
||||
print(f'maximum prediction error for test data : {np.max(pred_error): .2f}% ')
|
||||
error_info(data[1], predict_val, 'test')
|
||||
|
||||
def predict(self, cp_points, cp_nozzle, board_width=None, board_height=None):
|
||||
pass
|
||||
@ -564,18 +547,29 @@ class SVREstimator(Estimator):
|
||||
return np.average(pred_error)
|
||||
|
||||
|
||||
def exact_assembly_time(pcb_data, component_data):
|
||||
component_result, cycle_result, feeder_slot_result = feeder_priority_assignment(component_data, pcb_data,
|
||||
hinter=False)
|
||||
placement_result, head_sequence_result = greedy_placement_route_generation(component_data, pcb_data,
|
||||
component_result, cycle_result,
|
||||
feeder_slot_result, hinter=False)
|
||||
info = placement_info_evaluation(component_data, pcb_data, component_result, cycle_result, feeder_slot_result,
|
||||
placement_result, head_sequence_result)
|
||||
# regression_info = [[info.cycle_counter, info.nozzle_change_counter, info.anc_round_counter,
|
||||
# info.pickup_counter, info.total_points]]
|
||||
# return self.lr.predict(regression_info)[0, 0]
|
||||
return info.total_time
|
||||
class MetricEstimator(Estimator):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.lr = LinearRegression()
|
||||
self.pickle_file = 'model/metric_model.pkl'
|
||||
if os.path.exists(self.pickle_file):
|
||||
with open(self.pickle_file, 'rb') as f:
|
||||
self.lr = pickle.load(f)
|
||||
|
||||
def training(self, params):
|
||||
x_fit, y_fit = data_mgr.metric('opt/' + params.train_file)
|
||||
self.lr.fit(x_fit, y_fit)
|
||||
print(self.lr.coef_)
|
||||
|
||||
def testing(self, params):
|
||||
x_fit, y_fit = data_mgr.metric('opt/' + params.test_file)
|
||||
|
||||
y_predict = self.lr.predict(x_fit)
|
||||
error_info(y_fit, y_predict, 'test')
|
||||
|
||||
def predict(self, cp_points, cp_nozzle, board_width=None, board_height=None):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
@ -587,13 +581,13 @@ if __name__ == '__main__':
|
||||
help='determine whether saving the parameters of network, linear regression model, etc.')
|
||||
parser.add_argument('--overwrite', default=False, type=bool,
|
||||
help='determine whether overwriting the training and testing data')
|
||||
parser.add_argument('--train_file', default='train_data - bp.txt', type=str, help='training file path')
|
||||
parser.add_argument('--test_file', default='test_data - bp.txt', type=str, help='testing file path')
|
||||
parser.add_argument('--num_epochs', default=10000, type=int, help='number of epochs for training process')
|
||||
parser.add_argument('--batch_size', default=1000, type=int, help='size of training batch')
|
||||
parser.add_argument('--train_file', default='train_data.txt', type=str, help='training file path')
|
||||
parser.add_argument('--test_file', default='test_data.txt', type=str, help='testing file path')
|
||||
parser.add_argument('--num_epochs', default=8000, type=int, help='number of epochs for training process')
|
||||
parser.add_argument('--batch_size', default=2000, type=int, help='size of training batch')
|
||||
parser.add_argument('--lr', default=1e-5, type=float, help='learning rate for the network')
|
||||
parser.add_argument('--model', default='neural-network', help='method for assembly time estimation')
|
||||
|
||||
parser.add_argument('--machine_optimizer', default='feeder-scan', type=str, help='optimizer for single machine')
|
||||
params = parser.parse_args()
|
||||
|
||||
data_mgr = DataMgr()
|
||||
@ -611,14 +605,13 @@ if __name__ == '__main__':
|
||||
# data_mgr.remover() # remove the last saved data
|
||||
# data_mgr.saver('data/' + file_name, pcb_data) # save new data
|
||||
|
||||
info = base_optimizer(1, pcb_data, component_data,
|
||||
feeder_data=pd.DataFrame(columns=['slot', 'part', 'arg']),
|
||||
method='feeder-scan', hinter=True)
|
||||
info = base_optimizer(1, pcb_data, component_data, pd.DataFrame(columns=['slot', 'part', 'arg']),
|
||||
params, hinter=True)
|
||||
|
||||
data_mgr.recorder(f, info, pcb_data, component_data)
|
||||
f.close()
|
||||
|
||||
estimator = NeuralEstimator()
|
||||
estimator = MetricEstimator()
|
||||
|
||||
estimator.training(params)
|
||||
estimator.testing(params)
|
||||
|
Reference in New Issue
Block a user