<jupyter_start><jupyter_text><NAME> Прикладной математики и информатики МФТИ  Лаборатория нейронных сетей и глубокого обучения (DeepHackLab)  Домашнее задание необходимо загрузить в общий репозиторий с именной папкой   Домашнее задание 1 Основы Python и пакет NumPy---<jupyter_code>import numpy as np
import random
import scipy.stats as sps<jupyter_output><empty_output><jupyter_text>Задача 1В первой задаче вам предлагается перемножить две квадратные матрицы двумя способами -- без использования пакета ***numpy*** и с ним.<jupyter_code># Для генерации матриц используем фукнцию random -- она используется для генерации случайных объектов 
# функция sample создает случайную выборку. В качестве аргумента ей передается кортеж (i,j), здесь i -- число строк,
# j -- число столбцов.
a = np.random.sample((1000,1000))
b = np.random.sample((1000,1000))
# выведите размерность (ранг) каждой матрицы с помощью функции ndim.
# Используйте функцию shape, что она вывела?
# ========
# тут можно писать код 
print("a.ndim - {}".format(a.ndim))
print("a.shape - {}".format(a.shape))
print("ранг a - {}".format(np.linalg.matrix_rank(a)))

print("b.ndim - {}".format(b.ndim))
print("b.shape - {}".format(b.shape))
print("ранг b - {}".format(np.linalg.matrix_rank(b)))



# ========
print(a)
print(b)
def mult(a, b):
    # здесь напишите перемножение матриц без 
    # использования NumPy и выведите результат 
    if a.shape[1]==b.shape[0]:
        m=a.shape[1]
        r=a.shape[0]
        c=b.shape[1]

        res=np.zeros((r,c))
        for i in range(r):
            for j in range(c):
                for r in range(m):
                    res[i,j]+=a[i,r]*b[r,j]
        print(res)
    else:
        print("error")
    
def np_mult(a, b):
    # здесь напишите перемножение матриц с
    # использованием NumPy и выведите результат
    print(a @ b)
%%time
# засечем время работы функции без NumPy
mult(a,b)
%%time
# засечем время работы функции с NumPy
np_mult(a,b)<jupyter_output>[[248.39864326 254.75810245 238.3594142  ... 248.33934315 250.27878142
  244.07166614]
 [249.7395416  256.60852034 246.98063695 ... 251.08365068 256.56682103
  252.59956924]
 [248.74491727 258.06130182 239.25661863 ... 249.45550826 251.51971929
  241.60256377]
 ...
 [252.32234902 256.33239441 238.76994321 ... 252.61632628 248.82140913
  248.77812908]
 [248.30271933 258.67321864 241.99512431 ... 244.73953388 248.081074
  243.46775751]
 [254.87204503 260.27377512 240.38362573 ... 251.85129813 248.77354095
  248.44272778]]
CPU times: user 95.3 ms, sys: 5.92 ms, total: 101 ms
Wall time: 30 ms<jupyter_text>Задача 2Напишите функцию, которая по данной последовательности $\{A_i\}_{i=1}^n$ строит последовательность $S_n$, где $S_k = \frac{A_1 + ... + A_k}{k}$.  Аналогично -- с помощью библиотеки **NumPy** и без нее. Сравните скорость, объясните результат.<jupyter_code># функция, решающая задачу с помощью NumPy
def sec_av(A):
    # Ваш код здесь
    return np.cumsum(A)/np.arange(1,len(A)+1)
# функция без NumPy
def stupid_sec_av(A):
    S = [0 for i in range(len(A))]
    for i in range(len(A)):
        # Ваш код здесь
        cs=0
        for k in range(i+1):
            # Ваш код здесь
            cs+=A[k]
        S[i]=cs/(i+1)
    return S
from tqdm import tqdm
def stupid_sec_av(A):
    S = [0 for i in range(len(A))]
    for i in tqdm(range(len(A))):
        # Ваш код здесь
        cs=0
        for k in tqdm(range(i+1)):
            # Ваш код здесь
            cs+=A[k]
        S[i]=cs/(i+1)
    return S
# зададим некоторую последовательность и проверим ее на ваших функциях. 
# Первая функция должна работать ~ в 50 раз быстрее
A = sps.uniform.rvs(size=10 ** 4) 

%time S1 = sec_av(A)
%time S2 = stupid_sec_av(A)
#проверим корректность:
np.abs(S1 - S2).sum()<jupyter_output>CPU times: user 396 µs, sys: 318 µs, total: 714 µs
Wall time: 461 µs
CPU times: user 7.34 s, sys: 4.18 ms, total: 7.34 s
Wall time: 7.34 s<jupyter_text>Задача 3Пусть задан некоторый массив $X$. Надо построить новый массив, где все элементы с нечетными индексами требуется заменить на число $a$ (если оно не указано, то на 1). Все элементы с четными индексами исходного массива нужно возвести в куб и записать в обратном порядке относительно позиций этих элементов. Массив $X$ при этом должен остаться без изменений. В конце требуется слить массив X с преобразованным X и вывести в обратном порядке.<jupyter_code># функция, решающая задачу с помощью NumPy
def transformation(X, a=1):
    # Ваш код здесь
    return Y
# функция, решающая задачу  без NumPy
def stupid_transformation(X):
    # Ваш код здесь
    return Y
X = sps.uniform.rvs(size=10 ** 7) 
# здесь код эффективнее примерно в 20 раз. 
# если Вы вдруг соберетесь печатать массив без np -- лучше сначала посмотрите на его размер
%time S1 = transformation(X)
%time S2 = stupid_transformation(X)
# проверим корректность:
np.abs(S1 - S2).sum()<jupyter_output><empty_output><jupyter_text>Почему методы ***numpy*** оказываются эффективнее?<jupyter_code># Ваш ответ
# Потому что написаны на  С++<jupyter_output><empty_output><jupyter_text>Дополнительные задачи Дополнительные задачи подразумевают, что Вы самостоятельно разберётесь в некоторых функциях ***numpy***, чтобы их сделать.  Эти задачи не являются обязательными, но могут повлиять на Ваш рейтинг в лучшую сторону (точные правила учёта доп. задач будут оглашены позже).  Задача 4* Дана функция двух переменных: $f(x, y) = sin(x)cos(y)$ (это просто такой красивый 3D-график), а также дана функция для отрисовки $f(x, y)$ (`draw_f()`), которая принимает на вход двумерную сетку, на которой будет вычисляться функция.  Вам нужно разобраться в том, как строить такие сетки (подсказка - это одна конкретная функция ***numpy***), и подать такую сетку на вход функции отрисовки.<jupyter_code>from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline

def f(x, y):
    '''Функция двух переменных'''
    return np.sin(x) * np.cos(y)

def draw_f(grid_x, grid_y):
    '''Функция отрисовки функции f(x, y)'''
    fig = plt.figure(figsize=(10, 8))
    ax = Axes3D(fig)
    ax.plot_surface(grid_x, grid_y, f(grid_x, grid_y), cmap='inferno')
    plt.show()
x = np.arange(-5, 5, 0.1)
y = np.arange(-5, 5, 0.1)
grid_x, grid_y = np.meshgrid(x, y)# Ваш код здесь
draw_f(grid_x, grid_y)<jupyter_output><empty_output><jupyter_text>Задача 5* Вам дана картинка. При загрузке её размерность равна 3: **(w, h, num_channels)**, где **w** - ширина картинки в пикселях, **h** - высота картинки в пикселях, **num_channels** - количество каналов *(R, G, B, alpha)*.Вам нужно "развернуть" картинку в одномерный массив размера w \* h \* num_channels, написав **одну строку кода**.<jupyter_code>from matplotlib import pyplot as plt
%matplotlib inline
path_to_image = 'image.png'
image_array = plt.imread(path_to_image)
plt.imshow(image_array);
flat_image_array = # Ваш код здесь
# здесь выведите размер нового массива
print(image_array[400,400])
image_array[:2,:2]
image_array.shape
i=np.reshape(image_array, 597*741*4)
i.
i[:16]<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11903409090909091, 'fraction_numerical': 0.0737215909090909, 'mean_word_length': 4.007823613086771, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '661102', 'license': 'MIT', 'n_tokens_mistral': 3293, 'n_tokens_neox': 3303, 'n_words': 766, 'path': 'Students/lipilin_kv/Hometask_1_lipilin_kv.ipynb', 'repo_name': 'Alken1/Sberbank_ML', 'size': '7052'}