@
目录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)