Using scikit-learn Without Panic
Create, fit, predict, check
In this lesson
Everything so far you built by hand, which was the point — none of it was magic. Now meet the library that does it properly.
scikit-learn is the standard Python machine-learning toolkit, and its best feature is consistency. Every model, from a straight line to a forest of decision trees, is driven by the same four steps. Learn them once and you can use hundreds of algorithms.
Explain it like I’m 5
scikit-learn gives you a predictable set of buttons: create the model, fit it to your examples, predict new answers, check how it did. Every model has the same buttons.
X and y, and the four steps
Two conventions first, because every example you will ever read uses them. X (capital, because it is a table) is the feature matrix: one row per example, one column per feature. y (lowercase, because it is a single column) is the target.
Then the workflow: create the model, fit() it to your data, predict() for new rows, score() to evaluate. fit() is where the learning happens; everything else is bookkeeping.
from sklearn.linear_model import LinearRegression
import numpy as np
# X is the feature matrix: one row per example, one column per feature.
X = np.array([[1], [2], [3], [4], [5], [6]])
# y is the target: one value per row of X.
y = np.array([52, 55, 61, 64, 70, 72])
model = LinearRegression() # 1. create
model.fit(X, y) # 2. fit - this is the learning
prediction = model.predict([[7]]) # 3. predict
score = model.score(X, y) # 4. check
print("learned slope:", round(float(model.coef_[0]), 2))
print("predict 7 hours:", round(float(prediction[0]), 1))
print("r-squared:", round(float(score), 3))
learned slope: 4.23 predict 7 hours: 77.1 r-squared: 0.986
The shape error everyone hits
scikit-learn insists that X is two-dimensional (a table) even when there is only one feature and one row. Passing a bare list of numbers produces an error that is genuinely helpful once you know how to read it.
from sklearn.linear_model import LinearRegression
import numpy as np
X = np.array([[1], [2], [3]])
y = np.array([10, 20, 30])
model = LinearRegression().fit(X, y)
try:
model.predict([4]) # one bare number, not a row
except ValueError as err:
print("ValueError:", str(err).split(".")[0])
print("correct way:", round(float(model.predict([[4]])[0]), 1))
ValueError: Expected 2D array, got 1D array instead: array=[4] correct way: 40.0
Run the four-step workflow yourself on house data. Create a LinearRegression, fit it to X and y, predict the price of a 90 m² house, and report the model's score. Watch the brackets on the prediction.
from sklearn.linear_model import LinearRegression
import numpy as np
X = np.array([[50], [75], [110], [135]])
y = np.array([150, 205, 295, 355])
# TODO: 1. create the model
model = None
# TODO: 2. fit it to X and y
# TODO: 3. predict for a 90 m2 house, and 4. score the model
print("predict 90 m2:", 0)
print("score:", 0)
model = LinearRegression(), then model.fit(X, y). Predict with model.predict([[90]]) (double brackets) and take [0] for the single answer. Round the prediction to 1 decimal and the score to 3.
from sklearn.linear_model import LinearRegression
import numpy as np
X = np.array([[50], [75], [110], [135]])
y = np.array([150, 205, 295, 355])
model = LinearRegression()
model.fit(X, y)
print("predict 90 m2:", round(float(model.predict([[90]])[0]), 1))
print("score:", round(float(model.score(X, y)), 3))
predict 90 m2: 245.2
score: 0.999
Swapping the model is one line
Here is the payoff for the consistency. Every scikit-learn model exposes the same methods, so changing algorithm means changing the line that creates it and nothing else.
LinearRegression() becomes DecisionTreeRegressor() or RandomForestRegressor(), and the fit/predict/score calls are untouched. The same applies across classifiers.
That is why the workflow is worth memorizing rather than any individual algorithm. It also makes comparing models genuinely easy: a loop over a list of models is a completely reasonable thing to write.
Common mistake: Mixing up X and y
They are both just arrays passed to the same call.
X is the features you know, y is the answer you want. fit(X, y) is always in that order.
Common mistake: Passing one row with the wrong shape
model.predict([4]) looks like the obvious way to ask about a single value.
X must be two-dimensional. Use [[4]], or .reshape(-1, 1) on a flat array.
Common mistake: Calling predict() before fit()
Creating the model looks like it has already done something.
Creating only sets up the algorithm. fit() is where learning happens, and scikit-learn raises NotFittedError if you skip it.
Common mistake: Copying a workflow without knowing which step does what
The four lines are short and work when pasted.
Learn what each step does once. Everything else in scikit-learn is a variation on these four calls.
What does fit() do?
fit() is the learning step. Everything before it just sets up the algorithm.
What shape must X be?
Even a single prediction needs [[4]], a table with one row.
Why swap LinearRegression for another model so easily?
The consistent interface is scikit-learn's main design idea: change the creation line and nothing else.
Mini exercise (hard)
Compare two models on the same data with a loop, the payoff of the shared interface. Fit a LinearRegression and a DecisionTreeRegressor (with random_state=0) to the same house data, print each one's score, and predict a 90 m² house with both. The predictions will differ noticeably.
Take the wheel. Complete the code, hit Run, and check your output right here.
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
X = np.array([[50], [75], [110], [135]])
y = np.array([150, 205, 295, 355])
models = [
("linear", LinearRegression()),
("tree ", DecisionTreeRegressor(random_state=0)),
]
# TODO: fit each model, then print its score and its prediction for 90 m2.
# The code inside the loop is identical for both - that is the point.
for name, model in models:
pass
Put the models in a list of (name, model) pairs and loop. Inside the loop the code is identical for both: model.fit(X, y), then model.score(X, y) and model.predict([[90]]).
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
X = np.array([[50], [75], [110], [135]])
y = np.array([150, 205, 295, 355])
models = [
("linear", LinearRegression()),
("tree ", DecisionTreeRegressor(random_state=0)),
]
for name, model in models:
model.fit(X, y)
score = model.score(X, y)
prediction = model.predict([[90]])[0]
print(f"{name}: score {round(float(score), 3)} | predict 90 m2 {round(float(prediction), 1)}")
linear: score 0.999 | predict 90 m2 245.2
tree : score 1.0 | predict 90 m2 205.0
lin, tree = models[0][1], models[1][1]
assert hasattr(lin, "coef_"), "each model must be fitted before it can predict"
assert hasattr(tree, "tree_"), "the decision tree needs fitting too"
assert round(float(lin.predict([[90]])[0]), 1) == 245.2, "the linear model should predict 245.2 for 90 m2"
assert round(float(tree.score(X, y)), 3) == 1.0, "a tree memorizes its training rows, so it scores a perfect 1.0"
print("✓ Looks good!")