Python Flask + Echarts +sklearn做个简单的线性回归

Flask + Echarts + sklearn 做个简单的线性回归

@

Echarts官网的线性回归示例是用了echarts-stat.js这个插件https://github.com/ecomfe/echarts-stat,在前端完成训练模型和预测的操作

正好最近解除了python机器学习里面的线性回归,可以用sklearn在后端训练后把数据传给前端,下面就来简单实现一下

1. 项目结构

和正常的Flask结构差不多,blueprints放个蓝图echarts。static为静态资源目录,templates为模板目录,config.py里是相关环境配置,extension.py为第三方拓展如flask-sqlalchemy等,__init__.py里放个工厂函数。main.py为程序入口。

image-20210408141108277

1.1 配置文件

上来先写配置,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
}

1.2 拓展文件

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()


def init_ext(app):
    db.init_app(app)

1.3 模板文件

就一个图,加一个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>

1.4 视图文件

先写这个样子,后面再陆续补充

from flask import Blueprint, render_template

echarts = Blueprint('echarts', __name__)


@echarts.route('/')
def index():
    return render_template('index.html')

1.5 初始化文件

导入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

1.6 程序入口

传入系统配置并接受工厂函数的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)

上面都完成后就可以把框架跑起来了

2. 完善后端视图文件

2.1 使用sklearn训练模型

为了把散点图和折线图(其实是直线)放在一起,预测的数据必须和原数据一样是二维列表形式,也就是一个坐标列表

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

2.2 定义接口

因为我不太喜欢把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

3.编写前端js文件

3.1 发起Ajax请求

let echartsData;

$.ajax({
    url: '/echartsData',
    async: false,
    success: function(data) {
        echartsData = data
    }
})

这里的async设为false,方便将数据赋值为全局变量echartsData

3.2 echarts部分

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)

4. 结果展示

在这里插入图片描述

posted @ 2022-04-07 11:22  王舰  阅读(472)  评论(0编辑  收藏  举报