退休后闲得无聊自学python,打发时间。近日有人问询关于一元线性回归计算方法,多年没有接触数学问题,已经完全忘了。回头在网上查了一下,便有了试着编一个程序来处理。
首先用Qt5做一个简单界面:
界面代码:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_LR(object):
def setupUi(self, LR):
LR.setObjectName("LR")
LR.resize(300, 317)
self.label = QtWidgets.QLabel(LR)
self.label.setGeometry(QtCore.QRect(20, 50, 54, 12))
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(LR)
self.label_2.setGeometry(QtCore.QRect(20, 70, 21, 16))
self.label_2.setObjectName("label_2")
self.xinput = QtWidgets.QLineEdit(LR)
self.xinput.setGeometry(QtCore.QRect(40, 70, 91, 20))
self.xinput.setObjectName("xinput")
self.label_3 = QtWidgets.QLabel(LR)
self.label_3.setGeometry(QtCore.QRect(160, 70, 21, 16))
self.label_3.setObjectName("label_3")
self.yinput = QtWidgets.QLineEdit(LR)
self.yinput.setGeometry(QtCore.QRect(180, 70, 91, 20))
self.yinput.setObjectName("yinput")
self.addshj = QtWidgets.QPushButton(LR)
self.addshj.setGeometry(QtCore.QRect(110, 100, 75, 23))
self.addshj.setObjectName("addshj")
self.textBrowser = QtWidgets.QTextBrowser(LR)
self.textBrowser.setGeometry(QtCore.QRect(70, 130, 151, 101))
self.textBrowser.setObjectName("textBrowser")
self.label_4 = QtWidgets.QLabel(LR)
self.label_4.setGeometry(QtCore.QRect(130, 20, 54, 12))
self.label_4.setObjectName("label_4")
self.abconput = QtWidgets.QPushButton(LR)
self.abconput.setGeometry(QtCore.QRect(110, 240, 75, 23))
self.abconput.setObjectName("abconput")
self.label_5 = QtWidgets.QLabel(LR)
self.label_5.setGeometry(QtCore.QRect(160, 270, 21, 16))
self.label_5.setObjectName("label_5")
self.label_6 = QtWidgets.QLabel(LR)
self.label_6.setGeometry(QtCore.QRect(20, 270, 21, 16))
self.label_6.setObjectName("label_6")
self.boutput = QtWidgets.QLineEdit(LR)
self.boutput.setGeometry(QtCore.QRect(180, 270, 91, 20))
self.boutput.setReadOnly(True)
self.boutput.setObjectName("boutput")
self.aoutput = QtWidgets.QLineEdit(LR)
self.aoutput.setGeometry(QtCore.QRect(40, 270, 91, 20))
self.aoutput.setReadOnly(True)
self.aoutput.setObjectName("aoutput")
self.retranslateUi(LR)
QtCore.QMetaObject.connectSlotsByName(LR)
def retranslateUi(self, LR):
_translate = QtCore.QCoreApplication.translate
LR.setWindowTitle(_translate("LR", "线性回归"))
self.label.setText(_translate("LR", "数据输入"))
self.label_2.setText(_translate("LR", "x="))
self.label_3.setText(_translate("LR", "y="))
self.addshj.setText(_translate("LR", "添加数据"))
self.label_4.setText(_translate("LR", "y=a*x+b"))
self.abconput.setText(_translate("LR", "计算a,b"))
self.label_5.setText(_translate("LR", "b="))
self.label_6.setText(_translate("LR", "a="))
程序处理分为数据输入、计算处理、图形显示三部分 。
输入部分将x,y样本数据组成xlist和ylist两序列。
计算处理部分是依据公式:
线性方程:y=a * x+b,
a,b参数计算公式在网上找的,在此不推导。
a=(xyp-xp * yp) / (x2p-xp * xp),
b=yp-xp * a
其中:xp为样本x的平均值,yp为样本y的平均值,xyp为样本x*y的平均值,x2p为样本x平方的平均值。
图形显示部分将样本点和回归拟合的直线显示在一个图上。
处理代码:
# -*- coding: utf-8 -*
# linear regression 线性回归
import sys
from PyQt5.QtWidgets import *
import numpy as np
import matplotlib.pyplot as plt
import Ui_LR
xlist = []
ylist = []
def printf(mes): # 界面显示
ui.textBrowser.append(mes) # 在指定的区域显示提示信息
ui.cursot = ui.textBrowser.textCursor()
ui.textBrowser.moveCursor(ui.cursot.End)
return
#界面输入x,y数据。组成x,y数组序列xlist和ylist。
def shujinput():
global xlist, ylist
xn = ui.xinput.text()
yn = ui.yinput.text()
try:
xt = float(xn)
yt = float(yn)
except:
printf("输入数据错误")
return
if len(xlist) == 0:
ui.textBrowser.clear()
xlist.append(xt)
ylist.append(yt)
n = str(len(xlist))
#输入在界面显示
mem = n + "[" + xn + "," + yn + "]"
printf(mem)
ui.xinput.setText("")
ui.yinput.setText("")
return
#根据x,y序列计算a,b值。
def lrshow():
global xlist, ylist
listn = len(xlist)
#序列数小于等于2返回。
if listn <= 2:
return
x = np.array(xlist)
y = np.array(ylist)
#求x,y序列的平均值xp,yp。
xp = x.mean()
yp = y.mean()
#求x[i]*y[i]的平均值xyp,求x[i]平方的平均值x2p。
xyp=0
x2p=0
for i in range(listn):
xyp+=xlist[i]*ylist[i]
x2p+=xlist[i]*xlist[i]
xyp=xyp/listn
x2p=x2p/listn
#依据公式求得a,b值。
a=(xyp-xp*yp)/(x2p-xp*xp)
b=yp-xp*a
y1 = a * x + b
plt.figure(figsize=(10, 5), facecolor="w")
#画出点的分布图。画出回归直线图。
plt.plot(x, y, "ro", lw=2, markersize=6)
plt.plot(x, y1, "r-", lw=2, markersize=6)
plt.grid(visible=True, ls=":")
plt.xlabel("X", fontsize=16)
plt.ylabel("Y", fontsize=16)
plt.show()
a_s = "%.5f" % a
b_s = "%.5f" % b
#界面显示a,b值。
ui.aoutput.setText(a_s)
ui.boutput.setText(b_s)
#清空序列,开始新的计算。
xlist.clear()
ylist.clear()
return
def csh():
ui.addshj.clicked.connect(shujinput)#添加数据到序列。
ui.abconput.clicked.connect(lrshow)#进行线性回归计算。
if __name__ == "__main__":
app = QApplication(sys.argv)
LRWin = QWidget()
ui = Ui_LR.Ui_LR()
ui.setupUi(LRWin)
LRWin.show()
csh()
sys.exit(app.exec_())