构建使用机器学习模型的Web应用程序:UFO目击预测案例
摘要
本报告详细介绍了构建一个使用机器学习模型的Web应用程序的完整过程。具体而言,我们使用来自Kaggle的NUFORC UFO目击数据集训练了一个机器学习模型,并使用Flask框架构建了一个Web应用程序来展示该模型的预测结果。通过这个案例研究,我们探讨了如何准备数据、训练模型、序列化模型,以及如何在Web应用程序中使用该模型。
引言
在当今的数据驱动世界中,将机器学习模型集成到Web应用程序中变得越来越常见。本报告将指导您完成一个完整的项目:从数据准备到模型训练,再到构建一个使用该模型的Flask Web应用程序。我们的目标是预测UFO目击事件发生的国家,基于持续时间、纬度和经度三个特征。
数据集概述
我们使用来自Kaggle的NUFORC UFO目击数据集,该数据集包含过去一个世纪的80,000多份UFO目击报告[33]。该数据集包括城市、州、国家、形状、发生时间以及目击对象的持续时间等信息。
数据集特征
UFO数据集包含多个列,但我们将重点关注以下几列:
duration (seconds)
:目击持续时间(秒)latitude
:目击地点的纬度longitude
:目击地点的经度country
:目击发生国家
数据准备和清理
在训练机器学习模型之前,我们需要对数据进行准备和清理。以下是我们在Jupyter Notebook中执行的主要步骤:
导入必要的库
我们首先导入所需的Python库:
import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report
import pickle
加载和探索数据
我们使用Pandas加载CSV数据集并查看其结构:
# 加载数据
ufos = pd.read_csv('../data/ufos.csv')
# 查看数据的前几行
print(ufos.head())
数据转换和清理
接下来,我们创建一个新的DataFrame,只包含我们需要的列:
ufos = pd.DataFrame({'Seconds': ufos['duration (seconds)'], 'Country': ufos['country'],'Latitude': ufos['latitude'],'Longitude': ufos['longitude']
})
然后,我们删除空值并过滤持续时间在1到60秒之间的数据:
# 删除空值
ufos.dropna(inplace=True)
# 过滤持续时间在1到60秒之间的数据
ufos = ufos[(ufos['Seconds'] >= 1) & (ufos['Seconds'] <= 60)]
标签编码
我们将国家名称转换为数字,以便机器学习模型能够处理:
# 使用LabelEncoder将国家名称转换为数字
label_encoder = LabelEncoder()
ufos['Country'] = label_encoder.fit_transform(ufos['Country'])
模型训练
划分训练集和测试集
我们将数据划分为训练集和测试集:
# 选择特征和目标变量
selected_features = ['Seconds', 'Latitude', 'Longitude']
X = ufos[selected_features]
y = ufos['Country']
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
训练逻辑回归模型
我们使用逻辑回归模型进行训练:
# 创建逻辑回归模型
model = LogisticRegression()
# 训练模型
model.fit(X_train, y_train)
# 进行预测
predictions = model.predict(X_test)
# 评估模型性能
print(classification_report(y_test, predictions))
print('Accuracy:', accuracy_score(y_test, predictions))
经过训练,我们的模型在测试集上达到了约95%的准确率,这主要是因为国家与纬度和经度之间存在很强的关联。
模型序列化
为了在Web应用程序中使用训练好的模型,我们需要将其序列化。我们使用Python的Pickle模块来实现这一点:
# 保存模型
import pickle
model_filename = 'ufo-model.pkl'
with open(model_filename, 'wb') as file:pickle.dump(model, file)
# 测试加载模型
loaded_model = pickle.load(open(model_filename, 'rb'))
print(loaded_model.predict([[50, 44, -12]])) # 示例预测
构建Flask Web应用程序
现在,我们将构建一个Flask Web应用程序,该应用程序将使用我们训练好的模型根据用户输入的持续时间、纬度和经度预测UFO目击事件发生的国家。
项目结构
我们的Web应用程序项目结构如下:
web-app/
├── static/
│ └── css/
├── templates/
├── app.py
├── requirements.txt
└── ufo-model.pkl
安装依赖项
在requirements.txt
文件中,我们列出了应用程序所需的依赖项:
scikit-learn
pandas
numpy
flask
安装这些依赖项:
cd web-app
pip install -r requirements.txt
CSS样式
在static/css/styles.css
文件中,我们定义了应用程序的样式:
body {width: 100%;height: 100%;font-family: 'Helvetica';background: black;color: #fff;text-align: center;letter-spacing: 1.4px;font-size: 30px;
}
input {min-width: 150px;
}
.grid {width: 300px;border: 1px solid #2d2d2d;display: grid;justify-content: center;margin: 20px auto;
}
.box {color: #fff;background: #2d2d2d;padding: 12px;display: inline-block;
}
HTML模板
在templates/index.html
文件中,我们定义了应用程序的用户界面:
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>🛸 UFO Appearance Prediction! 👽</title><link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
</head>
<body><div class="grid"><div class="box"><p>According to the number of seconds, latitude and longitude, which country is likely to have reported seeing a UFO?</p><form action="{{ url_for('predict')}}" method="post"><input type="number" name="seconds" placeholder="Seconds" required="required" min="0" max="60" /><input type="text" name="latitude" placeholder="Latitude" required="required" /><input type="text" name="longitude" placeholder="Longitude" required="required" /><button type="submit" class="btn">Predict country where the UFO is seen</button></form><p>{{ prediction_text }}</p></div></div>
</body>
</html>
Flask应用程序
在app.py
文件中,我们定义了Flask应用程序及其路由:
import numpy as np
from flask import Flask, request, render_template
import pickle
app = Flask(__name__)
# 加载模型
model = pickle.load(open("./ufo-model.pkl", "rb"))
@app.route("/")
def home():return render_template("index.html")
@app.route("/predict", methods=["POST"])
def predict():# 获取表单数据并转换为整数seconds = request.form['seconds']latitude = request.form['latitude']longitude = request.form['longitude']int_features = [int(seconds), int(latitude), int(longitude)]final_features = [np.array(int_features)]# 进行预测prediction = model.predict(final_features)# 获取国家名称countries = ["Australia", "Canada", "Germany", "UK", "US"]predicted_country = countries[prediction[0]]# 渲染模板并显示预测结果return render_template("index.html", prediction_text=f"Likely country: {predicted_country}")
if __name__ == "__main__":app.run(debug=True)
运行应用程序
要运行应用程序,请执行以下命令:
python app.py
这将启动一个本地Web服务器,您可以通过访问http://localhost:5000
来使用应用程序。输入持续时间(秒)、纬度和经度,点击"Predict"按钮即可查看模型预测的国家。
挑战与扩展
挑战
一个挑战是在Flask应用程序中训练模型,而不是在Jupyter Notebook中。这可以通过以下方式实现:
- 在
app.py
中添加一个/train
路由 - 在该路由中加载数据、准备数据并训练模型
- 将训练好的模型保存为Pickle文件
这种方法的优缺点:
- 优点:应用程序可以在部署后自行训练,便于更新数据
- 缺点:增加了复杂性,训练过程可能较慢,不适合高流量应用程序
其他方法
除了Flask和Pickle之外,还有其他方法可以在Web应用程序中使用机器学习模型:
- TensorFlow.js:如果您使用TensorFlow训练模型,可以使用TensorFlow.js在Web浏览器中使用该模型
- ONNX:如果您使用PyTorch训练模型,可以将其导出为ONNX格式,然后在Web应用程序中使用Onnx Runtime
- Lobe.ai或Azure Custom Vision:这些平台提供了为多种平台导出模型的方法,包括构建一个可以在云中查询的定制API
结论
在这个案例研究中,我们成功构建了一个使用机器学习模型的Web应用程序,该模型根据UFO目击事件的持续时间、纬度和经度预测发生国家。我们使用了Kaggle上的NUFORC UFO目击数据集,使用Scikit-learn训练了一个逻辑回归模型,并使用Flask框架构建了一个Web应用程序来展示该模型的预测结果。
这个项目展示了如何将机器学习模型集成到Web应用程序中,使其能够为用户提供实时预测。通过遵循本报告中概述的步骤,您也可以使用类似的方法将机器学习模型集成到自己的Web应用程序中。