多变量优化 - scipy.optimize输入解析错误

时间:2016-04-07 14:50:11

标签: python image numpy math least-squares

rgb image

我将上面的rgb图像保存为tux.jpg。现在我想得到这个图像的最接近的近似值,它是两个向量Ie的外积,其形式为A · B T

这是我的代码 -

#load image to memory
import Image
im = Image.open('tux.jpg','r')
#save image to numpy array
import numpy as np
mat = np.asfarray(im.convert(mode='L')) # mat is a numpy array of dimension 354*300
msizex,msizey = mat.shape
x0 = np.sum(mat,axis=1)/msizex
y0 = np.sum(mat,axis=0)/msizey

X0 = np.concatenate((x0,y0)) # X0.shape is (654,)
# define error of outer product with respect to original image
def sumsquares(X):
    """ sum of squares - 
    calculates the difference between original and outer product

    input X is a 1D numpy array with the first 354 elements
    representing vector A and the rest 300 representing vector B.
    The error is obtained by subtracting the trial  $A\cdot B^T$ 
    from the original and then adding the square of all entries in 
    the matrix.
    """
    assert X.shape[0] == msizex+msizey
    x = X0[:msizex]
    y = X0[msizex:]
    return np.sum(
        (
        np.outer(x,y) - mat
        )**2
    )
#import minimize
from scipy.optimize import minimize
res = minimize(sumsquares, X0,
               method='nelder-mead',
               options={'disp':True}
)
xout = res.x[:msizex]
yout = res.x[msizex:]
mout = np.outer(xout,yout)
imout= Image.fromarray(mout,mode='L')
imout.show()

结果是the following image

     Optimization terminated successfully.
     Current function value: 158667093349733.531250
     Iterations: 19
     Function evaluations: 12463

这对我来说不够好看。有没有办法改善这个?输出中的噪声甚至与原始图像中的结构的长度不同。我的猜测是算法没有通过。我该如何调试或改进?

EDIT1:我使用代码

创建了下面的图片
size = 256
mat0 = np.zeros((size,size))
mat0[size/4:3*size/4,size/4:3*size/4] = 1000
#mat0[size/4:3*size/4,] = 1000
#mat0[:3*size/4,size/4:] = 1000

im0 = Image.fromarray(mat0)
im0.show() 

两个注释掉的行导致另外两个图像。以下是我的实验结果 -

  1. 中间的广场。 输入 - square middle
    输出 - 相同
  2. 乐队在中间。 输入 - band middle
    输出 - square middle
  3. 东北方的白色大块 输入 - north east
    输出 - north west
  4. 虽然这比我预期的要好得多,但案例2和3仍然最终出错。我希望minimize函数的参数意味着我认为它们的含义。

1 个答案:

答案 0 :(得分:0)

1)第一张图片的渲染问题似乎是从numpy数组转换为图像的问题。我通过运行来获得正确的渲染:

imout = Image.fromarray(mout/np.max(mout)*255)

(即将图像标准化为最大值255并让它自动确定模式)。

通常,要检查Image.fromarray是否正常工作,将imout.show()的输出与

进行比较是有用的。
import matplotlib.pyplot as plt
plt.matshow(mout/np.max(mout)*255, cmap=plt.cm.gray)

你应该得到相同的结果。顺便说一句,通过这样做,我得到了所有其他3个案例。

2)其次,tux.png的主要问题是不可能仅使用两个1-D向量的外积来重建具有这种详细结构的图像。

(这往往适用于简单的图像,如上面所示的块状图像,但不适用于对称性和细节很少的图像)。

要证明这一点:

  • 存在矩阵分解技术,其允许将矩阵重构为两个低秩矩阵M = AB的乘积,例如sklearn.decomposition.NMF

  • 在这种情况下,将A和B的等级设置为1将等同于您的问题(使用不同的优化技术)。

  • 使用下面的代码,您可以很容易地看到n_components = 1(相当于两个1-D向量的外积),得到的重构矩阵看起来非常类似于您的方法输出的矩阵而且,对于更大的n_components,重建越好。

重现性:

import matplotlib.pyplot as plt
from sklearn.decomposition import NMF

nmf = NMF(n_components=20)
prj = nmf.fit_transform(mat)

out = prj.dot(nmf.components_)
out = np.asarray(out, dtype=float)

imout = Image.fromarray(out)
imout.show()

为了说明,这是使用1个分量的NMF重建(这正是两个1-D矢量之间的外部产品):

NMF reconstruction with 1 component, equivalent to outer product of 2 vectors

有2个组成部分:

2 components

这是NMF重建的20个组成部分。

NMF reconstruction with 20 components, equivalent to the sum of 20 1-D vector outer products)

这清楚地表明单个1-D外部产品对于此图像是不够的。然而,它适用于块状图像。

如果您不局限于向量的外积,那么矩阵分解可以是另一种选择。顺便说一下,存在大量的矩阵分解技术。 sklearn的另一个选择是SVD

3)最后,x0和y0可能存在缩放问题。请注意,np.outer(x0,y0)的元素比mat的元素高几个数量级。

虽然使用提供的代码我仍然可以获得3个块状示例的良好结果,但一般来说,在采用方差时具有可比较的比例是一个好习惯。例如,您可能希望缩放x0和y0,以使np.outer的范数与mat的范数相当。