Домашнее задание №3#

В общем итоге необходимо реализовать 11 функций:

  • Матрица Вандермонда;

  • Максимальный остаток;

  • Обработка данных (6 функций):

    1. Чистка данных;

    2. Вычисление mean и std;

    3. Нормализация;

    4. Масштабирование;

    5. Нормирование;

    6. Усечение зашкаливающих значений;

  • Заполнение матрицы (3 функции):

    1. Крест;

    2. Квадрат;

    3. Шахматная доска

Warning

Ни одна из этих функций не должна содержать python циклов, при этом списковые включения, генераторные выражения и функция map приравниваются к циклам python.

Матрица Вандермонда#

Для заданного набора чисел \(x = \{x_i,\,i=1,\ldots,n\}\) определитель Вандермонда — определитель следующей матрицы.

\[\begin{split} \begin{pmatrix} 1 & x_1 & \cdots & x_1^{n-1} \\ 1 & x_2 & \cdots & x_2^{n-1} \\ \vdots & \vdots & \ddots & \vdots \\ 1 & x_n & \cdots & x_n^{n-1} \end{pmatrix}. \end{split}\]

Метод np.vander принимает на вход массив x и возвращает матрицу Вандермонда, но в зеркальном отражении относительно вертикальной оси.

Реализовать функцию vander, принимающую на вход набор чисел x в виде массива ndarray и возвращающую матрицу Вандермонда для этого набора чисел именно в таком виде, в каком она представлена выше.

def vander(x):
    ...

Warning

Ваша функция не должна содержать вызовов функции np.vander.

Максимальный остаток#

Рассмотрим набор целых чисел \(x = \{x_i \in \mathbb{N},\,i=1,\ldots,n\}\). Пусть \(\mathrm{mod}_{ij}\) — остаток от деления \(x_i\) на \(x_j\). Найти максимальный такой остаток.

def largest_mod(x):
    ...

x = [3, 7, 9, 15]
print(largest_mod(x)) # 9

Обработка данных#

Представим себе эксперимент, в котором измеряется \(m\) величин \(x_j,\,j=0,\ldots,m-1\) в моменты времени \(t_i,\,i=0,\ldots,n-1\). Будем считать, что все измерения поступают нам в виде матрицы X (двумерный массив ndarray) размера \(n \times m\), \(j\)-й столбец которой соответствует измеряемой величине \(x_j\), а \(i\)-я строка — моменту времени \(t_i\), т.е. X[i, j] — измерение величины \(x_j\) в момент времени \(t_i\).

\(x_0\)

\(\cdots\)

\(x_j\)

\(\cdots\)

\(x_{m-1}\)

\(t_0\)

X[0, 0]

\(\cdots\)

X[0, j]

\(\cdots\)

X[0, m-1]

\(\cdots\)

\(\cdots\)

\(\cdots\)

\(\cdots\)

\(\cdots\)

\(\cdots\)

\(t_i\)

X[i, 0]

\(\cdots\)

X[i, j]

\(\cdots\)

X[i, m-1]

\(\cdots\)

\(\cdots\)

\(\cdots\)

\(\cdots\)

\(\cdots\)

\(\cdots\)

\(t_{n-1}\)

X[n-1, 0]

\(\cdots\)

X[n-1, j]

\(\cdots\)

X[n-1, m-1]

1. Чистка данных#

Допустим, что если измерение \(X_{ij}\) (измерение \(x_j\) при \(t=t_i\)) не удалось произвести, то в массив попадает значение X[i, j] = np.nan. Ваша задача реализовать процедуру чистки таблицы X от всех строк, в которых есть хотя бы один np.nan.

def clear(X):
    ...
    
    
X = np.array([
    [0,         1,          2], 
    [1,         np.nan,     2], 
    [np.nan,    np.nan,     np.nan], 
    [-1,        -2,         -3]
])

print(clear(X)) # [[0, 1, 2], [-1, -2, -3]]

Tip

Вам могут помочь функции np.isnan, np.any и np.all.

2. Нормализация#

Нередко такие числовые ряды рассматриваются в задачах анализа данных и машинного обучения. В ряде задач удобнее анализировать такие данные, если они заведомо обладают определенными свойствами. Ваша задача — реализовать следующие три распространенных подхода к обработке данных.

  • Рассмотрим новый ряд \(y = \{y_i,\,i=1,\ldots,n\}\), который получается из набора \(x\) по формуле

\[ y_i = \frac{x_i - \bar{x}}{S}, \quad i=1,\ldots,n. \]

Здесь \(\bar{x}\) — среднее значение чисел \(x\), а \(S\) — среднеквадратичное отклонение, которые определяются формулами

\[ \bar{x} = \frac{1}{n}\sum_{i=1}^n x_i, \]
\[ S = \sqrt{\frac{1}{n}\sum_{i=1}^{n} (x_i - \bar{x})^2}. \]

Среднее значение получившегося ряда чисел \(y\) заведомо равно нулю, а среднеквадратичное отклонение — единице.

  • Отмасштабируем данные в отрезок \([0, 1]\). Для этого найдем минимальное и максимальное значения \(x_{\min}=\min\limits_{i=1}^n x_i\) и \(x_{\max}=\max\limits_{i=1}^n x_i\) в \(x\) и применим следующее преобразование:

\[ y_i = \frac{x_i - x_{\min}}{x_{\max} - x_{\min}}, \quad i=1,\ldots,n. \]

Все числа получившегося ряда \(y\) заведомо располагаются в диапазоне \([0, 1]\).

  • Представим измерения \(x=\{x_i,\, i=1,\ldots,n\}\) в виде вектора в \(\mathbb{R}^n\) и отнормируем его:

\[ y = \frac{x}{\|x\|}. \]

Ряд \(y\) как вектор имеет единичную длину (по евклидовой метрике) и коллинеарен вектору \(x\).

Ваша задача реализовать нормализацию данных тремя этими способами сразу для таблицы таких измерений X.

2.1. Векторная реализации нормализации каждой строки двумерного массива#

2.1.1. Вычисление mean и std#

a) Напишите функцию, которая принимает на вход матрицу и возвращает два массива:

  • mean — массив средних значений каждого столбца (mean[j] — среднее столбца исходного массива X[:, j]).

  • std — массив среднеквадратичных отклонений каждого столбца (std[j] — среднеквадратичное отклонение строки исходного массива X[:, j]).

def mean_and_std(X):
    n, m = X.shape
    # здесь ваш код
    return mean, std

Tip

Обратите внимание на аргумент axis функции np.sum.

Warning

Ваша функция не должна содержать вызовов функций np.mean и np.std.

2.1.2. Нормализация#

Дополнить предыдущий пример, реализовав функцию process, которая принимает на вход массив X и возвращает массив Y, у которого столбец Y[:, j] представляет из себя нормализацию столбца X[:, j].

def process(X):
    ...

Warning

Ваша функция может содержать вызов функции stat2d или вызывать библиотечные функции np.mean и np.std.

2.2. Векторная реализация масштабирования каждой строки двумерного массива#

Реализуйте функцию scale, которая принимает на вход массив X и возвращает массив Y, такой, что каждый его столбец Y[:, j] представляет отмасштабированный столбец X[:, j] в отрезок \([0, 1]\).

def scale(X):
    ...

Warning

Разрешается использовать функции np.min и np.max.

2.3 Векторная реализация нормирования#

Реализуйте функции normalize, нормирующую все столбцы матрицы.

def normalize(X):
    ...

3. Усечение зашкаливающих значений#

Пусть из физических соображений известно, что все измеряемые величины заведом находятся в диапазоне от \([-M, M], \, M > 0\), но в результате погрешности измерений в результирующем массиве могут оказаться значения, несколько ниже \(-M\) или несколько выше \(M\). Реализуйте процедуру усечения диапазона значений в диапазон \([-M, M]\) по формуле

\[\begin{split} y = \begin{cases} -M, \quad &\text{если } x \le -M \\ x, \quad &\text{если } -M \leqslant x \leqslant M \\ M, \quad &\text{если } x > M \end{cases}, \end{split}\]

т.е. превышающие \(M\) значения занижаются до \(M\), меньшие \(-M\) значения завышаются до \(-M\), а остальные значения не претерпевают изменений.

def clip(X, M):
    ...

Заполнение матриц#

Крест#

Реализовать функцию, которая создаёт матрицу заданного размера \(n\), элементы которой определяются следующим образом

\[\begin{split} \begin{cases} a_{ij} = 1, \quad & m < i \leq n - m \text{ или } m < j \leq n - m \\ a_{ij} = 0, \quad & \text{ иначе}. \end{cases} \end{split}\]

Размер матрицы определяется параметром n, размер нулевых квадратов по углам параметром m. При n=6 и m=2 матрица должна выглядеть следующим образом.

\[\begin{split} \begin{equation} \begin{pmatrix} 0 & 0 & 1 & 1 & 0 & 0 \\ 0 & 0 & 1 & 1 & 0 & 0 \\ 1 & 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 & 1 \\ 0 & 0 & 1 & 1 & 0 & 0 \\ 0 & 0 & 1 & 1 & 0 & 0 \\ \end{pmatrix}. \end{equation} \end{split}\]
def cross(n, m):
    ...

Note

Для удобства можно считать, что m < n и оба они четны.

Квадрат#

Реализовать функцию, которая создаёт матрицу заданного размера \(n\), элементы которой определяются следующим образом

\[\begin{split} \begin{cases} a_{ij} = 1, \quad & m < i \leq n - m \text{ и } m < j \leq n - m \\ a_{ij} = 0, \quad & \text{ иначе} \end{cases} \end{split}\]

Размер матрицы определяется параметром n, размер маленького квадрата из единицы параметром m. При n=6 и m=2 матрица должна выглядеть следующим образом.

\[\begin{split} \begin{equation} \begin{pmatrix} 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 1 & 0 & 0 \\ 0 & 0 & 1 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 \\ \end{pmatrix}. \end{equation} \end{split}\]
def square(n, m):
    ...

Note

Для удобства можно считать, что m < n и оба они четны.

Шахматная доска#

Реализовать функцию, которая создаёт матрицу заданного размера n, содержащую единицы и нули, расположенные в шахматном порядке.

\[\begin{split}\begin{pmatrix} 1 & 0 & 1 & \cdots & 1 & 0 \\ 0 & 1 & 0 & \cdots & 0 & 1 \\ 1 & 0 & 1 & \cdots & 1 & 0 \\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots \\ 1 & 0 & 1 & \cdots & 1 & 0 \\ 0 & 1 & 0 & \cdots & 0 & 1 \end{pmatrix}. \end{split}\]
def chess_board(n):
    ...

Note

Для удобства можно считать, что n четно.