содержание
-
Реализация алгоритма машинного обучения на Python
- 1. Линейная регрессия
- 2. Логистическая регрессия
- Логистическая регрессия_Распознавание рукописных цифр_OneVsAll
- 3. Нейронная сеть БП
- В-четвертых, машина опорных векторов SVM
- Пять, алгоритм кластеризации K-средних
-
6. Анализ основных компонентов PCA (уменьшение размерности)
- 1. Используйте
- 2. 2D-->1D, nD-->kD
- 3. Разница между PCA и линейной регрессией
- 4. Процесс уменьшения размерности PCA
- 5. Восстановление данных
- 6. Выбор количества главных компонентов (т. е. уменьшаемой размерности)
- 7. Рекомендации по применению
- 8. Запуск результатов
- 9. Используйте PCA в библиотеке scikit-learn для уменьшения размерности
-
Семь, обнаружение аномалий Обнаружение аномалий
- 1. Распределение Гаусса (нормальное распределение)
- 2. Алгоритм обнаружения аномалий
- 3. Качество оценки и отбора
- 4. Выберите, какую функцию использовать (единичное распределение Гаусса)
- 5. Многомерное распределение Гаусса
- 6. Единичные и многомерные характеристики распределения Гаусса
- 7. Результаты работы программы
один,Линейная регрессия
1. Функция стоимости
-
Далее следует запросить тета, чтобы минимизировать стоимость, что означает, что уравнение, которое мы подгоняем, ближе всего к истинному значению.
-
Имеется m элементов данных, из которыхПредставляет квадрат расстояния от уравнения, которое мы хотим подогнать к истинному значению. Причина квадрата в том, что могут быть отрицательные значения, а положительные и отрицательные могут смещаться
-
коэффициент перед
2
Причина в том, что следующий градиент должен найти частную производную каждой переменной,2
можно устранить -
Код реализации:
# 计算代价函数
def computerCost(X,y,theta):
m = len(y)
J = 0
J = (np.transpose(X*theta-y))*(X*theta-y)/(2*m) #计算代价J
return J
скопировать код
- Обратите внимание, что X здесь — это столбец 1, добавленный перед реальными данными, потому что есть тета (0)
2. Алгоритм градиентного спуска
- пара функций стоимостиНайдите частную производную, чтобы получить:
- Таким образом, обновление для тета может быть записано как:
- вэто скорость обучения, которая контролирует скорость градиентного спуска, обычно принимая0.01,0.03,0.1,0.3.....
- Почему градиентный спуск может постепенно уменьшать функцию стоимости
- Гипотетическая функция
f(x)
- Расширение Тейлора:
f(x+△x)=f(x)+f'(x)*△x+o(△x)
- сделать:
△x=-α*f'(x)
, то есть отрицательное направление градиента умножается на небольшой размер шагаα
- будет
△x
Подставляем в разложение Тейлора:f(x+x)=f(x)-α*[f'(x)]²+o(△x)
- Как можно заметить,
α
состоит в том, чтобы получить небольшое положительное число,[f'(x)]²
также является положительным числом, поэтому мы можем получить:f(x+△x)<=f(x)
- так вдольотрицательный градиентОпусти, функция убывающая, а многомерная ситуация та же.
- код реализации
# 梯度下降算法
def gradientDescent(X,y,theta,alpha,num_iters):
m = len(y)
n = len(theta)
temp = np.matrix(np.zeros((n,num_iters))) # 暂存每次迭代计算的theta,转化为矩阵形式
J_history = np.zeros((num_iters,1)) #记录每次迭代计算的代价值
for i in range(num_iters): # 遍历迭代次数
h = np.dot(X,theta) # 计算内积,matrix可以直接乘
temp[:,i] = theta - ((alpha/m)*(np.dot(np.transpose(X),h-y))) #梯度的计算
theta = temp[:,i]
J_history[i] = computerCost(X,y,theta) #调用计算代价函数
print '.',
return theta,J_history
скопировать код
3. Средняя нормализация
- Цель состоит в том, чтобы все данные масштабировались в диапазоне, который легко использовать алгоритм градиентного спуска.
- вэто среднее значение всех этих данных о функциях
- возможномаксимальное значение минимальное значение, или данные, соответствующие этому признакусреднеквадратичное отклонение
- Код реализации:
# 归一化feature
def featureNormaliza(X):
X_norm = np.array(X) #将X转化为numpy数组对象,才可以进行矩阵的运算
#定义所需变量
mu = np.zeros((1,X.shape[1]))
sigma = np.zeros((1,X.shape[1]))
mu = np.mean(X_norm,0) # 求每一列的平均值(0指定为列,1代表行)
sigma = np.std(X_norm,0) # 求每一列的标准差
for i in range(X.shape[1]): # 遍历列
X_norm[:,i] = (X_norm[:,i]-mu[i])/sigma[i] # 归一化
return X_norm,mu,sigma
скопировать код
- Обратите внимание, что при прогнозировании также требуются данные, нормализованные по среднему значению.
4. Окончательный результат работы
5.Реализовано с использованием линейных моделей из библиотеки scikit-learn.
- импортный пакет
from sklearn import linear_model
from sklearn.preprocessing import StandardScaler #引入缩放的包
скопировать код
- Нормализованный
# 归一化操作
scaler = StandardScaler()
scaler.fit(X)
x_train = scaler.transform(X)
x_test = scaler.transform(np.array([1650,3]))
скопировать код
- Подгонка линейной модели
# 线性模型拟合
model = linear_model.LinearRegression()
model.fit(x_train, y)
скопировать код
- предсказывать
#预测结果
result = model.predict(x_test)
скопировать код
два,логистическая регрессия
1. Функция стоимости
- Это можно резюмировать так:в:
- Почему бы не использовать функцию стоимости линейной регрессии, потому что функция стоимости линейной регрессии может быть невыпуклой.Для задач классификации трудно получить минимальное значение с помощью градиентного спуска.Приведенная выше функция стоимости является выпуклой функцией
-
Изображение выглядит следующим образом, т.е.
y=1
Время:
Видно, что когдакак правило1
,y=1
, в соответствии с предсказанным значением, цена, уплаченная в это времяcost
как правило0
,каккак правило0
,y=1
, ценаcost
Значение очень велико, наша конечная цель - минимизировать себестоимость
2. Градиент
- Также возьмем частную производную функции стоимости:
Можно видеть, что частные производные линейной регрессии согласуются с - нажать на обработку
3. Регуляризация
- Цель состоит в том, чтобы предотвратить переоснащение
- Добавьте термин в функцию стоимости
- Обратите внимание, что j начинается с 1, потому что тета (0) является постоянным термином, и 1 столбец 1 будет добавлен к первому столбцу в X, поэтому произведение по-прежнему будет тета (0), признак не имеет значения, есть нет необходимости упорядочивать
- Стоимость после регуляризации:
# 代价函数
def costFunction(initial_theta,X,y,inital_lambda):
m = len(y)
J = 0
h = sigmoid(np.dot(X,initial_theta)) # 计算h(z)
theta1 = initial_theta.copy() # 因为正则化j=1从1开始,不包含0,所以复制一份,前theta(0)值为0
theta1[0] = 0
temp = np.dot(np.transpose(theta1),theta1)
J = (-np.dot(np.transpose(y),np.log(h))-np.dot(np.transpose(1-y),np.log(1-h))+temp*inital_lambda/2)/m # 正则化的代价方程
return J
скопировать код
- Градиент регуляризованной стоимости
# 计算梯度
def gradient(initial_theta,X,y,inital_lambda):
m = len(y)
grad = np.zeros((initial_theta.shape[0]))
h = sigmoid(np.dot(X,initial_theta))# 计算h(z)
theta1 = initial_theta.copy()
theta1[0] = 0
grad = np.dot(np.transpose(X),h-y)/m+inital_lambda/m*theta1 #正则化的梯度
return grad
скопировать код
4. Сигмовидная функция (т.е.)
- Код реализации:
# S型函数
def sigmoid(z):
h = np.zeros((len(z),1)) # 初始化,与z的长度一置
h = 1.0/(1.0+np.exp(-z))
return h
скопировать код
5. Преобразование в полиномиальное
- Поскольку размер данных может быть небольшим, что приводит к большим отклонениям, создаются некоторые комбинации признаков.
- например: форма отображения в степени 2:
- Код реализации:
# 映射为多项式
def mapFeature(X1,X2):
degree = 3; # 映射的最高次方
out = np.ones((X1.shape[0],1)) # 映射后的结果数组(取代X)
'''
这里以degree=2为例,映射为1,x1,x2,x1^2,x1,x2,x2^2
'''
for i in np.arange(1,degree+1):
for j in range(i+1):
temp = X1**(i-j)*(X2**j) #矩阵直接乘相当于matlab中的点乘.*
out = np.hstack((out, temp.reshape(-1,1)))
return out
скопировать код
6. Используйтеscipy
метод оптимизации
- Использование градиентного спуска
scipy
серединаoptimize
серединаfmin_bfgs
функция - Вызов алгоритма оптимизации fmin_bfgs в scipy (квазиньютоновский метод Broyden-Fletcher-Goldfarb-Shanno
- costFunction — это функция стоимости, реализованная сама по себе.
- initial_theta представляет собой инициализированное значение,
- fprime указывает градиент costFunction
- args — это оставшиеся параметры теста, которые передаются в виде кортежей, и, наконец, будет возвращен тета, который минимизирует costFunction.
result = optimize.fmin_bfgs(costFunction, initial_theta, fprime=gradient, args=(X,y,initial_lambda))
скопировать код
7. Запуск результатов
8,Реализовано с использованием модели логистической регрессии в библиотеке scikit-learn.
- импортный пакет
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.cross_validation import train_test_split
import numpy as np
скопировать код
- Разделите тренировочный набор и тестовый набор
# 划分为训练集和测试集
x_train,x_test,y_train,y_test = train_test_split(X,y,test_size=0.2)
скопировать код
- Нормализованный
# 归一化
scaler = StandardScaler()
scaler.fit(x_train)
x_train = scaler.fit_transform(x_train)
x_test = scaler.fit_transform(x_test)
скопировать код
- логистическая регрессия
#逻辑回归
model = LogisticRegression()
model.fit(x_train,y_train)
скопировать код
- предсказывать
# 预测
predict = model.predict(x_test)
right = sum(predict == y_test)
predict = np.hstack((predict.reshape(-1,1),y_test.reshape(-1,1))) # 将预测值和真实值放在一块,好观察
print predict
print ('测试集准确率:%f%%'%(right*100.0/predict.shape[0])) #计算在测试集上的准确度
скопировать код
Логистическая регрессия_Распознавание рукописных цифр_OneVsAll
1. Случайным образом отобразить 100 номеров
- Я не использовал набор данных в scikit-learn, пиксели 20 * 20 пикселей, карта цветов выглядит следующим образом.Изображение в оттенках серого:
- Код реализации:
# 显示100个数字
def display_data(imgData):
sum = 0
'''
显示100个数(若是一个一个绘制将会非常慢,可以将要画的数字整理好,放到一个矩阵中,显示这个矩阵即可)
- 初始化一个二维数组
- 将每行的数据调整成图像的矩阵,放进二维数组
- 显示即可
'''
pad = 1
display_array = -np.ones((pad+10*(20+pad),pad+10*(20+pad)))
for i in range(10):
for j in range(10):
display_array[pad+i*(20+pad):pad+i*(20+pad)+20,pad+j*(20+pad):pad+j*(20+pad)+20] = (imgData[sum,:].reshape(20,20,order="F")) # order=F指定以列优先,在matlab中是这样的,python中需要指定,默认以行
sum += 1
plt.imshow(display_array,cmap='gray') #显示灰度图像
plt.axis('off')
plt.show()
скопировать код
2. Один против всех
- Как использовать логистическую регрессию для решения проблемы множественной классификации, OneVsAll рассматривает текущий класс как один класс, а все остальные классы как один класс, поэтому становится проблемой двух классов.
- Как показано на рисунке ниже, данные в пути делятся на три категории.Сначала красные считаются одной категорией, а остальные расцениваются как другая категория.Выполняется логистическая регрессия, а затем рассматриваются синие как одну категорию, а другие рассматриваются как одна категория.аналогия...
- Можно видеть, что в случае более 2 категорий, сколько раз выполняется классификация логистической регрессии
3. Распознавание рукописных цифр
- Всего 0-9, 10 номеров, нужно 10 классификаций
- потому чтонабор данных удано
0,1,2...9
числа, в то время как логистическая регрессия требует0/1
Тег label, поэтому вам нужно иметь дело с y - Давайте поговорим о наборах данных, например
500
один0
,500-1000
да1
,...
, поэтому, как показано ниже, обработанныйy
,Первый столбец первых 500 строк равен 1, остальные 0, второй столбец 500-1000 строк равен 1, а остальные 0.... - тогда позвониАлгоритм градиентного спускарешать
theta
- Код реализации:
# 求每个分类的theta,最后返回所有的all_theta
def oneVsAll(X,y,num_labels,Lambda):
# 初始化变量
m,n = X.shape
all_theta = np.zeros((n+1,num_labels)) # 每一列对应相应分类的theta,共10列
X = np.hstack((np.ones((m,1)),X)) # X前补上一列1的偏置bias
class_y = np.zeros((m,num_labels)) # 数据的y对应0-9,需要映射为0/1的关系
initial_theta = np.zeros((n+1,1)) # 初始化一个分类的theta
# 映射y
for i in range(num_labels):
class_y[:,i] = np.int32(y==i).reshape(1,-1) # 注意reshape(1,-1)才可以赋值
#np.savetxt("class_y.csv", class_y[0:600,:], delimiter=',')
'''遍历每个分类,计算对应的theta值'''
for i in range(num_labels):
result = optimize.fmin_bfgs(costFunction, initial_theta, fprime=gradient, args=(X,class_y[:,i],Lambda)) # 调用梯度下降的优化方法
all_theta[:,i] = result.reshape(1,-1) # 放入all_theta中
all_theta = np.transpose(all_theta)
return all_theta
скопировать код
4. Прогноз
- Как было сказано ранее, прогнозируемый результатзначение вероятности, используя изученное
theta
Замените предсказанныйсигмовидная функция, максимальное значение каждой строки — это максимальная вероятность числа, гденомер столбцаявляется истинным значением предсказанного числа, потому что при классификации все0
будетy
Сопоставляется в первом столбце, 1 отображается во втором столбце и т. д. - Код реализации:
# 预测
def predict_oneVsAll(all_theta,X):
m = X.shape[0]
num_labels = all_theta.shape[0]
p = np.zeros((m,1))
X = np.hstack((np.ones((m,1)),X)) #在X最前面加一列1
h = sigmoid(np.dot(X,np.transpose(all_theta))) #预测
'''
返回h中每一行最大值所在的列号
- np.max(h, axis=1)返回h中每一行的最大值(是某个数字的最大概率)
- 最后where找到的最大概率所在的列号(列号即是对应的数字)
'''
p = np.array(np.where(h[0,:] == np.max(h, axis=1)[0]))
for i in np.arange(1, m):
t = np.array(np.where(h[i,:] == np.max(h, axis=1)[i]))
p = np.vstack((p,t))
return p
скопировать код
5. Запуск результатов
6.Реализовано с использованием модели логистической регрессии в библиотеке scikit-learn.
- 1. Импортируйте пакет
from scipy import io as spio
import numpy as np
from sklearn import svm
from sklearn.linear_model import LogisticRegression
скопировать код
- 2. Загрузите данные
data = loadmat_data("data_digits.mat")
X = data['X'] # 获取X数据,每一行对应一个数字20x20px
y = data['y'] # 这里读取mat文件y的shape=(5000, 1)
y = np.ravel(y) # 调用sklearn需要转化成一维的(5000,)
скопировать код
- 3. Подгонка модели
model = LogisticRegression()
model.fit(X, y) # 拟合
скопировать код
- 4. Прогноз
predict = model.predict(X) #预测
print u"预测准确度为:%f%%"%np.mean(np.float64(predict == y)*100)
скопировать код
3. Нейронная сеть БП
1. Нейросетевая модель
-
Сначала введите трехслойную нейронную сеть, как показано на следующем рисунке.
-
Входной слой состоит из трех блоков (Это дополнительное смещение, обычно устанавливаемое на
1
) -
во-первых
j
слой доj+1
Весовая матрица сопоставления слоев — это вес каждого ребра. -
Итак, вы можете получить:
-
выходной слой
в,сигмовидная функция, также становитсяФункция возбуждения
2. Функция стоимости
- Предполагая последний вывод, что означает, что выходной слой имеет K единиц
-
в,представитель
i
единица продукции - Функция стоимости с логистической регрессиейПочти, то есть добавить каждый выход (всего K выходов)
3. Регуляризация
-
L
-->Количество всех слоев -
--> Раздел
l
Количество единиц слоя - нормализованныйфункция стоимостиза
-
общий
L-1
Этаж, - Затем накопите тета-матрицу, соответствующую каждому слою, обратите внимание, что тета (0), соответствующая члену смещения, не включена
- Код реализации функции регуляризованных затрат:
# 代价函数
def nnCostFunction(nn_params,input_layer_size,hidden_layer_size,num_labels,X,y,Lambda):
length = nn_params.shape[0] # theta的中长度
# 还原theta1和theta2
Theta1 = nn_params[0:hidden_layer_size*(input_layer_size+1)].reshape(hidden_layer_size,input_layer_size+1)
Theta2 = nn_params[hidden_layer_size*(input_layer_size+1):length].reshape(num_labels,hidden_layer_size+1)
# np.savetxt("Theta1.csv",Theta1,delimiter=',')
m = X.shape[0]
class_y = np.zeros((m,num_labels)) # 数据的y对应0-9,需要映射为0/1的关系
# 映射y
for i in range(num_labels):
class_y[:,i] = np.int32(y==i).reshape(1,-1) # 注意reshape(1,-1)才可以赋值
'''去掉theta1和theta2的第一列,因为正则化时从1开始'''
Theta1_colCount = Theta1.shape[1]
Theta1_x = Theta1[:,1:Theta1_colCount]
Theta2_colCount = Theta2.shape[1]
Theta2_x = Theta2[:,1:Theta2_colCount]
# 正则化向theta^2
term = np.dot(np.transpose(np.vstack((Theta1_x.reshape(-1,1),Theta2_x.reshape(-1,1)))),np.vstack((Theta1_x.reshape(-1,1),Theta2_x.reshape(-1,1))))
'''正向传播,每次需要补上一列1的偏置bias'''
a1 = np.hstack((np.ones((m,1)),X))
z2 = np.dot(a1,np.transpose(Theta1))
a2 = sigmoid(z2)
a2 = np.hstack((np.ones((m,1)),a2))
z3 = np.dot(a2,np.transpose(Theta2))
h = sigmoid(z3)
'''代价'''
J = -(np.dot(np.transpose(class_y.reshape(-1,1)),np.log(h.reshape(-1,1)))+np.dot(np.transpose(1-class_y.reshape(-1,1)),np.log(1-h.reshape(-1,1)))-Lambda*term/2)/m
return np.ravel(J)
скопировать код
4. БП обратного распространения
-
Вышеупомянутое прямое распространение может быть рассчитано
J(θ)
, с помощью метода градиентного спуска также необходимо найти его градиент -
Цель обратного распространения BP — найти градиент функции стоимости.
-
Предполагая 4-слойную нейронную сеть,Отметить как -->
l
слойj
единичная ошибка -
Поскольку сигмовидная функцияПроизводная от:, так что вышеа такжеможно вычислить в прямом проходе
-
Процесс обратного распространения для вычисления градиента:
-
for i=1-m:
-
- Расчет прямого распространения(л=2,3,4...л)
- Обратный расчет,... ;
-
-
-
В конце концов, то есть получается градиент функции стоимости
-
Код реализации:
# 梯度
def nnGradient(nn_params,input_layer_size,hidden_layer_size,num_labels,X,y,Lambda):
length = nn_params.shape[0]
Theta1 = nn_params[0:hidden_layer_size*(input_layer_size+1)].reshape(hidden_layer_size,input_layer_size+1).copy() # 这里使用copy函数,否则下面修改Theta的值,nn_params也会一起修改
Theta2 = nn_params[hidden_layer_size*(input_layer_size+1):length].reshape(num_labels,hidden_layer_size+1).copy()
m = X.shape[0]
class_y = np.zeros((m,num_labels)) # 数据的y对应0-9,需要映射为0/1的关系
# 映射y
for i in range(num_labels):
class_y[:,i] = np.int32(y==i).reshape(1,-1) # 注意reshape(1,-1)才可以赋值
'''去掉theta1和theta2的第一列,因为正则化时从1开始'''
Theta1_colCount = Theta1.shape[1]
Theta1_x = Theta1[:,1:Theta1_colCount]
Theta2_colCount = Theta2.shape[1]
Theta2_x = Theta2[:,1:Theta2_colCount]
Theta1_grad = np.zeros((Theta1.shape)) #第一层到第二层的权重
Theta2_grad = np.zeros((Theta2.shape)) #第二层到第三层的权重
'''正向传播,每次需要补上一列1的偏置bias'''
a1 = np.hstack((np.ones((m,1)),X))
z2 = np.dot(a1,np.transpose(Theta1))
a2 = sigmoid(z2)
a2 = np.hstack((np.ones((m,1)),a2))
z3 = np.dot(a2,np.transpose(Theta2))
h = sigmoid(z3)
'''反向传播,delta为误差,'''
delta3 = np.zeros((m,num_labels))
delta2 = np.zeros((m,hidden_layer_size))
for i in range(m):
#delta3[i,:] = (h[i,:]-class_y[i,:])*sigmoidGradient(z3[i,:]) # 均方误差的误差率
delta3[i,:] = h[i,:]-class_y[i,:] # 交叉熵误差率
Theta2_grad = Theta2_grad+np.dot(np.transpose(delta3[i,:].reshape(1,-1)),a2[i,:].reshape(1,-1))
delta2[i,:] = np.dot(delta3[i,:].reshape(1,-1),Theta2_x)*sigmoidGradient(z2[i,:])
Theta1_grad = Theta1_grad+np.dot(np.transpose(delta2[i,:].reshape(1,-1)),a1[i,:].reshape(1,-1))
Theta1[:,0] = 0
Theta2[:,0] = 0
'''梯度'''
grad = (np.vstack((Theta1_grad.reshape(-1,1),Theta2_grad.reshape(-1,1)))+Lambda*np.vstack((Theta1.reshape(-1,1),Theta2.reshape(-1,1))))/m
return np.ravel(grad)
скопировать код
5. Причина, по которой АД может найти градиент
- на самом деле используется
链式求导
закон - Поскольку единица измерения следующего слоя использует единицу измерения предыдущего слоя в качестве входных данных для вычисления
- Общий процесс вывода выглядит следующим образом, в конце мы хотим предсказать функцию и известную
y
Очень близко, средний квадрат градиента вдоль этого градиента минимизирует функцию стоимости. Процесс нахождения градиента выше можно сравнить. - Найдите более подробный процесс вывода ошибки:
6. Проверка градиента
- Проверить использование
BP
Правильно ли получен градиент? - Используйте определение производной, чтобы проверить:
- Полученный численный градиент должен быть очень близок к градиенту, полученному с помощью BP.
- После проверки правильности BP нет необходимости выполнять алгоритм проверки градиента.
- Код реализации:
# 检验梯度是否计算正确
# 检验梯度是否计算正确
def checkGradient(Lambda = 0):
'''构造一个小型的神经网络验证,因为数值法计算梯度很浪费时间,而且验证正确后之后就不再需要验证了'''
input_layer_size = 3
hidden_layer_size = 5
num_labels = 3
m = 5
initial_Theta1 = debugInitializeWeights(input_layer_size,hidden_layer_size);
initial_Theta2 = debugInitializeWeights(hidden_layer_size,num_labels)
X = debugInitializeWeights(input_layer_size-1,m)
y = 1+np.transpose(np.mod(np.arange(1,m+1), num_labels))# 初始化y
y = y.reshape(-1,1)
nn_params = np.vstack((initial_Theta1.reshape(-1,1),initial_Theta2.reshape(-1,1))) #展开theta
'''BP求出梯度'''
grad = nnGradient(nn_params, input_layer_size, hidden_layer_size,
num_labels, X, y, Lambda)
'''使用数值法计算梯度'''
num_grad = np.zeros((nn_params.shape[0]))
step = np.zeros((nn_params.shape[0]))
e = 1e-4
for i in range(nn_params.shape[0]):
step[i] = e
loss1 = nnCostFunction(nn_params-step.reshape(-1,1), input_layer_size, hidden_layer_size,
num_labels, X, y,
Lambda)
loss2 = nnCostFunction(nn_params+step.reshape(-1,1), input_layer_size, hidden_layer_size,
num_labels, X, y,
Lambda)
num_grad[i] = (loss2-loss1)/(2*e)
step[i]=0
# 显示两列比较
res = np.hstack((num_grad.reshape(-1,1),grad.reshape(-1,1)))
print res
скопировать код
7. Случайная инициализация весов
- Нейронные сети нельзя инициализировать, как логистическую регрессию.
theta
за0
, потому что если вес каждого ребра равен 0, каждый нейрон имеет одинаковый выход, и при обратном распространении будет получен один и тот же градиент, и в конце будет предсказан только один результат. - Поэтому он должен быть инициализирован числом, близким к 0
- код реализации
# 随机初始化权重theta
def randInitializeWeights(L_in,L_out):
W = np.zeros((L_out,1+L_in)) # 对应theta的权重
epsilon_init = (6.0/(L_out+L_in))**0.5
W = np.random.rand(L_out,1+L_in)*2*epsilon_init-epsilon_init # np.random.rand(L_out,1+L_in)产生L_out*(1+L_in)大小的随机矩阵
return W
скопировать код
8. Прогноз
- Результаты предсказания прямого распространения
- код реализации
# 预测
def predict(Theta1,Theta2,X):
m = X.shape[0]
num_labels = Theta2.shape[0]
#p = np.zeros((m,1))
'''正向传播,预测结果'''
X = np.hstack((np.ones((m,1)),X))
h1 = sigmoid(np.dot(X,np.transpose(Theta1)))
h1 = np.hstack((np.ones((m,1)),h1))
h2 = sigmoid(np.dot(h1,np.transpose(Theta2)))
'''
返回h中每一行最大值所在的列号
- np.max(h, axis=1)返回h中每一行的最大值(是某个数字的最大概率)
- 最后where找到的最大概率所在的列号(列号即是对应的数字)
'''
#np.savetxt("h2.csv",h2,delimiter=',')
p = np.array(np.where(h2[0,:] == np.max(h2, axis=1)[0]))
for i in np.arange(1, m):
t = np.array(np.where(h2[i,:] == np.max(h2, axis=1)[i]))
p = np.vstack((p,t))
return p
скопировать код
9. Вывод результатов
- Проверка градиента:
- Произвольное отображение 100 рукописных чисел
- показать веса тета1
- Точность предсказания тренировочного набора
- Точность предсказания нормализованного тренировочного набора
В-четвертых, машина опорных векторов SVM
1. Функция стоимости
- В логистической регрессии наша стоимость составляет:
,
в:, - Как показано на рисунке, если
y=1
,cost
Функция стоимости представлена на рис.
мы хотим,Сейчасz>>0
,В этом случаеcost
Функция стоимости будет стремиться к минимуму (это то, что нам нужно), поэтому использованиекрасныйФункцияЗамена стоимости в логистической регрессии - когда
y=0
в то же время, используйтезаменять - Окончательная функция стоимости:
Наконец мы хотим - Функция затрат в нашей логистической регрессии была следующей:
можно рассмотреть здесь, это просто вопрос выражения, здесьC
Чем больше значение , тем больше граница решения SVM.margin
также больше, как будет объяснено ниже
2. Большая маржа
-
Как показано на рисунке ниже, в классификации SVM будет использоваться самый большой
margin
отделить его
-
Давайте сначала поговорим о векторном внутреннем продукте.
-
向量V
существует向量u
Длина проекции на обозначается какp
, затем: векторный внутренний продукт:
Его можно вывести по формуле векторного угла, -
Как уже было сказано, когда
C
больше,margin
больше, наша цель — минимизировать функцию стоимостиJ(θ)
,когдаmargin
максимум,C
срок продуктабыть маленьким, поэтому приближение:
,
Наша конечная цель – минимизировать затратыθ
-
Зависит от
Вы можете получить:
,p
то естьx
существуетθ
проекция на -
Как показано на рисунке ниже, предполагая, что граница решения показана на рисунке, найдите одну из точек, чтобы
θ
Проекция наp
,ноили,еслиp
маленький, тебе нуженбольшой, что соответствует тому, что нам нужноθ
Сделатьнаименее противоречивый,такПоследний запросlarge margin
3. Ядро SVM (функция ядра)
-
Для линейно отделимых задач используйтеЛинейная функция ядраТолько что
-
Для линейно неразделимых задач в логистической регрессии мы будем
feature
Сопоставьте форму с помощью полиномов,SVM
Также вПолиномиальная функция ядра, но чащеФункция ядра Гаусса, также известен какЯдро РБФ -
Функция ядра Гаусса:
Предполагая несколько точек на рисунке,сделать:
. . . -
Видно, что если
x
а такжеРасстояние ближе, ==", (то есть сходство больше)
еслиx
а такжеРасстояние далеко, ==", (т.е. меньшее сходство)
4. Используйтеscikit-learn
серединаSVM
код модели
- весь код
- Линейно отделимый, задайте функцию ядра как
linear
:
'''data1——线性分类'''
data1 = spio.loadmat('data1.mat')
X = data1['X']
y = data1['y']
y = np.ravel(y)
plot_data(X,y)
model = svm.SVC(C=1.0,kernel='linear').fit(X,y) # 指定核函数为线性核函数
скопировать код
- Нелинейно отделимая функция ядра по умолчанию
rbf
'''data2——非线性分类'''
data2 = spio.loadmat('data2.mat')
X = data2['X']
y = data2['y']
y = np.ravel(y)
plt = plot_data(X,y)
plt.show()
model = svm.SVC(gamma=100).fit(X,y) # gamma为核函数的系数,值越大拟合的越好
скопировать код
5. Запуск результатов
Пять, алгоритм кластеризации K-средних
1. Процесс кластеризации
-
Кластеризация относится к обучению без учителя, а метки, не знающие y, делятся на K категорий.
-
Алгоритм K-средних разделен на два этапа.
-
Первый шаг: назначение кластера, случайный выбор
K
указать как центр, вычислить этоK
расстояние точек, разделенное наK
кластеры -
Шаг 2. Переместите центры кластеров: пересчитайте каждыйкластерцентр, переместите центр и повторите описанные выше шаги.
-
Как показано ниже:
-
Вычислите, в какой центр каждый фрагмент данных попадает в самый последний код реализации:
# 找到每条数据距离哪个类中心最近
def findClosestCentroids(X,initial_centroids):
m = X.shape[0] # 数据条数
K = initial_centroids.shape[0] # 类的总数
dis = np.zeros((m,K)) # 存储计算每个点分别到K个类的距离
idx = np.zeros((m,1)) # 要返回的每条数据属于哪个类
'''计算每个点到每个类中心的距离'''
for i in range(m):
for j in range(K):
dis[i,j] = np.dot((X[i,:]-initial_centroids[j,:]).reshape(1,-1),(X[i,:]-initial_centroids[j,:]).reshape(-1,1))
'''返回dis每一行的最小值对应的列号,即为对应的类别
- np.min(dis, axis=1)返回每一行的最小值
- np.where(dis == np.min(dis, axis=1).reshape(-1,1)) 返回对应最小值的坐标
- 注意:可能最小值对应的坐标有多个,where都会找出来,所以返回时返回前m个需要的即可(因为对于多个最小值,属于哪个类别都可以)
'''
dummy,idx = np.where(dis == np.min(dis, axis=1).reshape(-1,1))
return idx[0:dis.shape[0]] # 注意截取一下
скопировать код
- Код реализации центра расчетных классов:
# 计算类中心
def computerCentroids(X,idx,K):
n = X.shape[1]
centroids = np.zeros((K,n))
for i in range(K):
centroids[i,:] = np.mean(X[np.ravel(idx==i),:], axis=0).reshape(1,-1) # 索引要是一维的,axis=0为每一列,idx==i一次找出属于哪一类的,然后计算均值
return centroids
скопировать код
2. Целевая функция
- также называемыйФункция стоимости искажения
- В итоге мы хотим получить:
- возначает первый
i
Какой центр класса ближе всего к фрагменту данных, - вцентр кластера
3. Выбор кластерных центров
- Случайная инициализация, случайный выбор K из заданных данных в качестве центров кластера
- Результат случайного один раз может быть не очень хорошим, вы можете рандомизировать его много раз и, наконец, взять тот, который минимизирует функцию стоимости, в качестве центра.
- Код реализации: (случайно здесь)
# 初始化类中心--随机取K个点作为聚类中心
def kMeansInitCentroids(X,K):
m = X.shape[0]
m_arr = np.arange(0,m) # 生成0-m-1
centroids = np.zeros((K,X.shape[1]))
np.random.shuffle(m_arr) # 打乱m_arr顺序
rand_indices = m_arr[:K] # 取前K个
centroids = X[rand_indices,:]
return centroids
скопировать код
4. Выбор количества кластеров K
- Кластеризация не знает метки y, поэтому она не знает реального количества кластеров.
- Локтевой метод
- как функция стоимости
J
а такжеK
, если есть точка перегиба, как показано на рисунке ниже,K
Просто возьмите значение в точке перегиба, как показано на рисунке нижеK=3
- Если очень гладко, то непонятно, искусственный выбор.
- Во-вторых, это человеческое наблюдение и отбор.
5. Применение — сжатие изображений
- Разделите пиксели изображения на несколько категорий, а затем используйте эту категорию для замены исходного значения пикселя.
- Код алгоритма для выполнения кластеризации:
# 聚类算法
def runKMeans(X,initial_centroids,max_iters,plot_process):
m,n = X.shape # 数据条数和维度
K = initial_centroids.shape[0] # 类数
centroids = initial_centroids # 记录当前类中心
previous_centroids = centroids # 记录上一次类中心
idx = np.zeros((m,1)) # 每条数据属于哪个类
for i in range(max_iters): # 迭代次数
print u'迭代计算次数:%d'%(i+1)
idx = findClosestCentroids(X, centroids)
if plot_process: # 如果绘制图像
plt = plotProcessKMeans(X,centroids,previous_centroids) # 画聚类中心的移动过程
previous_centroids = centroids # 重置
centroids = computerCentroids(X, idx, K) # 重新计算类中心
if plot_process: # 显示最终的绘制结果
plt.show()
return centroids,idx # 返回聚类中心和数据属于哪个类
скопировать код
6.Реализуйте кластеризацию, используя линейные модели из библиотеки scikit-learn.
- импортный пакет
from sklearn.cluster import KMeans
скопировать код
- Сопоставьте данные с моделью
model = KMeans(n_clusters=3).fit(X) # n_clusters指定3类,拟合数据
скопировать код
- центр кластера
centroids = model.cluster_centers_ # 聚类中心
скопировать код
7. Запуск результатов
6. Анализ основных компонентов PCA (уменьшение размерности)
1. Используйте
- Сжатие данных для ускорения работы программ
- Визуализируйте данные, такие как
3D-->2D
Ждать - ......
2. 2D-->1D, nD-->kD
- Как показано на рисунке ниже, все точки данных можно спроецировать на линию, т.е.сумма квадратов проектируемых расстояний(ошибка проецирования) минимум
- Обратите внимание на потребности в данных
归一化
иметь дело с - Идея состоит в том, чтобы найти
1
индивидуальный向量u
, все данные проецируются на него, чтобы минимизировать расстояние проецирования - Так
nD-->kD
просто ищуk
векторы, все данные проецируются на него, чтобы минимизировать ошибку проецирования - например: 3D -> 2D, 2 вектораОн представляет собой плоскость, и ошибка проецирования всех точек, спроецированных на эту плоскость, наименьшая.
3. Разница между PCA и линейной регрессией
- Линейная регрессия заключается в том, чтобы найти
x
а такжеy
отношение, которое затем используется для предсказанияy
-
PCA
Нужно найти проекционную поверхность и минимизировать ошибку проецирования данных на эту проекционную поверхность.
4. Процесс уменьшения размерности PCA
- Предварительная обработка данных (нормализация среднего)
- формула:
- Нужно вычесть среднее значение соответствующего признака, а затем разделить на стандартное отклонение соответствующего признака (оно также может быть максимально-минимальным значением).
- Код реализации:
# 归一化数据
def featureNormalize(X):
'''(每一个数据-当前列的均值)/当前列的标准差'''
n = X.shape[1]
mu = np.zeros((1,n));
sigma = np.zeros((1,n))
mu = np.mean(X,axis=0)
sigma = np.std(X,axis=0)
for i in range(n):
X[:,i] = (X[:,i]-mu[i])/sigma[i]
return X,mu,sigma
скопировать код
- рассчитать
协方差矩阵Σ
(Ковариационная матрица): - Обратите внимание здесь
Σ
отличается от знака суммы - ковариационная матрица
对称正定
(Если вы не понимаете Zhengding, посмотрите на генерацию строк) - размер
nxn
,n
заfeature
измерение - Код реализации:
Sigma = np.dot(np.transpose(X_norm),X_norm)/m # 求Sigma
скопировать код
- рассчитать
Σ
собственные значения и собственные векторы - может быть использован
svd
Функция разложения по сингулярным числам:U,S,V = svd(Σ)
- вернулся с
Σ
Диагональные массивы одинакового размераS
(Зависит отΣ
Собственные значения )[Уведомление:matlab
Функция возвращает диагональную матрицу вpython
возвращается как вектор, экономя место] - еще дваУнитарная матрицаU и V, и
-
Уведомление:
svd
функция найденаS
сортируются в порядке убывания собственных значений, если не используютсяsvd
, нужно нажатьсобственные значенияИзменить размерU
- Снижение размерности
- Выбрать
U
спередиK
столбец (при условии, что вы хотите уменьшить доK
измерение) -
Z
Это данные после соответствующего уменьшения размера - Код реализации:
# 映射数据
def projectData(X_norm,U,K):
Z = np.zeros((X_norm.shape[0],K))
U_reduce = U[:,0:K] # 取前K个
Z = np.dot(X_norm,U_reduce)
return Z
скопировать код
- Краткое описание процесса:
Sigma = X'*X/m
U,S,V = svd(Sigma)
Ureduce = U[:,0:k]
Z = Ureduce'*x
5. Восстановление данных
- так как:
- так:(обратите внимание, что это приближение X)
- и потому, что
Ureduce
является положительно определенной матрицей, [положительно определенная матрица удовлетворяет:,так:], так вот: - Код реализации:
# 恢复数据
def recoverData(Z,U,K):
X_rec = np.zeros((Z.shape[0],U.shape[0]))
U_recude = U[:,0:K]
X_rec = np.dot(Z,np.transpose(U_recude)) # 还原数据(近似)
return X_rec
скопировать код
6. Выбор количества главных компонентов (т. е. уменьшаемой размерности)
- как выбрать
- ошибка проекции(ошибка проекта):
- полная вариация(общая вариация):
- подобноЧастота ошибок(коэффициент ошибки):, это называется
99%
сохранить разницу - Частота ошибок обычно принимается
1%,5%,10%
Ждать - Как добиться
- Это слишком дорого, чтобы попробовать один за другим
- До
U,S,V = svd(Sigma)
, мы получилиS
, здесь коэффициент ошибки коэффициент ошибки:
- можно постепенно увеличивать
K
пытаться.
7. Рекомендации по применению
- Не используйте PCA для решения проблемы переобучения.
Overfitting
или используйте метод регуляризации (это нормально, если вы сохраняете высокую дисперсию) - Рассмотрите возможность использования PCA только в том случае, если у вас есть хорошие результаты на исходных данных, но операция выполняется очень медленно.
8. Запуск результатов
- 2D-данные сведены к 1D
- направление к проекту
- 2D сводится к 1D и соответствующим отношениям
- уменьшение размерности данных лица
- Необработанные данные
- часть визуализации
U
матричная информация
- Восстановление данных
9,Снижение размерности с помощью PCA из библиотеки scikit-learn
- Импортируйте необходимые пакеты:
#-*- coding: utf-8 -*-
# Author:bob
# Date:2016.12.22
import numpy as np
from matplotlib import pyplot as plt
from scipy import io as spio
from sklearn.decomposition import pca
from sklearn.preprocessing import StandardScaler
скопировать код
- нормализованные данные
'''归一化数据并作图'''
scaler = StandardScaler()
scaler.fit(X)
x_train = scaler.transform(X)
скопировать код
- Подбирайте данные с помощью модели PCA и уменьшайте размерность
-
n_components
В соответствии с размером, который будет
'''拟合数据'''
K=1 # 要降的维度
model = pca.PCA(n_components=K).fit(x_train) # 拟合数据,n_components定义要降的维度
Z = model.transform(x_train) # transform就会执行降维操作
скопировать код
- Восстановление данных
-
model.components_
Будет использовано уменьшение размерностиU
матрица
'''数据恢复并作图'''
Ureduce = model.components_ # 得到降维用的Ureduce
x_rec = np.dot(Z,Ureduce) # 数据恢复
скопировать код
Семь, обнаружение аномалий Обнаружение аномалий
1. Распределение Гаусса (нормальное распределение)Gaussian distribution
- Функция распределения:
- в,
u
для данныхиметь в виду,σ
для данныхсреднеквадратичное отклонение -
σ
Пересекатьмаленький, соответствующее изображение большенаконечник - Оценка параметра(
parameter estimation
)
2. Алгоритм обнаружения аномалий
- пример
- Обучающий набор:,в
- ПредположениеНезависимо друг от друга постройте модель модели:
- обработать
- Выберите тот, у которого репрезентативное исключение
feature
:xi - Оценка параметра:
- рассчитать
p(x)
,еслиP(x)<ε
считается ненормальным, еслиε
критическое значение вероятности, которое нам требуетсяthreshold
- вот толькоЕдиница распределения Гаусса, предполагая
feature
независимы, как будет показано нижеМногомерное распределение Гаусса, будет автоматически захватыватьfeature
Отношение между - Оценка параметракод реализации
# 参数估计函数(就是求均值和方差)
def estimateGaussian(X):
m,n = X.shape
mu = np.zeros((n,1))
sigma2 = np.zeros((n,1))
mu = np.mean(X, axis=0) # axis=0表示列,每列的均值
sigma2 = np.var(X,axis=0) # 求每列的方差
return mu,sigma2
скопировать код
3. Оценкаp(x)
хорошо или плохо, иε
выбор
-
правильноискаженные данныемера ошибки
-
Поскольку данные могут быть оченьперекос(то есть,
y=1
Количество очень маленькое(y=1
указывает на исключение)), поэтому вы можете использоватьPrecision/Recall
,рассчитатьF1Score
(существуетНабор перекрестной проверки резюменачальство) -
Например: предсказание рака, предполагая, что модель может получить
99%
уметь правильно прогнозировать,1%
частота ошибок, но фактическая вероятность рака очень мала, только0.5%
, то мы всегда предсказываем, что рака y=0 нет, но можем получить меньшую частоту ошибок. использоватьerror rate
Ненаучно оценивать. -
,который:Правильно предсказанные положительные результаты/все предсказанные положительные результаты
-
,который:Правильно прогнозировать положительные образцы/истинные значения являются положительными образцами
-
пусть всегда
y=1
(меньше классов), вычислитьPrecision
а такжеRecall
-
Возьмем в качестве примера предсказание рака, предполагая, что все прогнозы не содержат рака, TN=199, FN=1, TP=0, FP=0, поэтому: Precision=0/0, Recall=0/1=0, хотя точность = 199/200 = 99,5%, но не заслуживает доверия.
-
ε
выбор -
попробовать несколько
ε
стоимость, сделатьF1Score
значение высокое -
код реализации
# 选择最优的epsilon,即:使F1Score最大
def selectThreshold(yval,pval):
'''初始化所需变量'''
bestEpsilon = 0.
bestF1 = 0.
F1 = 0.
step = (np.max(pval)-np.min(pval))/1000
'''计算'''
for epsilon in np.arange(np.min(pval),np.max(pval),step):
cvPrecision = pval<epsilon
tp = np.sum((cvPrecision == 1) & (yval == 1)).astype(float) # sum求和是int型的,需要转为float
fp = np.sum((cvPrecision == 1) & (yval == 0)).astype(float)
fn = np.sum((cvPrecision == 1) & (yval == 0)).astype(float)
precision = tp/(tp+fp) # 精准度
recision = tp/(tp+fn) # 召回率
F1 = (2*precision*recision)/(precision+recision) # F1Score计算公式
if F1 > bestF1: # 修改最优的F1 Score
bestF1 = F1
bestEpsilon = epsilon
return bestEpsilon,bestF1
скопировать код
4. Выберите, какую функцию использовать (единичное распределение Гаусса)
- Если некоторые данные не удовлетворяют распределению Гаусса, вы можете изменить данные, например
log(x+C),x^(1/2)
Ждать - если
p(x)
Значение очень велико, независимо от того, является ли оно ненормальным или нет, вы можете попытаться объединить несколькоfeature
, (поскольку между функциями может быть связь)
5. Многомерное распределение Гаусса
- Проблема с единичным распределением Гаусса
- Как показано на рисунке ниже, красные точки — это аномальные точки, а остальные — нормальные точки (например, изменения в процессоре и памяти).
- Распределение Гаусса, соответствующее x1, выглядит следующим образом:
- Распределение Гаусса, соответствующее x2, выглядит следующим образом:
- Видно, что соответствующие значения p(x1) и p(x2) сильно не меняются, поэтому их нельзя будет считать аномальными.
- Поскольку мы думаем, что функции не зависят друг от друга, приведенное выше изображение основано наИдеальный кругспособ расширить
- Многомерное распределение Гаусса
-
, не устанавливать
p(x1),p(x2)...p(xn)
, а установить единуюp(x)
- Среди параметров:,
Σ
заковариационная матрица - такой же,
|Σ|
чем меньшеp(x)
более острый - Например:
,
Указывает x1,x2положительная корреляция, то есть чем больше x1, тем больше x2, как показано на рисунке ниже, можно проверить красную аномальную точку
подобно:
,
Указывает x1,x2отрицательная корреляция - Код реализации:
# 多元高斯分布函数
def multivariateGaussian(X,mu,Sigma2):
k = len(mu)
if (Sigma2.shape[0]>1):
Sigma2 = np.diag(Sigma2)
'''多元高斯分布函数'''
X = X-mu
argu = (2*np.pi)**(-k/2)*np.linalg.det(Sigma2)**(-0.5)
p = argu*np.exp(-0.5*np.sum(np.dot(X,np.linalg.inv(Sigma2))*X,axis=1)) # axis表示每行
return p
скопировать код
6. Единичные и многомерные характеристики распределения Гаусса
- Единица распределения Гаусса
- могут быть захвачены людьми
feature
может использоваться, когда отношения между - Небольшой объем расчета
- Многомерное распределение Гаусса
- Автоматически захватывать соответствующие функции
- Это вычислительно дорого, потому что:
-
m>n
илиΣ
Может использоваться при обратимости. (Если это необратимо, может быть избыточный x из-за линейной корреляции, необратимого или просто m