대회 개요

엘리스 플랫폼에서 군인들을 대상으로 진행하는 국방 AI 미니경진대회가 열렸다. 캐글, 데이콘처럼 문제 상황을 주고 AI 모델을 이용해 더 정확히 예측할 수록 높은 점수를 받는 대회이다.

주제는 시계열 회귀 (Time-Series Regression) - 공정 프로세스 최종 품질값 예측이었다. 시계열 데이터는 처음 다뤄봤고, 시간의 흐름이 추가되기에 그냥 회귀분석과는 다르게 접근해야겠다고 생각했다.

초 단위로 끊어진 데이터에서 앞으로의 데이터를 예측(10000초의 연속적인 데이터가 있고 앞으로 2000초의 데이터를 예측)하는 것이 일반적인 시계열 예측대회의 구성이다. 근데 이 대회는 특이하게도 앞으로 몇 초가 아니라 중간중간 비는 데이터를 Submission Data에 넣어 예측하도록 구성했다. 일반적인 시계열 대회와 다르다는 것을 깨달았다.

 

접근 방법 1

먼저 전처리를 진행했다. raw_df는 85개의 input과 30개의 output으로 이루어지고, submission_df는 85개의 input과 NaN 값을 갖는 30개의 output으로 이루어져있다. 일단 85개의 input을 모두 사용하지 않을 예정이다. 그래도 문제에서 권하는 필요없는 input column을 제거하는 코드를 작성했다. column_names에 Setpoint가 들어있다면 그 column을 drop한다. 그러면 raw_df와 submission_df는 55개의 input을 갖게 된다.

# Setpoint를 가진 column 제거
including_Setpoint = []
column_names = list(raw_df.columns)

for i in range(len(column_names)):
    if "Setpoint" in column_names[i]:
        including_Setpoint.append(i)
        
raw_df.drop(raw_df.columns[including_Setpoint], axis=1, inplace=True)
submission_df.drop(submission_df.columns[including_Setpoint], axis=1, inplace=True)

다음으로 raw_df와 submission_df를 합쳤다. 보통 AI 대회에서는 상상하지 못할 일이다. 합친 후 index 오름차순으로 (시간 순으로) 정렬했다. 총 11000행의 데이터가 나왔고, output열은 드문드문 비어있게 된다. 즉, 예측해야 할 output의 가장 가까운 이전시간 output와 다음시간 output은 높은 확률로 1초 전 데이터, 1초 후 데이터라는 것이다.

result = pd.concat([raw_df, submission_df])
result = result.sort_index(ascending=True)
tag1 = []
for i in range(len(result.columns)):
    if result.columns[i].find('Stage1')==-1 and result.columns[i].find('Stage2')==-1:
        tag1.append(i)
        
result.drop(result.columns[tag1], axis=1, inplace=True)
result

 

접근 방법 2

행마다 탐색하며 output이 NaN으로 찍혀있다면, 투포인터 마냥 그 행에서 위, 아래로 가면서 output 데이터가 있는 행을 찾는다. 찾았다면 각각 toput1, toput2에 저장하고, 행 번호는 l, r에 저장한다. 못 찾았다면 toput1, toput2는 -1이다.

toput1, toput2 중 적어도 하나는 -1이 아니므로, 둘 중 하나가 -1이라면 -1이 아닌 데이터로 예측한다. 만약 둘 다 구했다면, 내분점을 구하면 된다. 내분점은 아래와 같은 공식으로 구했다.

pnt = 0
for i in range(result.shape[0]):
    if np.isnan(result.iloc[i,0]):
        for j in range(result.shape[1]):
            toput1 = -1
            toput2 = -1
            toput = 0
            top = 0
            l = 0
            r = 0
            
            for k in range(i-1,-1,-1):
                if not np.isnan(result.iloc[k,0]):
                    toput1 = result.iloc[k,j]
                    l = k
                    break
            for k in range(i+1,result.shape[0]):
                if not np.isnan(result.iloc[k,0]):
                    toput2 = result.iloc[k,j]
                    r = k
                    break
                    
            if toput1==-1:
                toput=toput2
            elif toput2==-1:
                toput=toput1
            else:
            # 내분점 구하는 공식
                if toput1 < toput2:
                    toput = toput1 + (toput2-toput1)*(i-l)/(r-l)
                else:
                    toput = toput2 + (toput1-toput2)*(r-i)/(r-l)
                    
            if j < 15:
                stage1_sub_pred[pnt][j] = toput
            else:
                stage2_sub_pred[pnt][j-15] = toput
        pnt+=1
stage1_sub_pred

 

대회 결과

2등으로 마무리하며 갤럭시탭 S8+ 키보드에디션 512gb (약 180만원)을 받게 되었다. 이후에 input 데이터를 활용하고자 n차 차분과 lasso 모델을 활용했는데, 위 예측보다 좋은 점수를 받지 못해 결국 모델을 사용하지 않고 제출했다. 이런 방식은 보통의 시계열 예측에서는 쓸 수 없기에, 어떻게 보면 잔머리를 써서 높은 성적을 받은 것이다. 그래도 시계열 데이터에 대한 관심을 갖고 공부도 하게 되어 좋은 시간이었다.

+ Recent posts