feat: 예측 시, sm_hyper > 0이 2개 미만이어도 나머지 예측이 동작되도록 수정
parent
97cb8f5735
commit
c660ba22e2
Binary file not shown.
|
|
@ -101,6 +101,11 @@ def settlement_prediction(business_code, cons_code):
|
|||
additional_predict_percent=300,
|
||||
asaoka_interval=3))
|
||||
|
||||
# 결과가 None이면 DB 저장을 건너뛰고 종료 (시스템 crash 방지)
|
||||
if results is None:
|
||||
print(f"[Python Log] [Skip] {cons_code}: 유효한 예측 결과가 없어 DB 저장을 중단합니다.")
|
||||
return
|
||||
|
||||
# prediction method code
|
||||
# 1: original hyperbolic method (쌍곡선법)
|
||||
# 2: nonlinear hyperbolic method (비선형 쌍곡선법)
|
||||
|
|
|
|||
|
|
@ -290,69 +290,78 @@ def run_settle_prediction(point_name, np_time, np_surcharge, np_settlement,
|
|||
# 초기 침하량에 대한 침하량 조정
|
||||
sm_hyper = sm_hyper - s0_hyper
|
||||
|
||||
# =========================================================
|
||||
# 데이터 유효성 검사 및 예측 거부 로직
|
||||
# =========================================================
|
||||
# 분석이 완전히 불가능한 경우를 체크합니다.
|
||||
is_invalid = np.any(settle < 0) or np.max(sm_hyper) <= 0
|
||||
|
||||
if is_invalid:
|
||||
print(f"[Python Log] [Error] {point_name}: 누적침하량이 유효하지 않아 기본 예측으로 대체합니다.")
|
||||
# 실패 시 시스템이 멈추지 않도록 마지막 계측값을 그대로 유지하는 배열을 생성합니다.
|
||||
dummy_sp = np.full_like(time_hyper, settle[-1])
|
||||
dummy_sp_asaoka = np.full_like(time_hyper, settle[-1])
|
||||
dummy_sp_step = np.full_like(time[step_start_index[0]:], settle[-1])
|
||||
|
||||
# None 대신 모든 결과 리스트를 반환하여 controller.py의 에러를 방지합니다.
|
||||
return [time_hyper, dummy_sp, # Original
|
||||
time_hyper, dummy_sp, # Nonlinear
|
||||
time_hyper, dummy_sp, # Weighted
|
||||
time_hyper, dummy_sp_asaoka, # Asaoka
|
||||
time[step_start_index[0]:], dummy_sp_step] # Step Loading
|
||||
|
||||
# 계수 변수 기본값 초기화 (데이터 부족 시에도 UnboundLocalError 방지)
|
||||
x_hyper_nonlinear = np.array([1.0, 1.0])
|
||||
x_hyper_weight_nonlinear = np.array([1.0, 1.0])
|
||||
x_hyper_original = np.array([1.0, 1.0])
|
||||
|
||||
# 회귀분석 시행 (비선형 쌍곡선)
|
||||
x0 = np.ones(2)
|
||||
res_lsq_hyper_nonlinear = least_squares(fun_hyper_nonlinear, x0,
|
||||
args=(tm_hyper, sm_hyper))
|
||||
#x0 = np.ones(2)
|
||||
# res_lsq_hyper_nonlinear = least_squares(fun_hyper_nonlinear, x0,
|
||||
# args=(tm_hyper, sm_hyper))
|
||||
# 비선형 쌍곡선 법 계수 저장 및 출력
|
||||
x_hyper_nonlinear = res_lsq_hyper_nonlinear.x
|
||||
#x_hyper_nonlinear = res_lsq_hyper_nonlinear.x
|
||||
|
||||
if len(tm_hyper) >= 2:
|
||||
try:
|
||||
res_lsq = least_squares(fun_hyper_nonlinear, x_hyper_nonlinear, args=(tm_hyper, sm_hyper)) # 결과가 나올 때만
|
||||
x_hyper_nonlinear = res_lsq.x # 값을 업데이트
|
||||
except Exception as e:
|
||||
print(f"[Warning] ... failed: {e}") # 실패하면 초기값(1.0) 유지
|
||||
|
||||
# 가중 비선형 쌍곡선 가중치 산정
|
||||
# 시간 합계가 0인 경우(데이터 부족 등) 0으로 나누는 에러 방지
|
||||
# 가중 비선형 쌍곡선법 (Weighted Nonlinear)
|
||||
sum_tm = np.sum(tm_hyper)
|
||||
if sum_tm == 0:
|
||||
weight = np.ones_like(tm_hyper) # 가중치를 모두 1로 설정
|
||||
else:
|
||||
if sum_tm > 0 and len(tm_hyper) >= 2:
|
||||
weight = tm_hyper / sum_tm
|
||||
try:
|
||||
# 두 번째 인자인 'x_hyper_weight_nonlinear'가 반드시 포함되어야 함
|
||||
res_lsq = least_squares(fun_hyper_weight_nonlinear, x_hyper_weight_nonlinear, args=(tm_hyper, sm_hyper, weight))
|
||||
x_hyper_weight_nonlinear = res_lsq.x
|
||||
except Exception as e:
|
||||
print(f"[Warning] Weighted Nonlinear Hyperbolic failed for {point_name}: {e}")
|
||||
|
||||
# 회귀분석 시행 (가중 비선형 쌍곡선)
|
||||
x0 = np.ones(2)
|
||||
res_lsq_hyper_weight_nonlinear = least_squares(fun_hyper_weight_nonlinear, x0,
|
||||
args=(tm_hyper, sm_hyper, weight))
|
||||
# 비선형 쌍곡선 법 계수 저장 및 출력
|
||||
x_hyper_weight_nonlinear = res_lsq_hyper_weight_nonlinear.x
|
||||
|
||||
# 회귀분석 시행 (기존 쌍곡선법) - (0, 0)에 해당하는 초기 데이터를 제외하고 회귀분석 실시
|
||||
x0 = np.ones(2)
|
||||
# [로그 추가] 입력 데이터의 상태를 확인
|
||||
print(f"[LOG] {point_name} - tm_hyper size: {len(tm_hyper)}, sm_hyper contains zero: {np.any(sm_hyper == 0)}")
|
||||
if np.any(sm_hyper <= 0):
|
||||
print(f"[LOG] Problematic sm_hyper values: {sm_hyper[sm_hyper <= 0]}")
|
||||
|
||||
# 1. 침하량이 0보다 큰 유효한 데이터만 필터링 (0으로 나누기 근본적 방지)
|
||||
# 기존 쌍곡선법 (Original Hyperbolic)
|
||||
valid_indices = np.where(sm_hyper > 0)[0]
|
||||
|
||||
# 2. 필터링된 데이터가 최소 2개 이상인지 확인 (회귀분석을 위한 최소 조건)
|
||||
if len(valid_indices) >= 2:
|
||||
tm_hyper_valid = tm_hyper[valid_indices]
|
||||
sm_hyper_valid = sm_hyper[valid_indices]
|
||||
|
||||
# (0, 0) 제외 로직이 이미 필터링에 포함되어 있으므로 [1:] 없이 수행 가능
|
||||
x0 = np.ones(2)
|
||||
try:
|
||||
res_lsq_hyper_original = least_squares(fun_hyper_original, x0,
|
||||
args=(tm_hyper_valid, sm_hyper_valid))
|
||||
x_hyper_original = res_lsq_hyper_original.x
|
||||
except ValueError as e:
|
||||
print(f"[Warning] Optimization failed for Original Hyperbolic: {e}")
|
||||
x_hyper_original = np.ones(2) * 0.001 # 실패 시 기본값 세팅
|
||||
# 초기값으로 np.array([1.0, 1.0])을 직접 전달
|
||||
res_lsq = least_squares(fun_hyper_original, np.array([1.0, 1.0]), args=(tm_hyper_valid, sm_hyper_valid))
|
||||
x_hyper_original = res_lsq.x
|
||||
except Exception as e:
|
||||
print(f"[Warning] Original Hyperbolic failed for {point_name}: {e}")
|
||||
x_hyper_original = np.array([0.001, 0.001])
|
||||
else:
|
||||
# 데이터가 부족할 경우 에러 대신 기본값이나 알림 처리
|
||||
print(f"[Warning] {point_name}: Not enough valid settlement data (>0) for Original Hyperbolic.")
|
||||
x_hyper_original = np.ones(2) * 0.001
|
||||
x_hyper_original = np.array([0.001, 0.001])
|
||||
|
||||
# 기존 쌍곡선 법 계수 저장 및 출력
|
||||
x_hyper_original = res_lsq_hyper_original.x
|
||||
|
||||
# 현재 단계 예측 침하량 산정 (침하 예측 끝까지)
|
||||
sp_hyper_nonlinear = generate_data_hyper(x_hyper_nonlinear, time_hyper)
|
||||
sp_hyper_weight_nonlinear = generate_data_hyper(x_hyper_weight_nonlinear, time_hyper)
|
||||
sp_hyper_original = generate_data_hyper(x_hyper_original, time_hyper)
|
||||
|
||||
# 예측 침하량 산정
|
||||
sp_hyper_nonlinear = sp_hyper_nonlinear + s0_hyper
|
||||
sp_hyper_weight_nonlinear = sp_hyper_weight_nonlinear + s0_hyper
|
||||
sp_hyper_original = sp_hyper_original + s0_hyper
|
||||
# 최종 예측값 산정
|
||||
sp_hyper_nonlinear = generate_data_hyper(x_hyper_nonlinear, time_hyper) + s0_hyper
|
||||
sp_hyper_weight_nonlinear = generate_data_hyper(x_hyper_weight_nonlinear, time_hyper) + s0_hyper
|
||||
sp_hyper_original = generate_data_hyper(x_hyper_original, time_hyper) + s0_hyper
|
||||
time_hyper = time_hyper + t0_hyper
|
||||
|
||||
# ===============================
|
||||
|
|
|
|||
Loading…
Reference in New Issue