Python最小二乘法拟合(直线)

Python的第三方matplot库的确优秀,如果没有什么“高端计算”,它完全可以替代Matlab了。

下面是小弟使用该库搞的一个最小二乘法(直线)简易拟合程序,一方面娱乐娱乐,另一方面也方便了解最小二乘法。

最小二乘法公式(公式图片摘自网络):

least_squares.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

'''
LeastSquares
Copyright 2017 YanWen <i@yanwen.email>

file:
    least_squares.py
last modified:
    2017-11-14
NOTE:
    A simple demo of the least squares method
'''

import matplotlib.pyplot as plt

class LeastSquares(object):
    '''docstring for LeastSquares.

    private:
        __coordinate
        __coordinate_num
        __coefficient
        __cardinality

        __set_coefficient
        __set_cardinality
    public:
        evaluate
    '''

    __coordinate = 0
    __coordinate_num = 0
    __coefficient = 0
    __cardinality = 0

    def __init__(self, coordinate):
        ''' Constructor

        Args:
            coordinate: Hash
        Returns:
            none
        Raises:
            coordinate data is incomplete
        '''

        super(LeastSquares, self).__init__()
        self.__coordinate = coordinate

        if len(coordinate['x']) is not len(coordinate['y']):
            raise Exception('coordinate data is incomplete')
        else:
            self.__coordinate_num = len(coordinate['x']) | len(coordinate['y'])

        # Calculate
        self.__set_coefficient()
        self.__set_cardinality()


    def __set_coefficient(self):
        ''' Calculate coefficient

        Args:
            none
        Returns:
            none
        Raises:
            none
        '''

        # x * y: list
        xXy = map((lambda x, y: x * y), self.__coordinate['x'], self.__coordinate['y'])
        # x * x: list
        xXx = map((lambda x: x ** 2.0), self.__coordinate['x'])

        molecular = sum(xXy) - (1.0 / self.__coordinate_num) * sum(self.__coordinate['x']) * sum(self.__coordinate['y'])
        denominator = sum(xXx) - (1.0 / self.__coordinate_num) * (sum(self.__coordinate['x']) ** 2.0)

        self.__coefficient = molecular / denominator

    def __set_cardinality(self):
        ''' Calculate cardinality

        Args:
            none
        Returns:
            none
        Raises:
            none
        '''

        self.__cardinality = sum(self.__coordinate['y']) / self.__coordinate_num - self.__coefficient * sum(self.__coordinate['x']) / self.__coordinate_num

    def evaluate(self, arg):
        ''' evaluate

        Args:
            arg: List(Number)
        Returns:
            result: List(Number)
        Raises:
            none
        '''

        return [result * self.__coefficient + self.__cardinality for result in arg]

    def __del__(self):
        pass

# Main
if __name__ == '__main__':
    sample = {
        'x': [0.0, 1.0, 4.0, 9.0, 15.0],
        'y': [1.1, 1.9, 3.1, 3.9, 4.9]
    }

    least_squares = LeastSquares(sample)

    data_test = [0.0, 15.0]
    result = least_squares.evaluate(data_test)

    # Plot
    plt.plot(sample['x'], sample['y'], 'ro')
    plt.plot(data_test,  result, 'b-')
    plt.show()

简易测试:

python3 least_squares demo
python3 least_squares demo

参考:

作者: YanWen

Web 开发者

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google photo

You are commenting using your Google account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s