0

Ok, so I'm writing a function for linear least squares in python and it's pretty much just one equation. Yet for some reason, I'm getting a ValueError. My best guess is it has something to do with the .reshape function, since in this question I had a very similar problem and reshaping was the solution. I've read up on it and from what I gather, w in my function is in format (n,) and the result would be in (n,1) as in my previously mentioned question. I tried reshaping x_train and y_train but I only got an error that I can't change the size of the array. I guess my parameters were set wrong. Right now I'm lost, and I have many more functions like these to go through -- I wish I could understand what am I missing in my code. The equation seems to be in order, so I suppose there's something I should be adding everytime - possibly the reshape function cause I'm still using the same models as in the last situation. I hope it's the right place to post this question, I don't know what else to do but I really want to understand so I won't have these problems in the future, thank you.

Code (np. stands for numpy):

def least_squares(x_train, y_train, M):
    '''
    :param x_train: training input vector  Nx1
    :param y_train: training output vector Nx1
    :param M: polynomial degree
    :return: tuple (w,err), where w are model parameters and err mean squared error of fitted polynomial
    '''
    w = np.linalg.inv(design_matrix(x_train, M). * design_matrix(x_train, M)) * design_matrix(x_train, M).T * y_train
    err = mean_squared_error(x_train, y_train, w)
    return (w, err)

design_matrix and mean_squared_error are working just fine. Traceback:

ERROR: test_least_squares_err (test.TestLeastSquares)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "\content.py", line 48, in least_squares
    w = np.linalg.inv(design_matrix(x_train, M).T * design_matrix(x_train, M)) * design_matrix(x_train, M).T * y_train
ValueError: operands could not be broadcast together with shapes (7,20) (20,7)
3
  • 1
    looks like that you are using component-wise multiplication * instead of matrix-matrix, matrix-vector product np.dot
    – ewcz
    Commented Mar 12, 2017 at 12:04
  • 1
    You might also want to look at using np.linalg.lstsq, which is likely to be faster and more numerically stable
    – Eric
    Commented Mar 12, 2017 at 12:08
  • @Eric thank you, will check out! might come in handy in the future. this time i was supposed to write the function myself but i won't say no to it when i'll have to use it again :)
    – user7220560
    Commented Mar 12, 2017 at 12:16

1 Answer 1

2

Assuming that design_matrix returns a matrix, this code

design_matrix(x_train, M).T * design_matrix(x_train, M)

most likely does not do what is intended since * is performing element-wise multiplication (Hadamard product of two matrices). Because your matrices are not square, it thus complains about incompatible shape.

To obtain matrix-matrix product, one might do (assuming numpy was imported as import numpy as np):

np.dot(design_matrix(x_train, M).T, design_matrix(x_train, M))

Similar reasoning then applies to the rest of the statement * design_matrix(x_train, M).T * y_train...

Also, you might want to evaluate design_matrix only once, e.g., to put something like

mat = design_matrix(x_train, M)

before the line calculating w and then use merely mat.

6
  • thank you SO much! just did this, and it worked! can't believe i've spent hours trying to find a mistake and didn't come across this. it only doesn't work for err now, though w is accepted. i have no idea why won't it accept err? i don't get any kind of error in this function, just that it failed for err :(
    – user7220560
    Commented Mar 12, 2017 at 12:14
  • @LinK you are welcome :) hard to say without knowing mean_squared_error - perhaps the expected shape of the result is different?
    – ewcz
    Commented Mar 12, 2017 at 13:10
  • the error I got is: TypeError: type numpy.ndarray doesn't define round method but it's in the test file, the one I'm only relying on, not supposed to change it. The mean_squared_error is just err = sum(np.power(y - polynomial(x, w), 2)) / len(x) so I would say it's the same shape? But I'm not sure, shapes are really confusing to me.
    – user7220560
    Commented Mar 12, 2017 at 13:27
  • 1
    @LinK does np.sum instead of sum make a difference?
    – ewcz
    Commented Mar 12, 2017 at 13:34
  • IT DOES!!! oh my God. thank you so much. I'm sitting the entire weekend trying to solve all these and I can't believe the amount of documentation I've read and it turns out to be such small changes that make it right ugh. Anyway. Thanks. I'm so happy to get this going :)
    – user7220560
    Commented Mar 12, 2017 at 13:37