содержание
-
Реализация алгоритма машинного обучения на 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/mU,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