Spaces:
Sleeping
Sleeping
File size: 8,110 Bytes
a582ede | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | import streamlit as st
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error
from mp_api.client import MPRester
import time
from matminer.featurizers.conversions import StrToComposition
from matminer.featurizers.composition import ElementProperty
import plotly.express as px
import plotly.graph_objects as go
# 请替换为你自己的 Material Project API 密钥
API_KEY = "bLi1JNyQysy3R4OdR9DZYj1beCkK1mru"
# 从 Material Project 爬取数据
def fetch_materials_data(elements, num_data):
try:
with MPRester(API_KEY) as mpr:
progress_bar = st.progress(0)
status_text = st.empty()
if num_data == "全部":
all_docs = []
chunk_size = 1000
offset = 0
while True:
docs = mpr.materials.summary.search(elements=elements, num_chunks=chunk_size, offset=offset)
if not docs:
break
all_docs.extend(docs)
offset += chunk_size
else:
num_data = int(num_data)
all_docs = mpr.materials.summary.search(elements=elements, num_chunks=num_data)
# 手动筛选数据
if num_data != "全部":
all_docs = all_docs[:num_data]
total_docs = len(all_docs)
data = []
for i, doc in enumerate(all_docs):
entry = {
"formula": doc.formula_pretty,
"energy_per_atom": doc.energy_per_atom,
"formation_energy_per_atom": doc.formation_energy_per_atom,
"band_gap": doc.band_gap
}
data.append(entry)
progress = (i + 1) / total_docs
progress_bar.progress(progress)
status_text.text(f"正在搜索材料数据: {int(progress * 100)}%")
status_text.text("材料数据搜索完成!")
df = pd.DataFrame(data)
return df
except Exception as e:
st.error(f"在从 Material Project 获取数据时发生错误: {e}")
return pd.DataFrame()
# 处理 formula 转换为特征值
def convert_formula_to_features(data):
if 'formula' in data.columns:
st.write("正在将 formula 转换为特征值...")
# 将字符串化学式转换为 Composition 对象
stc = StrToComposition()
data = stc.featurize_dataframe(data, "formula")
# 添加元素属性特征
ep_feat = ElementProperty.from_preset(preset_name="magpie")
data = ep_feat.featurize_dataframe(data, col_id="composition")
st.write("formula 转换为特征值完成。")
return data
# 模拟自动机器学习功能
def auto_ml_function(data, predict_variable):
if data.empty:
st.warning("未获取到有效数据,请检查输入的元素。")
return None, None, None
try:
# 筛选出数值列
numeric_columns = data.select_dtypes(include=['number']).columns
if predict_variable not in numeric_columns:
st.error(f"需要预测值 {predict_variable} 不是数值类型,请重新选择。")
return None, None, None
X = data[numeric_columns.drop(predict_variable)]
y = data[predict_variable]
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 机器学习进度条
progress_bar = st.progress(0)
status_text = st.empty()
model = RandomForestRegressor()
# 模拟训练进度
for i in range(100):
time.sleep(0.01)
progress_bar.progress(i + 1)
status_text.text(f"模型训练中: {i + 1}%")
status_text.text("模型训练完成!")
progress_bar.empty()
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
rmse = mse ** 0.5
return rmse, y_test, y_pred, model.feature_importances_, X.columns
except Exception as e:
st.error(f"模型训练过程中出现错误: {e}")
return None, None, None
def main():
# 初始化会话状态
if 'step' not in st.session_state:
st.session_state.step = 1
if 'elements' not in st.session_state:
st.session_state.elements = []
if 'data' not in st.session_state:
st.session_state.data = pd.DataFrame()
if 'predict_variable' not in st.session_state:
st.session_state.predict_variable = None
if 'num_data' not in st.session_state:
st.session_state.num_data = "100"
st.title("自动机器学习演示")
st.markdown("此应用允许你输入材料元素名字,从 Material Project 爬取数据,运行自动机器学习模型,并查看模型的准确率。")
if st.session_state.step == 1:
# 用户输入材料元素名字
elements_input = st.text_input("输入想要计算的材料元素名字,用逗号分隔(例如:Fe,O)",
','.join(st.session_state.elements))
st.session_state.elements = [element.strip() for element in elements_input.split(",") if element.strip()]
# 用户选择提取的数据量
st.session_state.num_data = st.selectbox("选择提取的数据量", ["100", "200", "500", "全部"])
if st.session_state.elements:
if st.button("从 Material Project 爬取数据"):
st.session_state.step = 2
if st.session_state.step == 2:
with st.spinner("正在从 Material Project 爬取数据..."):
st.session_state.data = fetch_materials_data(st.session_state.elements, st.session_state.num_data)
if not st.session_state.data.empty:
# 转换 formula 为特征值
st.session_state.data = convert_formula_to_features(st.session_state.data)
st.write("数据基本信息:")
st.session_state.data.info()
st.write("数据前几行信息:")
st.dataframe(st.session_state.data.head())
# 选择需要预测值
numeric_columns = st.session_state.data.select_dtypes(include=['number']).columns
st.session_state.predict_variable = st.selectbox("选择需要预测值", numeric_columns)
if st.session_state.predict_variable:
if st.button("运行自动机器学习"):
st.session_state.step = 3
if st.session_state.step == 3:
rmse, y_test, y_pred, feature_importances, feature_names = auto_ml_function(st.session_state.data,
st.session_state.predict_variable)
if rmse is not None:
st.write("自动机器学习模型均方根误差:")
st.metric(label="均方根误差", value=f"{rmse:.2f}")
# 绘制预测值与真实值的散点图
fig1 = px.scatter(x=y_test, y=y_pred, labels={'x': '真实值', 'y': '预测值'},
title='预测值与真实值的散点图')
fig1.add_trace(go.Scatter(x=[y_test.min(), y_test.max()], y=[y_test.min(), y_test.max()],
mode='lines', name='完美预测线'))
st.plotly_chart(fig1)
# 绘制特征重要性柱状图
feature_importance_df = pd.DataFrame({
'特征': feature_names,
'重要性': feature_importances
})
feature_importance_df = feature_importance_df.sort_values(by='重要性', ascending=False)
fig2 = px.bar(feature_importance_df, x='特征', y='重要性', title='特征重要性柱状图')
st.plotly_chart(fig2)
st.session_state.step = 1 # 完成后回到第一步
if __name__ == "__main__":
main()
|