Lotto645와 Deep Learning
서론
현재 나눔 로또645는 1부터 45개의 수에서 6개의 조합을 맞추는 게임이다. 랜덤하게 추첨되는 로또번호를 과연 딥러닝으로 예측할 수 있는가? 물론 정답은 "예측할 수 없다"이다. 그러나 랜덤 알고리즘으로 번호를 생성하는 것이나 딥러닝으로 학습한 데이터로 생성한 번호나 어짜피 추첨 번호가 랜덤이라면 똑 같은 조건이 되겠지만 그래도 뭔가 마음의 위안은 되지 않을 까 한다. 인간은 항상 기본 원리를 추구하고 가설을 세우고 이를 증명하고자 노력해왔다. 우리 두뇌의 생각원리가 그리되어 있는 건지 아니면 역사적으로 학습된 사고방식인지는 모르나 이로 인하여 학문이 탄생하고 종교와 문화가 생성되고 유지된다는 생각을 떨쳐 버릴 수가 없는 나 역시 그 사고 틀에서 벗어나지 못한다. 로또를 매주하는 많은 사람들이 추첨되는 번호를 보면서 뭔가 자기 나름의 패턴을 찾고 예측하고자 노력한다. 어찌 보면 패턴이 있는 듯이 보일 때도 있다. 착각일 수도 있겠지만 내가 생각하는 방식대로 세상이 보이는 이치와 같은 것 일 것이다. 그래서 딥러닝 방식으로 패턴을 찾고 이를 이용하여 다음 회차의 당첨번호를 예측하여 보기로 한다.
본론
텐서플로우 2.0기반 keras를 이용하여 가급적 단순하게 구성하여 보자. 기본 가설은 "이번 회차의 당첨번호가 다음 회차에 영향을 준다"이다. 완전 틀린 말도 아니다. 지난주의 당첨 번호가 그대로 나올 확율은 거의 없기 때문이다. 패턴을 찾는 사람들은 연계수에 주목한다. 여기서 시도 하고자 하는 방식은 전회차의 당첨번호와 다음 회차의 당첨 번호를 무작위로 학습 기억시키어 네트워크 자체적으로 패턴을 학습시키는 원리이다. 알파고의 원리와 유사한 셈이다. 문제점은 많다. 일단 학습데이터가 너무 한정적이라는 것이다. 아직 1000회를 넘지 못하였다. 어짜피 취미로 만들어 보는 것이니 너무 가혹하게 혹평하지 말자. 다음과 같이 모델을 구성한다.
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
========================================
lstm (LSTM) (None, 128) 69120
_________________________________________________________________
dense (Dense) (None, 45) 5805
========================================
def create_model():
model = tf.keras.models.Sequential([
keras.layers.LSTM(64, input_shape=(1,6), stateful=False), #64 또는 128
#keras.layers.Dense(45, activation='softmax'),
keras.layers.Dense(45, activation='relu'),
])
opt = keras.optimizers.Adam(learning_rate=0.01)
model.compile(optimizer="adam",
loss='categorical_crossentropy',
metrics=['accuracy'])
return model
학습은 아래의 코드와 같이 한다. num_epochs=10000으로 설정하였다. 학습데이터는 262차부터 최근까지의 당첨번호를 이용한다. 데이터를 1회차부터 사용하지 않는 이유는 중간에 추첨 기계가 변경되었기 때문이다. 다른 학습방법으로는 추첨 기계가 3개임으로 추첨 기계별로 따로 학습시키는 방법도 시도하였으나 학습 데이터가 더욱 적어지고 이번 회차에 어떤 기계를 사용할 지를 알 수 없으므로 의미가 없었다고 판단하였다.
model.fit(trainX, trainY, ### validation_data=(testX, testY),
epochs=6000, batch_size=16, verbose=2, shuffle=True, callbacks=[history])
로또 추첨번호가 램덤이라 그런지 학습은 제대로 이루어 지지 않는다. 학습데이터에 특정 패턴이 존재하지는 않는듯하다. 학습할 때에 한 회차의 입력 6개의 숫자는 셔플을 한다.
recall은 다음과 같이 한다. 전 회차의 당첨번호를 셔플하면서 입력하면 이번회차의 당첨 예정번호가 출력되는데 여러개의 예상 조합의 수에서 출력값이 강하게 나온(출력의 합) 상위 열개의 조합의 수만 선탹한다.
preds = model.predict(x_inval)
y_temp = heapq.nlargest(6, range(len(preds[0])), preds[0].take)
#출력이 0이 경우는 제외한다.
for idx2 in reversed(range(6)):
if preds[0,y_temp[idx2]]<0.01:
y_temp.remove(y_temp[idx2])
y_temp.sort()
response_sum = 0
for w in range(len(y_temp)):
if numpy.isnan(preds[0,y_temp[w]]) != True:
response_sum= response_sum+ preds[0,y_temp[w]]
맺는말
로또 번호를 정확히 예측할 수는 없지만 그 동안의 패턴을 통하여 예상 번호를 계산할 수는 있다. 이는 어디까지나 Hobby Coding일 뿐 그 이상의 다른 의미가 없다. 더 좋은 방법을 생각할 필요성을 느낀다.