我可以从奇异值分解中获得数据传播(噪声)吗?

时间:2016-03-22 12:54:32

标签: python numpy linear-algebra svd

我希望使用奇异值分解来估计eliptoid数据的标准偏差。我不确定这是否是最好的方法,我可能会过度思考整个过程,所以我需要一些帮助。

我使用以下脚本模拟了一些数据......

from matplotlib import pyplot as plt
import numpy


def svd_example():
    # simulate some data...
    # x values have standard deviation 3000
    xdata = numpy.random.normal(0, 3000, 5000).reshape(-1, 1)
    # y values standard deviation 300
    ydata = numpy.random.normal(0, 300, 5000).reshape(-1, 1)
    # apply some rotation
    ydata_rotated = ydata + (xdata * 0.5)
    data = numpy.hstack((xdata, ydata_rotated))

    # get singular values
    left_singular_matrix, singular_values, right_singular_matrix = numpy.linalg.svd(data)
    print 'singular values', singular_values

    # plot data....
    plt.scatter(data[:, 0], data[:, 1], s=5)
    plt.ylim(-15000, 15000)
    plt.show()

svd_example()

我得到奇异的......

>>> singular values [ 234001.71228678   18850.45155942]

我的数据看起来像这样......

enter image description here

我假设奇异值会给我一些数据传播的指示,无论它的轮换如何,对吧?但这些价值观[234001.71228678 18850.45155942]对我来说毫无意义。我的标准偏差是3000和300.这些奇异值是否代表方差?我该如何转换它们?

1 个答案:

答案 0 :(得分:1)

奇异值确实给出了传播的一些指示。实际上,它们与这些方向的标准偏差有关。但是,它们没有正常化。如果除以数字样本的平方根,您将得到与用于创建数据的标准偏差非常相似的值:

singular_values / np.sqrt(5000)
# array([ 3398.61320614,   264.00975837])

为什么你得到3400和264而不是3000和300?这是因为ydata + (xdata * 0.5)不是旋转而是剪切操作。真正的旋转将保留原始的标准偏差。

例如,以下代码将数据旋转40度:

# apply some rotation
s = numpy.sin(40 * numpy.pi / 180)
c = numpy.cos(40 * numpy.pi / 180)
data = numpy.hstack((xdata, ydata)).dot([[c, s], [-s, c]])

通过这样的旋转,您将获得与原始标准偏差非常接近的标准化奇异值。

修改 关于规范化

我不得不承认,规范化可能不适合在这里适用。它并不一定意味着将值缩放到特定范围。正如我所说,归一化是将值带入一个定义的范围,与样本数量无关。

为了理解除sqrt(5000)之间的除法,让我们来谈谈标准偏差。设xn样本的数据向量,均值为零。然后标准偏差计算为sqrt(sum(x**2)/n)sqrt(sum(x**2)) / sqrt(n)。现在,你可以想到奇异值分解只计算sqrt(sum(x**2))部分,所以我们必须自己除sqrt(n)

我担心,这不是一个非常数学的解释,但希望它传达了这个想法。