<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 -', a.ndim)
print ('ранг b -', b.ndim)
print ('размеры a -', a.shape)
print ('размеры b -', b.shape , '\n')
# ========
print(a)
print(b)
def mult(a, b):
    
    #за основу беру готовые матрицы с размерами 1000, т.е. не сравниваю и опередляю их размеры. 
    
    irow=0
    c = [[0 for i in range(1000)] for j in range(1000)]
    for k in range(len(c)):   # цикл в цикле и в цикле... - это жесть для проца...
        for g in range(len(c)):
                for d in range(len(c)):
                    c[k][g]+=a[k][d]*b[d][g]
    for row in c: # для красивого вывода информации
        irow+=1
        if irow<4 or irow>997:
            if irow==998: 
                print ("\n...")
            print(row[:3], "...", row[-3:])
    
    # здесь напишите перемножение матриц без 
    # использования NumPy и выведите результат 
def np_mult(a, b):
    print(a@b)
    #  @ - она считается как использование NumPy? =)
    
    # здесь напишите перемножение матриц с
    # использованием NumPy и выведите результат
%%time
# засечем время работы функции без NumPy
mult(a,b)
%%time
# засечем время работы функции с NumPy
np_mult(a,b)<jupyter_output>[[249.52129556 236.59780703 262.94215551 ... 241.84637164 253.08186269
  260.41590484]
 [257.39618323 243.41103427 264.22808044 ... 248.85245461 262.43436777
  264.44553559]
 [247.38399908 237.65279834 257.13294748 ... 245.51812787 256.56463181
  255.12817202]
 ...
 [246.42496268 229.94398697 255.6037826  ... 242.65215701 254.41078488
  249.62345657]
 [248.98234708 240.17260286 257.24353864 ... 247.45622257 254.40449152
  259.44858847]
 [250.65569607 241.04323486 258.76337701 ... 246.67010481 256.40828429
  257.79857415]]
Wall time: 134 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):
    # Ваш код здесь
    
    #print ('S1=', np.mean(A))
    #return float(np.mean(A))
    print ('np.avg S = ', A.cumsum()[-1]/len(A))
    return A.cumsum()[-1]/len(A)
# функция без NumPy
def stupid_sec_av(A):
    P=0.0
    S = [0 for i in range(len(A))]
    
    for i in range(len(A)):
        # Ваш код здесь
        S[i]=A[i]
        P+=S[i]
    print ('avg S = ', P/len(S))
    return P/len(S)

# зададим некоторую последовательность и проверим ее на ваших функциях. 
# Первая функция должна работать ~ в 50 раз быстрее
A = sps.uniform.rvs(size=10 ** 7) 
%time S1 = sec_av(A)
%time S2 = stupid_sec_av(A)
#проверим корректность:
np.abs(S1 - S2).sum()<jupyter_output>np.avg S =  0.5000361905683356
Wall time: 552 ms
avg S =  0.5000361905683356
Wall time: 9.44 s<jupyter_text>Задача 3Пусть задан некоторый массив $X$. Надо построить новый массив, где все элементы с нечетными индексами требуется заменить на число $a$ (если оно не указано, то на 1). Все элементы с четными индексами исходного массива нужно возвести в куб и записать в обратном порядке относительно позиций этих элементов. Массив $X$ при этом должен остаться без изменений. В конце требуется слить массив X с преобразованным X и вывести в обратном порядке.<jupyter_code># функция, решающая задачу с помощью NumPy
def transformation(X, a=1):
    Y = X.copy()
    if a == 0:
        Y[1::2]=1 
    else: 
        Y[1::2]=a
    Y2 = Y[0::2]
    print('\nвырезка чёт',Y2)
    Y2**=3
    print('\nвырезка в ^3',Y2)
    Y2=Y2[::-1]
    print('\nразворот её',Y2)
    Y[::2] = Y2
    print('\nврезка [Y] -',Y, ', count - ',len(Y))
    # Ваш код здесь
    print ("\n[X+Y](разворот) -", np.hstack((X,Y))[::-1], ', count - ', len(np.hstack((X,Y))), '\n')
    return np.hstack((X,Y))[::-1]
  
# функция, решающая задачу  без NumPy
def stupid_transformation(X, a=1):
    # Ваш код здесь
    c=0
    Y = X.copy()
    if a == 0:
        for i in range(len(Y)):
            if not i%2==0:
                Y[i] = 1
    else: 
        for i in range(len(Y)):
            if not i%2==0:
                Y[i] = a 

    dl = len(Y)
    Y2 = []    
    for i in range(len(Y)):
        if i%2==0: # вырезаем четные
            Y2.append(Y[i]**3) # четные в новый массив и сразу в ^3
    print('\nвырезка чёт', Y2[0:2], "...", Y2[-2:], ', count -' , len(Y2))
    for i in range(len(Y)):
        if i%2==0:
            Y[i] = Y2[int(-(i/2+1))]
    print('\nнаоборот -> [Y]', Y[0:3], "...", Y[-4:], ', count -' , len(Y))    
    
    XY = list(X)+list(Y)
    YX= []
    for i in range(len(XY)):
            YX.append(XY[-(i+1)])

    print ("\n[X+Y] -", YX[:3], '...',YX[-3:], ', count - ', len(YX))
    
    print ('\n')
    return YX
#Y= [0 for i in range(100)]
#№Y[0:6]
#№print (Y)
X = sps.uniform.rvs(size=10 ** 7) 
print ("__________________________________________")
print ('[X] - ' , X, ', count - ', len (X))
a=0
# здесь код эффективнее примерно в 20 раз. 
# если Вы вдруг соберетесь печатать массив без np -- лучше сначала посмотрите на его размер
%time S1 = transformation(X)
print ("__________________________________________")
print ('[X] - ' , X, ', count - ', len (X))
%time S2 = stupid_transformation(X)
print ("__________________________________________")
# проверим корректность:
np.abs(S1 - S2).sum()<jupyter_output>__________________________________________
[X] -  [0.16137378 0.33389676 0.99443845 ... 0.94801099 0.92813923 0.48038097] , count -  10000000

вырезка чёт [0.16137378 0.99443845 0.28557787 ... 0.28452075 0.50838299 0.92813923]

вырезка в ^3 [0.00420241 0.98340798 0.02329022 ... 0.02303254 0.13139324 0.79953852]

разворот её [0.79953852 0.13139324 0.02303254 ... 0.02329022 0.98340798 0.00420241]

врезка [Y] - [0.79953852 1.         0.13139324 ... 1.         0.00420241 1.        ] , count -  10000000

[X+Y](разворот) - [1.         0.00420241 1.         ... 0.99443845 0.33389676 0.16137378] , count -  20000000 

Wall time: 861 ms
__________________________________________
[X] -  [0.16137378 0.33389676 0.99443845 ... 0.94801099 0.92813923 0.48038097] , count -  10000000

вырезка чёт [0.004202414539510648, 0.9834079822313548] ... [0.13139324276710826, 0.7995385157214955] , count - 5000000

наоборот -> [Y] [0.79953852 1.         0.13139324] ... [0.98340798 1.         0.00420241 1.        ] ,[...]<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.cos(y)*np.exp(x/2)

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()
grid_x, grid_y = np.meshgrid(np.linspace(1, 10, 200), np.linspace(15, 3,200))

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
import matplotlib.image as mpimg
%matplotlib inline
path_to_image = './5ex 1.png'
image_array = plt.imread(path_to_image) 
plt.imshow(image_array[:,:,:])

#plt.colorbar()
# одномерный массив
print (image_array.reshape(image_array.size))
# здесь выведите размер нового массива
print (image_array.size)
#крайний диапазон нули, т.к. углы белые.<jupyter_output>1041600
{'fraction_non_alphanumeric': 0.13997068676716917, 'fraction_numerical': 0.11442629815745393, 'mean_word_length': 3.3841211564938045, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, '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': '597575', 'license': 'MIT', 'n_tokens_mistral': 4680, 'n_tokens_neox': 4426, 'n_words': 996, 'path': 'Students/KaptelovMV/Hometask_1.ipynb', 'repo_name': 'Alken1/Sberbank_ML', 'size': '9564'}