我试图将一段代码从Matlab翻译成Python,但我遇到了一些错误:
Matlab的:
function [beta] = linear_regression_train(traindata)
y = traindata(:,1); %output
ind2 = find(y == 2);
ind3 = find(y == 3);
y(ind2) = -1;
y(ind3) = 1;
X = traindata(:,2:257); %X matrix,with size of 1389x256
beta = inv(X'*X)*X'*y;
的Python:
def linear_regression_train(traindata):
y = traindata[:,0] # This is the output
ind2 = (labels==2).nonzero()
ind3 = (labels==3).nonzero()
y[ind2] = -1
y[ind3] = 1
X = traindata[ : , 1:256]
X_T = numpy.transpose(X)
beta = inv(X_T*X)*X_T*y
return beta
我收到错误:操作数无法与计算beta的行上的形状(257,0,1389)(1389,0,257)一起广播。
感谢任何帮助!
谢谢!
答案 0 :(得分:2)
问题是你正在使用numpy数组,而不是MATLAB中的矩阵。默认情况下,矩阵执行矩阵数学运算。因此,X*Y
执行X
和Y
的矩阵乘法。但是,对于数组,缺省情况是使用逐个元素的操作。因此,X*Y
会将X
和Y
的每个对应元素相乘。这相当于MATLAB的.*
操作。
但就像MATLAB的矩阵如何进行逐元素操作一样,Numpy的数组可以进行矩阵乘法。所以你需要做的是使用numpy的矩阵乘法而不是逐元素乘法。对于Python 3.5或更高版本(这是您应该用于此类工作的版本),这只是@
运算符。所以你的行变成了:
beta = inv(X_T @ X) @ X_T @ y
或者,更好的是,您可以使用更简单的.T
转置,它与np.transpose
相同,但更简洁(您可以完全摆脱`np.transpose行):< / p>
beta = inv(X.T @ X) @ X.T @ y
对于Python 3.4或更早版本,您需要使用np.dot
,因为那些版本的python没有@
矩阵乘法运算符:
beta = np.dot(np.dot(inv(np.dot(X.T, X)), X.T), y)
Numpy有一个矩阵对象,默认情况下使用矩阵运算,就像MATLAB矩阵一样。 不要使用它!它很慢,支持很差,而且几乎不是你真正想要的。 Python社区已经对数组进行了标准化,因此请使用它们。
traindata
的尺寸可能还存在一些问题。为了使其正常工作,traindata.ndim
应该等于3
。要使y
和X
为2D,traindata
应为3D
。
如果traindata
是2D并且您希望y
是MATLAB样式的“向量”(MATLAB称为“向量”不是真正的向量),这可能是一个问题。在numpy中,使用像traindata[:, 0]
这样的单个索引会减少维度的数量,而像traindata[:, :1]
这样的切片则不会。因此,当y
为2D时,要保持traindata
2D,只需执行长度为1的切片traindata[:, :1]
。这是完全相同的值,但保持与traindata
相同的维度数。
备注:使用逻辑索引可以显着简化您的代码:
def linear_regression_train(traindata):
y = traindata[:, 0] # This is the output
y[labels == 2] = -1
y[labels == 3] = 1
X = traindata[:, 1:257]
return inv(X.T @ X) @ X.T @ y
return beta
此外,在定义X
时,您的切片是错误的。 Python切片排除了最后一个值,因此要获得256个长切片,您需要执行1:257
,如上所述。
最后,请记住,对函数内部数组的修改会在函数外部进行,索引不会复制。因此,对y
(将某些值设置为1
,将其他值设置为-1
)的更改将影响您的函数之外的traindata
。如果您想避免这种情况,则需要在进行更改之前进行复制:
y = traindata[:, 0].copy()