본문 바로가기
IT - 코딩/AI, 예측모델

전력 사용량 예측

by 조기정 2023. 8. 7.

전체 코드

# pip install koreanize_matplotlib # @ 한글 깨짐 방지
import math #math 모듈을 먼저 import해야 한다.    
import matplotlib.pyplot as plt
import koreanize_matplotlib
# import seaborn as sns

    # 데이터 프레임 모든 컬럼 그리기
    # 함수명으로도 정의하기
def columns_plot(data): # y좌표
    
#     col_list_plt = list(data.select_dtypes(exclude = "object").columns)
    col_list_plt = list(data.select_dtypes(include = ["float","int"]).columns)
    x_plt_n = 3 # 한번에 그릴 plt x 축 수
    y_plt_n = 4 # 한번에 그릴 plt y 축 수
    w_space = 0.2 # float("0."+str(x_plt_n)
    h_space = 0.2 # float("0."+str(y_plt_n)
    
    if (x_plt_n < math.ceil(len(col_list_plt) / y_plt_n)):
        x_plt_n = math.ceil(len(col_list_plt) / y_plt_n)

    #plot 이쁘게 
    f, axes = plt.subplots(x_plt_n, y_plt_n)
    f.set_size_inches((20, 15))
    plt.subplots_adjust(wspace = w_space, hspace = h_space)

    for i in range(len(col_list_plt)):

        bb = math.ceil(((i )// y_plt_n))
        axes[bb][i - math.ceil(((i )// y_plt_n)) * y_plt_n].plot(data[col_list_plt[i]],label = col_list_plt[i] )#, color = 'blue', marker = 'o')
        axes[bb][i - math.ceil(((i )// y_plt_n)) * y_plt_n].set_title(col_list_plt[i])
    plt.rc('font', family='Malgun Gothic')
    plt.show()
    
    
import pandas as pd

import os

os.getcwd()
path = os.getcwd()  # 주피터 노트북 파일 경로
os_file_list = os.listdir(path)  # 내 경로 읽어서 파일 리스트 읽음
# print(os_file_list)  # 경로에 있는 파일 리스트


from tqdm import tqdm

os_file_list = ['data']
All_data = {}
# 모든 csv 파일 한번에 불러옴
for i in range(len(os_file_list)):
    print(os_file_list[i])
    
    os_file_list_1 = os.listdir(path+"\\"+os_file_list[i])
    import pandas as pd
    
    for j in range(len(os_file_list_1)):
        All_data[os_file_list_1[j][:-4]] = pd.read_csv(path+"\\"+os_file_list[i]+"\\"+os_file_list_1[j],)
#         All_data[os_file_list_1[j][:-4]].set_index("index",inplace = True)

def time_set(A_col_name):
#     A_col_name = "train"
    for i in tqdm(range(len(All_data[A_col_name]))):
        aa = All_data[A_col_name]["num_date_time"][i].split("_")[1]
        All_data[A_col_name]["num_date_time"][i] = aa[:4] +"-"+aa[4:6] +"-"+ aa[6:8] +"-"+ aa[9:]
    return All_data[A_col_name]
    
All_data["train"] = time_set("train")
All_data["test"] = time_set("test")


All_data["train"]["num_date_time"] = pd.to_datetime(All_data["train"]["num_date_time"])
All_data["test"]["num_date_time"] = pd.to_datetime(All_data["test"]["num_date_time"])

def val_table_set(df):
    df["건물유형"] = None
    df["연면적(m2)"] = None
    df["냉방면적(m2)"] = None
    
    for i in tqdm(range(len(df))):
        a = All_data["building_info"].loc[df["건물번호"][i] == All_data["building_info"]["건물번호"]]

        df["건물유형"][i] = a["건물유형"].iloc[0]
        df["연면적(m2)"][i] = a["연면적(m2)"].iloc[0]
        df["냉방면적(m2)"][i] = a["냉방면적(m2)"].iloc[0]
    return df
    
    
All_data["train"] = val_table_set(All_data["train"])
All_data["test"] = val_table_set(All_data["test"])

All_data["train"].to_csv("train1.csv",index = False)
All_data["test"].to_csv("test1.csv",index = False)

# 맞추어야 하는 컬럼명 저장
train_columns = list(All_data["train"].columns)
test_columns = list(All_data["test"].columns)

target_col = list(set(train_columns) - set(test_columns))

target_col = ["전력소비량(kWh)"]

#타겟 데이터 따로 저장
target_data = All_data["train"][target_col]
train_data_len = len(All_data["train"])

X_all = pd.concat([All_data["train"],All_data["test"]],axis = 0)
X_all["day_of_week"] = X_all["num_date_time"].dt.day_of_week

X_all["연면적(m2)"] = X_all["연면적(m2)"].astype('float')
X_all["냉방면적(m2)"] = X_all["냉방면적(m2)"].astype('float')

del X_all["일시"]
all_col = list(X_all.columns)
# y_col = [""] 
un_use_col = target_col # @ 여기에 y컬럼도 추가해줘야함.
use_col = [_ for _ in all_col if (_ in un_use_col)==False]

X_all = pd.get_dummies(X_all[use_col],dummy_na= False,drop_first = True)
X_all = X_all.drop(["강수량(mm)","일조(hr)","일사(MJ/m2)","num_date_time"], axis = 1)

from sklearn.preprocessing import MinMaxScaler,PowerTransformer,LabelEncoder,StandardScaler

# 이부분 class로 변환할까? 나중에 정해진 범위까지만 데이터 스케일링 할 수도 있음.
# def MinMaxScaler_fun(df): #맞춤 변환 함수와 그에 맞는 데이터를 돌려줌
#     col = list(df.columns)
#     Scaler = MinMaxScaler()
#     Scaler.fit(df)
#     df = Scaler.transform(df)
# #     df = Scaler_X.fit_transform(df)
#     df = pd.DataFrame(df, columns = X_col)
#     return df, Scaler
# X_data ,Scaler = MinMaxScaler_fun(X_data)
# Y_data , Y_data_Scaler = MinMaxScaler_fun(Y_data)

X_col = list(X_all.columns)

Scaler = MinMaxScaler()

#     df = Scaler_X.fit_transform(df)
X_all = pd.DataFrame(X_all, columns = X_col)
X_train = X_all[:train_data_len]
X_test = X_all[train_data_len:]


import numpy as np
# a = int(np.floor(train_data_len/10))
# a = train_data_len - a

# x_train_1 = x_train[:a]
# x_val_1 = x_train[a:]

# print(x_train_1.index)
# print(x_val_1.index)

# y_train_1 = y_train[:a]
# y_val_1 = y_train[a:]

#여기서 모델 선정
from sklearn.svm import SVC
from sklearn.ensemble import HistGradientBoostingRegressor
from sklearn.ensemble import RandomForestRegressor
from xgboost import XGBRFRegressor
model = XGBRFRegressor()
model.fit(X_train,y_train[target_col]) # 벨류셋 가능
All_data["sample_submission"]["answer"] = model.predict(x_test)

pd.DataFrame(All_data["sample_submission"]).to_csv("전력 사용량 예측.csv",index = False)
pd.read_csv("전력 사용량 예측.csv")

def time_set(A_col_name):
#     A_col_name = "train"
    for i in tqdm(range(len(All_data[A_col_name]))):
        aa = All_data[A_col_name]["num_date_time"][i].split("_")[1]
        All_data[A_col_name]["num_date_time"][i] = aa[:4] +"-"+aa[4:6] +"-"+ aa[6:8] +"-"+ aa[9:]
    return All_data[A_col_name]
    
All_data["train"] = time_set("train")
All_data["test"] = time_set("test")

먼저 데이터프레임의 시간순서를 맞추기 위해 이런식으로 시간 부분을 전처리 하였습니다

All_data["train"]["num_date_time"] = pd.to_datetime(All_data["train"]["num_date_time"])
All_data["test"]["num_date_time"] = pd.to_datetime(All_data["test"]["num_date_time"])
def val_table_set(df):
    df["건물유형"] = None
    df["연면적(m2)"] = None
    df["냉방면적(m2)"] = None
    
    for i in tqdm(range(len(df))):
        a = All_data["building_info"].loc[df["건물번호"][i] == All_data["building_info"]["건물번호"]]

        df["건물유형"][i] = a["건물유형"].iloc[0]
        df["연면적(m2)"][i] = a["연면적(m2)"].iloc[0]
        df["냉방면적(m2)"][i] = a["냉방면적(m2)"].iloc[0]
    return df
    
    
All_data["train"] = val_table_set(All_data["train"])
All_data["test"] = val_table_set(All_data["test"])

All_data["train"].to_csv("train1.csv",index = False)
All_data["test"].to_csv("test1.csv",index = False)

건물 유형에 따른 건물마다 특징이 저장되어 있는 building_info 의 테이블과 매칭시킵니다.

 

# 맞추어야 하는 컬럼명 저장
train_columns = list(All_data["train"].columns)
test_columns = list(All_data["test"].columns)

target_col = list(set(train_columns) - set(test_columns))

target_col = ["전력소비량(kWh)"]

#타겟 데이터 따로 저장
target_data = All_data["train"][target_col]
train_data_len = len(All_data["train"])

train데이터를 가지고 수정!

X_all = pd.concat([All_data["train"],All_data["test"]],axis = 0)
X_all["day_of_week"] = X_all["num_date_time"].dt.day_of_week

X_all["연면적(m2)"] = X_all["연면적(m2)"].astype('float')
X_all["냉방면적(m2)"] = X_all["냉방면적(m2)"].astype('float')

del X_all["일시"]
all_col = list(X_all.columns)
# y_col = [""] 
un_use_col = target_col # @ 여기에 y컬럼도 추가해줘야함.
use_col = [_ for _ in all_col if (_ in un_use_col)==False]

X_all = pd.get_dummies(X_all[use_col],dummy_na= False,drop_first = True)
X_all = X_all.drop(["강수량(mm)","일조(hr)","일사(MJ/m2)","num_date_time"], axis = 1)

X_all 에 저장해서 번에 전처리 합니다.

.NA값이 너무 많은 컬럼은 드롭해서 우선 갑니다.

from sklearn.preprocessing import MinMaxScaler,PowerTransformer,LabelEncoder,StandardScaler

# 이부분 class로 변환할까? 나중에 정해진 범위까지만 데이터 스케일링 할 수도 있음.
# def MinMaxScaler_fun(df): #맞춤 변환 함수와 그에 맞는 데이터를 돌려줌
#     col = list(df.columns)
#     Scaler = MinMaxScaler()
#     Scaler.fit(df)
#     df = Scaler.transform(df)
# #     df = Scaler_X.fit_transform(df)
#     df = pd.DataFrame(df, columns = X_col)
#     return df, Scaler
# X_data ,Scaler = MinMaxScaler_fun(X_data)
# Y_data , Y_data_Scaler = MinMaxScaler_fun(Y_data)

X_col = list(X_all.columns)

Scaler = MinMaxScaler()

#     df = Scaler_X.fit_transform(df)
X_all = pd.DataFrame(X_all, columns = X_col)
X_train = X_all[:train_data_len]
X_test = X_all[train_data_len:]

Min,Max로 정규화 한 이후 다시 X_all을 나누어 줍니다.

 

import numpy as np
# a = int(np.floor(train_data_len/10))
# a = train_data_len - a

# x_train_1 = x_train[:a]
# x_val_1 = x_train[a:]

# print(x_train_1.index)
# print(x_val_1.index)

# y_train_1 = y_train[:a]
# y_val_1 = y_train[a:]

#여기서 모델 선정
from sklearn.svm import SVC
from sklearn.ensemble import HistGradientBoostingRegressor
from sklearn.ensemble import RandomForestRegressor
from xgboost import XGBRFRegressor
model = XGBRFRegressor()
model.fit(X_train,y_train[target_col]) # 벨류셋 가능
All_data["sample_submission"]["answer"] = model.predict(x_test)

pd.DataFrame(All_data["sample_submission"]).to_csv("전력 사용량 예측.csv",index = False)
pd.read_csv("전력 사용량 예측.csv")

여러가지 모델중 XGBOOST를 먼저 사용해보았습니다.

날짜 데이터를 추가해서 하니 0.5 점 정도로 개선되었습니다.