Apache MXNet - symbol interfejsu API języka Python

W tym rozdziale dowiemy się o interfejsie w MXNet, który jest określany jako Symbol.

Mxnet.ndarray

Symbol API Apache MXNet to interfejs do programowania symbolicznego. Symbol API wykorzystuje następujące elementy -

  • Grafy obliczeniowe

  • Zmniejszone zużycie pamięci

  • Optymalizacja funkcji przed użyciem

Poniższy przykład pokazuje, jak można utworzyć proste wyrażenie przy użyciu interfejsu API symboli MXNet -

NDArray przy użyciu „tablicy” 1-W i 2-W ze zwykłej listy w Pythonie -

import mxnet as mx
# Two placeholders namely x and y will be created with mx.sym.variable
x = mx.sym.Variable('x')
y = mx.sym.Variable('y')
# The symbol here is constructed using the plus ‘+’ operator.
z = x + y

Output

Zobaczysz następujący wynik -

<Symbol _plus0>

Example

(x, y, z)

Output

Dane wyjściowe podano poniżej -

(<Symbol x>, <Symbol y>, <Symbol _plus0>)

Omówmy teraz szczegółowo klasy, funkcje i parametry API ndarray w MXNet.

Zajęcia

Poniższa tabela zawiera klasy Symbol API MXNet -

Klasa Definicja
Symbol (uchwyt) Ta klasa, a mianowicie symbol, jest symbolicznym wykresem Apache MXNet.

Funkcje i ich parametry

Poniżej przedstawiono niektóre z ważnych funkcji i ich parametrów, które obejmuje mxnet.Symbol API -

Funkcja i jej parametry Definicja
Aktywacja ([data, act_type, out, name]) Stosuje elementową funkcję aktywacji do wejścia. To wspierarelu, sigmoid, tanh, softrelu, softsign funkcje aktywacji.
BatchNorm ([dane, gamma, beta, move_mean,…]) Służy do normalizacji partii. Ta funkcja normalizuje pakiet danych na podstawie średniej i wariancji. Stosuje skalęgamma i offset beta.
BilinearSampler ([dane, siatka, cudnn_off,…]) Ta funkcja stosuje próbkowanie bilinearne do mapy obiektów wejściowych. Właściwie jest to klucz do „Przestrzennych sieci transformatorowych”. Jeśli znasz funkcję remapowania w OpenCV, użycie tej funkcji jest dość podobne. Jedyną różnicą jest to, że ma przejście do tyłu.
BlockGrad ([dane, wyjście, nazwa]) Jak nazwa wskazuje, funkcja ta zatrzymuje obliczenia gradientu. Zasadniczo powstrzymuje nagromadzony gradient danych wejściowych przed przepływem przez tego operatora w kierunku wstecznym.
cast ([data, dtype, out, name]) Ta funkcja będzie rzutować wszystkie elementy wejścia na nowy typ.
Ta funkcja będzie rzutować wszystkie elementy wejścia na nowy typ. Ta funkcja, zgodnie z nazwą, zwraca nowy symbol o podanym kształcie i typie, wypełniony zerami.
jedynki (kształt [, typ]) Funkcja ta, zgodnie z nazwą, zwraca nowy symbol o podanym kształcie i typie, wypełniony jedynkami.
pełny (shape, val [, dtype]) Ta funkcja, jak określono w nazwie, zwraca nową tablicę o podanym kształcie i typie, wypełnioną podaną wartością val.
arange (start [, stop, step, repeat,…]) Zwróci równomiernie rozmieszczone wartości w podanym przedziale. Wartości są generowane w ramach półotwartego interwału [start, stop], co oznacza, że ​​przedział obejmujestart ale wyklucza stop.
linspace (początek, stop, num [, punkt końcowy, nazwa,…]) Zwróci równomiernie rozmieszczone liczby w określonym przedziale. Podobnie jak w przypadku funkcji aranżuj (), wartości są generowane w ramach półotwartego interwału [start, stop], co oznacza, że ​​interwał zawierastart ale wyklucza stop.
histogram (a [, przedziały, zakres]) Jak sama nazwa wskazuje, funkcja ta obliczy histogram danych wejściowych.
moc (podstawa, exp) Jak nazwa wskazuje, funkcja ta zwróci wynik w postaci elementu base element podniesiony do potęg z expelement. Oba wejścia, tj. Base i exp, mogą być symbolami lub skalarami. Zwróć uwagę, że nadawanie nie jest dozwolone. Możesz użyćbroadcast_pow jeśli chcesz skorzystać z funkcji transmisji.
SoftmaxActivation ([dane, tryb, nazwa, atr, wyjście]) Ta funkcja powoduje aktywację softmax na wejściu. Przeznaczony jest na warstwy wewnętrzne. W rzeczywistości jest przestarzały, możemy użyćsoftmax() zamiast.

Przykłady wdrożeń

W poniższym przykładzie będziemy używać funkcji power() który zwróci wynik elementu bazowego podniesiony do potęg z elementu exp:

import mxnet as mx
mx.sym.power(3, 5)

Output

Zobaczysz następujący wynik -

243

Example

x = mx.sym.Variable('x')
y = mx.sym.Variable('y')
z = mx.sym.power(x, 3)
z.eval(x=mx.nd.array([1,2]))[0].asnumpy()

Output

Daje to następujący wynik -

array([1., 8.], dtype=float32)

Example

z = mx.sym.power(4, y)
z.eval(y=mx.nd.array([2,3]))[0].asnumpy()

Output

Po wykonaniu powyższego kodu powinieneś zobaczyć następujące dane wyjściowe -

array([16., 64.], dtype=float32)

Example

z = mx.sym.power(x, y)
z.eval(x=mx.nd.array([4,5]), y=mx.nd.array([2,3]))[0].asnumpy()

Output

Dane wyjściowe są wymienione poniżej -

array([ 16., 125.], dtype=float32)

W poniższym przykładzie będziemy używać funkcji SoftmaxActivation() (or softmax()) który zostanie zastosowany na wsad i jest przeznaczony na warstwy wewnętrzne.

input_data = mx.nd.array([[2., 0.9, -0.5, 4., 8.], [4., -.7, 9., 2., 0.9]])
soft_max_act = mx.nd.softmax(input_data)
print (soft_max_act.asnumpy())

Output

Zobaczysz następujący wynik -

[[2.4258138e-03 8.0748333e-04 1.9912292e-04 1.7924475e-02 9.7864312e-01]
[6.6843745e-03 6.0796250e-05 9.9204916e-01 9.0463174e-04 3.0112563e-04]]

symbol.contrib

Interfejs API Contrib NDArray jest zdefiniowany w pakiecie symbol.contrib. Zazwyczaj udostępnia wiele użytecznych eksperymentalnych interfejsów API dla nowych funkcji. Ten interfejs API działa jako miejsce dla społeczności, w którym mogą wypróbować nowe funkcje. Współtwórca funkcji również otrzyma opinię.

Funkcje i ich parametry

Poniżej przedstawiono niektóre z ważnych funkcji i ich parametrów objętych mxnet.symbol.contrib API -

Funkcja i jej parametry Definicja
rand_zipfian (true_classes, num_sampled,…) Ta funkcja pobiera losowe próbki z rozkładu w przybliżeniu Zipfian. Podstawowym rozkładem tej funkcji jest rozkład Zipfian. Ta funkcja losowo próbkuje num_sampled kandydatów, a elementy sampled_candidates są pobierane z podstawowego rozkładu podanego powyżej.
foreach (body, data, init_states) Jak sama nazwa wskazuje, funkcja ta uruchamia pętlę z obliczeniami zdefiniowanymi przez użytkownika na tablicach NDArrays w wymiarze 0. Ta funkcja symuluje pętlę for, a body wykonuje obliczenia dla iteracji pętli for.
while_loop (cond, func, loop_vars [,…]) Jak sama nazwa wskazuje, ta funkcja uruchamia pętlę while z obliczeniami zdefiniowanymi przez użytkownika i warunkiem pętli. Ta funkcja symuluje pętlę while, która dosłownie wykonuje niestandardowe obliczenia, jeśli warunek jest spełniony.
cond (pred, then_func, else_func) Jak sama nazwa wskazuje, ta funkcja uruchamia warunek if-then-else przy użyciu warunku zdefiniowanego przez użytkownika i obliczeń. Ta funkcja symuluje gałąź if-like, która wybiera wykonanie jednego z dwóch obliczeń dostosowanych do określonego warunku.
getnnz ([dane, oś, wyjście, nazwa]) Ta funkcja daje nam liczbę przechowywanych wartości dla rzadkiego tensora. Zawiera również wyraźne zera. Obsługuje tylko macierz CSR na procesorze.
rekwantyzować ([dane, zakres_min, zakres_maksymalny,…]) Ta funkcja wymienia dane dane, które są kwantowane w int32 i odpowiadające im progi, do int8 przy użyciu minimalnych i maksymalnych progów obliczonych w czasie wykonywania lub podczas kalibracji.
index_copy ([stary_tensor, indeks_wektor,…]) Ta funkcja kopiuje elementy pliku new_tensor into the old_tensor by selecting the indices in the order given in index. The output of this operator will be a new tensor that contains the rest elements of old tensor and the copied elements of new tensor.
interleaved_matmul_encdec_qk ([zapytania,…]) Ten operator oblicza mnożenie macierzy między rzutami zapytań i kluczy w przypadku uwagi wielogłowicowej używanej jako koder-dekoder. Warunkiem jest, aby dane wejściowe były tensorem rzutów zapytań, które są zgodne z układem: (seq_length, batch_size, num_heads *, head_dim).

Przykłady wdrożeń

W poniższym przykładzie będziemy używać funkcji rand_zipfian do rysowania losowych próbek z dystrybucji w przybliżeniu Zipfian -

import mxnet as mx
true_cls = mx.sym.Variable('true_cls')
samples, exp_count_true, exp_count_sample = mx.sym.contrib.rand_zipfian(true_cls, 5, 6)
samples.eval(true_cls=mx.nd.array([3]))[0].asnumpy()

Output

Zobaczysz następujący wynik -

array([4, 0, 2, 1, 5], dtype=int64)

Example

exp_count_true.eval(true_cls=mx.nd.array([3]))[0].asnumpy()

Output

Dane wyjściowe są wymienione poniżej -

array([0.57336551])

Example

exp_count_sample.eval(true_cls=mx.nd.array([3]))[0].asnumpy()

Output

Zobaczysz następujący wynik -

array([1.78103594, 0.46847373, 1.04183923, 0.57336551, 1.04183923])

W poniższym przykładzie będziemy używać funkcji while_loop do uruchamiania pętli while dla obliczeń zdefiniowanych przez użytkownika i warunku pętli -

cond = lambda i, s: i <= 7
func = lambda i, s: ([i + s], [i + 1, s + i])
loop_vars = (mx.sym.var('i'), mx.sym.var('s'))
outputs, states = mx.sym.contrib.while_loop(cond, func, loop_vars, max_iterations=10)
print(outputs)

Output

Wynik podano poniżej:

[<Symbol _while_loop0>]

Example

Print(States)

Output

Daje to następujący wynik -

[<Symbol _while_loop0>, <Symbol _while_loop0>]

W poniższym przykładzie będziemy używać funkcji index_copy która kopiuje elementy new_tensor do old_tensor.

import mxnet as mx
a = mx.nd.zeros((6,3))
b = mx.nd.array([[1,2,3],[4,5,6],[7,8,9]])
index = mx.nd.array([0,4,2])
mx.nd.contrib.index_copy(a, index, b)

Output

Po wykonaniu powyższego kodu powinieneś zobaczyć następujące dane wyjściowe -

[[1. 2. 3.]
[0. 0. 0.]
[7. 8. 9.]
[0. 0. 0.]
[4. 5. 6.]
[0. 0. 0.]]
<NDArray 6x3 @cpu(0)>

symbol.image

Interfejs API Image Symbol jest zdefiniowany w pakiecie symbol.image. Jak sama nazwa wskazuje, jest on zwykle używany do obrazów i ich funkcji.

Funkcje i ich parametry

Poniżej przedstawiono niektóre z ważnych funkcji i ich parametrów objętych mxnet.symbol.image API -

Funkcja i jej parametry Definicja
Adjust_lighting ([dane, alfa, wyjście, nazwa]) Jak sama nazwa wskazuje, funkcja ta dostosowuje poziom oświetlenia wejścia. Jest zgodny ze stylem AlexNet.
przyciąć ([dane, x, y, szerokość, wysokość, na zewnątrz, nazwa]) Za pomocą tej funkcji możemy przyciąć obraz NDArray kształtu (wys. X szer. X gł.) Lub (szer. X wys. X gł.) Do podanego przez użytkownika rozmiaru.
normalize ([data, mean, std, out, name]) Normalizuje tensor kształtu (C x H x W) lub (N x C x H x W) z mean i standard deviation(SD).
random_crop ([dane, xrange, yrange, width,…]) Podobnie jak crop (), losowo przycina obraz NDArray kształtu (H x W x C) lub (N x H x W x C) do rozmiaru podanego przez użytkownika. Będzie próbkować wynik, jeślisrc jest mniejszy niż size.
random_lighting([data, alpha_std, out, name]) Jak sama nazwa wskazuje, funkcja ta losowo dodaje szum PCA. Jest również zgodny ze stylem AlexNet.
random_resized_crop ([dane, xrange, yrange,…]) Przycina również losowo obraz NDArray kształtu (wys. X szer. X głęb.) Lub (szer. X wys. X gł.) Do podanego rozmiaru. Będzie próbkować wynik, jeśli src jest mniejszy niż rozmiar. Spowoduje to również randomizację obszaru i współczynnika kształtu.
resize ([data, size, keep_ratio, interp,…]) Jak sama nazwa wskazuje, ta funkcja zmieni rozmiar obrazu NDArray kształtu (wys. X szer. X gł.) Lub (szer. X szer. X gł.) Do rozmiaru podanego przez użytkownika.
to_tensor ([dane, out, nazwa]) Konwertuje obraz NDArray kształtu (H x W x C) lub (N x H x W x C) z wartościami z zakresu [0, 255] na tensorowy NDArray kształtu (C x H x W) lub ( N x C x H x W) z wartościami z zakresu [0, 1].

Przykłady wdrożeń

W poniższym przykładzie użyjemy funkcji to_tensor do konwersji obrazu NDArray kształtu (H x W x C) lub (N x H x W x C) z wartościami z zakresu [0, 255] na tensor NDArray kształtu (C x H x W) lub (N x C x H x W) z wartościami z zakresu [0, 1].

import numpy as np

img = mx.sym.random.uniform(0, 255, (4, 2, 3)).astype(dtype=np.uint8)

mx.sym.image.to_tensor(img)

Output

Dane wyjściowe podano poniżej -

<Symbol to_tensor4>

Example

img = mx.sym.random.uniform(0, 255, (2, 4, 2, 3)).astype(dtype=np.uint8)

mx.sym.image.to_tensor(img)

Output

Wynik jest wymieniony poniżej:

<Symbol to_tensor5>

W poniższym przykładzie użyjemy funkcji normalize () do normalizacji tensora kształtu (C x H x W) lub (N x C x H x W) z mean i standard deviation(SD).

img = mx.sym.random.uniform(0, 1, (3, 4, 2))

mx.sym.image.normalize(img, mean=(0, 1, 2), std=(3, 2, 1))

Output

Poniżej podano wynik kodu -

<Symbol normalize0>

Example

img = mx.sym.random.uniform(0, 1, (2, 3, 4, 2))

mx.sym.image.normalize(img, mean=(0, 1, 2), std=(3, 2, 1))

Output

Wyjście pokazano poniżej -

<Symbol normalize1>

symbol.random

Interfejs API symboli losowych jest zdefiniowany w pakiecie symbol.random. Jak sama nazwa wskazuje, jest to API Symbol generatora dystrybucji losowej MXNet.

Funkcje i ich parametry

Poniżej przedstawiono niektóre z ważnych funkcji i ich parametrów objętych mxnet.symbol.random API -

Funkcja i jej parametry Definicja
jednolity ([niski, wysoki, kształt, dtype, ctx, out]) Generuje losowe próbki z jednolitego rozkładu.
normalny ([loc, skala, kształt, dtype, ctx, out]) Generuje losowe próbki z rozkładu normalnego (Gaussa).
randn (* kształt, ** kwargs) Generuje losowe próbki z rozkładu normalnego (Gaussa).
poisson ([lam, shape, dtype, ctx, out]) Generuje losowe próbki z rozkładu Poissona.
wykładniczy ([skala, kształt, dtype, ctx, out]) Generuje próbki z rozkładu wykładniczego.
gamma ([alpha, beta, shape, dtype, ctx, out]) Generuje losowe próbki z rozkładu gamma.
wielomian (dane [, kształt, get_prob, out, dtype]) Generuje równoczesne próbkowanie z wielu wielomianowych rozkładów.
minus_binomial ([k, p, kształt, dtype, ctx, out]) Generuje losowe próbki z ujemnego rozkładu dwumianowego.
generalized_negative_binomial ([mu, alfa,…]) Generuje losowe próbki z uogólnionego ujemnego rozkładu dwumianowego.
shuffle (dane, ** kwargs) Losowo tasuje elementy.
randint (low, high [, shape, dtype, ctx, out]) Generuje losowe próbki z dyskretnego, jednolitego rozkładu.
exponential_like ([data, lam, out, name]) Generuje losowe próbki z rozkładu wykładniczego zgodnie z kształtem tablicy wejściowej.
gamma_like ([dane, alfa, beta, wyjście, nazwa]) Generuje losowe próbki z rozkładu gamma zgodnie z kształtem tablicy wejściowej.
generalized_negative_binomial_like ([dane,…]) Generuje losowe próbki z uogólnionego ujemnego rozkładu dwumianowego zgodnie z kształtem tablicy wejściowej.
negatywne_binomialne_podobne ([dane, k, p, wyj, nazwa]) Generuje losowe próbki z ujemnego rozkładu dwumianowego zgodnie z kształtem tablicy wejściowej.
normal_like ([data, loc, scale, out, name]) Generuje losowe próbki z rozkładu normalnego (Gaussa) zgodnie z kształtem tablicy wejściowej.
poisson_like ([dane, lam, out, nazwa]) Generuje losowe próbki z rozkładu Poissona zgodnie z kształtem tablicy wejściowej.
uniform_like ([dane, low, high, out, name]) Generuje losowe próbki z jednolitego rozkładu zgodnie z kształtem tablicy wejściowej.

Przykłady wdrożeń

W poniższym przykładzie będziemy losowo tasować elementy za pomocą funkcji shuffle (). Powoduje to przetasowanie tablicy wzdłuż pierwszej osi.

data = mx.nd.array([[0, 1, 2], [3, 4, 5], [6, 7, 8],[9,10,11]])
x = mx.sym.Variable('x')
y = mx.sym.random.shuffle(x)
y.eval(x=data)

Output

Zobaczysz następujące dane wyjściowe:

[
[[ 9. 10. 11.]
[ 0. 1. 2.]
[ 6. 7. 8.]
[ 3. 4. 5.]]
<NDArray 4x3 @cpu(0)>]

Example

y.eval(x=data)

Output

Po wykonaniu powyższego kodu powinieneś zobaczyć następujące dane wyjściowe -

[
[[ 6. 7. 8.]
[ 0. 1. 2.]
[ 3. 4. 5.]
[ 9. 10. 11.]]
<NDArray 4x3 @cpu(0)>]

W poniższym przykładzie narysujemy losowe próbki z uogólnionego ujemnego rozkładu dwumianowego. Do tego będzie używać funkcjigeneralized_negative_binomial().

mx.sym.random.generalized_negative_binomial(10, 0.1)

Output

Dane wyjściowe podano poniżej -

<Symbol _random_generalized_negative_binomial0>

symbol.sparse

Interfejs API Sparse Symbol jest zdefiniowany w pakiecie mxnet.symbol.sparse. Jak nazwa wskazuje, zapewnia rzadkie wykresy sieci neuronowych i automatyczne różnicowanie na procesorze.

Funkcje i ich parametry

Poniżej przedstawiono niektóre z ważnych funkcji (w tym procedury tworzenia symboli, procedury manipulowania symbolami, funkcje matematyczne, funkcje trygonometryczne, funkcje hybrydowe, funkcje redukcyjne, zaokrąglanie, moce, sieć neuronowa) oraz ich parametry objęte mxnet.symbol.sparse API -

Funkcja i jej parametry Definicja
ElementWiseSum (* args, ** kwargs) Ta funkcja doda wszystkie argumenty wejściowe mądrze. Na przykład _ (1,2,… = 1 + 2 + ⋯ +). Tutaj widzimy, że add_n jest potencjalnie bardziej wydajne niż wywołanie add n razy.
Osadzanie ([dane, waga, input_dim,…]) Zmapuje indeksy liczb całkowitych na reprezentacje wektorowe, tj. Osadzenia. W rzeczywistości odwzorowuje słowa na wektory o wartościach rzeczywistych w wielowymiarowej przestrzeni, która nazywa się osadzaniem słów.
LinearRegressionOutput ([dane, etykieta,…]) Oblicza i optymalizuje pod kątem kwadratu strat podczas propagacji wstecznej, dając tylko dane wyjściowe podczas propagacji do przodu.
LogisticRegressionOutput ([dane, etykieta,…]) Stosuje do danych wejściowych funkcję logistyczną, która jest również nazywana funkcją sigmoidalną. Funkcja jest obliczana jako 1/1 + exp (−x).
MAERegressionOutput ([dane, etykieta,…]) Ten operator oblicza średni bezwzględny błąd wejścia. MAE jest w rzeczywistości miernikiem ryzyka odpowiadającym oczekiwanej wartości błędu bezwzględnego.
abs ([dane, nazwa, atr, wyj]) Jak sama nazwa wskazuje, funkcja ta zwróci elementarną wartość bezwzględną wejścia.
adagrad_update ([waga, grad, historia, lr,…]) Jest to funkcja aktualizacji dla AdaGrad optimizer.
adam_update ([waga, grad, średnia, zmienna, lr,…]) Jest to funkcja aktualizacji dla Adam optimizer.
add_n (* args, ** kwargs) Jak sama nazwa wskazuje, doda wszystkie argumenty wejściowe według elementów.
arccos ([dane, nazwa, atr, wyjście]) Ta funkcja zwróci odwrotny cosinus z tablicy wejściowej.
kropka ([lhs, rhs, transpose_a, transpose_b,…]) Jak nazwa wskazuje, da iloczyn skalarny dwóch tablic. Będzie to zależeć od wymiaru tablicy wejściowej: 1-D: iloczyn wewnętrzny wektorów 2-D: mnożenie macierzy ND: iloczyn sumy ostatniej osi pierwszego wejścia i pierwszej osi drugiego wejścia.
elemwise_add ([lewa, prawa oś, nazwa, atr, koniec]) Jak sama nazwa wskazuje, będzie add argumenty element mądry.
elemwise_div ([lewa, prawa oś, nazwa, atr, koniec]) Jak sama nazwa wskazuje, będzie divide argumenty element mądry.
elemwise_mul ([lewa, prawa oś, nazwa, atr, koniec]) Jak sama nazwa wskazuje, będzie Multiply argumenty element mądry.
elemwise_sub ([lewa, prawa oś, nazwa, atr, koniec]) Jak sama nazwa wskazuje, będzie to mądre odejmowanie argumentów.
exp ([dane, nazwa, atr, wyj]) Ta funkcja zwróci elementarną wartość wykładniczą danego wejścia.
sgd_update ([waga, grad, lr, wd,…]) Działa jako funkcja aktualizacji dla optymalizatora Stochastic Gradient Descent.
sigmoid ([dane, nazwa, atr, wyj]) Jak sama nazwa wskazuje, to obliczy sigmoid x element mądry.
sign ([data, name, attr, out]) Zwróci mądry znak elementu podanego wejścia.
sin ([dane, nazwa, atr, wyj]) Jak nazwa wskazuje, funkcja ta obliczy element mądry sinus z danej tablicy wejściowej.

Przykład implementacji

W poniższym przykładzie będziemy losowo tasować elementy za pomocą ElementWiseSum()funkcjonować. Będzie odwzorowywać indeksy liczb całkowitych na reprezentacje wektorowe, tj. Osadzanie słów.

input_dim = 4
output_dim = 5

Example

/* Here every row in weight matrix y represents a word. So, y = (w0,w1,w2,w3)
y = [[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 10., 11., 12., 13., 14.],
[ 15., 16., 17., 18., 19.]]
/* Here input array x represents n-grams(2-gram). So, x = [(w1,w3), (w0,w2)]
x = [[ 1., 3.],
[ 0., 2.]]
/* Now, Mapped input x to its vector representation y.
Embedding(x, y, 4, 5) = [[[ 5., 6., 7., 8., 9.],
[ 15., 16., 17., 18., 19.]],
[[ 0., 1., 2., 3., 4.],
[ 10., 11., 12., 13., 14.]]]