简体   繁体   English

如何绘制最适合多元线性回归的平面?

[英]How to plot plane of best fit for multivariate linear regression?

I am implementing multivariate linear regression using numpy , pandas and matplotlib .我正在使用numpypandasmatplotlib实现多元线性回归。 I am reading data from a file which looks like this:我正在从一个看起来像这样的文件中读取数据:

data.head()

   ldr1  ldr2  servo
0   971   956     -2
1   691   825   -105
2   841   963    -26
3   970   731     44
4   755   939    -69

在此处输入图片说明

I proceed to implement gradient descent and computing the cost function.我继续实施梯度下降并计算成本函数。 I include reading from file and plotting for completeness.我包括从文件中读取并绘制完整性。

def read_data(file):
    # read in data using pandas
    data = pd.read_csv(file, sep=" ", header=None)
    data.columns = ["ldr1", "ldr2", "servo"]    # read the data
    print(data.head())
    # print(file_data)
    return data


def plot_data(file_data):
    ldr1 = my_data.iloc[:, 0:1]
    ldr2 = my_data.iloc[:, 1:2]
    servo_correction = my_data.iloc[:, 2:3]

    fig = plt.figure()
    ax = Axes3D(fig)
    ax.scatter(ldr2, ldr1, servo_correction)
    ax.set_zlabel('Delta Servo')
    plt.xlabel("LDR2")
    plt.ylabel("LDR1")
    plt.gca().invert_xaxis()
    plt.show()
    return ldr1, ldr2, servo_correction


# compute cost
def compute_cost(X, y, theta):
    to_be_summed = np.power(((X @ theta.T)-y), 2)
    return np.sum(to_be_summed)/(2 * len(X))


# gradient descent
def gradient_descent(X, y, theta, iters, alpha):
    cost = np.zeros(iters)
    for i in range(iters):
        theta = theta - (alpha / len(X)) * np.sum(X * (X @ theta.T - y), axis=0)
        cost[i] = compute_cost(X, y, theta)
    return theta, cost

I call these functions like so:我这样称呼这些函数:

my_data = read_data(filename)
ldr1, ldr2, servo = plot_data(my_data)

# we need to normalize the features using mean normalization
my_data = (my_data - my_data.mean())/my_data.std()
# print(my_data.head())

# setting the matrices
X = my_data.iloc[:, 0:2]
ones = np.ones([X.shape[0], 1])
X = np.concatenate((ones, X), axis=1)

y = my_data.iloc[:, 2:3].values  # values converts it from pandas.core.frame.DataFrame to numpy.ndarray
theta = np.zeros([1, 3])

# set hyper parameters
alpha = 0.01
iterations = 1000

# running the gd and cost function
g, cost = gradient_descent(X, y, theta, iterations, alpha)
print("Thetas: ", g)

finalCost = compute_cost(X, y, g)
print("Final Cost: ", finalCost)

I am trying to fit the plane of best fit to this data.我正在尝试将最适合此数据的平面拟合。 Currently my output is:目前我的输出是:

Thetas:  [[-3.86865143e-17  8.47885685e-01 -5.39083511e-01]]
Final Cost:  0.11972883176814067

在此处输入图片说明

This is what I came up with when trying to plot the plane of best fit.这就是我在尝试绘制最适合的平面时想到的。 I can't seem to get this to work:我似乎无法让这个工作:

def plot_plane(theta, ldr1, ldr2, servo, X, Y):
    z = theta.flat[0] * X + theta.flat[1] * X + theta.flat[2]

    fig = plt.figure()
    ax = Axes3D(fig)
    ax.plot_surface(X, Y, z, rstride=1, cstride=1, alpha=0.2)
    ax.scatter(ldr2, ldr1, servo)
    ax.set_zlabel('Delta Servo')
    plt.xlabel("LDR2")
    plt.ylabel("LDR1")
    plt.gca().invert_xaxis()
    plt.show()

plot_plane(g, ldr1, ldr2, servo, X, y)

Any suggestions on how this can be done?关于如何做到这一点的任何建议?

Data set can be accessed here: https://www.dropbox.com/s/wycoi7gm2sbjr95/数据集可以在这里访问: https : //www.dropbox.com/s/wycoi7gm2sbjr95/


在此处输入图片说明

Here is example surface fitting code with your data that has both a flat plane and a curved surface fitting, please look for the phrase "choose model by commenting".这是示例曲面拟合代码,其中包含具有平面和曲面拟合的数据,请查找短语“通过评论选择模型”。

import numpy, scipy, scipy.optimize
import matplotlib
from mpl_toolkits.mplot3d import  Axes3D
from matplotlib import cm # to colormap 3D surfaces from blue to red
import matplotlib.pyplot as plt


graphWidth = 800 # units are pixels
graphHeight = 600 # units are pixels

# 3D contour plot lines
numberOfContourLines = 16

xData = numpy.array([971.0, 691.0, 841.0, 970.0, 755.0, 684.0, 938.0, 956.0, 658.0, 838.0, 879.0, 752.0, 690.0, 970.0, 964.0, 966.0, 901.0, 671.0, 660.0, 666.0, 765.0, 831.0, 899.0, 668.0, 969.0, 967.0, 651.0, 929.0, 805.0, 812.0, 936.0, 650.0, 964.0, 719.0, 654.0, 646.0, 932.0, 827.0, 917.0, 945.0, 724.0, 956.0, 966.0, 969.0, 968.0, 967.0, 718.0, 966.0, 812.0, 649.0, 645.0, 675.0, 959.0, 966.0, 962.0, 967.0, 956.0, 757.0, 964.0, 817.0, 666.0, 812.0, 902.0, 969.0, 661.0, 962.0, 752.0, 802.0, 670.0, 663.0, 966.0, 967.0, 773.0, 663.0, 818.0, 917.0, 952.0, 834.0, 516.0, 547.0, 846.0, 458.0, 490.0, 835.0, 579.0, 472.0, 557.0, 652.0, 471.0, 455.0, 837.0, 842.0, 832.0, 675.0, 529.0, 509.0, 533.0, 493.0, 572.0, 695.0, 464.0, 846.0, 845.0, 505.0, 833.0, 544.0, 550.0, 594.0, 486.0, 847.0, 471.0, 533.0, 497.0, 838.0, 832.0, 830.0, 847.0, 844.0, 837.0, 831.0, 671.0, 844.0, 824.0, 841.0, 532.0, 576.0, 852.0, 471.0, 496.0, 839.0, 587.0, 478.0, 565.0, 657.0, 481.0, 463.0, 841.0, 842.0, 832.0, 682.0, 532.0, 509.0, 539.0, 497.0, 574.0, 704.0, 472.0, 850.0, 849.0, 512.0, 834.0, 540.0, 542.0, 603.0, 481.0, 847.0, 472.0, 529.0, 496.0, 836.0, 570.0, 588.0, 837.0, 474.0, 781.0, 842.0, 855.0, 846.0, 845.0, 518.0, 854.0, 585.0, 531.0, 539.0, 536.0])
yData = numpy.array([956.0, 825.0, 963.0, 731.0, 939.0, 879.0, 523.0, 962.0, 880.0, 962.0, 536.0, 942.0, 902.0, 954.0, 662.0, 959.0, 550.0, 798.0, 836.0, 778.0, 945.0, 959.0, 532.0, 880.0, 783.0, 733.0, 833.0, 526.0, 955.0, 956.0, 959.0, 863.0, 714.0, 924.0, 778.0, 849.0, 523.0, 957.0, 960.0, 559.0, 925.0, 959.0, 955.0, 760.0, 953.0, 952.0, 921.0, 713.0, 955.0, 838.0, 819.0, 781.0, 956.0, 950.0, 714.0, 937.0, 955.0, 947.0, 739.0, 957.0, 864.0, 957.0, 531.0, 896.0, 796.0, 954.0, 945.0, 955.0, 762.0, 878.0, 951.0, 953.0, 951.0, 877.0, 959.0, 958.0, 609.0, 791.0, 496.0, 786.0, 597.0, 615.0, 574.0, 432.0, 805.0, 599.0, 793.0, 344.0, 617.0, 615.0, 792.0, 456.0, 807.0, 328.0, 504.0, 543.0, 494.0, 644.0, 803.0, 319.0, 611.0, 690.0, 471.0, 543.0, 392.0, 774.0, 783.0, 812.0, 597.0, 478.0, 627.0, 508.0, 576.0, 799.0, 803.0, 421.0, 534.0, 645.0, 791.0, 422.0, 321.0, 790.0, 384.0, 803.0, 520.0, 797.0, 563.0, 629.0, 581.0, 441.0, 809.0, 602.0, 797.0, 354.0, 625.0, 621.0, 796.0, 463.0, 806.0, 333.0, 511.0, 543.0, 501.0, 648.0, 804.0, 323.0, 620.0, 689.0, 483.0, 554.0, 396.0, 767.0, 777.0, 806.0, 596.0, 479.0, 625.0, 506.0, 574.0, 411.0, 801.0, 811.0, 426.0, 626.0, 811.0, 809.0, 515.0, 805.0, 804.0, 651.0, 564.0, 795.0, 589.0, 576.0, 495.0])
zData = numpy.array([-2.0, -105.0, -26.0, 44.0, -69.0, -65.0, 60.0, -22.0, -77.0, -24.0, 58.0, -36.0, -66.0, -3.0, 34.0, -8.0, 57.0, -82.0, -98.0, -90.0, -55.0, -23.0, 60.0, -61.0, 29.0, 36.0, -72.0, 61.0, -44.0, -47.0, -27.0, -73.0, 40.0, -37.0, -107.0, -89.0, 68.0, -32.0, -38.0, 63.0, -54.0, -33.0, 16.0, 34.0, 3.0, 15.0, -61.0, 54.0, -39.0, -72.0, -77.0, -97.0, -16.0, 0.0, 45.0, 11.0, -9.0, -57.0, 47.0, -37.0, -82.0, -15.0, 63.0, 21.0, -73.0, 4.0, -55.0, -23.0, -87.0, -74.0, 24.0, -1.0, -46.0, -59.0, -47.0, -18.0, 41.0, 18.0, -104.0, -25.0, 18.0, -55.0, -64.0, 55.0, -35.0, -56.0, -25.0, 63.0, -46.0, -70.0, 16.0, 59.0, -17.0, 78.0, -86.0, -102.0, -113.0, -41.0, -53.0, 68.0, -56.0, 28.0, 24.0, -88.0, 42.0, -59.0, -35.0, -38.0, -79.0, 48.0, -65.0, -113.0, -73.0, 4.0, -8.0, 63.0, 28.0, 23.0, 25.0, 48.0, 74.0, 7.0, 45.0, 11.0, -92.0, -38.0, 29.0, -69.0, -87.0, 56.0, -31.0, -60.0, -29.0, 59.0, -43.0, -53.0, -4.0, 50.0, -5.0, 74.0, -89.0, -84.0, -116.0, -53.0, -42.0, 46.0, -69.0, 32.0, 36.0, -83.0, 57.0, -64.0, -36.0, -18.0, -94.0, 52.0, -72.0, -87.0, -77.0, 44.0, -57.0, -33.0, 53.0, -76.0, -33.0, -12.0, 15.0, 9.0, -6.0, -70.0, 43.0, -58.0, -100.0, -78.0, -97.0])


# Simple_SimpleEquation_42_Offset_model from zunzun.com
def curvedModel(data, a, b, c, Offset):
    x = data[0]
    y = data[1]
    return numpy.exp(a+b/y+c*numpy.log(x)) + Offset

def flatModel(data, a, b, Offset):
    x = data[0]
    y = data[1]
    return a*x + b*y + Offset


# choose model by commenting
#func = flatModel
#initialParameters = [1.0, 1.0, 1.0] # these are the same as scipy default values in this example
func = curvedModel 
initialParameters = [1.0, 1.0, 1.0, 1.0] # these are the same as scipy default values in this example



def SurfacePlot(func, data, fittedParameters):
    f = plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)

    matplotlib.pyplot.grid(True)
    axes = Axes3D(f)

    x_data = data[0]
    y_data = data[1]
    z_data = data[2]

    xModel = numpy.linspace(min(x_data), max(x_data), 20)
    yModel = numpy.linspace(min(y_data), max(y_data), 20)
    X, Y = numpy.meshgrid(xModel, yModel)

    Z = func(numpy.array([X, Y]), *fittedParameters)

    axes.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=1, antialiased=True)

    axes.scatter(x_data, y_data, z_data) # show data along with plotted surface

    axes.set_title('Surface Plot (click-drag with mouse)') # add a title for surface plot
    axes.set_xlabel('X Data') # X axis data label
    axes.set_ylabel('Y Data') # Y axis data label
    axes.set_zlabel('Z Data') # Z axis data label

    plt.show()
    plt.close('all') # clean up after using pyplot or else thaere can be memory and process problems


def ContourPlot(func, data, fittedParameters):
    f = plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)
    axes = f.add_subplot(111)

    x_data = data[0]
    y_data = data[1]
    z_data = data[2]

    xModel = numpy.linspace(min(x_data), max(x_data), 20)
    yModel = numpy.linspace(min(y_data), max(y_data), 20)
    X, Y = numpy.meshgrid(xModel, yModel)

    Z = func(numpy.array([X, Y]), *fittedParameters)

    axes.plot(x_data, y_data, 'o')

    axes.set_title('Contour Plot') # add a title for contour plot
    axes.set_xlabel('X Data') # X axis data label
    axes.set_ylabel('Y Data') # Y axis data label

    CS = matplotlib.pyplot.contour(X, Y, Z, numberOfContourLines, colors='k')
    matplotlib.pyplot.clabel(CS, inline=1, fontsize=10) # labels for contours

    plt.show()
    plt.close('all') # clean up after using pyplot or else thaere can be memory and process problems


def ScatterPlot(data):
    f = plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)

    matplotlib.pyplot.grid(True)
    axes = Axes3D(f)
    x_data = data[0]
    y_data = data[1]
    z_data = data[2]

    axes.scatter(x_data, y_data, z_data)

    axes.set_title('Scatter Plot (click-drag with mouse)')
    axes.set_xlabel('X Data')
    axes.set_ylabel('Y Data')
    axes.set_zlabel('Z Data')

    plt.show()
    plt.close('all') # clean up after using pyplot or else thaere can be memory and process problems


if __name__ == "__main__":
    data = [xData, yData, zData]

    # here a non-linear surface fit is made with scipy's curve_fit()
    fittedParameters, pcov = scipy.optimize.curve_fit(func, [xData, yData], zData, p0 = initialParameters)

    ScatterPlot(data)
    SurfacePlot(func, data, fittedParameters)
    ContourPlot(func, data, fittedParameters)

    print('fitted prameters', fittedParameters)

    modelPredictions = func(data, *fittedParameters) 

    absError = modelPredictions - zData

    SE = numpy.square(absError) # squared errors
    MSE = numpy.mean(SE) # mean squared errors
    RMSE = numpy.sqrt(MSE) # Root Mean Squared Error, RMSE
    Rsquared = 1.0 - (numpy.var(absError) / numpy.var(zData))
    print('RMSE:', RMSE)
    print('R-squared:', Rsquared)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM