쿠버네티스,쿠버플로우

던전앤파이터 시세 예측[2]

세용용용용 2023. 8. 24. 15:59

터미널에 pip 설치하기 

1. wget https://bootstrap.pypa.io/get-pip.py
2. python3 get-pip.py

3. 환경 변수 설정 : export PATH=$PATH:/home/cloudcccr3/.local/bin

4. 변경사항 즉시 적용 : ~/.bashrc

5. pip 설치 되는지 테스트 해보기 : pip install lightgbm

 

1. 몽고db연결 간단 전처리

import pandas as pd
from pymongo import MongoClient

# MongoDB 연결 설정
client = MongoClient("mongodb://3.38.178.84:27017/")
db = client["donpa"]  # 데이터베이스명
collection = db["donpa_data"]  # 컬렉션명

# 컬렉션 데이터 조회
data = collection.find()

# 데이터프레임으로 변환
df = pd.DataFrame(data)

# _id 컬럼은 제거해주자
df = df.drop(columns="_id") 

# 출력
print("데이터의 row수:",len(df))


from datetime import datetime
# object타입의 데이터 datetime타입으로 변경하는 코드
df['soldDate'] = pd.to_datetime(df['soldDate'])

# 년월일시분 정보만 추출하여 원하는 형식으로 출력, 10 단위로 변환하고 다시 분 단위로 합치기
df['soldDate'] = df['soldDate'].dt.strftime("%Y-%m-%d %H:") + (df['soldDate'].dt.minute // 10 * 10).astype(str)

# soldDate 다시 datetime타입으로 변경하는 코드
df['soldDate'] = pd.to_datetime(df['soldDate'])

# unitPrice 컬럼 float타입으로 변경
df['unitPrice'] = df['unitPrice'].astype('float')

# soldDate, itemName컬럼으로 묶어주기 unitPrice는 평균으로 ㄱㄱ
df = df.groupby(['soldDate','itemName']).mean('unitPrice')
df.reset_index(drop=False, inplace=True)

#soldDate 컬럼 인덱스로 변경
# df.set_index('soldDate', inplace=True)

# 잘 수정했는지 확인
df.info()
df.head()

출력 화면

 

 

2. 피처 엔지니어링

new_df = df
# 년 컬럼 추가
new_df['year'] = new_df['soldDate'].dt.year

# 월 컬럼 추가
new_df['month'] = new_df['soldDate'].dt.month

# 일 컬럼 추가
new_df['day'] = new_df['soldDate'].dt.day

# 시간 컬럼 추가
new_df['hour'] = new_df['soldDate'].dt.hour

# 분 컬럼 추가
new_df['minute'] = new_df['soldDate'].dt.minute

# 요일 컬럼 추가해주자
new_df['day_name'] = new_df['soldDate'].dt.day_name()

# 타겟 컬러 맨뒤로 보내기
unit_price_column = new_df.pop('unitPrice')
new_df['unitPrice'] = unit_price_column

# 필요 없는 컬럼 삭제
new_df = new_df.drop(columns = ['soldDate','itemName'])
new_df.head()

 

 

3. 타겟값 분리해주자

X_train = new_df.drop(columns = 'unitPrice')
y_train = new_df['unitPrice']

display(X_train.head())
y_train.head()

 

 

4. 왜도 있는지 확인후 있으면 로그변환ㄱㄱ (데이터 마다 다르지만 보통 절대값이 1이 넘어가면 왜도가 있다고 판단)

from scipy.stats import skew

# 왜도 있는 컬럼 모은 리스트
log_list = [] 

# 수치형 컬럼들만 돌려야됨
for i in X_train.select_dtypes(exclude='object').columns:
    skewness = skew(X_train[i])
    
    # 절대값이 1이 넘어가면 왜도가 있다고 판단
    if abs(skewness) >= 1:
        log_list.append(i)

print(log_list)

# 왜도 있는 컬럼들만 로그변환을 해주자
import numpy as np
for i in log_list:
    if X_train[i].min() < 0:
        X_train[i] = X_train.map(lambda x : x+abs(X_train[i].min()))
    X_train[i] = np.log1p(X_train[i])

X_train

 

 

5. 데이터를 분할하자 학습용8, 테스트2

from sklearn.model_selection import train_test_split
X_train, X_validation, Y_train, Y_validation = train_test_split(X_train,y_train, test_size=0.2, random_state=1)

#print(X_train.shape, X_validation.shape, Y_train.shape, Y_validation.shape)
X_train.reset_index(drop=True, inplace=True)
X_validation.reset_index(drop=True, inplace=True)

 

 

6. 수치형 데이터  StandardScaler 해주자!!

obj_col = X_train.select_dtypes(include='object').columns

from sklearn.preprocessing import StandardScaler
sds = StandardScaler()
sds.fit(X_train.drop(columns = obj_col))

X_train_sc = sds.transform(X_train.drop(columns = obj_col))
X_train_sc = pd.DataFrame(X_train_sc, columns = X_train.drop(columns = obj_col).columns)

X_validation_sc = sds.transform(X_validation.drop(columns = obj_col))
X_validation_sc = pd.DataFrame(X_validation_sc, columns = X_validation.drop(columns = obj_col).columns)


# object 타입 컬럼 붙여주기
for i in obj_col:
    X_train_sc[i] = X_train[i]
    X_validation_sc[i] = X_validation[i]

 

 

7. 원핫 인코딩 돌려주자

from sklearn.preprocessing import OneHotEncoder

# OneHotEncoder 객체 생성
encoder = OneHotEncoder()

X_full = pd.concat([X_train_sc, X_validation_sc])

# 범주형 열만 선택
obj_df = X_full.select_dtypes(include='object')

# 숫자형 열만 선택
no_obj_df = X_full.select_dtypes(exclude='object')

# 범주형 열을 원핫 인코딩
encoded_features = encoder.fit_transform(obj_df)

# 인코딩된 결과를 데이터프레임으로 변환
encoded_df = pd.DataFrame(encoded_features.toarray(), columns=encoder.get_feature_names(obj_df.columns))

# 인코딩된 범주형 열과 숫자형 열을 합침
X_train_sc_ec = pd.concat([no_obj_df[:len(X_train_sc)] , encoded_df[:len(X_train_sc)]], axis = 1)
X_validation_sc_ec = pd.concat([no_obj_df[len(X_train_sc):] , encoded_df[len(X_train_sc):].reset_index(drop=True)], axis = 1)
#X_validation_sc_ec

 

 

8. 모델 선정 (랜포 vs xgboost vs lgbm)

1) RandomForest

from sklearn.ensemble import RandomForestRegressor
RFC = RandomForestRegressor(random_state=10)
RFC.fit(X_train_sc_ec, Y_train)

pred_train = RFC.predict(X_train_sc_ec)
pred_validation = RFC.predict(X_validation_sc_ec)

# 성능평가
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
mse_train = mean_squared_error(Y_train, pred_train)
mse_validation = mean_squared_error(Y_validation, pred_validation)

mae_train = mean_absolute_error(Y_train, pred_train)
mae_validation = mean_absolute_error(Y_validation, pred_validation)

r2_train = r2_score(Y_train, pred_train)
r2_validation = r2_score(Y_validation, pred_validation)

print('mse_train',mse_train)
print('mae_train',mae_train)
print('r2_train',r2_train)
print('\n')
print('mse_validation',mse_validation)
print('mae_validation',mae_validation)
print('r2_validation',r2_validation)

예측 데이터 그래프로 시각화

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))
plt.plot(np.array(Y_validation), label='Actual')
plt.plot(pred_validation, label='Predicted', linestyle='--')
plt.xlabel('Sample Index')
plt.ylabel('Value')
plt.title('Actual vs Predicted')
plt.legend()
plt.show()

 

 

 

2) xgboost

import xgboost as xgb
xgb = xgb.XGBRegressor(random_state=10)
xgb.fit(X_train_sc_ec, Y_train)

pred_train = xgb.predict(X_train_sc_ec)
pred_validation = xgb.predict(X_validation_sc_ec)

# 성능평가
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
mse_train = mean_squared_error(Y_train, pred_train)
mse_validation = mean_squared_error(Y_validation, pred_validation)

mae_train = mean_absolute_error(Y_train, pred_train)
mae_validation = mean_absolute_error(Y_validation, pred_validation)

r2_train = r2_score(Y_train, pred_train)
r2_validation = r2_score(Y_validation, pred_validation)

print('mse_train',mse_train)
print('mae_train',mae_train)
print('r2_train',r2_train)
print('\n')
print('mse_validation',mse_validation)
print('mae_validation',mae_validation)
print('r2_validation',r2_validation)

예측 데이터 그래프로 시각화

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))
plt.plot(np.array(Y_validation), label='Actual')
plt.plot(pred_validation, label='Predicted', linestyle='--')
plt.xlabel('Sample Index')
plt.ylabel('Value')
plt.title('Actual vs Predicted')
plt.legend()
plt.show()

 

 

 

3) lgbm

import lightgbm as lgb

# LGBMRegressor 객체 생성
LGBMR = lgb.LGBMRegressor(random_state=10)

# 모델 학습
LGBMR.fit(X_train_sc_ec, Y_train)

# 학습된 모델로 예측
pred_train = LGBMR.predict(X_train_sc_ec)
pred_validation = LGBMR.predict(X_validation_sc_ec)

# 성능 평가
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score

mse_train = mean_squared_error(Y_train, pred_train)
mse_validation = mean_squared_error(Y_validation, pred_validation)

mae_train = mean_absolute_error(Y_train, pred_train)
mae_validation = mean_absolute_error(Y_validation, pred_validation)

r2_train = r2_score(Y_train, pred_train)
r2_validation = r2_score(Y_validation, pred_validation)

print('mse_train', mse_train)
print('mae_train', mae_train)
print('r2_train', r2_train)
print('\n')
print('mse_validation', mse_validation)
print('mae_validation', mae_validation)
print('r2_validation', r2_validation)

예측 데이터 그래프로 시각화

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))
plt.plot(np.array(Y_validation), label='Actual')
plt.plot(pred_validation, label='Predicted', linestyle='--')
plt.xlabel('Sample Index')
plt.ylabel('Value')
plt.title('Actual vs Predicted')
plt.legend()
plt.show()

 

 

 

9. 모델 선정해 최적의 매개변수 찾기(아직은 모델을 정하기 못함.. 코드만 일단 짜둠)

#Xgboost가 더 잘나옴 최적의 파라미터 찾아보자
from sklearn.model_selection import GridSearchCV
import xgboost as xgb
model = xgb.XGBClassifier(random_state=11)
#help(xgb.XGBClassifier(random_state=11))
parameters = {
    'n_estimators':[35,40,45],
    'max_depth':[7,8,10,11,12]
}

gridsh = GridSearchCV(model, parameters, cv = 5)
gridsh.fit(X_train_sc, Y_train)
print('최적의 매개변수', gridsh.best_params_)

 

 

10. 이제 10분뒤 가격을 예측하는 코드

# 데이터 에서 가장 최신의 시간을 가져온다
predit_df = df.iloc[-1,0]

# 10분을 더한 Timestamp 객체 생성
predit_df = predit_df + pd.Timedelta(minutes=10)
predit_df

# 데이터 프레임으로 만들어준다
predit_df = {'soldDate': [predit_df]}
predit_df = pd.DataFrame(predit_df)

# 년 컬럼 추가
predit_df['year'] = predit_df['soldDate'].dt.year

# 월 컬럼 추가
predit_df['month'] = predit_df['soldDate'].dt.month

# 일 컬럼 추가
predit_df['day'] = predit_df['soldDate'].dt.day

# 시간 컬럼 추가
predit_df['hour'] = predit_df['soldDate'].dt.hour

# 분 컬럼 추가
predit_df['minute'] = predit_df['soldDate'].dt.minute

# 요일 컬럼 추가해주자
predit_df['day_name'] = predit_df['soldDate'].dt.day_name()

# 필요 없는 컬럼 삭제
predit_df = predit_df.drop(columns = ['soldDate'])

display(predit_df)

# 원핫인코딩 객체를 불러와서 인코딩 시켜주자
# 범주형 열만 선택
obj_df = predit_df.select_dtypes(include='object')

# 숫자형 열만 선택
no_obj_df = predit_df.select_dtypes(exclude='object')

# 범주형 열을 원핫 인코딩
encoded_features = encoder.transform(obj_df)

# 인코딩된 결과를 데이터프레임으로 변환
encoded_df = pd.DataFrame(encoded_features.toarray(), columns=encoder.get_feature_names(obj_df.columns))

# 인코딩된 범주형 열과 숫자형 열을 합침
predit_df = pd.concat([no_obj_df, encoded_df], axis=1)

# 10분뒤 가격을 예측!!!!
pred_ten_min_rf = RFC.predict(predit_df)
pred_ten_min_xb = xgb.predict(predit_df)
pred_ten_min_lm = LGBMR.predict(predit_df)
print('rf:',pred_ten_min_rf)
print('xb:',pred_ten_min_xb)
print('lm:',pred_ten_min_lm)

 

 

 

 

 

앞선 모델은 머신러닝 앙상블모델로 실습해봄

이제는 딥러닝 모델인 lstm모델을 사용하여 실습을 해보겠습니다!!

 

lstml : rnn의 한종류이며 시퀀스 데이터의 긴 의존성을 학습할 수 있는 능력을 가지고 있어서 이전 정보를 잘 유지하면서 현재 정보를 활용하여 예측이나 분류 작업을 수행할 수 있다!!!

 

 

 

1. 데이터 불러와 간단 전처리, 피처엔지니어링

import pandas as pd
from pymongo import MongoClient

# MongoDB 연결 설정
client = MongoClient("mongodb://3.38.178.84:27017/")
db = client["donpa"]  # 데이터베이스명
collection = db["donpa_data"]  # 컬렉션명

# 컬렉션 데이터 조회
data = collection.find()

# 데이터프레임으로 변환
df = pd.DataFrame(data)

# _id 컬럼은 제거해주자
df = df.drop(columns="_id") 

# 출력
print("데이터의 row수:",len(df))


from datetime import datetime
# object타입의 데이터 datetime타입으로 변경하는 코드
df['soldDate'] = pd.to_datetime(df['soldDate'])

# 년월일시분 정보만 추출하여 원하는 형식으로 출력, 10 단위로 변환하고 다시 분 단위로 합치기
df['soldDate'] = df['soldDate'].dt.strftime("%Y-%m-%d %H:") + (df['soldDate'].dt.minute // 10 * 10).astype(str)

# soldDate 다시 datetime타입으로 변경하는 코드
df['soldDate'] = pd.to_datetime(df['soldDate'])

# unitPrice 컬럼 float타입으로 변경
df['unitPrice'] = df['unitPrice'].astype('float')

# soldDate, itemName컬럼으로 묶어주기 unitPrice는 평균으로 ㄱㄱ
df = df.groupby(['soldDate','itemName']).mean('unitPrice')
df.reset_index(drop=False, inplace=True)

#soldDate 컬럼 인덱스로 변경
df.set_index('soldDate', inplace=True)

# 잘 수정했는지 확인
# df.info()
display(df.head())

# itemName컬럼은 사용하지 안을거임 제거해주자
df = df.drop(columns= 'itemName')
df = df.reset_index(drop=False)

# 피처 엔지니어링
# 30분 이평선
ma3 = df['unitPrice'].rolling(window=3).mean()
df.insert(len(df.columns), 'ma3', ma3)

# 기존 데이터가 있다면 NaN에 이동평균선 값을 채워넣어주는 방법
# 기존 데이터가 없다면 NaN에 0 값을 채워줘야 함
df = df.fillna(0)
df.info()
df

 

 

 

2. lstm을 이용해 unitPrice를 예측하는 것을 목표로

나중에 예측값과 실제값을 비교하기 위해 따로 뗴어 저장하자, 그래프 그리기 위해 날짜도 따로 저장하자

# 실제 값
original_open = df['unitPrice'].values

# 날짜 값
dates = pd.to_datetime(df['soldDate'])

-----------------------------------------------------

# 사용할 컬럼만 가져오기
cols = list(df)[1:]

# 데이터타입 float로 변경
df = df[cols].astype(float)
df.info()

 

 

 

3. lstm 활성 함수가 tanh와 sigmoid이므로 다음과 같이 학습용 데이터 정규화 해야됨

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
scaler = scaler.fit(df)
df_scaler = scaler.transform(df)
# 앞에 5개만 확인하기
df_scaler[:5]

 

 

 

4. 학습용 테스트 데이터 9대1비율로 나눈다

n_train = int(0.9*df_scaler.shape[0]) # 90퍼 비율
train_data_scaled = df_scaler[:n_train] # train 데이터
train_dates = dates[:n_train] # train 날짜

test_data_scaled = df_scaler[n_train:] # test 데이터
test_dates = dates[n_train:] # test 날짜
test_data_scaled

 

 

 

5. 직전 24개의 데이터를 기반으로 10분뒤 가격을 예측하는 것을 목표

데이터 구조를 lstm의 입력과 출력에 맞게 바꿔주자

import numpy as np
pred_days = 1
seq_len = 7
input_dim = 2

X_train = []
Y_train = []
X_test = []
Y_test = []

for i in range(seq_len, n_train-pred_days +1):
    X_train.append(train_data_scaled[i - seq_len:i, 0:train_data_scaled.shape[1]])
    Y_train.append(train_data_scaled[i + pred_days - 1:i + pred_days, 0])

for i in range(seq_len, len(test_data_scaled)-pred_days +1):
    X_test.append(test_data_scaled[i - seq_len:i, 0:test_data_scaled.shape[1]])
    Y_test.append(test_data_scaled[i + pred_days - 1:i + pred_days, 0])

X_train, Y_train = np.array(X_train), np.array(Y_train)
X_test, Y_test = np.array(X_test), np.array(Y_test)

X_test.shape

 

 

6. lstm모델

# TensorFlow에서 Keras 모듈을 불러옵니다
import tensorflow as tf
# 레이어를 선형으로 쌓아 순차적으로 연결하여 모델을 만드는 방식
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense

# 나머지 모델 구성 및 학습 코드를 이어서 작성하세요


model = Sequential()
model.add(LSTM(64, input_shape=(X_train.shape[1], X_train.shape[2]), # (seq length, input dimension)
               return_sequences=True))
model.add(LSTM(32, return_sequences=False))
model.add(Dense(Y_train.shape[1]))

 

 

7. 모델 컴파일

모델 피팅

from tensorflow.keras.optimizers import Adam

# specify your learning rate
learning_rate = 0.01
# create an Adam optimizer with the specified learning rate
optimizer = Adam(learning_rate=learning_rate)
# compile your model using the custom optimizer
model.compile(optimizer=optimizer, loss='mse')

# 모델 피팅
history = model.fit(X_train, Y_train, epochs=30, batch_size=32,
                    validation_split=0.1, verbose=1)

 

 

8. 모델 예측

# prediction
prediction = model.predict(X_test)
print(prediction.shape, X_test.shape)

# generate array filled with means for prediction
mean_values_pred = np.repeat(scaler.mean_[np.newaxis, :], prediction.shape[0], axis=0)

# substitute predictions into the first column
mean_values_pred[:, 0] = np.squeeze(prediction)

# inverse transform
y_pred = scaler.inverse_transform(mean_values_pred)[:,0]
print(y_pred.shape)

# generate array filled with means for testY
mean_values_testY = np.repeat(scaler.mean_[np.newaxis, :], Y_test.shape[0], axis=0)

# substitute testY into the first column
mean_values_testY[:, 0] = np.squeeze(Y_test)

# inverse transform
testY_original = scaler.inverse_transform(mean_values_testY)[:,0]
print(testY_original.shape)

import matplotlib.pyplot as plt


# plotting
plt.figure(figsize=(80, 60))

# plot original 'Open' prices
plt.plot(dates, original_open, color='green', label='Original Open Price')

# plot actual vs predicted
plt.plot(test_dates[seq_len:], testY_original, color='blue', label='Actual Open Price')
plt.plot(test_dates[seq_len:], y_pred, color='red', linestyle='--', label='Predicted Open Price')
plt.xlabel('Date')
plt.ylabel('Open Price')
plt.title('Original, Actual and Predicted Open Price')
plt.legend()
plt.show()

 

 

 

9. 마지막 데이터를 기준으로 10분뒤 가격 예측하기

# 마지막 데이터에 대한 예측을 위한 입력 데이터 준비
last_input = df_scaler[-seq_len:]

# 하나만 예측하므로 배치크기는 1
last_input = last_input.reshape(1, seq_len, input_dim)

# 10분 뒤의 unitPrice 예측
predicted_unitPrice = model.predict(last_input)

# 스케일링을 원래 데이터 범위로 되돌리기
predicted_unitPrice = scaler.inverse_transform(np.array([[predicted_unitPrice[0][0], 0]]))[0][0]

# 예측 결과 출력
print("10분 뒤의 예측된 unitPrice:", predicted_unitPrice)

 

 

 

 

최종적으로 10분 후의 가격을 예측한것을 마리아db에 넣어주자 

만약 해당아이템이 db에 있으면 오버라이팅 해줘야됨

 

0. pvc생성 

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
        name: db-pvc
spec:
        accessModes:
                - ReadWriteMany
        resources:
                requests:
                        storage: 1Gi

 

1. 마리아 db 파드, 외부접속을 위한 서비스 생성

vim mariadb-dp.yaml >>> 디플로이먼트 파드 생성

# Deployment 리소스의 API 버전
apiVersion: apps/v1

# Deployment 리소스를 생성
kind: Deployment

# 이 Deployment 리소스의 이름을 지정
metadata:
  name: mariadb-deployment
  
# Deployment의 세부사항을 정의
spec:
  # 파드를 하나만 복제
  replicas: 1
  
  # 파드를 선택하기 위한 라벨 셀렉터를 지정
  selector:
    matchLabels:
      # app: mariadb 라벨을 가진 파드를 선택
      app: mariadb
      
  # 파드의 템플릿을 정의
  template:
    metadata:
      labels:
        # app: mariadb 라벨이 파드에 적용
        app: mariadb
    # 파드 스펙을 정의
    spec:
      containers:
        - name: mariadb
          # 컨테이너에 사용할 이미지를 지정
          image: mariadb:latest
          # 컨테이너의 환경 변수를 지정
          env:
          	# MariDB의 루트 비밀번호를 1234로 지정
            - name: MYSQL_ROOT_PASSWORD
              value: "1234"
          # 컨테이너가 개방할 포트 정보를 정의
          ports:
            - containerPort: 3306
          volumeMounts:
            - name: db-volume
              mountPath: /usr/share/db
      volumes:
        - name: db-volume
          persistentVolumeClaim:
                  claimName: db-pvc

 

 

vim mariadb-svc-lb.yaml >>> 로드밸런서 서비스 생성

apiVersion: v1
kind: Service
metadata:
  name: mariadb-service
spec:
  selector:
    app: mariadb
  ports:
    - protocol: TCP
      port: 3306  # 서비스가 생성하는 엔드포인트의 포트
      targetPort: 3306  # 실제 MariaDB 파드의 포트

 

파드, 서비스 실행

kubectl create -f mariadb-db.yaml

kubectl create -f mariadb-svc-lb.yaml

kubectl create -f db-pvc.yaml

 

서비스 생성 확인( 외부ip 10.106.151.195 )

 

마리아db 접속해보기

kubectl run mysql-client -it --image=ghcr.io/c1t1d0s7/network-multitool --rm bash

mysql -h 10.109.90.46 -u root -p

 

 

create database donpa_item; >>> 데이터베이스 생성

use donpa_item >>> 데이터 베이스 사용

CREATE TABLE donpa_item1 (     
	item_img TEXT,     
    item_name TEXT,     
    price FLOAT,     
    before_now FLOAT,     
    before_one FLOAT,     
    before_two FLOAT,     
    before_three FLOAT,     
    before_four FLOAT,     
    before_five FLOAT,     
    before_six FLOAT,     
    before_seven FLOAT,     
    before_eight FLOAT,     
    before_nine FLOAT,     
    before_ten FLOAT 
);


# TEXT 데이터 타입은 문자열을 무제한으로 저장할 수 있는 데이터 타입

show tables; >>> 테이블 확인하는 명령어

 

연결확인

import pymysql

# 연결 정보 설정
host = "10.109.90.46"
port = 3306
database = "donpa_item"
user = "root"
password = "1234"

# 연결
connection = pymysql.connect(
    host=host,
    port=port,
    user=user,
    password=password,
    database=database
)


# 연결 성공 여부 확인
if connection:
    print("마리아DB에 연결되었습니다.")