1. 문제
- typeerror: '>' not supported between instances of 'nonetype' and 'int' 오류 발생
세미 프로젝트 진행 중 최종 모델을 pkl 파일로 load해서, streamlit 앱 내에서 작동시키는 작업을 진행하고 있었습니다. 모든 작업을 올바르게 했는데, predict를 실행시키면 위와 같은 오류가 발생하더라고요.
코드는 다음과 같았습니다.
import streamlit as st
import joblib
import numpy as np
import pandas as pd
# 모델 불러오기
model1 = joblib.load("models/gm_model.pkl")
model2 = joblib.load("models/ngm_model.pkl")
# 데이터 프레임 불러오기
df = pd.read_csv('data/전체_수정_streamlit용.csv')
df1 = pd.read_csv('data/골목_streamlit용.csv')
df2 = pd.read_csv('data/비골목_streamlit용.csv')
# main text
st.subheader('🔎 강남구 편의점 매출 예측 서비스 - 상세')
st.markdown('☝️ 좌측 side bar에서 상권/시간대/분기를 선택해주세요!')
st.markdown('✌️ slide를 조정한 후, 예측하기 버튼을 눌러주세요!')
st.markdown('---')
# side bar
with st.sidebar:
# Select market
unique_market = df['상권_코드_명'].unique().tolist()
selected_feature1 = st.selectbox("상권을 선택하세요", unique_market)
# Select time
unique_time = ['시간대1(00 ~ 06)', '시간대2(06 ~ 11)', '시간대3(11 ~ 14)', '시간대4(14 ~ 17)', '시간대5(17 ~ 21)', '시간대6(21 ~ 24)']
selected_feature2 = st.selectbox("시간대를 선택하세요", unique_time)
# Select quarter
unique_quarter = ['1분기', '2분기', '3분기', '4분기']
selected_feature3 = st.selectbox("분기를 선택하세요!", unique_quarter)
## 지도 영역
## 변수 영역
feature_names_gol = df1.iloc[:, 7:].columns.tolist()
feature_names_ngol = df2.iloc[:, 7:].columns.tolist()
# st.write(feature_names_gol)
# st.write(feature_names_ngol)
# 시간대, 분기 제외한 피쳐 slider로 입력
user_input = []
if selected_feature1 in df1['상권_코드_명'].tolist():
for i, feature_name in enumerate(feature_names_gol):
max_value_feature = float(df1[feature_name].max())
min_value_feature = float(df1[feature_name].min())
# 각 피쳐당 22년 평균을 default 값으로 설정
condition = (df1['상권_코드_명'] == selected_feature1) & (df1['기준_년_코드'] == 2022)
value = df1.loc[condition, feature_name]
default_value = value.mean()
#default_value = (max_value_feature + min_value_feature) / 2
user_input.append(st.slider(f"{feature_name}:", min_value=min_value_feature, max_value=max_value_feature, value=default_value))
else:
for i, feature_name in enumerate(feature_names_ngol):
max_value_feature = float(df2[feature_name].max())
min_value_feature = float(df2[feature_name].min())
# 각 피쳐당 22년 평균을 default 값으로 설정
condition = (df2['상권_코드_명'] == selected_feature1) & (df2['기준_년_코드'] == 2022)
value = df2.loc[condition, feature_name]
default_value = value.mean()
user_input.append(st.slider(f"{feature_name}:", min_value=min_value_feature, max_value=max_value_feature, value=default_value))
# ----------------------------------------------------- 시간대, 분기 값 리스트의 앞에 넣기------------------------------------------------------
# 초기식
time1, time2, time3, time4, time5, quarter1, quarter2, quarter3 = 0, 0, 0, 0, 0, 0, 0, 0
if selected_feature2 == unique_time[0]:
time1 = 1
time2 = 0
time3 = 0
time4 = 0
time5 = 0
elif selected_feature2 == unique_time[1]:
time1 = 0
time2 = 1
time3 = 0
time4 = 0
time5 = 0
elif selected_feature2 == unique_time[2]:
time1 = 0
time2 = 0
time3 = 1
time4 = 0
time5 = 0
elif selected_feature2 == unique_time[3]:
time1 = 0
time2 = 0
time3 = 0
time4 = 1
time5 = 0
elif selected_feature2 == unique_time[4]:
time1 = 0
time2 = 0
time3 = 0
time4 = 0
time5 = 1
else:
time1 = 0
time2 = 0
time3 = 0
time4 = 0
time5 = 0
if selected_feature3 == unique_quarter[0]:
quarter1 = 1
quarter2 = 0
quarter3 = 0
elif selected_feature3 == unique_quarter[1]:
quarter1 = 0
quarter2 = 1
quarter3 = 0
elif selected_feature3 == unique_quarter[2]:
quarter1 = 0
quarter2 = 0
quarter3 = 1
else :
quarter1 = 0
quarter2 = 0
quarter3 = 0
user_input[:0] = [time1, time2, time3, time4, time5, quarter1, quarter2, quarter3]
# 문자열 데이터를 숫자로 변환
numeric_user_input = []
for value in user_input:
try:
numeric_value = float(value)
numeric_user_input.append(numeric_value)
# 예외처리
except ValueError:
st.error(f"입력값 '{value}'은(는) 숫자로 변환할 수 없습니다.")
# 예측
if st.button("예측하기"):
# 입력 데이터를 2D 배열로 변환 - 골목상권, 비골목상권의 피쳐 개수 만큼
if selected_feature1 in df1['상권_코드_명'].tolist():
if len(numeric_user_input) == len(feature_names_gol) + 8:
numeric_user_input = np.array(numeric_user_input).reshape(1, -1)
predictions = model1.predict(numeric_user_input)
# 예측 결과 출력
if predictions is not None:
st.subheader('예측 결과')
st.write(f"{selected_feature1}의 {selected_feature3} {selected_feature2} 예상 매출은 {predictions[0]:,.0f}원입니다.")
else:
if len(numeric_user_input) == len(feature_names_ngol) + 8:
numeric_user_input = np.array(numeric_user_input).reshape(1, -1)
predictions = model2.predict(numeric_user_input)
# 예측 결과 출력
if predictions is not None:
st.subheader('예측 결과')
st.write(f"{selected_feature1}의 {selected_feature3} {selected_feature2} 예상 매출은 {predictions[0]:,.0f}원입니다.")
코드를 직접적으로 해석했을 때 제가 넣은 feature중에 None값이 있다는 것인데, 아무리 검사해봐도 전부 float형태로 잘 되어있었습니다.. 이 오류로 인해 5일을 넘게 추가 작업을 못했고, 마땅한 해결책도 찾을 수 없었습니다.(구글링, GPT 모두 검색..)
2. 해결책
문제는 최종 모델 파일에 있었습니다. 저와 함께 작업한 분이 mac
을 사용하시는데, pkl 파일을 그 분께 받아서 사용했었습니다. 혹시 호환에 문제가 있을까 싶어서, 모델링 코드를 직접 받아서 pkl파일을 추출해서 사용했더니, 해결되었습니다. 파일용량도 같아서 이것도 해결이 안되지 않을까 싶었는데.. 감동의 눈물을 흘렸습니다. 혹시 저와 같은 오류를 겪으시는 분이 계신다면, pkl파일 한 번 확인해보시고, mac유저와 같이 협업하신다면 협업과정에서 문제가 있을 확률이 높으니 확인해보세요 ㅠ
'공부 > Data Analysis' 카테고리의 다른 글
[python/visualization] Streamlit을 활용한 데이터 시각화 1 (0) | 2023.09.21 |
---|---|
[Python/ML] Category Feature의 Encoding 방법 (0) | 2023.09.13 |
[Python/crawling]BeautifulSoap를 활용한 크롤링 정리 (0) | 2023.08.10 |