Stack the examples as the rows of X, with a column of ones for the constant. Least squares chooses the weights that minimize the squared error ‖Xw − y‖², and setting the gradient to zero gives the normal equations:
w = (XᵀX)⁻¹ Xᵀy
Training fits w on some examples. Testing scores it on others it never saw, which estimates how it will do on new ones: training and testing.
Try it
A line through examples
Fit the line on the first sixteen points by the normal equations, and score it on those and on the eight held back.
import numpy as np
# point, x, y, group, from the table: the first sixteen to fit, the last eight held back
P = np.array([[1.9, 2.2, 1], [0.9, 1.9, 0], [2.4, 1.5, 1], [2.5, 1.2, 1],
[1.3, 1.6, 0], [0.5, 1.8, 0], [2.4, 1.4, 1], [2.8, 0.8, 1],
[0.9, 2.6, 0], [2.0, 2.3, 1], [2.0, 2.1, 1], [1.8, 1.5, 1],
[-0.1, 2.1, 0], [-0.1, 2.2, 0], [1.8, 2.0, 0], [1.2, 2.4, 0],
[2.0, 1.9, 1], [2.5, 1.0, 1], [1.4, 2.1, 0], [0.4, 1.9, 0],
[1.3, 2.8, 0], [1.1, 1.9, 0], [1.1, 0.9, 1], [1.2, 1.5, 1]])
A = np.c_[P[:, :2], np.ones(len(P))] # x, y and a constant
w = np.linalg.solve(A[:16].T @ A[:16], A[:16].T @ P[:16, 2])
right = (A @ w > 0.5) == P[:, 2]
print(np.round(w, 3), right[:16].sum(), "of 16 fitted,", right[16:].sum(), "of 8 held back")
You should seeWeights of about 0.469 on x, −0.003 on y and −0.204 for the constant: 15 of 16 right on the points it was fitted on, and 6 of 8 on the points held back.