import streamlit as st
import pandas as pd
import numpy as np
import time
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
import plotly.express as px
st.title("☕ あなたにぴったりのメニュー診断 (ランダムフォレスト分類)")
## 改善案, plot改善
## アンケート→制度改善に役立てられます
## 管理画面機能
## ランダムフォレストの結果の可視化
##
# --- メニューの特徴データ(教師ありラベル付き) ---
menu_data = pd.DataFrame({
"メニュー": ["コーヒー", "エスプレッソ", "キャラメルマキアート", "カフェラテ", "モカ", "アメリカーノ", "マキアート"],
"苦味": [3, 5, 2, 2, 4, 3, 5],
"香り": [4, 5, 3, 4, 5, 3, 5],
"酸味": [2, 1, 4, 3, 2, 3, 1],
"種別": ["メニュー"] * 7
})
# --- 入力フォーム ---
with st.form("form"):
st.subheader("あなたのコーヒーの好みを教えてください")
bitterness = st.slider("苦味の強さが好き", 0, 5, 3)
aroma = st.slider("香りの強さが好き", 0, 5, 3)
acidity = st.slider("酸味の強さが好き", 0, 5, 3)
submitted = st.form_submit_button("診断する")
if submitted:
with st.spinner("あなたの味覚をAIが分析中... ☕️🔍"):
time.sleep(2)
# あなたのデータ
user_data = pd.DataFrame([{
"メニュー": "あなた",
"苦味": bitterness,
"香り": aroma,
"酸味": acidity,
"種別": "あなた"
}])
# ダミーデータ(過去の回答者)
np.random.seed(42)
dummy_data = pd.DataFrame({
"メニュー": [f"回答者{i+1}" for i in range(30)],
"苦味": np.random.randint(0, 6, 30),
"香り": np.random.randint(0, 6, 30),
"酸味": np.random.randint(0, 6, 30),
"種別": ["回答者"] * 30
})
# 結合
full_data = pd.concat([menu_data, dummy_data, user_data], ignore_index=True)
# 特徴量
X_train = menu_data[["苦味", "香り", "酸味"]]
y_train = menu_data["メニュー"]
# 学習
clf = RandomForestClassifier(random_state=0)
clf.fit(X_train, y_train)
# あなたのデータから予測
X_user = user_data[["苦味", "香り", "酸味"]]
y_pred = clf.predict(X_user)[0]
# full_data に「分類されたラベル」列を追加(可視化用)
full_data["予測メニュー"] = "未分類"
full_data.loc[full_data["種別"] == "あなた", "予測メニュー"] = y_pred
full_data.loc[full_data["種別"] == "メニュー", "予測メニュー"] = full_data["メニュー"]
# --- 3Dプロット(クラスタではなく予測メニューで色分け)---
fig = px.scatter_3d(
full_data,
x="苦味", y="香り", z="酸味",
color="予測メニュー",
size=[15 if m == "あなた" else 8 for m in full_data["メニュー"]],
title="☕ 3D分類結果:あなたとメニュー、他ユーザーの分布"
)
fig.update_layout(
scene=dict(
xaxis_title="苦味",
yaxis_title="香り",
zaxis_title="酸味"
),
margin=dict(l=0, r=0, b=0, t=40),
height=800
)
st.plotly_chart(fig, use_container_width=True)
# --- おすすめ表示 ---
st.success(f"🎯 あなたにおすすめのメニューは **{y_pred}** です!")