Span, independence and basis
Span, independence and basis (lesson 3.5.1)
0 of 8 correct
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
How to type answers
- Powers with
^:x^7,2^(1/3),a^-2. - Multiply with
*or by writing side by side:3x^2,2(x+1). ln(x)is the natural log,log(x, 2)is log base 2,eis Euler's number,sqrt(x)is a square root.sin(x),cos(x)andtan(x)take radians; writepifor π andsin(x)^2for sin²x.- Your first answer to each question is saved: it counts towards your score and brings the question back for review.
- Exact answers like
ln(20)/ln(3)are best. Decimals need about 4 significant figures.
Orthogonal projection
Orthogonal projection (lesson 3.5.2)
0 of 8 correct
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
How to type answers
- Powers with
^:x^7,2^(1/3),a^-2. - Multiply with
*or by writing side by side:3x^2,2(x+1). ln(x)is the natural log,log(x, 2)is log base 2,eis Euler's number,sqrt(x)is a square root.sin(x),cos(x)andtan(x)take radians; writepifor π andsin(x)^2for sin²x.- Your first answer to each question is saved: it counts towards your score and brings the question back for review.
- Exact answers like
ln(20)/ln(3)are best. Decimals need about 4 significant figures.
Least squares
Least squares (lesson 3.5.3)
0 of 8 correct
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
How to type answers
- Powers with
^:x^7,2^(1/3),a^-2. - Multiply with
*or by writing side by side:3x^2,2(x+1). ln(x)is the natural log,log(x, 2)is log base 2,eis Euler's number,sqrt(x)is a square root.sin(x),cos(x)andtan(x)take radians; writepifor π andsin(x)^2for sin²x.- Your first answer to each question is saved: it counts towards your score and brings the question back for review.
- Exact answers like
ln(20)/ln(3)are best. Decimals need about 4 significant figures.
Coding exercise
A projection, and a line that survives awkward data
Write two functions, with NumPy.
project(A, b)returns(p, r): the projection ofbonto the column space ofAand the residualb - p, as in lesson 3.5.2. A 1-DAis a single column. RaiseValueErrorifAandbhave different numbers of rows, or if the columns ofAare dependent.fit_line(x, y)returns(c, m, ss): the intercept, the slope and the sum of squared residuals of the least-squares line . Use the centred form of lesson 3.5.3, and . RaiseValueErrorif the lengths differ, there are fewer than two points, or every is the same.
The tests use the examples of lessons 3.5.2 and 3.5.3 and the bad inputs above. One test has values near , such as times counted in seconds. There the normal equations, and even lstsq, return nonsense, while the centred form gets the slope exactly.
See the tests
import numpy as np
X5 = [0, 1, 2, 3, 4]
Y5 = [1, 2, 4, 4, 6]
PLANE = [[1, 0], [0, 1], [1, 1]]
def _raises_value_error(fn, *args):
try:
fn(*args)
except ValueError:
return True
return False
def test_project_onto_a_line():
"""(1, 2) projected onto the line through (3, 1) is (1.5, 0.5), with residual (−0.5, 1.5)"""
p, r = project([3, 1], [1, 2])
expect_close(p, [1.5, 0.5], what="projection onto the line")
expect_close(r, [-0.5, 1.5], what="residual")
def test_project_onto_a_plane():
"""(0, 1, 4) projected onto the plane of (1, 0, 1) and (0, 1, 1) is (1, 2, 3), with residual (−1, −1, 1)"""
p, r = project(PLANE, [0, 1, 4])
expect_close(p, [1, 2, 3], what="projection onto the plane")
expect_close(r, [-1, -1, 1], what="residual")
def test_residual_is_orthogonal():
"""For a random 5 × 3 matrix, the residual is orthogonal to every column"""
rng = np.random.default_rng(3)
A = rng.normal(size=(5, 3))
b = rng.normal(size=5)
p, r = project(A, b)
expect_close(A.T @ r, [0, 0, 0], abs_tol=1e-9, what="A.T @ r")
expect_close(p + r, b, what="p + r")
def test_point_in_the_plane():
"""(2, 3, 5) is in the plane already: it is its own projection, with residual 0"""
p, r = project(PLANE, [2, 3, 5])
expect_close(p, [2, 3, 5], what="projection of a point in the plane")
expect_close(r, [0, 0, 0], abs_tol=1e-9, what="residual")
def test_dependent_columns():
"""Columns (1, 2, 3) and (2, 4, 6) are dependent: ValueError"""
if not _raises_value_error(project, [[1, 2], [2, 4], [3, 6]], [1, 0, 0]):
raise AssertionError("expected ValueError for dependent columns")
def test_rows_differ():
"""A with 3 rows and b with 2 entries: ValueError"""
if not _raises_value_error(project, PLANE, [1, 2]):
raise AssertionError("expected ValueError when A and b have different numbers of rows")
def test_fit_five_points():
"""The five points of lesson 3.5.3 give y = 1 + 1.2x with a sum of squares of 0.8"""
c, m, ss = fit_line(X5, Y5)
expect_close([c, m, ss], [1.0, 1.2, 0.8], what="(c, m, ss)")
def test_fit_two_points():
"""Two points (1, 3) and (3, 7) give the line through them, y = 1 + 2x, with nothing left over"""
c, m, ss = fit_line([1, 3], [3, 7])
expect_close([c, m], [1.0, 2.0], what="(c, m)")
expect_close(ss, 0.0, abs_tol=1e-12, what="sum of squares")
def test_noisy_line():
"""Lesson 3.5.3's 20 noisy points (seed 353) give c = 2.4162, m = 0.4571 and a sum of squares of 24.0997"""
rng = np.random.default_rng(353)
x = np.arange(1, 21, dtype=float)
y = 2 + 0.5 * x + rng.normal(0, 1, 20)
c, m, ss = fit_line(x, y)
A = np.column_stack([np.ones(20), x])
expected, residual, _, _ = np.linalg.lstsq(A, y, rcond=None)
expect_close([c, m], expected, what="(c, m)")
expect_close(ss, residual[0], what="sum of squares")
def test_large_x():
"""x near 10⁸ with y = 2 + 0.5(x − 10⁸): the slope is exactly 0.5 and the intercept 2 − 0.5 × 10⁸"""
x = 1e8 + np.arange(5.0)
y = 2 + 0.5 * np.arange(5.0)
c, m, ss = fit_line(x, y)
expect_close(m, 0.5, rel=1e-12, what="slope")
expect_close(c, 2 - 0.5e8, rel=1e-12, what="intercept")
def test_all_x_equal():
"""Points (2, 1), (2, 3), (2, 5) all have x = 2: ValueError"""
if not _raises_value_error(fit_line, [2, 2, 2], [1, 3, 5]):
raise AssertionError("expected ValueError when every x is the same")
def test_lengths_differ():
"""Five x values and four y values: ValueError"""
if not _raises_value_error(fit_line, X5, Y5[:4]):
raise AssertionError("expected ValueError when the lengths differ")
def test_one_point():
"""A single point does not fix a line: ValueError"""
if not _raises_value_error(fit_line, [1], [2]):
raise AssertionError("expected ValueError for one point")