Echarts官网的线性回归示例是用了echarts-stat.js这个插件https://github.com/ecomfe/echarts-stat,在前端完成训练模型和预测的操作
正好最近解除了python机器学习里面的线性回归,可以用sklearn在后端训练后把数据传给前端,下面就来简单实现一下
和正常的Flask结构差不多,blueprints放个蓝图echarts。static为静态资源目录,templates为模板目录,config.py里是相关环境配置,extension.py为第三方拓展如flask-sqlalchemy等,__init__.py里放个工厂函数。main.py为程序入口。
上来先写配置,BaseConfig为基本配置,有SECRET_KEY为后期作session准备的当然这个小例子用不到,SQLALCHEMY_TRACK_MODIFICATIONS设置为False。如果设置成 True (默认为None),Flask-SQLAlchemy 将会追踪对象的修改并且发送信号。这需要额外的内存, 如果不必要的可以禁用它。
import os
class BaseConfig:
SECRET_KEY = os.urandom(24)
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(BaseConfig):
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:mysql@localhost:3306/demo?charset=utf8'
class TestingConfig(BaseConfig):
pass
class ProductionConfig(BaseConfig):
pass
config = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig,
'default': DevelopmentConfig
}
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def init_ext(app):
db.init_app(app)
就一个图,加一个div就行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/js/jquery.min.js"></script>
<script src="/js/echarts.min.js"></script>
</head>
<body>
<div id="regression" style="height: 600px; width:800px"></div>
<script src="/js/myEcharts.js"></script>
</body>
</html>
先写这个样子,后面再陆续补充
from flask import Blueprint, render_template
echarts = Blueprint('echarts', __name__)
@echarts.route('/')
def index():
return render_template('index.html')
导入Flask,视图,拓展,配置,一一加载,注册。最终返回app
from flask import Flask
from demo.blueprints import init_blueprints
from demo.extension import init_ext
from demo.config import config
app = Flask(__name__, static_url_path='/')
def create_app(config_name):
app.config.from_object(config.get(config_name))
init_blueprints(app)
init_ext(app)
return app
传入系统配置并接受工厂函数的app实例
import os
from demo import create_app
config = os.getenv('FLASK_EBV', 'development')
app = create_app(config)
if __name__ == '__main__':
app.run(debug=True)
上面都完成后就可以把框架跑起来了
为了把散点图和折线图(其实是直线)放在一起,预测的数据必须和原数据一样是二维列表形式,也就是一个坐标列表
from sklearn.linear_model import LinearRegression
def get_linear_regression():
# 数据太多了,暂时省略
data = [[...]]
reg = LinearRegression()
data_X = [[row[0]] for row in data]
data_y = [row[1] for row in data]
# 训练模型
reg.fit(data_X, data_y)
temp = reg.predict(data_X)
data_y_predict = []
for i in range(len(temp)):
data_y_predict.append([data_X[i][0], temp[i]])
# 一元函数表达式
expression = f'y = {round(reg.intercept_, 3)}x + {round(reg.coef_[0], 3)}'
return data, data_y_predict, expression
因为我不太喜欢把js和html和css放在一起,所有我决定拆分它们,单独写js。那么这时候jinja2模板就用不到了,后端传数据的方式改为Ajax请求接口
定义一个接口
@echarts.route('/echartsData')
def get_echarts_data():
data, data_y_predict, expression = get_linear_regression()
echarts_data = {
'data': data,
'data_y_predict': data_y_predict,
'expression': expression
}
return echarts_data
let echartsData;
$.ajax({
url: '/echartsData',
async: false,
success: function(data) {
echartsData = data
}
})
这里的async设为false,方便将数据赋值为全局变量echartsData
let divEle = $('#regression')[0]
let myEcharts = echarts.init(divEle)
// 线性回归
option = {
title: {
text: '线性回归',
subtext: '使用sklearn',
textStyle: {
color: 'red',
fontStyle: 'italic'
},
subtextStyle: {
color: 'black',
fontSize: 15
},
link: 'https://echarts.apache.org/v4/examples/zh/editor.html?c=scatter-linear-regression',
sublink: 'https://scikit-learn.org/stable/auto_examples/linear_model/plot_ols.html',
left: 'center'
},
legend: {
left: '25%',
top: '5%'
},
tooltip: {
type: 'axis',
axisPointer: {
type: 'cross'
}
},
xAxis: {
type: 'value'
},
yAxis: {
type: 'value',
min: 2
},
series: [
{
name: 'scatter',
type: 'scatter',
data: echartsData.data
},
{
name: 'line',
type: 'line',
data: echartsData.data_y_predict,
// 不展示特征,如圆点
showSymbol: false,
// 图标标注
markPoint: {
itemStyle: {
// 透明色
color: 'transparent'
},
label: {
show: true,
position: 'left',
formatter: echartsData.expression,
fontSize: 15,
color: '#333'
},
data: [
{
name: '自定义像素点',
x: '50%',
y: '30%'
}
]
}
}
]
};
myEcharts.setOption(option)