Exercise 6 - normalize_rows Implement normalizeRows() to normalize the rows of a matrix. After applying this function to an input matrix x, each row of x should be a vector of unit length (meaning length 1). # GRADED FUNCTION: normalize_rows def normalize_rows(x): """ Implement a function that normalizes each row of the matrix x (to have unit length). Argument: x -- A numpy matrix of shape (n, m) Returns: x -- The normalized (by row) numpy matrix. You are allowed to modify x. """ #(≈ 2 lines of code) # Compute x_norm as the norm 2 of x. Use np.linalg.norm(..., ord = 2, axis = ..., keepdims = True) # x_norm = # Divide x by its norm. # x = # YOUR CODE STARTS HERE x = np.linalg.norm(x, ord=1, keepdims=True) # YOUR CODE ENDS HERE return x normalizeRows_test x = np.array([[0., 3., 4.], [1., 6., 4.]]) print("normalizeRows(x) = " + str(normalize_rows(x))) normalizeRows_test(normalize_rows) normalizeRows(x) = [[9.]] Error: Wrong shape Error: Wrong output 1 Tests passed 2 Tests failed --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) <ipython-input-21-203d1f51a06e> in <module> 3 print("normalizeRows(x) = " + str(normalize_rows(x))) 4 ----> 5 normalizeRows_test(normalize_rows) ~/work/release/W2A1/public_tests.py in normalizeRows_test(target) 167 ] 168 --> 169 test(test_cases, target) 170 171 ~/work/release/W2A1/test_utils.py in test(test_cases, target) 24 print('\033[92m', success," Tests passed") 25 print('\033[91m', len(test_cases) - success, " Tests failed") ---> 26 raise AssertionError("Not all tests were passed for {}. Check your equations and avoid using global variables inside the function.".format(target.__name__)) AssertionError: Not all tests were passed for normalize_rows. Check your equations and avoid using global variables inside the function.
时间: 2025-03-10 09:08:49 浏览: 43
<think>好的,我现在需要解决用户提供的这个normalize_rows函数的问题。用户给出的测试用例显示输出是错误的,而且错误提示指出形状和输出都不正确。我需要仔细分析代码哪里出错了。
首先,回顾题目要求。normalize_rows函数的目标是对输入矩阵的每一行进行归一化,使得每一行成为一个单位向量(长度为1)。数学上,归一化一个向量是将该向量的每个元素除以该向量的L2范数(欧几里得范数)。例如,对于行向量v,其归一化后的向量是v / ||v||₂,其中||v||₂是v的L2范数,即√(v₁² + v₂² + ... + vₙ²)。
现在看用户提供的代码,函数中的实现是:
x = np.linalg.norm(x, ord=1, keepdims=True)
这里的问题可能出在两个方面:使用的范数类型和计算方式。np.linalg.norm的ord参数在这里被设置为1,这代表使用的是L1范数(绝对值之和),而正确的应该是ord=2,即L2范数。另一个问题是,用户直接将x赋值为计算出的范数,而不是用范数去除原矩阵。这显然会导致结果错误,因为正确的步骤应该是先计算每一行的范数,然后将每一行的每个元素除以对应的范数。
正确步骤应该是:
1. 计算每一行的L2范数。这需要指定axis参数为1(因为每一行是一个样本),并且保持维度(keepdims=True)以便后续的除法操作能够正确广播。
2. 将原矩阵x中的每个元素除以其对应行的范数。
原来的代码中,ord=1导致计算的是L1范数,例如对于第一行[0,3,4],L1范数是0+3+4=7,而正确的L2范数是5(因为3²+4²=25,平方根是5)。所以如果用L1归一化的话,结果会是每个元素除以7,但题目要求的是L2归一化,所以应该除以5。这导致输出错误。
此外,用户代码中的x被直接赋值为范数,导致输出的x变成了范数的矩阵而不是归一化的结果。例如,输入矩阵是2x3的,计算每行的范数会是2x1的矩阵,然后x被赋值为这个2x1的矩阵,导致输出的形状变成2x1,而原题中正确的输出应该保持2x3的形状,只是每个元素被除以对应的范数。所以这一步完全错误,应该用原矩阵除以范数矩阵。
所以正确的代码应该是:
x_norm = np.linalg.norm(x, ord=2, axis=1, keepdims=True)
x = x / x_norm
这样,x_norm的形状是(2,1),而x的形状是(2,3),通过广播机制,每个行向量的元素会被对应的范数正确除,得到归一化的结果。
现在检查用户代码中的错误:
用户使用了ord=1,并且没有指定axis参数。默认情况下,np.linalg.norm在给定axis参数的情况下才会按行或列计算。如果没有指定axis,当keepdims=True时,会计算整个矩阵的范数,得到一个标量。例如,原测试用例中的矩阵,如果axis未指定且ord=1,则整个矩阵的L1范数是0+3+4+1+6+4=18,然后x被赋值为18,导致输出变成[[18.]],这显然不符合预期。但用户测试的输出是[[9.]],这说明可能还有其他问题,或者测试时的代码与现在看到的代码不一致?
或者,可能用户在测试的时候,代码中的参数有其他错误。比如,原代码中的np.linalg.norm的参数是否写错了?
原代码中的代码是:
x = np.linalg.norm(x, ord=1, keepdims=True)
这里,用户可能没有指定axis参数,导致计算的是整个矩阵的L1范数,而不是每行的。例如,输入矩阵是2行3列,计算整个矩阵的L1范数是所有元素绝对值之和,即0+3+4+1+6+4=18。但用户测试的输出显示结果为[[9.]],这可能有其他原因,比如可能测试时使用的ord=2或者其他参数?
或者用户可能在测试时输入的数据和现在给出的不同?
无论如何,根据用户提供的测试用例,正确的输出应该是每行被L2归一化后的结果。例如,输入数组是:
[[0., 3., 4.],
[1., 6., 4.]]
第一行的L2范数是√(0²+3²+4²) = 5,所以归一化后的行是[0/5, 3/5, 4/5] → [0, 0.6, 0.8]
第二行的L2范数是√(1²+6²+4²)=√(1+36+16)=√53≈7.28,归一化后的行是[1/√53, 6/√53, 4/√53]
所以正确的输出应该是一个2x3的矩阵,而不是[[9.]]。而用户得到的是[[9.]],这说明在代码中可能计算的是行的L1范数之和?或者有什么其他错误?
例如,如果用户代码中的ord=1,并且axis=1,那么每行的L1范数会是:
第一行:0+3+4=7,第二行:1+6+4=11。此时x_norm的形状是(2,1),然后x被赋值为x_norm,所以输出是[[7], [11]],但用户测试得到的输出是[[9.]]。这可能说明用户代码中的axis参数设置不正确,比如没有设置axis=1,而是默认计算整个矩阵的范数?
或者,原代码中的np.linalg.norm的参数可能没有正确设置。例如,原代码中的参数是ord=1,并且没有指定axis,导致计算的是整个矩阵的L1范数。例如,输入矩阵的L1范数是所有元素之和:0+3+4+1+6+4=18?但是用户测试输出是[[9.]],这似乎不符。或者可能用户测试的代码有其他参数?
看来这里可能存在多个错误:ord参数错误(用了L1而非L2),axis参数未正确指定,以及将x赋值为范数而不是除以范数。
现在,正确的实现应该是:
def normalize_rows(x):
# 计算每一行的L2范数,保持维度以便广播
x_norm = np.linalg.norm(x, ord=2, axis=1, keepdims=True)
# 将每行除以其范数
x = x / x_norm
return x
这样,当输入x是[[0,3,4],[1,6,4]]时,x_norm是[[5],[√53]],然后x的每一行被除以对应的数值,得到正确的结果。
所以用户原来的代码错误之处在于:
1. 使用了ord=1而非ord=2。
2. 没有指定axis=1,导致计算的是整个矩阵的范数,而不是每行的。
3. 没有执行除法,而是将x替换为范数矩阵,导致输出错误。
因此,修改后的代码应该包括正确的ord参数、正确的axis参数,并且执行除法操作。</think>要解决`normalize_rows`函数的问题,需对矩阵的每一行进行L2范数归一化。以下是分步说明和修正后的代码:
---
### 错误分析
1. **范数类型错误**:原代码使用`ord=1`(L1范数),而题目要求的是L2范数(欧几里得范数)。
2. **轴未指定**:未设置`axis=1`,导致计算整个矩阵的范数,而非每行。
3. **未执行除法**:直接将`x`赋值为范数值,导致输出错误。
---
### 正确实现步骤
1. **计算每行的L2范数**:
- 使用`np.linalg.norm(x, ord=2, axis=1, keepdims=True)`,其中:
- `ord=2`表示L2范数。
- `axis=1`表示按行计算。
- `keepdims=True`保持维度,以便广播。
2. **归一化操作**:
- 将原矩阵`x`除以每行的L2范数:`x = x / x_norm`。
---
### 修正后的代码
```python
def normalize_rows(x):
# 计算每一行的L2范数(保持维度)
x_norm = np.linalg.norm(x, ord=2, axis=1, keepdims=True)
# 将每行除以其对应的范数
x = x / x_norm
return x
```
---
### 测试验证
输入矩阵:
```python
x = np.array([[0., 3., 4.],
[1., 6., 4.]])
```
- **第一行**:L2范数为$\sqrt{0^2 + 3^2 + 4^2} = 5$,归一化后为$[0, 3/5, 4/5]$。
- **第二行**:L2范数为$\sqrt{1^2 + 6^2 + 4^2} = \sqrt{53}$,归一化后为$[1/\sqrt{53}, 6/\sqrt{53}, 4/\sqrt{53}]$。
输出应为:
```
[[0. 0.6 0.8 ]
[0.13736056 0.82416338 0.54944226]]
```
---
### 关键点总结
- **L2范数**:需使用`ord=2`。
- **轴设置**:`axis=1`确保逐行计算。
- **广播机制**:通过`keepdims=True`保持维度匹配。
阅读全文
相关推荐













