"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


[DL] 딥러닝을 이용한 로또 번호 생성기
728x90

 

딥러닝 LSTM 모델을 이용한 로또 번호 예측기를 알아보겠습니다. 

사실 로또는 이전 회차 번호를 학습하여 신규 번호를 예측하는 것이 무의미 합니다. 당첨번호 간, 당첨회차 간 전혀 관계가 없기 떄문입니다.

단순히 재미로, 딥러닝 프로젝트를 연습하기 위해서 LSTM을 이용한 로또 번호 생성기를 만들어 보겠습니다.

데이터 수집 - 데이터 변환 - 훈련 및 딥러닝 모델 생성 - 로또 번호 생성의 과정으로 진행하겠습니다.

 

모든 회차 로또 당첨 번호 수집하기 (데이터 수집)

동행복권 사이트에 들어가면 모든 로또 당첨 번호를 수집 할 수 있습니다.

 

 

로또6/45 - 회차별 당첨번호

1050회 당첨결과 (2023년 01월 14일 추첨) 당첨번호 6 12 31 35 38 43 1050회 순위별 등위별 총 당첨금액, 당첨게임 수, 1게임당 당첨금액, 당첨기준, 비고 안내 순위 등위별 총 당첨금액 당첨게임 수 1게임

dhlottery.co.kr

 

하단에 보면 회차를 지정해서 엑셀다운로드 하는 기능이 있습니다. 해당 기능을 이용해서 당첨번호를 엑셀로 다운로드 하고, csv 파일로 변환하여 훈련 데이터로 사용합니다.

 

엑셀 자료에 불필요한 필드들을 제거 하여  생성한 csv 파일을 사용하셔도 됩니다.

lotto.csv
0.03MB

 

 

로또 번호 생성기 훈련 데이터 생성 (데이터 변환)

lotto.csv 파일을 데이터 프레임으로 읽어 옵니다.

df = pd.read_csv("lotto.csv")
df.head()

회차번호와 연도는 불필요한 데이터이고, 보너스 번호를 넣는다고 해도 크게 의미가 없기 때문에 당첨번호 6개만 훈련 데이터로 사용합니다.

 

훈련용 데이터(X)는 45개의 원소로 이루어진 array에 당첨번호를 array의 인덱스로 지정하여 해당 인덱스의 값을 1로 변환하는 형태로 생성합니다.

 

라벨 데이터(Y)는 크게 의미가 없기 때문에 적당히 지정하였습니다. 마찬가지로 훈련, 검증용 데이터도 큰 의미가 없기 때문에 검증용 데이터도 1개만 생성하였습니다.

# 로또 결과 데이터개수 x 45 행렬 생성하여 0으로 초기화
oh_data = np.zeros(shape=(len(df), 45))

# 당첨번호의 인덱스 값을 1로 변경
for i in range(len(df)):
    for k in range(2,8):
        oh_data[i][df.iloc[i,k]-1] = 1

# 훈련데이터 X, 라벨데이터 Y 생성
X = np.array(oh_data[0:len(oh_data)-1])
Y = np.array(oh_data[1:len(oh_data)])

# 훈련용, 검증용 데이터 split
x_train, x_valid, y_train, y_valid = train_test_split(X, Y, test_size=0.0001)

1049회까지 있는 데이터이기 때문에 X와 Y는 1048행, 45열의 행렬로 생성하였고,

x_train과 x_test는 1047개, 1개로 생성하였습니다.

 

 

훈련 및 LSTM 딥러닝 모델 생성

훈련데이터(x_train)를 우선 LSTM 모델에 넣기 위해 3차원으로 reshape 합니다.

x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
print(x_train.shape)

 

 

45 x 1의 input을 갖고, 45개의 output 나오는 LSTM 모델을 만듭니다. 이전 층의 가중치가 큰 의미가 없기 때문에 stateful을 false로 해서 모델을 생성합니다. 사실 loss나 optimizer로 영향을 미치지 않기 때문에 적당히 지정합니다.

model = keras.Sequential([
    keras.layers.LSTM(128, input_shape=(x_train.shape[1],1), return_sequences=False, stateful=False),
    keras.layers.Dense(45, activation='sigmoid')
])

model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
model.summary()

 

batch 크기와 epoch를 지정해서 훈련 합니다. 6개의 로또 번호만 구하면 되기 떄문에 이부분의 파라미터도 크게 중요하지 않습니다.

model.fit(x_train, y_train, batch_size=16, epochs=100)

모델 훈련이 완료되었습니다. 다음으로 생성한 모델로 로또 번호 6개를 예측 하도록 합니다.

 

로또 번호 생성

로또 번호 예측 시 사용하는 인풋 데이터는 이전에 검증용으로 나눠 놓은 데이터를 사용합니다.

x_test를 input으로 하여 predict를 수행합니다.

x_valid = np.reshape(x_valid, (x_valid.shape[0], x_valid.shape[1], 1))
pred = model.predict(x_valid)

 

활성화 함수를 sigmoid를 사용했기 때문에 pred의 값을 출력하면 각 번호에 예측값을 볼 수 있습니다.

 

상위 6개의 예측값을 로또 당첨 번호로 이용하여 최종 로또 번호를 예측하였습니다.

# 내림차순으로 정렬
sorted_pred = np.sort(pred[0])[::-1]

# 상위 6개 번호를 결과 리스트에 저장
result = []
for i in range(0,6) :
    result.append((np.where(pred[0] == sorted_pred[i])[0] + 1)[0])

print (datetime.datetime.now())
print (result)

 

지금까지 5번 정도 로또를 구매했는데, 한 번도 당첨되지 않았고, 평균 2개 정도 맞췄습니다. 자동으로 한 것과 큰 차이가 없습니다.

로또 번호 6개를 구하기 위해 로또 당첨 번호 데이터를 어떻게 LSTM에 입력값으로 넣고, 출력을 어떤식으로 가져갈 지를 확인해보는 정도로 로또 번호 생성기를 구현해보면 좋을것 같습니다.

 

전체 소스 코드를 마지막으로 딥러닝을 이용한 로또 번호 생성기 구현 포스팅을 마칩니다.

import numpy as np
import pandas as pd
import datetime
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, models
from sklearn.model_selection import train_test_split

# 로또 데이터 읽어오기
df = pd.read_csv("lotto.csv")

# 데이터 변환
oh_data = np.zeros(shape=(len(df), 45))

for i in range(len(df)):
    for k in range(2,8):
#         print (df.iloc[i])
        oh_data[i][df.iloc[i,k]-1] = 1

X = np.array(oh_data[0:len(oh_data)-1])
Y = np.array(oh_data[1:len(oh_data)])
print (X.shape)
print (Y.shape)

# 훈련용 데이터 생성
x_train, x_valid, y_train, y_valid = train_test_split(X, Y, test_size=0.0001)
print (x_train.shape)
print (x_valid.shape)

x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
print(x_train.shape)

# 모델 생성 및 훈련
model = keras.Sequential([
    keras.layers.LSTM(128, input_shape=(x_train.shape[1],1), return_sequences=False, stateful=False),
    keras.layers.Dense(45, activation='sigmoid')
])

model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
model.summary()

model.fit(x_train, y_train, batch_size=16, epochs=50)

# 로또 번호 생성
x_valid = np.reshape(x_valid, (x_valid.shape[0], x_valid.shape[1], 1))
pred = model.predict(x_valid)

# 내림차순으로 정렬
sorted_pred = np.sort(pred[0])[::-1]

# 상위 6개 번호 확인
result = []
for i in range(0,6) :
    result.append((np.where(pred[0] == sorted_pred[i])[0] + 1)[0])

print (datetime.datetime.now())
print (result)

 

 

728x90
728x90
LIST