使用 Flask 規劃 AutoML 的完整網頁應用指南
打造一個全方位的自動化機器學習平台,從專案管理到模型訓練的全面解決方案
三大重點
- 全面的專案與數據管理功能:提供用戶友好的介面來管理機器學習專案和數據集。
- 完整的模型建立流程:涵蓋數據前處理、補值、特徵萃取、模型選擇、模型評估及重訓等。
- 模型列表與訓練隊列:方便用戶查看已訓練的模型並管理訓練任務。
一、專案結構規劃
首先,我們需要規劃專案的目錄結構,以確保應用程式的組織性和可維護性。以下是一個推薦的專案結構:
automl_flask/
│
├── app/
│ ├── __init__.py
│ ├── models/
│ │ ├── __init__.py
│ │ ├── project.py
│ │ ├── dataset.py
│ │ └── model.py
│ ├── services/
│ │ ├── __init__.py
│ │ ├── data_processor.py
│ │ ├── feature_extractor.py
│ │ └── model_trainer.py
│ ├── views/
│ │ ├── __init__.py
│ │ ├── project.py
│ │ ├── dataset.py
│ │ └── model.py
│ ├── templates/
│ │ ├── base.html
│ │ ├── projects/
│ │ │ ├── list.html
│ │ │ └── create.html
│ │ ├── datasets/
│ │ │ └── manage.html
│ │ └── models/
│ │ ├── list.html
│ │ └── training.html
│ └── static/
│ ├── css/
│ └── js/
│
├── requirements.txt
├── config.py
├── run.py
├── celery_config.py
└── README.md
二、安裝必要的依賴套件
在requirements.txt中列出所有需要的 Python 套件:
Flask==3.0.0
Flask-SQLAlchemy==3.0.0
pandas==2.0.0
scikit-learn==1.3.0
joblib==1.3.0
TPOT==0.12.0
h2o==3.40.0.1
Celery==5.2.7
redis==4.5.5
使用以下指令安裝依賴套件:
pip install -r requirements.txt
三、配置 Flask 應用程式
1. 初始化 Flask 和資料庫
在 app/__init__.py 中初始化 Flask 應用程式和 SQLAlchemy 資料庫:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import Config
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app)
from app.views import project, dataset, model
app.register_blueprint(project.bp)
app.register_blueprint(dataset.bp)
app.register_blueprint(model.bp)
return app
2. 設定檔案
在 config.py 中定義配置參數:
import os
class Config:
SECRET_KEY = 'your-secret-key'
SQLALCHEMY_DATABASE_URI = 'sqlite:///automl.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
UPLOAD_FOLDER = 'uploads'
ALLOWED_EXTENSIONS = {'csv', 'xlsx'}
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
3. 啟動應用程式
在 run.py 中啟動 Flask 應用程式:
from app import create_app, db
from flask_migrate import Migrate
app = create_app()
migrate = Migrate(app, db)
if __name__ == '__main__':
app.run(debug=True)
四、定義資料庫模型
在 app/models 目錄下定義專案管理、數據集和模型的資料庫模型。
1. 專案模型
在 app/models/project.py 中定義專案模型:
from app import db
from datetime import datetime
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
datasets = db.relationship('Dataset', backref='project', lazy=True)
models = db.relationship('Model', backref='project', lazy=True)
2. 數據集模型
在 app/models/dataset.py 中定義數據集模型:
from app import db
class Dataset(db.Model):
id = db.Column(db.Integer, primary_key=True)
project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False)
file_path = db.Column(db.String(100), nullable=False)
uploaded_at = db.Column(db.DateTime, default=datetime.utcnow)
3. 模型模型
在 app/models/model.py 中定義模型模型:
from app import db
class Model(db.Model):
id = db.Column(db.Integer, primary_key=True)
project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False)
model_info = db.Column(db.String(100), nullable=False)
accuracy = db.Column(db.Float, nullable=True)
trained_at = db.Column(db.DateTime, default=datetime.utcnow)
五、建立服務層
在 app/services 目錄下建立數據處理、特徵萃取和模型訓練的服務。
1. 數據處理器
在 app/services/data_processor.py 中定義數據處理器:
import pandas as pd
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
class DataProcessor:
def __init__(self):
self.imputer = SimpleImputer(strategy='mean')
self.scaler = StandardScaler()
def preprocess_data(self, df):
# 數據清理
df = df.dropna(how='all')
# 缺失值處理
numerical_columns = df.select_dtypes(include=['float64', 'int64']).columns
df[numerical_columns] = self.imputer.fit_transform(df[numerical_columns])
# 特徵標準化
df[numerical_columns] = self.scaler.fit_transform(df[numerical_columns])
return df
2. 特徵萃取器
在 app/services/feature_extractor.py 中定義特徵萃取器:
from sklearn.feature_selection import SelectKBest, f_classif
class FeatureExtractor:
def __init__(self, k=10):
self.selector = SelectKBest(score_func=f_classif, k=k)
def extract_features(self, X, y):
X_new = self.selector.fit_transform(X, y)
return X_new, self.selector.get_support(indices=True)
3. 模型訓練器
在 app/services/model_trainer.py 中定義模型訓練器:
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from tpot import TPOTClassifier
from h2o.automl import H2OAutoML
import joblib
class ModelTrainer:
def __init__(self):
self.models = {
'random_forest': RandomForestClassifier(),
'tpot': TPOTClassifier(generations=5, population_size=20, verbosity=2),
'h2o_automl': H2OAutoML(max_models=20, seed=1)
}
def train_model(self, X, y, model_name):
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
if model_name == 'h2o_automl':
import h2o
h2o.init()
train = h2o.H2OFrame(pd.concat([X_train, y_train], axis=1))
aml = self.models[model_name]
aml.train(y=y_train.name, training_frame=train)
model = aml.leader
y_pred = model.predict(train).as_data_frame()['predict']
accuracy = accuracy_score(y_test, y_pred)
h2o.shutdown(prompt=False)
else:
model = self.models[model_name]
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
return model, accuracy
def save_model(self, model, filename):
joblib.dump(model, filename)
六、建立視圖與路由
在 app/views 目錄下建立專案管理、數據管理和模型管理的視圖。
1. 專案管理視圖
在 app/views/project.py 中定義專案管理的路由:
from flask import Blueprint, render_template, request, redirect, url_for, flash
from app.models.project import Project
from app import db
bp = Blueprint('project', __name__)
@bp.route('/projects')
def list_projects():
projects = Project.query.all()
return render_template('projects/list.html', projects=projects)
@bp.route('/projects/create', methods=['GET', 'POST'])
def create_project():
if request.method == 'POST':
name = request.form['name']
description = request.form['description']
project = Project(name=name, description=description)
db.session.add(project)
db.session.commit()
flash('專案創建成功!', 'success')
return redirect(url_for('project.list_projects'))
return render_template('projects/create.html')
2. 數據管理視圖
在 app/views/dataset.py 中定義數據管理的路由:
import os
from flask import Blueprint, render_template, request, redirect, url_for, flash
from app.models.dataset import Dataset
from app import db
from app.services.data_processor import DataProcessor
bp = Blueprint('dataset', __name__)
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in {'csv', 'xlsx'}
@bp.route('/datasets', methods=['GET', 'POST'])
def manage_datasets():
if request.method == 'POST':
project_id = request.form['project_id']
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
filepath = os.path.join(current_app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
dataset = Dataset(project_id=project_id, file_path=filepath)
db.session.add(dataset)
db.session.commit()
flash('數據集上傳成功!', 'success')
return redirect(url_for('dataset.manage_datasets'))
else:
flash('無效的文件類型!', 'error')
projects = Project.query.all()
datasets = Dataset.query.all()
return render_template('datasets/manage.html', projects=projects, datasets=datasets)
3. 模型管理視圖
在 app/views/model.py 中定義模型管理的路由:
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
from app.models.model import Model
from app.models.dataset import Dataset
from app.models.project import Project
from app.services.model_trainer import ModelTrainer
from app import db
from celery_config import celery
import os
bp = Blueprint('model', __name__)
trainer = ModelTrainer()
@bp.route('/models', methods=['GET'])
def list_models():
models = Model.query.all()
return render_template('models/list.html', models=models)
@bp.route('/models/train', methods=['POST'])
def train_model():
data = request.json
project_id = data.get('project_id')
dataset_id = data.get('dataset_id')
target_column = data.get('target_column')
model_type = data.get('model_type')
task = train_model_task.delay(dataset_id, model_type, target_column)
return jsonify({'task_id': task.id}), 202
@celery.task
def train_model_task(dataset_id, model_type, target_column):
dataset = Dataset.query.get(dataset_id)
df = pd.read_csv(dataset.file_path)
processor = DataProcessor()
df_processed = processor.preprocess_data(df)
X = df_processed.drop(columns=[target_column])
y = df_processed[target_column]
model, accuracy = trainer.train_model(X, y, model_type)
model_filename = f"model_{dataset_id}_{model_type}.pkl"
model_path = os.path.join('models_trained', model_filename)
trainer.save_model(model, model_path)
new_model = Model(project_id=dataset.project_id, model_info=model_type, accuracy=accuracy, trained_at=datetime.utcnow())
db.session.add(new_model)
db.session.commit()
return {'model_path': model_path, 'accuracy': accuracy}
七、前端模板設計
在 app/templates 目錄下建立 HTML 模板,提供用戶界面。
1. 基礎模板
在 app/templates/base.html 中定義基礎模板:
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<title>AutoML 系統</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<header>
<h1>AutoML 系統</h1>
<nav>
<ul>
<li><span style="opacity: 0.2">專案管理</span></li>
<li><span style="opacity: 0.2">數據管理</span></li>
<li><span style="opacity: 0.2">模型管理</span></li>
</ul>
</nav>
</header>
<main>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul class="flashes">
{% for category, message in messages %}
<li class="{{ category }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</main>
<footer>
<p>© 2025 AutoML 系統</p>
</footer>
</body>
</html>
2. 專案列表模板
在 app/templates/projects/list.html 中定義專案列表頁面:
{% extends 'base.html' %}
{% block content %}
<h2>專案列表</h2>
<span style="opacity: 0.2">新增專案</span>
<table>
<tr>
<th>ID</th>
<th>名稱</th>
<th>描述</th>
<th>建立時間</th>
</tr>
{% for project in projects %}
<tr>
<td>{{ project.id }}</td>
<td>{{ project.name }}</td>
<td>{{ project.description }}</td>
<td>{{ project.created_at }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
3. 新增專案模板
在 app/templates/projects/create.html 中定義新增專案頁面:
{% extends 'base.html' %}
{% block content %}
<h2>新增專案</h2>
<form method="POST">
<label for="name">專案名稱:</label>
<input type="text" id="name" name="name" required>
<br>
<label for="description">專案描述:</label>
<textarea id="description" name="description"></textarea>
<br>
<button type="submit">創建專案</button>
</form>
{% endblock %}
4. 數據管理模板
在 app/templates/datasets/manage.html 中定義數據管理頁面:
{% extends 'base.html' %}
{% block content %}
<h2>數據管理</h2>
<form method="POST" enctype="multipart/form-data">
<label for="project_id">選擇專案:</label>
<select name="project_id" id="project_id">
{% for project in projects %}
<option value="{{ project.id }}">{{ project.name }}</option>
{% endfor %}
</select>
<br>
<label for="file">上傳數據文件:</label>
<input type="file" id="file" name="file" required>
<br>
<button type="submit">上傳數據</button>
</form>
<h3>已上傳的數據集</h3>
<table>
<tr>
<th>ID</th>
<th>專案ID</th>
<th>文件路徑</th>
<th>上傳時間</th>
</tr>
{% for dataset in datasets %}
<tr>
<td>{{ dataset.id }}</td>
<td>{{ dataset.project_id }}</td>
<td>{{ dataset.file_path }}</td>
<td>{{ dataset.uploaded_at }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
5. 模型列表模板
在 app/templates/models/list.html 中定義模型列表頁面:
{% extends 'base.html' %}
{% block content %}
<h2>模型列表</h2>
<table>
<tr>
<th>ID</th>
<th>專案ID</th>
<th>模型類型</th>
<th>準確率</th>
<th>訓練時間</th>
</tr>
{% for model in models %}
<tr>
<td>{{ model.id }}</td>
<td>{{ model.project_id }}</td>
<td>{{ model.model_info }}</td>
<td>{{ model.accuracy }}</td>
<td>{{ model.trained_at }}</td>
</tr>
{% endfor %}
</table>
<h3>訓練新模型</h3>
<form id="train-form">
<label for="project_id">選擇專案:</label>
<select id="project_id" name="project_id">
{% for project in projects %}
<option value="{{ project.id }}">{{ project.name }}</option>
{% endfor %}
</select>
<br>
<label for="dataset_id">選擇數據集:</label>
<select id="dataset_id" name="dataset_id">
{% for dataset in datasets %}
<option value="{{ dataset.id }}">{{ dataset.file_path }}</option>
{% endfor %}
</select>
<br>
<label for="target_column">目標欄位:</label>
<input type="text" id="target_column" name="target_column" required>
<br>
<label for="model_type">模型類型:</label>
<select id="model_type" name="model_type">
<option value="random_forest">隨機森林</option>
<option value="tpot">TPOT</option>
<option value="h2o_automl">H2O AutoML</option>
</select>
<br>
<button type="submit">開始訓練</button>
</form>
<script>
document.getElementById('train-form').addEventListener('submit', function(e){
e.preventDefault();
fetch('{{ url_for("model.train_model") }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
project_id: document.getElementById('project_id').value,
dataset_id: document.getElementById('dataset_id').value,
target_column: document.getElementById('target_column').value,
model_type: document.getElementById('model_type').value
})
}).then(response => response.json())
.then(data => {
alert('模型訓練已開始,任務ID:' + data.task_id);
});
});
</script>
{% endblock %}
八、配置 Celery 進行異步任務處理
為了處理模型訓練的耗時操作,我們使用 Celery 與 Redis 作為訊息代理。
1. Celery 配置
在 celery_config.py 中配置 Celery:
from celery import Celery
from config import Config
celery = Celery('tasks', broker=Config.CELERY_BROKER_URL)
celery.conf.update(result_backend=Config.CELERY_RESULT_BACKEND)
2. 啟動 Celery Worker
使用以下指令啟動 Celery Worker:
celery -A celery_config.celery worker --loglevel=info
九、啟動與測試應用程式
完成所有設定後,依序執行以下步驟來啟動應用程式:
- 啟動 Redis 伺服器。
- 啟動 Celery Worker:
- 啟動 Flask 應用程式:
- 在瀏覽器中訪問 http://localhost:5000 來使用應用程式。
celery -A celery_config.celery worker --loglevel=info
python run.py
確保每個步驟都正確執行,並監控終端機中的日誌以檢查是否有任何錯誤。
十、結論
透過上述步驟,我們成功建立了一個基於 Flask 的 AutoML 網頁應用程式,具備全面的專案管理、數據管理、模型建立流程及模型訓練隊列等功能。此應用程式能夠協助用戶自動化機器學習流程,提升開發效率和模型性能。
未來可以進一步優化前端介面、增加更多的模型類型支援、引入用戶認證機制,以及整合更先進的 AutoML 工具,以滿足更廣泛的需求。
參考資料
Last updated January 24, 2025