使用给定的基向量构建函数来近似计算矩阵的值

4

首先,如果标题听起来有点混乱,请原谅。英语不是我的母语,虽然我很流利,但有些技术术语可能不正确。请告诉我如何改进。

我在一门Python机器学习课程中被分配了一个任务。我有一个数值表(我相信我可以称之为矩阵),可以使用以下代码进行可视化:

import numpy as np
from numpy.linalg import inv
import pandas as pd
import matplotlib.pyplot as plt


h = np.array([x for x in range(0,5500,500)])
v = np.array([x for x in range(0,65,5)])

print(h.shape,v.shape)

y = np.array([83.4, 78.7, 74.1, 69.7, 65.4, 61.3, 57.4, 53.6, 50.0, 46.5, 43.2,
 75.1, 70.8, 66.6, 63.3, 59.5, 55.7, 52.7, 49.2, 46.4, 43.2, 40.5,
 69.7, 65.7, 62.2, 58.8, 55.2, 52.0, 48.9, 45.9, 43.1, 40.3, 37.6,
 64.4, 61.0, 57.6, 54.2, 51.0, 48.0, 45.1, 42.4, 39.7, 37.1, 34.7,
 59.9, 56.6, 53.3, 50.3, 47.5, 44.6, 41.9, 39.3, 36.8, 34.4, 32.1,
 56.1, 53.0, 50.1, 47.2, 44.5, 41.9, 39.3, 36.9, 34.6, 32.3, 30.2,
 53.3, 50.4, 47.5, 44.8, 42.2, 39.8, 37.4, 35.1, 32.8, 30.7, 28.6,
 50.9, 48.1, 45.4, 42.8, 40.3, 38.0, 35.7, 33.4, 31.3, 29.3, 27.3,
 48.7, 46.0, 43.4, 40.9, 38.6, 36.3, 34.1, 31.9, 29.9, 27.9, 26.1,
 46.4, 43.9, 41.4, 39.0, 36.8, 34.6, 32.4, 30.4, 28.5, 26.6, 24.8,
 44.1, 41.7, 39.3, 37.1, 34.9, 32.8, 30.7, 28.8, 26.9, 25.2, 23.4,
 41.7, 39.4, 37.2, 34.9, 32.9, 30.9, 29.0, 27.2, 25.4, 23.7, 22.0,
 39.3, 37.2, 34.9, 32.9, 31.0, 29.1, 27.3, 25.6, 23.8, 22.3, 20.7])

# Confirm lengths all match
y.shape
len(y) == len(h)*len(v)

###################################
# Matrix visualization with Pandas
dataframe = pd.DataFrame(y.reshape(13,11), index=v, columns=h)

print(dataframe)

为了进行情境化描述,行是飞艇的速度(米/秒),列是高度(米)。这些数值代表的是飞艇的推力(牛顿)。

需要解决的问题是:

使用以下基础元素中的元素构建函数来近似矩阵:{1、v、h、v²、h²、vh、v³、h³、v²h、vh²、v²h²、v³h、vh³}

首先,我真的不太理解问题的核心所在。这些是多元线性回归中的beta值对吗?使用这么多beta的优点是什么?

在朋友的帮助下,我成功地找到了以下解决方案:

base = []
i = 0
j = 0

for i in range(0,len(v)):
    for j in range(0,len(h)):
        base.append([1, v[i], h[j], v[i]**2 , h[j]**2, v[i] * h[j],
                    v[i]**3, h[j]**3, (v[i]**2) * h[j], v[i] * (h[j]**2),
                    (v[i]**2) * (h[j]**2), (v[i]**3) * h[j], v[i] * (h[j]**3)])

base = np.array(base)
base.shape
base_df = pd.DataFrame(base)
print(base_df)


base_tp = np.transpose(base)
d = np.dot(base_tp, base)
inv_d = inv(d)
# print(inv_d.shape, base_tp.shape)
x = np.dot(inv_d, base_tp)
beta = np.dot(x, y)

print(beta.shape,beta)

这是我目前的翻译。我相信它是正确的,但我不会为此承担风险。在继续之前,我应该使用y.reshape(143,1)重塑初始y数组吗?如果是这样,为什么?

2个回答

0
据我所理解,这是一个多元回归问题,其中使用飞行器速度(v)和高度(h)来建模推力(t) - 即“推力=模型(速度,高度)”。这意味着要使用给定的数据和提供的数学函数来建立某些数学公式,例如v平方,高度立方等。最简单的方法是使用“线性回归”,其中使用不同的给定函数组合,如“t = a + bh + cv”等。给定的“1”表示“a*1”,即“a”,这通常称为偏移参数。
我制作了一张数据的三维散点图,似乎有一些突然的不连续性,下面是显示这种情况的图片:

still.png

然而,通过这个3D动画GIF(6.6 MBytes),可以更容易地看到数据在三维空间中旋转的情况:http://zunzun.com/temp/static_images/rotation.gif

为了帮助您创建函数的3D散点图、3D曲面图和3D等高线图,这里提供了一些Python代码,用于进行线性拟合,并使用matplotlib创建这些图形。

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


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


def func(data, a, alpha, beta):
    t = data[0]
    p_p = data[1]
    return a * (t**alpha) * (p_p**beta)


if __name__ == "__main__":
    xData = numpy.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])
    yData = numpy.array([11.0, 12.1, 13.0, 14.1, 15.0, 16.1, 17.0, 18.1, 90.0])
    zData = numpy.array([1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.0, 9.9])

    data = [xData, yData, zData]

    # this example uses curve_fit()'s default initial paramter values
    fittedParameters, pcov = scipy.optimize.curve_fit(func, [xData, yData], zData)

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

    print('fitted prameters', fittedParameters)

0
首先,我不太明白问题的核心在哪里。那些是多元线性回归中的beta值对吧?这样做有这么多beta有什么优势呢?
现在的任务是假设y值可以被建模为以指定基元素的线性组合形式来表示的v和h值。你提到的"betas"就是各个基元素所贡献的系数。
形式上,我们要找到一个解A.betas = y,其中y作为一个一维数组(向量)输入,矩阵元素A_ij包含了第j个基元素在对应于y_i的v和h值上的计算结果(即用于"测量"y_i时的v和h的值)。

由于问题是过度确定的(矩阵A的行数比列数多),因此必须以某种方式放宽“解”的定义 - 一个可能的候选者是最小二乘解,可以正式地获得(如您已在问题中实现)作为方程组(A^T.A) . betas = A^T . y的解。

然而,矩阵(A^T.A)往往具有相当糟糕的条件,因此建议不要明确计算其逆矩阵,而是建议使用numpy提供的最小二乘求解器:

beta, res, rank, s = np.linalg.lstsq(base, y, rcond = -1)

或者使用伪逆矩阵

beta = np.dot(np.linalg.pinv(base), y)

现在,如果您检查所获得的“拟合”的最大相对误差:

np.max(np.abs((np.dot(base, beta) - y) / y))

基于计算矩阵 A^T.A 的直接逆的方法得到的结果约为 0.05,而最小二乘求解器提供了一个值为 0.01

在继续之前,我应该用 y.reshape(143,1) 重新塑造初始 y 数组吗?

如果您不对 y 进行重塑,则解决方案 beta 的形状将为 (13,),而如果您使用 y.reshape(143, 1),则 beta 的形状将为 (13, 1),但两种情况都是同样有效的...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接