Впереди написано: я объясню часто используемые алгоритмы машинного обучения с точки зрения новичка (уровень). Мой собственный уровень действительно ограничен, и если есть какие-то ошибки, я надеюсь, что вы укажете на них и не будете вводить вас в заблуждение. Есть много вещей, которые я хочу сказать о вводной главе, поэтому я возьму еще одну главу, чтобы представить свое личное понимание области машинного обучения и некоторое введение в здравый смысл. Если у вас есть больше времени, вы можете увидеть меня
前言
текстовое введение.
0 Предисловие
Представить личные мысли
0.1 О машинном обучении
Нет сомнений, что машинное обучение сейчас становится все более популярным, и спрос будет продолжать расти с последующим взрывом искусственного интеллекта. Независимо от того, работаете вы в этой области программирования или нет, необходимо понимать, что такое машинное обучение, по крайней мере иметь рациональное понимание, а не чувствовать себя очень загадочным. Но математические знания, связанные с алгоритмом, можно игнорировать, пока мы знаем, что можем достичь определенной цели с помощью определенных математических средств. Например, линейная регрессия, которая будет представлена здесь, основана на алгоритме градиентного спуска при обновлении весов. Вам не нужно знать, что такое градиентный спуск. Зная, что у математики есть свои собственные средства для решения оптимизации, конечно, это лучше, если ты это знаешь. Из-за характера машинного обучения практически невозможно быстро начать, и сейчас оно находится в стадии быстрого развития, и необходимо поддерживать энтузиазм для продолжения обучения. Кроме того, стоимость обучения на ранней стадии относительно высока.Прежде чем писать код самостоятельно, если вы хотите иметь немного уверенности, по крайней мере, вы должны быть правы.微积分
,线性代数
и概率论
Приложение нуждается в собственном понимании. Так что это тоже большое преимущество, и заменить его непросто.
0.2 О линейной регрессии
Кратчайший путь к рациональному пониманию машинного обучения — понять весь процесс алгоритма линейной регрессии.Если вы действительно понимаете линейную регрессию в этой статье, вам следует понять это предложение. Конечно, у большинства людей, прочитавших эту статью, вероятно, уже есть собственное понимание линейной регрессии. Но я хочу упомянуть здесь, что если вы не планируете начинать с машинного обучения, чтение о линейной регрессии также является хорошим способом расширить свои знания, потому что в основном большинство людей начинают именно с этого.
0.3 Об основах
Сначала нужно немногоБаза. Если нет, то легко научиться самостоятельно. Затем научитесь использовать следующие инструменты:NumPy
,Matplotlib
,sklearn
,TensorFlow
. Некоторые из них могут ссылаться на мои предыдущие статьи.
- Начало работы с машинным обучением с TensorFlow
- Официальное руководство по началу работы с NumPy (перевод)
- Основные операции Matplotlib
- Matplotlib сохраняет GIF-анимацию
С ними вам также нужна математическая основа. С точки зрения математики, я не думаю, что нужно учить все, да и не реально, математические доказательства можно искать, когда сталкиваешься с какими-то алгоритмами в процессе написания кода. Здесь я думаю, что некоторая популяризация математики на Zhihu на самом деле неплоха.В конце концов, это не математический факультет, поэтому я думаю, что это не проблема, чтобы использовать его после понимания основной логики.
0.4 О ссылках
Я очень благодарен таким учителям, как Ву Энда и Мо Фань, за их самоотверженную самоотверженность, а также многим людям, которые ведут блоги и делятся знаниями в Интернете, благодаря чему в индустрии программирования сформировалась хорошая учебная атмосфера. И в Интернете циркулирует много качественных учебных ресурсов, поэтому здесь я разобрала справочные материалы моего учебного процесса.GitHub, я думаю, что каждый вносит свой вклад для лучшего обучения других.Если есть какие-либо нарушения, я немедленно удалю это. Затем в этой серии статей я буду в основном записывать и практиковать с точки зрения начинающих на основе курсов г-на Ву Энда.
0.5 Обо мне
Студент бакалавриата, который собирается получить высшее образование с ограниченными знаниями, поэтому в статье должно быть много недостатков, надеюсь, вы меня поправите. Затем экспериментальный код находится вздесь.
1. Предпосылки
Сюжет рассказывать не буду, можете посмотреть видео. Далее, какую проблему я хочу решить? Часто в жизни бывает много явлений, и мы можем сделать определенные выводы из явлений, но если мы видим явление, которого никогда раньше не видели, мы не можем делать выводы. Но некоторые опытные люди могут делать прогнозы с богатым опытом. Например, ребенок в невежественном периоде не может предсказать, что будет дождь, когда увидит темную тучу, но взрослый узнает и напомнит ребенку, чтобы он взял с собой зонт, выходя на улицу. . . Ну а пока рассказываем, идем дальше ??? Разница между взрослыми и детьми в этом примере заключается в том, что они разные по возрасту, знаниям, уровню знаний, и суждения, которые они могут делать, естественно разные. Поэтому, если вы хотите предсказать явление, вы должны изучить Когда ребенок вырастет, он возьмет зонтик, когда увидит движение муравьев.
Что ж, давайте резюмируем вышеизложенную историю: явления можно сравнивать с данными, и поведение, вызванное выводом, тоже данные, с той лишь разницей, что вывод делается из явления, поэтому данные явления можно рассматривать как ввод и данные вывода в качестве вывода. Затем машинное обучение заключается в том, чтобы вводить входные данные в модель, а затем сравнивать выходные данные модели с предыдущими «правильными» выводами и медленно изменять модель до тех пор, пока модель не будет лучше прогнозировать входящие и исходящие данные, затем модель можно использовать. Абстрагировать это значит найти входи выводотображение между, так что для подавляющего большинстваможет быть нанесен на картупоправляйся.
Я не буду приводить пример с ценами на жилье, просто посмотрите на картинку ниже, чтобы понять, можно ли ее решить.
# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt
def draw():
X = np.linspace(0, 10, 50)
noise = np.random.normal(0, 0.5, X.shape)
Y = X * 0.5 + 3 + noise
plt.scatter(X, Y)
plt.savefig("scattergraph.png")
plt.show()
if __name__ == "__main__":
draw()
Ну, вы можете найти, что датьОн опирается на интуицию, поэтому ответы у всех разные, и для некоторых сфер с едиными стандартами (например, военных проектов) такого рода полагаться на интуицию категорически нельзя. Представьте, как можно полагаться на интуицию, чтобы успешно сражаться на современном информационном поле боя?
Итак, нам нужна модель, вы можете понять ее как черный ящик, поставьтекормить, положитьВынеси, и неважно кто, лишь бы черный ящик был один и тот же, тогда вклад каждогоЕсли то же самое, выведитето же самое. Итак, какова форма модели здесь? В настоящее время выбор остается за нашим человеческим вмешательством. Интуитивно это распределение можно рассматривать как очень толстую линию, затем мы выбираем линейную модель для имитации распределения. Так как же определить эту линейную модель? Вот главный герой сегодняшнего дня:Линейная регрессия
2 Одномерная линейная регрессия
Начнем с анализа одномерной линейной функции, Поскольку предполагается, что это одномерная линейность, наша подгоночная функция может быть определена как. Как и на предыдущем рисунке в качестве примера, наша текущая цель — найти, если найдено, задано любоеможно найтиприходящий.
2.1 Определение функции оценки - функция потерь
Вот как получитьвесь мыслительный процесс.
мы выбираем точкуИз-за наличия ошибок, т.. Аналогично, если точек много, то имеют место следующие результаты.Для удобства возьмем оценочное значение.
Наша цель, естественно, состоит в том, что чем меньше ошибка, тем лучше, поэтому ошибка выражается в виде суммы квадратов:
Вот, давайте посмотрим, как выглядит изображение?
PS: Картинка немного некрасивая, реально никак не сделать.Шум настроен так, что размах значений функции очень большой.Если немного изменить, то получится лицо. Я могу только создать точечную диаграмму, чтобы справиться с этим, и я надеюсь, что друзья, которые знают об этом, дадут мне знать. Что ж, не тратьте здесь слишком много времени, просто посмотрите на код.
# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = Axes3D(fig)
ax.set_xlabel(r'$Weight$')
ax.set_ylabel(r'$bias$')
ax.set_zlabel(r'$loss\ value$')
N = 200
X = np.linspace(0, 10, N)
noise = np.random.normal(0, 0.1, X.shape)
Y = X * 0.5 + 3 + noise
W = np.linspace(-10, 10, N)
b = np.linspace(-2, 8, N)
p = 0.6
plt.xlim(W.min() * p, W.max() * p)
plt.ylim(b.min() * p, b.max() * p)
ax.set_zlim(0, 1000)
h = []
for i in W:
for j in b:
h.append(np.sum(np.square(Y - (X * i + j))))
print(np.min(h))
h = np.asarray(h).reshape(N, N)
W, b = np.meshgrid(W, b)
ax.scatter(W, b, h, c='b')
plt.savefig("lossgraph.png")
plt.show()
Теперь мы знаем примерное положение для получения минимального значения визуальными средствами, на самом деле мы еще не достигли цели.конкретное значение.
2.2 Решение минимума — градиентный спуск
Проблема дополнительно уточняется, и ее нужно решить, когда следующие бинарные функции принимают экстремальные значения:
В это время высокий номер вышел на сцену и нашел картину
Тогда вопрос очень простой, просто спросите прямоЧастная производная равнасистема уравнений. Но это математический метод, который не соответствует компьютерному мышлению.Это похоже на решение одномерного линейного уравнения.Общий метод заключается в том, чтобы напрямую брать значения в области определения одно за другим, пока результаты не будут соответствовать ожидания. Конечно, чуть более продвинутый подход заключается в написании интерпретатора для программирования методов вычислений, выполняемых человеком. Очевидно, что здесь это нереально, и если тип уравнения изменится, интерпретатор, вероятно, не сработает. Поэтому мы по-прежнему придерживаемся «глупого» метода, одобренного машиной, и думаем о предложении, произнесенном учителем-вводником, оценивающим компьютеры в начале учебного года:fast but stupid
. Это показывает, что в этом случае мы можем принять быстро, чтобы компенсировать другие недостатки, пока расчетное значение шаг за шагом близко к конечному результату, оно может удовлетворить спрос. На самом деле здесь эти характеристики компьютеров, которые становятся быстрее, имеют определенную связь с развитием машинного обучения и искусственного интеллекта.
Что ж, давайте начнем думать о том, как сделать так, чтобы результат медленно приближался к экстремальному значению.
Мы можем думать об этом так: случайным образом поместить мяч на эту плоскость, и когда мяч запрещен, его положение является положением крайнего значения. Итак, как мы имитируем этот процесс?
Шаг 1: Положите мяч
Это легко сделать, просто случайным образом разместите его в любом месте области определения.
Шаг 2: прокрутите
Как имитировать качение — сложный момент, но его легко понять после тщательного анализа. Вы можете думать о себе как о мяче и начать стоять в очень нестабильном месте, тогда вашей естественной реакцией должно быть перейти на ровное место, при условии, что высота каждой позиции одинакова. Это означает, что места с большими уклонами имеют больше шансов быстрее упасть на дно. В этом примере есть неуместное место, вы можете подумать о следующей квадратичной функции, здесь в основном для опыта такого рода мышления, и мы можем быть гибкими. Когда у вас такое склонное мышление, с ним легко справиться.我们总是希望在给定步长的情况下,往水平最低的地方行进
. Среди них сложно определить, какой из них является самым низким. У компьютера нет интуиции. Если значение не установлено должным образом, это может привести к слишком медленной сходимости функции или прямому расхождению, что является вещами, которые машинное обучение должно попытайся избежать.
Чтобы лучше проанализировать проблему, воспользуемся методом управляющих переменных. Как видите, в функции потерь есть две переменные.,когдазанять определенное время,является квадратичной функцией.
# coding: utf-8
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
N = 200
X = np.linspace(0, 10, N * 2)
noise = np.random.normal(0, 0.1, X.shape)
Y = X * 0.5 + 3 + noise
W = 1
b = np.linspace(-5, 6, N)
h = []
for i in b:
h.append(np.sum(np.square(Y - (X * W + i))))
plt.plot(b, h)
plt.savefig("quadraticFunction.png")
plt.show()
Давайте взглянем непосредственно на курс г-на Ву Энда, я не хочу рисовать картинку. . .
Теперь мы можем вывести правило обновления.Чтобы найти здесь минимальное значение, это вывод для унарной функции и частичный вывод для многомерной функции. Очевидно, что когда наклон положительный, мы должны двигаться в отрицательном направлении, и наоборот. Таким образом, мы можем добавить функцию, которая обратно пропорциональна наклону, чтобы не отставать от нового значения, Что касается силы обновления, то есть, как далеко идти, это настройка скорости обучения. И чем дальше от крайней точки, тем больше абсолютное значение наклона, тем больше шаг, что соответствует логике обновления.
Что может быть чем-то вроде прыжка в голову, так это то, что все, кроме одного, вы можете думать с точки зрения количества данных или с точки зрения обновления наклона, потому что при обновлении веса мы не только вычисляем наклон точки, если прямое суммирование неизбежно приведет к чрезмерному весу и окончательный результат расходится, вы можете попробовать изменить код самостоятельно. Что ж, теперь, когда основные идеи готовы, давайте напишем код для их реализации.
# coding: utf-8
import matplotlib.pyplot as plt
import numpy as np
N = 200
X = np.linspace(0, 10, N * 2)
noise = np.random.normal(0, 0.5, X.shape)
Y = X * 0.5 + 3 + noise
def calcLoss(train_X, train_Y, W, b):
return np.sum(np.square(train_Y - (train_X * W + b)))
def gradientDescent(train_X, train_Y, W, b, learningrate=0.001, trainingtimes=500):
global loss
global W_trace
global b_trace
size = train_Y.size
for _ in range(trainingtimes):
prediction = W * train_X + b
tempW = W + learningrate * np.sum(train_X * (train_Y - prediction)) / size
tempb = b + learningrate * np.sum(train_Y - prediction) / size
W = tempW
b = tempb
loss.append(calcLoss(train_X, train_Y, W, b))
W_trace.append(W)
b_trace.append(b)
Training_Times = 100
Learning_Rate = 0.002
loss = []
W_trace = [-1]
b_trace = [1]
gradientDescent(X, Y, W_trace[0], b_trace[0], learningrate=Learning_Rate, trainingtimes=Training_Times)
print(W_trace[-1], b_trace[-1])
fig = plt.figure()
plt.title(r'$loss\ function\ change\ tendency$')
plt.xlabel(r'$learning\ times$')
plt.ylabel(r'$loss\ value$')
plt.plot(np.linspace(1, Training_Times, Training_Times), loss)
plt.savefig("gradientDescentLR.png")
plt.show()
На данный момент мы в основном реализуем линейную регрессию унарных переменных вручную, Здесь, чтобы облегчить время обучения, количество тренировок относительно невелико, толькораз, этого далеко не достаточно, я проверял, и, наверное, доходитТренировочный эффект лучше. Конечно, вы также можете настроить скорость обучения, начальное значение... Читатели могут попробовать сами.
3 Множественная линейная регрессия
Здесь мы сначала разделяем и понимаем, что многомерный представляет несколько независимых переменных, а линейный представляет, что независимые переменные удовлетворяют однородности и аддитивности, Регрессия - это метод выражения. Одномерное просто в обращении, мы можем реализовать визуализацию с помощью различных инструментов, но есть некоторые трудности в многомерном представлении, особенно в многомерном линейном пространстве, мы не можем себе этого представить. Таким образом, мы должны абстрагироваться и использовать математические обозначения вместо этих сложных переменных.
Возможно, вы уже подумали, да, да, мы собираемся использовать линейную алгебру. Если у вас раньше не было небольшой основы, вы можете потратить немного времени на Zhihu, чтобы понять, что делает линейная алгебра.Здесь задействованы только базовые знания и применение линейной алгебры.
Предположим, что у нас есть три независимые переменныеи зависимая переменная, и находится в соответствии с линейной зависимостью. Тогда будет выполняться следующее уравнение:
Предположим, у нас есть четыре набора данных, то есть:
Таким образом, мы можем абстрагироваться от следующего и записать его в виде матрицы:
Реферат:
в
Наша цель - решить, то есть уравнениесерединареши. Прямое решение уравнения даст нужный нам эффект, отлично, начнем прямо сейчас:
Если вы не поняли здесь, позвольте мне кратко сказать, что обратная операция должна быть в видеФорма, то есть строки и столбцы должны быть равны. Почему это так? Насколько я понимаю, матрица — это отображение из одного линейного пространства в другое линейное пространство, поэтому, если ранг матрицы меньше количества строк, то есть в ней есть линейно связанные векторы, когда линейное пространство трансформируется, на него может повлиять уменьшение размерности, то есть вызвать коллапс определенного измерения, этот эффект необратим, поэтому эта матрица восстанавливается без обратной матрицы. Если вы хотите сопоставить один вектор с другим вектором и обратно с другого вектора, эта матрица должна иметь обратную матрицу полного ранга. Есть еще такая вещь, как сингулярная матрица, вы можете узнать о ней, если вам интересно.
Вернемся к основной теме, давайте просто решим уравнение.
# coding: utf-8
import numpy as np
X1 = np.asarray([2104, 1416, 1534, 852]).reshape(4, 1)
X2 = np.asarray([5, 3, 3, 2]).reshape(4, 1)
X3 = np.asarray([1, 2, 2, 1]).reshape(4, 1)
X = np.mat(np.column_stack((X1, X2, X3, np.ones(shape=(4, 1)))))
noise = np.random.normal(0, 0.1, X1.shape)
Y = np.mat(2.5 * X1 - X2 + 2 * X3 + 4 + noise)
YTwin = np.mat(2.5 * X1 - X2 + 2 * X3 + 4)
W = (X.T * X).I * X.T * Y
WTWin = (X.T * X).I * X.T * YTwin
print(W, "\n", WTWin)
# output:
# [[ 2.50043958]
# [-1.16868808]
# [ 1.79213736]
# [ 4.27637958]]
# [[ 2.5]
# [-1. ]
# [ 2. ]
# [ 4. ]]
Здесь мы используем данные о доме г-на Ву Энда.Слишком большое сходство между данными, сгенерированными нами, и ошибка вычисленных результатов слишком велика.
В основном мы можем рассчитать множественную линейную регрессию, но это вообще не отражает словообучение в машинном обучении.Конечно, мы можем использовать приведенный выше пример, чтобы использовать его самостоятельно.функциональное решение. Здесь мы используемПомогите нам закончить.
# coding: utf-8
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
N = 1000
train_X1 = np.linspace(1, 10, N).reshape(N, 1)
train_X2 = np.linspace(1, 10, N).reshape(N, 1)
train_X3 = np.linspace(1, 10, N).reshape(N, 1)
train_X4 = np.linspace(1, 10, N).reshape(N, 1)
# train_X = np.column_stack((train_X1, np.ones(shape=(N, 1))))
train_X = np.column_stack((train_X1, train_X2, train_X3, train_X4, np.ones(shape=(N, 1))))
noise = np.random.normal(0, 0.5, train_X1.shape)
# train_Y = 3 * train_X1 + 4
train_Y = train_X1 + train_X2 + train_X3 + train_X4 + 4 + noise
length = len(train_X[0])
X = tf.placeholder(tf.float32, [None, length], name="X")
Y = tf.placeholder(tf.float32, [None, 1], name="Y")
W = tf.Variable(np.random.random(size=length).reshape(length, 1), dtype=tf.float32, name="weight")
activation = tf.matmul(X, W)
learning_rate = 0.006
loss = tf.reduce_mean(tf.reduce_sum(tf.pow(activation - Y, 2), reduction_indices=[1]))
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
training_epochs = 2000
display_step = 100
loss_trace = []
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for epoch in range(training_epochs):
sess.run(optimizer, feed_dict={X: train_X, Y: train_Y})
temp_loss = sess.run(loss, feed_dict={X: train_X, Y: train_Y})
loss_trace.append(temp_loss)
if 1 == epoch % display_step:
print('epoch: %4s'%epoch, '\tloss: %s'%temp_loss)
print("\nOptimization Finished!")
print("\nloss = ", loss_trace[-1], "\nWeight =\n", sess.run(W, feed_dict={X: train_X, Y: train_Y}))
plt.plot(np.linspace(0, 100, 100), loss_trace[:100])
plt.savefig("tensorflowLR.png")
plt.show()
# output:
# epoch: 1 loss: 118.413925
# epoch: 101 loss: 1.4500043
# epoch: 201 loss: 1.0270562
# epoch: 301 loss: 0.75373846
# epoch: 401 loss: 0.5771168
# epoch: 501 loss: 0.46298113
# epoch: 601 loss: 0.38922414
# epoch: 701 loss: 0.34156123
# epoch: 801 loss: 0.31076077
# epoch: 901 loss: 0.29085675
# epoch: 1001 loss: 0.27799463
# epoch: 1101 loss: 0.26968285
# epoch: 1201 loss: 0.2643118
# epoch: 1301 loss: 0.26084095
# epoch: 1401 loss: 0.2585978
# epoch: 1501 loss: 0.25714833
# epoch: 1601 loss: 0.25621164
# epoch: 1701 loss: 0.2556064
# epoch: 1801 loss: 0.2552152
# epoch: 1901 loss: 0.2549625
# Optimization Finished!
# loss = 0.25480175
# Weight =
# [[1.0982682 ]
# [0.9760315 ]
# [1.0619627 ]
# [0.87049955]
# [3.9700394 ]]
Эффект подгонки здесь не очень хороший. Я не знаю, проблема ли это в данных. Поскольку сходство роста данных слишком велико, я чувствую, что это может быть чрезмерная подгонка. Если кто-нибудь знает, пожалуйста, дайте мне знать. Вы можете увидеть на рисунке нижеСконденсировался рано.
4 Резюме
Процесс решения линейной регрессии интуитивно понятен и соответствует нашему пониманию. Существует предвзятое мнение об этой проблеме, что данные должны быть подобраны линейно, потому что это линейная регрессия. Конечно, метод, согласно которому распределение данных не является линейным, неприменим.Точно так же, если мы не можем видеть распределение данных и не можем оценить модель, мы можем проверить ее только шаг за шагом, поэтому машинное обучение начинается с выбора данные, которые подходят для текущих данных.Модель может быть понята как поиск разумного отношения отображения между входом и выходом, затем импорт данных, построение функции потерь, которая может правильно оценить эффект подгонки, а затем оптимизация функции потерь.Есть проблема, которая не упоминалась ранее.Если мы просто ищем случайным образом, на самом деле, мы не можем гарантировать, что то, что мы находим, является глобальным оптимумом.Конечно, в целом модель, полученная с помощью локального оптимума, уже может хорошо предсказывать результат. Это только мое личное понимание, все желающие могут обсудить, а затем экспериментальный код находится в моемGitHubНа, вы можете подобрать то, что вам нужно. Потом эта серия может продолжать обновляться, но до следующего обновления может пройти какое-то время, т.к. с Новым Годом ^_^, а справочные материалы даны ранее, так что не буду их все перечислять спасибо.