Почему NumPy важен даже тем, кто почти всегда работает через pandas и scikit-learn
NumPy редко оказывается главной звездой в первых проектах, но почти всегда работает под капотом. Как только ты делаешь векторные операции, передаешь матрицу признаков в модель, считаешь линейную комбинацию или смотришь на shape массива, ты уже живешь в мире NumPy. Поэтому полезно понимать его не как еще одну библиотеку, а как базовый язык численных вычислений в Python.
Если pandas учит мыслить таблицами, то NumPy учит мыслить массивами и операциями над ними. Это особенно важно для понимания того, почему цикл по строкам почти всегда хуже векторизации и откуда вообще появляется скорость в Python-коде для данных.
Что в NumPy действительно нужно на старте
На старте не нужен весь набор линейной алгебры и численных методов. Но нужно уверенно понимать `array`, форму массива, индексацию, broadcasting, поэлементные операции, агрегации, матричное умножение и базовые функции вроде `mean`, `std`, `sum`, `dot`. Этого уже достаточно, чтобы читать большинство учебных примеров в ML и не бояться формул, где фигурируют векторы и матрицы.
Очень полезно рано понять, что выражение над массивом — это не магия. Если ты пишешь `X @ w`, то буквально вычисляешь линейную комбинацию признаков с весами. Если пишешь `x.mean()`, то считаешь среднее по массиву. Эта прозрачность помогает увидеть связь между математикой и кодом.
Почему векторизация — это не только про скорость
Векторизация полезна не только потому, что она быстрее. Она еще и ближе к математической записи. Цикл часто заставляет думать о данных как о последовательности отдельных объектов, тогда как ML почти всегда работает сразу со всем пространством наблюдений. Когда студент привыкает к массивам, ему становится легче читать формулы, понимать линейные модели и интерпретировать shape промежуточных объектов в пайплайне.
import numpy as np # подключаем основную библиотеку массивов для численных вычислений
X = np.array([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]) # задаем матрицу признаков для трех объектов
w = np.array([0.4, 0.6]) # задаем вектор весов для линейной комбинации
scores = X @ w # считаем вектор скоров как матричное умножение признаков на веса
centered = X - X.mean(axis=0) # центрируем каждый столбец относительно среднего
std = X.std(axis=0) # оцениваем разброс признаков по столбцам
print('scores', scores.round(3).tolist()) # смотрим линейные оценки объектов
print('centered') # отдельно печатаем центрированные данные
print(centered.round(3)) # убеждаемся, что среднее по столбцам убрано
print('std', std.round(3).tolist()) # выводим стандартные отклонения признаковТакой пример хорошо показывает, зачем NumPy нужен на старте. Он связывает матрицу, веса, центрирование и разброс — то есть те самые идеи, из которых потом складываются и preprocessing, и линейные модели, и часть оптимизационных шагов.