Реализация алгоритма машинного обучения на Python

Python алгоритм машинное обучение

MIT license

содержание

один,Линейная регрессия

1. Функция стоимости

  • J(\theta ) = \frac{1}{{2{\text{m}}}}\sum\limits_{i = 1}^m {{{({h_\theta }({x^{(i)}}) - {y^{(i)}})}^2}}

  • в:{h_\theta }(x) = {\theta _0} + {\theta _1}{x_1} + {\theta _2}{x_2} + ...

  • Далее следует запросить тета, чтобы минимизировать стоимость, что означает, что уравнение, которое мы подгоняем, ближе всего к истинному значению.

  • Имеется m элементов данных, из которых{{{({h_\theta }({x^{(i)}}) - {y^{(i)}})}^2}}Представляет квадрат расстояния от уравнения, которое мы хотим подогнать к истинному значению. Причина квадрата в том, что могут быть отрицательные значения, а положительные и отрицательные могут смещаться

  • коэффициент перед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. Алгоритм градиентного спуска

  • пара функций стоимости{{\theta _j}}Найдите частную производную, чтобы получить:
    \frac{{\partial J(\theta )}}{{\partial {\theta j}}} = \frac{1}{m}\sum\limits{i = 1}^m {[({h_\theta }({x^{(i)}}) - {y^{(i)}})x_j^{(i)}]}
  • Таким образом, обновление для тета может быть записано как:
    {\theta j} = {\theta j} - \alpha \frac{1}{m}\sum\limits{i = 1}^m {[({h\theta }({x^{(i)}}) - {y^{(i)}})x_j^{(i)}]}
  • в\alpha это скорость обучения, которая контролирует скорость градиентного спуска, обычно принимая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. Средняя нормализация

  • Цель состоит в том, чтобы все данные масштабировались в диапазоне, который легко использовать алгоритм градиентного спуска.
  • {x_i} = \frac{{{x_i} - {\mu _i}}}{{{s_i}}}
  • в{{\mu _i}}это среднее значение всех этих данных о функциях
  • {{s_i}}возможномаксимальное значение минимальное значение, или данные, соответствующие этому признакусреднеквадратичное отклонение
  • Код реализации:
# 归一化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. Окончательный результат работы

  • Стоимость как функция количества итераций
    enter description here

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. Функция стоимости

  • \left{ \begin{gathered} J(\theta ) = \frac{1}{m}\sum\limits_{i = 1}^m {\cos t({h_\theta }({x^{(i)}}),{y^{(i)}})}  \hfill \ \cos t({h_\theta }(x),y) = \left{ {\begin{array}{c}    { - \log ({h_\theta }(x))} \    { - \log (1 - {h_\theta }(x))}  \end{array} \begin{array}{c}    {y = 1} \    {y = 0}  \end{array} } \right. \hfill \ \end{gathered}  \right.
  • Это можно резюмировать так:J(\theta ) =  - \frac{1}{m}\sum\limits_{i = 1}^m {[{y^{(i)}}\log ({h_\theta }({x^{(i)}}) + (1 - } {y^{(i)}})\log (1 - {h_\theta }({x^{(i)}})]в:{h_\theta }(x) = \frac{1}{{1 + {e^{ - x}}}}
  • Почему бы не использовать функцию стоимости линейной регрессии, потому что функция стоимости линейной регрессии может быть невыпуклой.Для задач классификации трудно получить минимальное значение с помощью градиентного спуска.Приведенная выше функция стоимости является выпуклой функцией
  • { - \log ({h_\theta }(x))}Изображение выглядит следующим образом, т.е.y=1Время:enter description here

Видно, что когда{{h_\theta }(x)}как правило1,y=1, в соответствии с предсказанным значением, цена, уплаченная в это времяcostкак правило0,как{{h_\theta }(x)}как правило0,y=1, ценаcostЗначение очень велико, наша конечная цель - минимизировать себестоимость

  • так же{ - \log (1 - {h_\theta }(x))}Картинка такая(y=0):
    enter description here

2. Градиент

  • Также возьмем частную производную функции стоимости:\frac{{\partial J(\theta )}}{{\partial {\theta j}}} = \frac{1}{m}\sum\limits{i = 1}^m {[({h_\theta }({x^{(i)}}) - {y^{(i)}})x_j^{(i)}]}
    Можно видеть, что частные производные линейной регрессии согласуются с
  • нажать на обработкуenter description here

3. Регуляризация

  • Цель состоит в том, чтобы предотвратить переоснащение
  • Добавьте термин в функцию стоимостиJ(\theta ) =  - \frac{1}{m}\sum\limits_{i = 1}^m {[{y^{(i)}}\log ({h_\theta }({x^{(i)}}) + (1 - } {y^{(i)}})\log (1 - {h_\theta }({x^{(i)}})] + \frac{\lambda }{{2m}}\sum\limits_{j = 1}^n {\theta _j^2}
  • Обратите внимание, что 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. Сигмовидная функция (т.е.{{h_\theta }(x)})

  • Код реализации:
# S型函数    
def sigmoid(z):
    h = np.zeros((len(z),1))    # 初始化,与z的长度一置
    
    h = 1.0/(1.0+np.exp(-z))
    return h
скопировать код

5. Преобразование в полиномиальное

  • Поскольку размер данных может быть небольшим, что приводит к большим отклонениям, создаются некоторые комбинации признаков.
  • например: форма отображения в степени 2:1 + {x_1} + {x_2} + x_1^2 + {x_1}{x_2} + x_2^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. Запуск результатов

  • граница решения data1 и точность
    enter description here enter description here
  • граница решения data2 и точность
    enter description here enter description here

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 пикселей, карта цветов выглядит следующим образом.enter description hereИзображение в оттенках серого:enter description here
  • Код реализации:
# 显示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 рассматривает текущий класс как один класс, а все остальные классы как один класс, поэтому становится проблемой двух классов.
  • Как показано на рисунке ниже, данные в пути делятся на три категории.Сначала красные считаются одной категорией, а остальные расцениваются как другая категория.Выполняется логистическая регрессия, а затем рассматриваются синие как одну категорию, а другие рассматриваются как одна категория.аналогия...enter description here
  • Можно видеть, что в случае более 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.... enter description here
  • тогда позвониАлгоритм градиентного спускарешать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. Запуск результатов

  • 10 классификаций, точность на тренировочном наборе:
    enter description here

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)
скопировать код
  • 5. Выходные результаты (точность на обучающей выборке)enter description here

3. Нейронная сеть БП

1. Нейросетевая модель

  • Сначала введите трехслойную нейронную сеть, как показано на следующем рисунке.

  • Входной слой состоит из трех блоков ({x_0}Это дополнительное смещение, обычно устанавливаемое на1)

  • a_i^{(j)}означает первыйjпервыйiстимул, также известный как единица

  • {\theta ^{(j)}}во-первыхjслой доj+1Весовая матрица сопоставления слоев — это вес каждого ребра.enter description here

  • Итак, вы можете получить:

  • Скрытый слой:
    a_1^{(2)} = g(\theta _{10}^{(1)}{x_0} + \theta _{11}^{(1)}{x_1} + \theta _{12}^{(1)}{x_2} + \theta _{13}^{(1)}{x_3})
    a_2^{(2)} = g(\theta _{20}^{(1)}{x_0} + \theta _{21}^{(1)}{x_1} + \theta _{22}^{(1)}{x_2} + \theta _{23}^{(1)}{x_3})
    a_3^{(2)} = g(\theta _{30}^{(1)}{x_0} + \theta _{31}^{(1)}{x_1} + \theta _{32}^{(1)}{x_2} + \theta _{33}^{(1)}{x_3})

  • выходной слой
    {h_\theta }(x) = a_1^{(3)} = g(\theta _{10}^{(2)}a_0^{(2)} + \theta _{11}^{(2)}a_1^{(2)} + \theta _{12}^{(2)}a_2^{(2)} + \theta _{13}^{(2)}a_3^{(2)})в,сигмовидная функцияg(z) = \frac{1}{{1 + {e^{ - z}}}}, также становитсяФункция возбуждения

  • Как можно заметить{\theta ^{(1)}}это матрица 3x4,{\theta ^{(2)}}это матрица 1x4

  • {\theta ^{(j)}}=="j+1Количество ячеек х (jКоличество юнитов в слое + 1)

2. Функция стоимости

  • Предполагая последний вывод{h_\Theta }(x) \in {R^K}, что означает, что выходной слой имеет K единиц
  • J(\Theta ) =  - \frac{1}{m}\sum\limits_{i = 1}^m {\sum\limits_{k = 1}^K {[y_k^{(i)}\log {{({h_\Theta }({x^{(i)}}))}k}} }  + (1 - y_k^{(i)})\log {(1 - {h\Theta }({x^{(i)}}))_k}]в,{({h_\Theta }(x))_i}представительiединица продукции
  • Функция стоимости с логистической регрессиейJ(\theta ) =  - \frac{1}{m}\sum\limits_{i = 1}^m {[{y^{(i)}}\log ({h_\theta }({x^{(i)}}) + (1 - } {y^{(i)}})\log (1 - {h_\theta }({x^{(i)}})]Почти, то есть добавить каждый выход (всего K выходов)

3. Регуляризация

  • L-->Количество всех слоев
  • {S_l}--> РазделlКоличество единиц слоя
  • нормализованныйфункция стоимостиза
    enter description here
  • \theta общий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-слойную нейронную сеть,\delta _{\text{j}}^{(l)}Отметить как -->lслойjединичная ошибка

  • \delta _{\text{j}}^{(4)} = a_j^{(4)} - {y_i}"==="{\delta ^{(4)}} = {a^{(4)}} - y(векторизованный)

  • {\delta ^{(3)}} = {({\theta ^{(3)}})^T}{\delta ^{(4)}}.*{g^}({a^{(3)}})

  • {\delta ^{(2)}} = {({\theta ^{(2)}})^T}{\delta ^{(3)}}.*{g^}({a^{(2)}})

  • нет{\delta ^{(1)}}, так как при вводе нет ошибки

  • Поскольку сигмовидная функция{\text{g(z)}}Производная от:{g^}(z){\text{ = g(z)(1 - g(z))}}, так что выше{g^}({a^{(3)}})а также{g^}({a^{(2)}})можно вычислить в прямом проходе

  • Процесс обратного распространения для вычисления градиента:

  • \Delta _{ij}^{(l)} = 0(\Delta пишется с большой буквы\delta )

  • for i=1-m:
    -{a^{(1)}} = {x^{(i)}}
    - Расчет прямого распространения{a^{(l)}}(л=2,3,4...л)
    - Обратный расчет{\delta ^{(L)}},{\delta ^{(L - 1)}}... {\delta ^{(2)}};
    -\Delta _{ij}^{(l)} = \Delta _{ij}^{(l)} + a_j^{(l)}{\delta ^{(l + 1)}}
    -D_{ij}^{(l)} = \frac{1}{m}\Delta _{ij}^{(l)} + \lambda \theta _{ij}^l\begin{array}{c}    {}& {(j \ne 0)}  \end{array}
    D_{ij}^{(l)} = \frac{1}{m}\Delta _{ij}^{(l)} + \lambda \theta _{ij}^lj = 0\begin{array}{c}    {}& {j = 0}  \end{array}

  • В конце концов\frac{{\partial J(\Theta )}}{{\partial \Theta {ij}^{(l)}}} = D{ij}^{(l)}, то есть получается градиент функции стоимости

  • Код реализации:

# 梯度
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Очень близко, средний квадрат градиента вдоль этого градиента минимизирует функцию стоимости. Процесс нахождения градиента выше можно сравнить.enter description here
  • Найдите более подробный процесс вывода ошибки:enter description here

6. Проверка градиента

  • Проверить использованиеBPПравильно ли получен градиент?
  • Используйте определение производной, чтобы проверить:\frac{{dJ(\theta )}}{{d\theta }} \approx \frac{{J(\theta  + \varepsilon ) - J(\theta  - \varepsilon )}}{{2\varepsilon }}
  • Полученный численный градиент должен быть очень близок к градиенту, полученному с помощью 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. Вывод результатов

  • Проверка градиента:
    enter description here
  • Произвольное отображение 100 рукописных чисел
    enter description here
  • показать веса тета1
    enter description here
  • Точность предсказания тренировочного набора
    enter description here
  • Точность предсказания нормализованного тренировочного набора
    enter description here

В-четвертых, машина опорных векторов SVM

1. Функция стоимости

  • В логистической регрессии наша стоимость составляет:
    \cos t({h_\theta }(x),y) = \left{ {\begin{array}{c}    { - \log ({h_\theta }(x))} \    { - \log (1 - {h_\theta }(x))}  \end{array} \begin{array}{c}    {y = 1} \    {y = 0}  \end{array} } \right.,
    в:{h_\theta }({\text{z}}) = \frac{1}{{1 + {e^{ - z}}}},z = {\theta ^T}x
  • Как показано на рисунке, еслиy=1,costФункция стоимости представлена ​​на рис.
    enter description here
    мы хотим{\theta ^T}x >  > 0,Сейчасz>>0,В этом случаеcostФункция стоимости будет стремиться к минимуму (это то, что нам нужно), поэтому использованиекрасныйФункция\cos {t_1}(z)Замена стоимости в логистической регрессии
  • когдаy=0в то же время, используйте\cos {t_0}(z)заменятьenter description here
  • Окончательная функция стоимости:
    J(\theta ) = C\sum\limits_{i = 1}^m {[{y^{(i)}}\cos {t_1}({\theta ^T}{x^{(i)}}) + (1 - {y^{(i)}})\cos {t_0}({\theta ^T}{x^{(i)}})} ] + \frac{1}{2}\sum\limits_{j = 1}^{\text{n}} {\theta _j^2}
    Наконец мы хотим\mathop {\min }\limits_\theta  J(\theta )
  • Функция затрат в нашей логистической регрессии была следующей:
    J(\theta ) =  - \frac{1}{m}\sum\limits_{i = 1}^m {[{y^{(i)}}\log ({h_\theta }({x^{(i)}}) + (1 - } {y^{(i)}})\log (1 - {h_\theta }({x^{(i)}})] + \frac{\lambda }{{2m}}\sum\limits_{j = 1}^n {\theta _j^2}
    можно рассмотреть здесьC = \frac{m}{\lambda }, это просто вопрос выражения, здесьCЧем больше значение , тем больше граница решения SVM.marginтакже больше, как будет объяснено ниже

2. Большая маржа

  • Как показано на рисунке ниже, в классификации SVM будет использоваться самый большойmarginотделить его
    enter description here

  • Давайте сначала поговорим о векторном внутреннем продукте.

  • u = \left[ {\begin{array}{c}    {{u_1}} \    {{u_2}}  \end{array} } \right],v = \left[ {\begin{array}{c}    {{v_1}} \    {{v_2}}  \end{array} } \right]

  • ||u||выражатьuизЕвклидова норма(европейская норма),||u||{\text{ = }}\sqrt {{\text{u}}_1^2 + u_2^2}

  • 向量Vсуществует向量uДлина проекции на обозначается какp, затем: векторный внутренний продукт:
    {{\text{u}}^T}v = p||u|| = {u_1}{v_1} + {u_2}{v_2}
    enter description here
    Его можно вывести по формуле векторного угла,\cos \theta  = \frac{{\overrightarrow {\text{u}} \overrightarrow v }}{{|\overrightarrow {\text{u}} ||\overrightarrow v |}}

  • Как уже было сказано, когдаCбольше,marginбольше, наша цель — минимизировать функцию стоимостиJ(θ),когдаmarginмаксимум,Cсрок продукта\sum\limits_{i = 1}^m {[{y^{(i)}}\cos {t_1}({\theta ^T}{x^{(i)}}) + (1 - {y^{(i)}})\cos {t_0}({\theta ^T}{x^{(i)}})} ]быть маленьким, поэтому приближение:
    J(\theta ) = C0 + \frac{1}{2}\sum\limits_{j = 1}^{\text{n}} {\theta j^2}  = \frac{1}{2}\sum\limits{j = 1}^{\text{n}} {\theta _j^2}  = \frac{1}{2}(\theta _1^2 + \theta _2^2) = \frac{1}{2}{\sqrt {\theta _1^2 + \theta _2^2} ^2},
    Наша конечная цель – минимизировать затратыθ

  • Зависит от
    \left{ {\begin{array}{c}    {{\theta ^T}{x^{(i)}} \geqslant 1} \    {{\theta ^T}{x^{(i)}} \leqslant  - 1}  \end{array} } \right.\begin{array}{c}    {({y^{(i)}} = 1)} \    {({y^{(i)}} = 0)}  \end{array} Вы можете получить:
    \left{ {\begin{array}{c}    {{p^{(i)}}||\theta || \geqslant 1} \    {{p^{(i)}}||\theta || \leqslant  - 1}  \end{array} } \right.\begin{array}{c}    {({y^{(i)}} = 1)} \    {({y^{(i)}} = 0)}  \end{array} ,pто естьxсуществуетθпроекция на

  • Как показано на рисунке ниже, предполагая, что граница решения показана на рисунке, найдите одну из точек, чтобыθПроекция наp,ноp||\theta || \geqslant 1илиp||\theta || \leqslant  - 1,еслиpмаленький, тебе нужен||\theta ||большой, что соответствует тому, что нам нужноθСделать||\theta || = \frac{1}{2}\sqrt {\theta _1^2 + \theta _2^2} наименее противоречивый,такПоследний запросlarge margin
    enter description here

3. Ядро SVM (функция ядра)

  • Для линейно отделимых задач используйтеЛинейная функция ядраТолько что

  • Для линейно неразделимых задач в логистической регрессии мы будемfeatureСопоставьте форму с помощью полиномов1 + {x_1} + {x_2} + x_1^2 + {x_1}{x_2} + x_2^2,SVMТакже вПолиномиальная функция ядра, но чащеФункция ядра Гаусса, также известен какЯдро РБФ

  • Функция ядра Гаусса:f(x) = {e^{ - \frac{{||x - u|{|^2}}}{{2{\sigma ^2}}}}}
    Предполагая несколько точек на рисунке,enter description hereсделать:
    {f_1} = similarity(x,{l^{(1)}}) = {e^{ - \frac{{||x - {l^{(1)}}|{|^2}}}{{2{\sigma ^2}}}}}
    {f_2} = similarity(x,{l^{(2)}}) = {e^{ - \frac{{||x - {l^{(2)}}|{|^2}}}{{2{\sigma ^2}}}}} . . .

  • Видно, что еслиxа также{l^{(1)}}Расстояние ближе, =="{f_1} \approx {e^0} = 1, (то есть сходство больше)
    еслиxа также{l^{(1)}}Расстояние далеко, =="{f_2} \approx {e^{ - \infty }} = 0, (т.е. меньшее сходство)

  • Функция ядра Гауссаσчем меньшеfтем быстрее спад
    enter description here enter description here

  • Как выбрать инициал{l^{(1)}}{l^{(2)}}{l^{(3)}}...

  • Обучающий набор:(({x^{(1)}},{y^{(1)}}),({x^{(2)}},{y^{(2)}}),...({x^{(m)}},{y^{(m)}}))

  • выберите:{l^{(1)}} = {x^{(1)}},{l^{(2)}} = {x^{(2)}}...{l^{(m)}} = {x^{(m)}}

  • для данногоx,рассчитатьf,сделать:f_0^{(i)} = 1так:{f^{(i)}} \in {R^{m + 1}}

  • минимизироватьJвыяснитьθ,
    J(\theta ) = C\sum\limits_{i = 1}^m {[{y^{(i)}}\cos {t_1}({\theta ^T}{f^{(i)}}) + (1 - {y^{(i)}})\cos {t_0}({\theta ^T}{f^{(i)}})} ] + \frac{1}{2}\sum\limits_{j = 1}^{\text{n}} {\theta _j^2}

  • если{\theta ^T}f \geqslant 0, == "Прогнозy=1

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. Запуск результатов

  • Линейно отделимая граница решения:
    enter description here
  • Линейная неразделимая граница решения:
    enter description here

Пять, алгоритм кластеризации K-средних

1. Процесс кластеризации

  • Кластеризация относится к обучению без учителя, а метки, не знающие y, делятся на K категорий.

  • Алгоритм K-средних разделен на два этапа.

  • Первый шаг: назначение кластера, случайный выборKуказать как центр, вычислить этоKрасстояние точек, разделенное наKкластеры

  • Шаг 2. Переместите центры кластеров: пересчитайте каждыйкластерцентр, переместите центр и повторите описанные выше шаги.

  • Как показано ниже:

  • Случайно назначенные кластерные центры
    enter description here

  • Пересчитать центры кластеров, переместиться один раз
    enter description here

  • В конце концов10Центр кластера после шага
    enter description here

  • Вычислите, в какой центр каждый фрагмент данных попадает в самый последний код реализации:

# 找到每条数据距离哪个类中心最近    
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. Целевая функция

  • также называемыйФункция стоимости искажения
  • J({c^{(1)}}, \cdots ,{c^{(m)}},{u_1}, \cdots ,{u_k}) = \frac{1}{m}\sum\limits_{i = 1}^m {||{x^{(i)}} - {u_{{c^{(i)}}}}|{|^2}}
  • В итоге мы хотим получить:
    enter description here
  • в{c^{(i)}}означает первыйiКакой центр класса ближе всего к фрагменту данных,
  • в{u_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 enter description here
  • Если очень гладко, то непонятно, искусственный выбор.
  • Во-вторых, это человеческое наблюдение и отбор.

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. Запуск результатов

  • Перемещение центров классов 2D-данных
    enter description here
  • Сжатие изображения
    enter description here

6. Анализ основных компонентов PCA (уменьшение размерности)

1. Используйте

  • Сжатие данных для ускорения работы программ
  • Визуализируйте данные, такие как3D-->2DЖдать
  • ......

2. 2D-->1D, nD-->kD

  • Как показано на рисунке ниже, все точки данных можно спроецировать на линию, т.е.сумма квадратов проектируемых расстояний(ошибка проецирования) минимумenter description here
  • Обратите внимание на потребности в данных归一化иметь дело с
  • Идея состоит в том, чтобы найти1индивидуальный向量u, все данные проецируются на него, чтобы минимизировать расстояние проецирования
  • ТакnD-->kDпросто ищуkвекторы?{u^{(1)}},{u^{(2)}} \ldots {u^{(k)}}?, все данные проецируются на него, чтобы минимизировать ошибку проецирования
  • например: 3D -> 2D, 2 вектора?{u^{(1)}},{u^{(2)}}?Он представляет собой плоскость, и ошибка проецирования всех точек, спроецированных на эту плоскость, наименьшая.

3. Разница между PCA и линейной регрессией

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

4. Процесс уменьшения размерности PCA

  • Предварительная обработка данных (нормализация среднего)
  • формула:?{\rm{x}}_j^{(i)} = {{{\rm{x}}_j^{(i)} - {u_j}} \over {{s_j}}}?
  • Нужно вычесть среднее значение соответствующего признака, а затем разделить на стандартное отклонение соответствующего признака (оно также может быть максимально-минимальным значением).
  • Код реализации:
    # 归一化数据
   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
скопировать код
  • рассчитать协方差矩阵Σ(Ковариационная матрица):?\Sigma  = {1 \over m}\sum\limits_{i = 1}^n {{x^{(i)}}{{({x^{(i)}})}^T}} ?
  • Обратите внимание здесьΣотличается от знака суммы
  • ковариационная матрица对称正定(Если вы не понимаете 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, и?\Sigma  = US{V^T}?
  • enter description here
  • Уведомление:svdфункция найденаSсортируются в порядке убывания собственных значений, если не используютсяsvd, нужно нажатьсобственные значенияИзменить размерU
  • Снижение размерности
  • ВыбратьUспередиKстолбец (при условии, что вы хотите уменьшить доKизмерение)
  • enter description here
  • 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. Восстановление данных

  • так как:?{Z^{(i)}} = U_{reduce}^T*{X^{(i)}}?
  • так:?{X_{approx}} = {(U_{reduce}^T)^{ - 1}}Z?(обратите внимание, что это приближение X)
  • и потому, чтоUreduceявляется положительно определенной матрицей, [положительно определенная матрица удовлетворяет:?A{A^T} = {A^T}A = E?,так:?{A^{ - 1}} = {A^T}?], так вот:
  • ?{X_{approx}} = {(U_{reduce}^{ - 1})^{ - 1}}Z = {U_{reduce}}Z?
  • Код реализации:
    # 恢复数据 
    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. Выбор количества главных компонентов (т. е. уменьшаемой размерности)

  • как выбрать
  • ошибка проекции(ошибка проекта):?{1 \over m}\sum\limits_{i = 1}^m {||{x^{(i)}} - x_{approx}^{(i)}|{|^2}} ?
  • полная вариация(общая вариация):?{1 \over m}\sum\limits_{i = 1}^m {||{x^{(i)}}|{|^2}} ?
  • подобноЧастота ошибок(коэффициент ошибки):?{{{1 \over m}\sum\limits_{i = 1}^m {||{x^{(i)}} - x_{approx}^{(i)}|{|^2}} } \over {{1 \over m}\sum\limits_{i = 1}^m {||{x^{(i)}}|{|^2}} }} \le 0.01?, это называется99%сохранить разницу
  • Частота ошибок обычно принимается1%,5%,10%Ждать
  • Как добиться
  • Это слишком дорого, чтобы попробовать один за другим
  • ДоU,S,V = svd(Sigma), мы получилиS, здесь коэффициент ошибки коэффициент ошибки:
    ?error{\kern 1pt} ;ratio = 1 - {{\sum\limits_{i = 1}^k {{S_{ii}}} } \over {\sum\limits_{i = 1}^n {{S_{ii}}} }} \le threshold?
  • можно постепенно увеличиватьKпытаться.

7. Рекомендации по применению

  • Не используйте PCA для решения проблемы переобучения.Overfittingили используйте метод регуляризации (это нормально, если вы сохраняете высокую дисперсию)
  • Рассмотрите возможность использования PCA только в том случае, если у вас есть хорошие результаты на исходных данных, но операция выполняется очень медленно.

8. Запуск результатов

  • 2D-данные сведены к 1D
  • направление к проекту
    enter description here
  • 2D сводится к 1D и соответствующим отношениям
    enter description here
  • уменьшение размерности данных лица
  • Необработанные данные
    enter description here
  • часть визуализацииUматричная информация
    enter description here
  • Восстановление данных
    enter description here

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

  • Функция распределения:?p(x) = {1 \over {\sqrt {2\pi } \sigma }}{e^{ - {{{{(x - u)}^2}} \over {2{\sigma ^2}}}}}?
  • в,uдля данныхиметь в виду,σдля данныхсреднеквадратичное отклонение
  • σПересекатьмаленький, соответствующее изображение большенаконечник
  • Оценка параметра(parameter estimation)
  • ?u = {1 \over m}\sum\limits_{i = 1}^m {{x^{(i)}}} ?
  • ?{\sigma ^2} = {1 \over m}\sum\limits_{i = 1}^m {{{({x^{(i)}} - u)}^2}} ?

2. Алгоритм обнаружения аномалий

  • пример
  • Обучающий набор:?{ {x^{(1)}},{x^{(2)}}, \cdots {x^{(m)}}} ??x \in {R^n}?
  • Предположение?{x_1},{x_2} \cdots {x_n}?Независимо друг от друга постройте модель модели:?p(x) = p({x_1};{u_1},\sigma _1^2)p({x_2};{u_2},\sigma _2^2) \cdots p({x_n};{u_n},\sigma n^2) = \prod\limits{j = 1}^n {p({x_j};{u_j},\sigma _j^2)} ?
  • обработать
  • Выберите тот, у которого репрезентативное исключениеfeature:xi
  • Оценка параметра:?{u_1},{u_2}, \cdots ,{u_n};\sigma _1^2,\sigma _2^2 \cdots ,\sigma _n^2?
  • рассчитать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Ненаучно оценивать.

  • Запишите следующим образом:
    enter description here

  • ?\Pr ecision = {{TP} \over {TP + FP}}?,который:Правильно предсказанные положительные результаты/все предсказанные положительные результаты

  • ?{\mathop{\rm Re}\nolimits} {\rm{call}} = {{TP} \over {TP + FN}}?,который:Правильно прогнозировать положительные образцы/истинные значения являются положительными образцами

  • пусть всегдаy=1(меньше классов), вычислитьPrecisionа такжеRecall

  • ?{F_1}Score = 2{{PR} \over {P + R}}?

  • Возьмем в качестве примера предсказание рака, предполагая, что все прогнозы не содержат рака, 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. Многомерное распределение Гаусса

  • Проблема с единичным распределением Гаусса
  • Как показано на рисунке ниже, красные точки — это аномальные точки, а остальные — нормальные точки (например, изменения в процессоре и памяти).
    enter description here
  • Распределение Гаусса, соответствующее x1, выглядит следующим образом:
    enter description here
  • Распределение Гаусса, соответствующее x2, выглядит следующим образом:
    enter description here
  • Видно, что соответствующие значения p(x1) и p(x2) сильно не меняются, поэтому их нельзя будет считать аномальными.
  • Поскольку мы думаем, что функции не зависят друг от друга, приведенное выше изображение основано наИдеальный кругспособ расширить
  • Многомерное распределение Гаусса
  • ?x \in {R^n}?, не устанавливатьp(x1),p(x2)...p(xn), а установить единуюp(x)
  • Среди параметров:?\mu  \in {R^n},\Sigma  \in {R^{n \times {\rm{n}}}}?,Σзаковариационная матрица
  • ?p(x) = {1 \over {{{(2\pi )}^{{n \over 2}}}|\Sigma {|^{{1 \over 2}}}}}{e^{ - {1 \over 2}{{(x - u)}^T}{\Sigma ^{ - 1}}(x - u)}}?
  • такой же,|Σ|чем меньшеp(x)более острый
  • Например:
    enter description here,
    Указывает x1,x2положительная корреляция, то есть чем больше x1, тем больше x2, как показано на рисунке ниже, можно проверить красную аномальную точкуenter description here
    подобно:
    enter description here,
    Указывает 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может использоваться, когда отношения между
  • Небольшой объем расчета
  • Многомерное распределение Гаусса
  • Автоматически захватывать соответствующие функции
  • Это вычислительно дорого, потому что:?\Sigma  \in {R^{n \times {\rm{n}}}}?
  • m>nилиΣМожет использоваться при обратимости. (Если это необратимо, может быть избыточный x из-за линейной корреляции, необратимого или просто m

7. Результаты работы программы

  • Данные дисплея
    enter description here
  • контурная линия
    enter description here
  • Маркировка выбросов
    enter description here