print("Привет, NumPy!")

NumPy

print("Привет, NumPy!")

Учиться больно, учись сегодня, теряй завтра. В такую ​​погоду сон самый комфортный.

Давайте говорить об этом, мы будем говорить об этом, но нам еще предстоит научиться.

У меня всегда была привычка делать конспекты в процессе обучения, но качество конспектов похвально быть не может, большинство из них не разобраны, но пересмотреть их - хороший выбор.

С тех пор, как я познакомился с Python, я много писал о краулерах, онлайн-романах, монетах виртуальных игр, банках экзаменационных вопросов и так далее, а также помогал другим сканировать многие веб-сайты для получения данных. Статью по краулеру я тоже раньше разбирал (лень, всего одну, а то есть время разобрать):Причудливый синтаксический анализ веб-страницы

После этого у меня появится определенный интерес к социальной инженерии.Может быть, мне нужно быть красноречивым, красноречивым и достичь уровня «Jianghu Liar», чтобы играть в социальную инженерию. Я также написал статью о проникновении в Интернет:Таойе проникла в штаб-квартиру черной платформы, и правда, стоящая за этим, была чрезвычайно ужасающей..

Тем не менее необходимо напомнить всем здесь, что для некоторых людей или информации, которым вы не доверяете, если у вас есть некоторые навыки, связанные с сетевой безопасностью, вы можете использовать их в качестве опыта проникновения, В противном случае лучший способ справиться с этим - это игнорируйте это и не позволяйте своему любопытству стать началом падения в пропасть, особенно в этом смешанном виртуальном сетевом мире. Всего несколько дней назад полиция раскрыла крупнейшее в стране дело о вымогательстве голых чатов в Интернете, в котором участвовало более 100 000 жертв и XXXXXXXXXXXXXXX, поэтому вам все еще нужно быть внимательным.

В любом случае, есть много сложных вещей, которые нужно изучить, и обучение не является точным, а записанные записи редко пересматриваются. Если вы хотите сделать хорошую работу, вы должны сначала отточить свои инструменты.Разве это не систематическое изучение машинного обучения, поэтому я хочу реорганизовать ранее записанные заметки «Три мушкетера» Numpy, Pandas и Matplotlib, которые могут расценивать как отзыв.

На более позднем этапе я изучу некоторые алгоритмы машинного обучения, в основном ссылаясь на «Машинное обучение в действии / Машинное обучение в действии» и арбузную книгу Чжоу Чжихуа «Машинное обучение», а также на некоторые технические статьи, написанные другими большими шишками в кругу. . Если ты можешь порвать руками, попробуй порвать руками, Если ты не можешь порвать руками, это лишь означает, что тебе еще нужно совершенствоваться.

Флаг стоит слишком много, и такое ощущение, что его дадут по морде. Все в порядке, не торопитесь, не бойтесь бить по лицу, все равно кожа грубая, а плоть толстая ( ̄_, ̄)

Давайте сначала разберем NumPy в этой статье, она может быть неполной, записаны только некоторые часто используемые, остальные будут использоваться позже, а затем обновляться. Следующий контент в основном относится к учебнику для новичков и официальной документации NumPy:

Что касается установки NumPy, я уже представил ее, когда представил построение среды глубокого обучения.Рекомендуется установить Anaconda, которая интегрирует большое количество сторонних инструментальных модулей без ручногоpip install ..., что немного похоже на Maven в Java. Анаконда может означать:Создание среды глубокого обучения на основе блокнота Ubuntu+Python+Tensorflow+Jupyter

Ничего страшного, если у вас не установлена ​​Anaconda, просто установите NumPy, выполнив следующую команду в среде Python:

> pip3 install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple

Версия NumPy, используемая в следующем контенте: 1.18.1.

In [1]: import numpy as np

In [2]: np.__version__
Out[2]: '1.18.1'

В NumPy большинство объектов операций — это типы ndarray, которые также можно назвать массивами, и мы можем думать о них как о матрицах или векторах.

Существует множество способов создания объектов np.ndarray. В NumPy также есть несколько API для вызова. Например, мы можем создать указанный объект ndarray следующими способами:

In [7]: temp_array = np.array([[1, 2, 3], [4, 5, 6]], dtype = np.int32)

In [8]: temp_array
Out[8]:
array([[1, 2, 3],
       [4, 5, 6]])

In [9]: type(temp_array)
Out[9]: numpy.ndarray       # 输出的类型为ndarray

Конечно, вы также можете позвонитьarange, затем сделать егоreshapeоперация по изменению его формы, преобразование вектора в матричную форму 2x3, тип объекта в это время все ещеnumpy.ndarray:

In [14]: temp_array = np.arange(1, 7).reshape(2, 3)     # arange产生向量,reshape改变形状,转化成矩阵

In [15]: temp_array
Out[15]:
array([[1, 2, 3],
       [4, 5, 6]])

In [16]: type(temp_array)       # 输出的类型依然是ndarray
Out[16]: numpy.ndarray

Из вышеизложенного мы можем обнаружить, что независимо от того, как создается объект (другие методы будут представлены позже), NumPy работает с типом ndarray, и объект этого типа в основном содержит следующие атрибуты:

  • **ndarray.ndim: ** указывает количество осей ndarray, которое также можно понимать как размерность, ** или можно понимать как количество внешних скобок. **Например, ndim для [1, 2, 3] равен 1, ndim для [[1], [2], [3]] равен 2, [[[1]], [[2] ], [[3] ]] имеет ndim 3 (обратите внимание на количество скобок во внешнем слое)
  • **ndarray.shape: ** указывает форму ndarray, а вывод представляет собой кортеж. ndarray имеет n строк и m столбцов, поэтому вывод равен (n, m), например, [[1], [2], [3]] выводит (3, 1), [[[1]], [ [2]], [[3]]] выходы (3, 1, 1), [[[1, 2]], [[3, 4]]] выходы (2, 1, 2). Благодаря приведенным выше трем примерам,Можно обнаружить, что форма представлена ​​в порядке снаружи внутрь
  • **ndarray.size:** Это проще понять, поскольку оно представляет собой общее количество элементов в ndarray, то есть произведение форм.
  • **ndarray.dtype: ** Указывает тип данных внутренних элементов ndarray, общие из нихnumpy.int32、numpy.int64、numpy.float32、numpy.float64Ждать

Выше приведены некоторые общие атрибуты в ndarray,Примечание: только некоторые, а не все остальные свойства могут ссылаться на официальные документы.

Мы можем наблюдать за различными атрибутами ndarray и тем, как следует изменять внутренние атрибуты, в следующих подразделах:

участвует в приведенном выше примереnp.expand_dimsиnp.astypeбудут представлены позже.

np.zeros может создать ndarray со всеми 0, а np.ones может создать ndarray со всеми 1. При создании можно указать форму ndarray, а можно указать тип данных внутренних элементов через атрибут dtype:

In [70]: np.zeros([2,3,2], dtype=np.float32)
Out[70]:
array([[[0., 0.],
        [0., 0.],
        [0., 0.]],

       [[0., 0.],
        [0., 0.],
        [0., 0.]]], dtype=float32)

In [71]: np.ones([3,2,2], dtype=np.float32)
Out[71]:
array([[[1., 1.],
        [1., 1.]],

       [[1., 1.],
        [1., 1.]],

       [[1., 1.],
        [1., 1.]]], dtype=float32)

Кроме того, в Tensorflow указанный тензор формы указанного элемента может быть сгенерирован с помощью tf.fill следующим образом для создания тензора 2x3, а внутренний элемент равен 100:

In [76]: import tensorflow as tf

In [77]: tf.fill([2,3], 100)
Out[77]:
<tf.Tensor: shape=(2, 3), dtype=int32, numpy=
array([[100, 100, 100],
       [100, 100, 100]])>

В NumPy тоже есть интерфейс fill, но fill можно вызывать только через существующий ndarray, а не напрямую np.fill:

In [79]: data = np.zeros([2, 3])

In [80]: data.fill(100)

In [81]: data
Out[81]:
array([[100., 100., 100.],
       [100., 100., 100.]])

np.arange аналогичен обычно используемому диапазону. Он используется для создания непрерывного ndarray с фиксированным интервалом. Обратите внимание, что левое не право, и массивы образуют арифметическую последовательность. Допуск может быть определен сам по себе (может быть десятичной), следующим образом:

In [85]: np.arange(10)
Out[85]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [86]: np.arange(3, 10, 2)
Out[86]: array([3, 5, 7, 9])

In [87]: np.arange(3, 10, 0.7)
Out[87]: array([3. , 3.7, 4.4, 5.1, 5.8, 6.5, 7.2, 7.9, 8.6, 9.3])

Функция numpy.linspace используется для создания одномерного массива.Массив состоит из арифметической последовательности.Вы можете указать количество элементов внутри элемента и содержит ли он стоп-значение. Таким образом, создайте арифметическую прогрессию с 10 элементами в интервале 1-5:

In [89]: np.linspace(1, 5, 10)      # 默认包含stop
Out[89]:
array([1.        , 1.44444444, 1.88888889, 2.33333333, 2.77777778,
       3.22222222, 3.66666667, 4.11111111, 4.55555556, 5.        ])

In [90]: np.linspace(1, 5, 10, endpoint = False)    # endpoint属性可以设置不包含stop
Out[90]: array([1. , 1.4, 1.8, 2.2, 2.6, 3. , 3.4, 3.8, 4.2, 4.6])

np.random.random и np.random.rand случайным образом генерируют объекты ndarray соответствующей формы от 0 до 1:

In [4]: np.random.random([3, 2])
Out[4]:
array([[0.68755531, 0.56727707],
       [0.86027161, 0.01362836],
       [0.56557302, 0.94283249]])

In [5]: np.random.rand(2, 3)
Out[5]:
array([[0.19894754, 0.8568503 , 0.35165264],
       [0.75464769, 0.29596171, 0.88393648]])

np.random.randint случайным образом генерирует ndarray указанного диапазона, а внутренние элементы имеют тип int:

In [6]: np.random.randint(0, 10, [2, 3])
Out[6]:
array([[0, 6, 9],
       [5, 9, 1]])

np.random.randn возвращает ndarray, удовлетворяющий стандартному нормальному распределению (среднее 0, дисперсия 1):

In [7]: np.random.randn(2,3)
Out[7]:
array([[ 2.46765106, -1.50832149,  0.62060066],
       [-1.04513254, -0.79800882,  1.98508459]])

Кроме того, когда мы используем random в NumPy, это случайно сгенерированный набор данных, иГенерировать одни и те же данные каждый раз, вам нужно установить его через np.random.seed:

In [33]: np.random.seed(100)

In [34]: np.random.randn(2, 3)
Out[34]:
array([[-1.74976547,  0.3426804 ,  1.1530358 ],
       [-0.25243604,  0.98132079,  0.51421884]])

In [35]: np.random.seed(100)

In [36]: np.random.randn(2, 3)
Out[36]:
array([[-1.74976547,  0.3426804 ,  1.1530358 ],
       [-0.25243604,  0.98132079,  0.51421884]])

В одномерном ndarray в NumPy он работает как список, который можно нарезать, пройти и т.д.:

In [5]: a
Out[5]: array([1., 2., 3., 4., 5., 6., 7., 8., 9.])

In [6]: a[2], a[2:5]
Out[6]: (3.0, array([3., 4., 5.]))

In [7]: a * 3, a ** 3   # 立方
Out[7]:
(array([ 3.,  6.,  9., 12., 15., 18., 21., 24., 27.]),
 array([  1.,   8.,  27.,  64., 125., 216., 343., 512., 729.]))
 
In [13]: for i in a:
...:     print(i, end=", ")
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0,

Если наш ndarray представляет собой не одномерный массив, а двумерную матрицу или многомерный ndarray, нам нужно разделить его на несколько измерений. иКогда мы пересекаем многомерный ndarray, размерность одного пройденного результата на единицу меньше, чем размерность элемента.Например, результат, полученный путем обхода двумерной матрицы, представляет собой одномерный вектор, а результат трехмерный обход представляет собой двумерную матрицу.

Кроме того, следует отметить, что размерность добавляемых мне данных довольно высока.Чтобы облегчить нам индексацию данных, NumPy предоставляет нам...Способ разделения на конкретном примере выглядит следующим образом:

In [14]: a = np.random.randint(0, 2, 6).reshape(2, 3)

In [15]: a
Out[15]:
array([[1, 1, 1],
       [1, 0, 1]])

In [16]: a[:, :2]
Out[16]:
array([[1, 1],
       [1, 0]])

In [17]: for i in a:        # 对矩阵进行遍历,则输出的是行向量,单个输出的维度比原维度少1
    ...:     print(i, end=", ")
[1 1 1], [1 0 1],

In [19]: data = np.random.randint(0, 2, [2, 2, 3])

In [20]: data
Out[20]:
array([[[0, 0, 1],
        [0, 1, 1]],

       [[1, 0, 0],
        [0, 1, 0]]])

In [21]: data[..., :2]      # ...则表示前两个维度全要,相当于 data[:, :, :2]
Out[21]:
array([[[0, 0],
        [0, 1]],

       [[1, 0],
        [0, 1]]])

операция формы:

  • a.ravel(), ndarray.flatten(), stretch ndarray (выпрямление в векторную форму)
  • a.reshape(), изменить форму
  • a.T, a.transpose(), возвращают перевернутую матрицу

Описанные выше операции возвращают новые результаты без изменения исходного ndarray(a). И ** Вышеупомянутые операции по умолчанию являются горизонтальными операциями. Если вам нужны вертикальные операции, вам необходимо управлять параметром порядка. Для конкретных операций, пожалуйста, обратитесь к руководству для новичков. **В дополнение к изменению формы существует также изменение размера, но изменение размера изменит результат вместо создания нового результата:

Еще одна хитрость, которую нужно освоить, заключается в том, что при изменении формы, если передается -1, соответствующий результат будет рассчитан автоматически. Например, для матрицы 2x3 a мы выполняем a.reshape(3, -1), тогда -1 здесь представляет 2. Когда у нас есть большой объем данных, это довольно удобно использовать:

In [44]: a
Out[44]:
array([[1, 1, 1],
       [1, 0, 1]])

In [45]: a.reshape([3, -1])
Out[45]:
array([[1, 1],
       [1, 1],
       [0, 1]])

Изменение размеров массива:

измерение описывать
broadcast_to широковещательный массив в новую форму
expand_dims Разверните форму массива
squeeze Удалить одномерные записи из формы массива

Конкретные операции заключаются в следующем:

Объединение массивов:

функция описывать
concatenate Объединение последовательностей массивов вдоль существующих осей
hstack Массивы в горизонтальной последовательности (ориентация столбца)
vstack Массивы в вертикальной последовательности (по строкам)

В следующем коде показана операция соединения массива, в которой конкатенация может определять направление соединения, контролируя значение оси, что эквивалентно hstack и vstack. Еще один момент, который следует отметить, заключается в том, что следующий пример предназначен только для соединения двух массивов, на самом деле несколько массивов могут быть подключены одновременно, напримерnp.concatenate((x, y, z), axis=1)

Разделите массив:

функция описывать
split Разделить массив на несколько подмассивов
hsplit Разбить массив по горизонтали на несколько подмассивов (по столбцам)
vsplit Разделить массив по вертикали на подмассивы (по строкам)

Как и при соединении массивов, сплит может достигать того же эффекта, что и hsplit и vsplit, управляя атрибутом оси.Ниже приведен только пример сплита.Для hsplit и vsplit, пожалуйста, обратитесь к официальным документам:

Добавление и удаление элементов массива:

функция описывать
append добавить значение в конец массива
insert Вставляет значение по указанной оси перед указанным нижним индексом
delete Удалить подмассив оси и вернуть новый массив после удаления

Вещание — это способ numpy выполнять числовые вычисления над массивами различной формы.Арифметические операции над массивами обычно выполняются над соответствующими элементами.

Если два массива a и b имеют одинаковую форму, то есть a.shape == b.shape, то результатом a*b является произведение соответствующих битов массивов a и b. Для этого требуется одинаковое количество измерений и одинаковая длина для каждого измерения.

In [8]: import numpy as np

In [9]: a = np.array([1,2,3,4])
   ...: b = np.array([10,20,30,40])

In [10]: a * b
Out[10]: array([ 10,  40,  90, 160])

Когда формы двух массивов в операции различны, numpy автоматически запускает механизм вещания. как:

In [11]: a = np.array([[ 0, 0, 0],
    ...:            [10,10,10],
    ...:            [20,20,20],
    ...:            [30,30,30]])
    ...: b = np.array([1,2,3])

In [12]: a + b
Out[12]:
array([[ 1,  2,  3],
       [11, 12, 13],
       [21, 22, 23],
       [31, 32, 33]])

На изображении ниже показано, как можно транслировать массив b, чтобы он был совместим с массивом a.

来源:菜鸟教程

np.tile может транслировать расширение массива целевых операций. Например, 1x3 можно транслировать как 4x6. Обратите внимание, что это отличается от упомянутого выше Broad_to. Broad_to должен быть расширен, а тайл может быть расширен или нет. конкретная операция Делайте это в соответствии с вашими реальными потребностями.

Читатели, имеющие опыт работы с Tensorflow, должны знать, что внутри также есть тайловые и широковещательные операции, но когда объем наших данных относительно велик, говорят, что эффективность тайлов ниже, чем у широковещательных.

In [20]: a
Out[20]: array([[1, 1, 0]])

In [21]: np.tile(a, [4, 2])     # 第二个参数表示各个维度广播的倍数,这里表示的是行扩4倍,列扩2倍
Out[21]:
array([[1, 1, 0, 1, 1, 0],
       [1, 1, 0, 1, 1, 0],
       [1, 1, 0, 1, 1, 0],
       [1, 1, 0, 1, 1, 0]])

О копировании и попытке в NumPy: эта часть знаний также является моментом, который я упустил, когда изучал NumPy раньше.Я воспользовался этой возможностью, чтобы записать это здесь.

  • нет копии

В связи с этим, собственно, ранее было зафиксированоГорячие вопросы LeetCode HOT 100 (01, добавление двух цифр)Это также было указано в алгоритме,Это по-прежнему требует особого внимания.

  • Просмотр или мелкая копия (просмотр)

Также используется тот же код, что и выше, только изменена строка 57, и y = x и y = x.view(), можно обнаружить, что значения id x и y в это время разные, то есть то есть их адреса памяти различны.Точно так же, после того как мы изменим форму x, форма y не изменится.

Однако, когда мы меняем не форму, а данные внутри массива переменных, другой массив тоже изменится

  • Копия или глубокая копия (копия)

Представление или неглубокая копия используетview, в то время как копия или глубокая копия используетcopy. использоватьcopyПри изменении формы одного массива или внутренних элементов другой массив не изменится.

(Что касается копирования, код здесь больше не демонстрируется, читатели могут работать сами, а затем сравнивать)

Наконец, чтобы подвести итог:

  • у = х, заявив х и уАдреса памяти одинаковые, измените один из них, и другой тоже изменится (будь то форма, или внутренние элементы)
  • у = х.вид(),Два адреса памяти разные, изменить форму одного из них,другой не изменится; при изменении внутреннего элемента одного из кортежей,тогда другой изменится
  • у = х.копировать(),Два адреса памяти разные, будь то изменение формы кортежа или внутренних элементов,Другой не изменится, два независимы друг от друга

Математически связанные функции в NumPy, в этой части не о чем говорить:

  • np.pi, возвращает значение числа пи
  • np.sin(), возвращает значение синуса
  • np.cos(), возвращает значение косинуса
  • np.tan(), возвращает касательную
  • numpy.ceil() возвращает наименьшее целое число, большее или равное указанному выражению, то есть округленное в большую сторону.
  • np.exp(2), возвращает значение экспоненты, то естьe2e^2

Другие связанные математические функции см. в официальной документации.

Арифметические операции в NumPy, в этой части особо не о чем говорить:

  • numpy.add(a,b): добавить два массива
  • numpy.subtract(a,b): вычесть два массива
  • numpy.multiply(a,b): умножить два массива
  • numpy.divide(a,b): разделить два массива
  • numpy.reciprocal(a), возвращает обратное
  • numpy.power(a, 4), возвращает четвертую степень

Статистические функции в NumPy, это небольшая запись:

В приведенном выше примере показано, как получить разницу между максимальным значением и максимальным значением в массиве.Если передан параметр оси, он будет получен в соответствии с соответствующим направлением.Если параметр оси не передан, это означает что получается общее максимальное значение массива. В дополнение к вышеупомянутым интерфейсам существуют другие общие статистические функции, а конкретные операции такие же, как и описанные выше, а именно:

  • np.amin(): получить минимальное значение
  • np.amax(): получить максимальное значение
  • np.ptp(): получить разницу между максимальными значениями
  • np.median(): получить медиану (медиану)
  • np.mean(): получить среднее значение
  • np.var(): получить дисперсию,о2=1ni=1n(xix)2\sigma^2 = \frac{1}{n}\sum_{i=1}^n(x_i-\overline{x})^2
  • np.std(): получить стандартное отклонение,о\sigma

Линейная алгебра в NumPy:

  • np.dot(a, b) — произведение двух матриц
  • np.vdot(a, b) Сумма произведений соответствующих номеров позиций двух матриц
  • np.inner(a, b) внутренний продукт, то есть сумма каждой строки a и каждой строки b

Например, a=[[1, 0], [1, 1]], b=[[1, 2], [1, 3]] np.inner(a, b) эквивалентен [1, 0] * [1, 2] = 1 -> первое число [1, 0] * [1, 3] = 1 -> второе число [1, 1] * [1, 2] = 3 -> третье число [1, 1] * [1, 3] = 4 -> четвертое число

Продукт матрицы представляет собой сумму произведений строк первой матрицы и произведений столбцов второй матрицы, а внутренний эквивалентен сумме произведений строк первой матрицы и второй матрицы.

  • np.matmul(a, b) в настоящее время выглядит так же, как np.dot(a, b), оба являются матричными продуктами
  • np.linalg.det(a) Вычислить значение определителя матрицы
  • np.linalg.solve(a, [[1], [1]]) Найдите решение системы линейных уравнений, первый параметр эквивалентен коэффициенту, второй параметр эквивалентен термину параметра
  • np.linalg.inv(a) вычисляет обратную матрицу

# 将数组保存到以 .npy 为扩展名的文件中。
numpy.save(file, arr, allow_pickle=True, fix_imports=True)
  • файл: файл, который нужно сохранить, с расширением .npy. Если путь к файлу не имеет расширения .npy в конце, расширение будет добавлено автоматически.
  • arr: массив для сохранения
  • allow_pickle: необязательный, логический, позволяет сохранять массивы объектов, используя пиклы Python, которые используются в Python для сериализации и десериализации объектов перед сохранением или чтением из файлов на диске.
  • fix_imports: необязательный, чтобы облегчить чтение данных, сохраненных Python3 в Pyhton2.
In [81]: a = np.random.randint(1, 10, [3, 4])

In [82]: np.save("a.npy", a)

In [83]: np.load("a.npy")
Out[83]:
array([[2, 7, 3, 1],
       [4, 6, 4, 3],
       [2, 2, 9, 5]])

Использованная литература:

Использованная литература:

[1] Учебник для новичков в NumPy:вооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооо.

[2] Официальная документация NumPy:номер py.org/doc/stable/…

Времени мало, да и позднее написание немного поспешное, но это не должно мешать нормальному чтению и дальнейшему обзору, так что пока займемся.

Примечание: Записаны только некоторые часто используемые. Если другие будут использоваться позже, они будут обновлены. Для другого контента вы можете самостоятельно обратиться к документации.

Изначально я планировал рвать код по книге "Машинное обучение в действии", но из практических соображений может понадобиться сначала рвать SVM вручную.. Этот алгоритм до сих пор чувствует себя достаточно головной болью, да и внутренности слишком , и очень мало данных для его полного вывода, а также включает много странных терминов, таких как: оптимизация при нелинейных ограничениях, условия ККТ, лагранжева двойственность, максимальный интервал, оптимальная нижняя граница, функции ядра и т. д., Тяньшу может, может быть, наверное, так. К счастью, я изучил SVM раньше, но мне все еще нужно потратить много усилий, чтобы разорвать его вручную, а также мне нужно обратиться к множеству материалов, включая, помимо прочего, «Машинное обучение в действии/Машинное обучение в Действие», «Машинное обучение», «Статистическое обучение».

Поэтому в следующем выпуске я должен начать рвать SVM вручную.Насчет того, удастся ли его успешно порвать вручную, сказать действительно сложно. Это может занять много времени, и в этот период LeetCode HOT 100 необходимо чистить щеткой в ​​обычном режиме.

Я Taoye, я люблю учиться, делиться и люблю различные технологии. В свободное время я люблю играть в шахматы, слушать музыку и говорить об анимации. Я надеюсь использовать это, чтобы записать свой собственный процесс роста и жизни. Я также надеюсь, что смогу завести больше друзей-единомышленников в кругу, и приглашаю посетить WeChat Princess для получения большего количества контента:Циничный кодер.

Рекомендуемое чтение:

Что ты не можешь сделать, сначала поешь
Таойе проникла в штаб-квартиру черной платформы, и правда, стоящая за этим, была чрезвычайно ужасающей.
«База данных Dahua» — когда выполняется оператор SQL, какие небольшие действия выполняет нижний уровень?
В те годы Git, в который мы играли, действительно ароматный
Создание среды глубокого обучения на основе блокнота Ubuntu+Python+Tensorflow+Jupyter
Причудливый синтаксический анализ веб-страницы
Рука об руку, чтобы помочь вам понять технологию контейнеров Docker
Подробное объяснение сайта Hexo+Github Xiaobai.
Правильный способ открытия ElasticSearch, kibana, logstash