七种算法包括:

  • 线性回归算法

  • Logistic 回归算法

  • 感知器

  • K 最近邻算法

  • K 均值聚类算法

  • 含单隐层的神经网络

  • 多项式的 Logistic 回归算法

01 线性回归算法

在线性回归中,我们想要建立一个模型,来拟合一个因变量 y 与一个或多个独立自变量(预测变量) x 之间的关系。

给定:

  • 数据集

  • 是d-维向量

  • 是一个目标变量,它是一个标量

线性回归模型可以理解为一个非常简单的神经网络:

  • 它有一个实值加权向量

  • 它有一个实值偏置量 b

  • 它使用恒等函数作为其激活函数

线性回归模型可以使用以下方法进行训练

a) 梯度下降法

b) 正态方程(封闭形式解):

其中 X 是一个矩阵,其形式为,包含所有训练样本的维度信息。

而正态方程需要计算的转置。这个操作的计算复杂度介于)和之间,而这取决于所选择的实现方法。因此,如果训练集中数据的特征数量很大,那么使用正态方程训练的过程将变得非常缓慢。

线性回归模型的训练过程有不同的步骤。首先(在步骤 0 中),模型的参数将被初始化。在达到指定训练次数或参数收敛前,重复以下其他步骤。

第 0 步:

用0 (或小的随机值)来初始化权重向量和偏置量,或者直接使用正态方程计算模型参数

第 1 步(只有在使用梯度下降法训练时需要):

计算输入的特征与权重值的线性组合,这可以通过矢量化和矢量传播来对所有训练样本进行处理:

其中 X 是所有训练样本的维度矩阵,其形式为;· 表示点积。

第 2 步(只有在使用梯度下降法训练时需要):

用均方误差计算训练集上的损失:

第 3 步(只有在使用梯度下降法训练时需要):

对每个参数,计算其对损失函数的偏导数:

所有偏导数的梯度计算如下:

第 4 步(只有在使用梯度下降法训练时需要):

更新权重向量和偏置量:

其中,表示学习率。

In [4]:


 

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split

np.random.seed()

数据集

In [5]:


 

# We will use a simple training set

X = 2 * np.random.rand(500, 1)

y = 5 + 3 * X + np.random.randn(500, 1)

fig = plt.figure(figsize=(8,6))

plt.scatter(X, y)

plt.title("Dataset")

plt.xlabel("First feature")

plt.ylabel("Second feature")

plt.show()

In [6]:


 

# Split the data into a training and test set

X_train, X_test, y_train, y_test = train_test_split(X, y)

print(f'Shape X_train: {X_train.shape}')

print(f'Shape y_train: {y_train.shape}')

print(f'Shape X_test: {X_test.shape}')

print(f'Shape y_test: {y_test.shape}')

Shape X_train: (375, 1)Shape y_train: (375, 1)Shape X_test: (125, 1)Shape y_test: (125, 1)

线性回归分类

In [23]:


 

class LinearRegression:

   

   def __init__(self):

       pass

   

   ., n_iters=):

       """

       Trains a linear regression model using gradient descent

       """

       # Step 0: Initialize the parameters

       n_samples, n_features = X.shape

       ))

       

       costs = []

       

       for i in range(n_iters):

           # Step 1: Compute a linear combination of the input features and weights

           y_predict = np.dot(X, self.weights) + self.bias

         

           # Step 2: Compute cost over training set

           cost = ( / n_samples) * np.sum((y_predict - y)**)

           costs.append(cost)

         

            == :

               print(f"Cost at iteration {i}: {cost}")

           

           # Step 3: Compute the gradients

           dJ_dw = ( / n_samples) * np.dot(X.T, (y_predict - y))

           dJ_db = ( / n_samples) * np.sum((y_predict - y))

           

           # Step 4: Update the parameters

           self.weights = self.weights - learning_rate * dJ_dw

           self.bias = self.bias - learning_rate * dJ_db

       

       return self.weights, self.bias, costs

 

   def train_normal_equation(self, X, y):

       """

       Trains a linear regression model using the normal equation

       """

       self.weights = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), y)

       

       

       return self.weights, self.bias

       

   def predict(self, X):

       return np.dot(X, self.weights) + self.bias

使用梯度下降进行训练

In [24]:


 

regressor = LinearRegression()

w_trained, b_trained, costs = regressor.train_gradient_descent(X_train, y_train, learning_rate=0.005, n_iters=600)

fig = plt.figure(figsize=(8,6))

plt.plot(np.arange(n_iters), costs)

plt.title("Development of cost during training")

plt.xlabel("Number of iterations")

plt.ylabel("Cost")

plt.show()


 

Cost at iteration 0: 66.45256981003433 Cost at iteration 100: 2.2084346146095934 Cost at iteration 200: 1.2797812854182806 Cost at iteration 300: 1.2042189195356685 Cost at iteration 400: 1.1564867816573 Cost at iteration 500: 1.121391041394467

测试(梯度下降模型)

In [28]:


 

n_samples, _ = X_train.shape

n_samples_test, _ = X_test.shape

y_p_train = regressor.predict(X_train)

y_p_test = regressor.predict(X_test)

error_train =  (1 / n_samples) * np.sum((y_p_train - y_train) ** 2)

error_test =  (1 / n_samples_test) * np.sum((y_p_test - y_test) ** 2)

print(f"Error on training set: {np.round(error_train, 4)}")

print(f"Error on test set: {np.round(error_test)}")

Error on training set: 1.0955

Error on test set: 1.0

使用正规方程(normal equation)训练


 

# To compute the parameters using the normal equation, we add a bias value of 1 to each input example
X_b_train = np.c_[np.ones((n_samples)), X_train]
X_b_test = np.c_[np.ones((n_samples_test)), X_test]

reg_normal = LinearRegression()
w_trained = reg_normal.train_normal_equation(X_b_train, y_train)

测试(正规方程模型)


 

y_p_train = reg_normal.predict(X_b_train)

y_p_test = reg_normal.predict(X_b_test)

error_train =  (1 / n_samples) * np.sum((y_p_train - y_train) ** 2)

error_test =  (1 / n_samples_test) * np.sum((y_p_test - y_test) ** 2)

print(f"Error on training set: {np.round(error_train, 4)}")

print(f"Error on test set: {np.round(error_test, 4)}")

Error on training set: 1.0228

Error on test set: 1.0432

可视化测试预测


 

# Plot the test predictions

fig = plt.figure(figsize=(8,6))

plt.scatter(X_train, y_train)

plt.scatter(X_test, y_p_test)

plt.xlabel("First feature")

plt.ylabel("Second feature")

plt.show()

02 Logistic 回归算法

在 Logistic 回归中,我们试图对给定输入特征的线性组合进行建模,来得到其二元变量的输出结果。例如,我们可以尝试使用竞选候选人花费的金钱和时间信息来预测选举的结果(胜或负)。Logistic 回归算法的工作原理如下。

给定:

  • 数据集

  • 是d-维向量

  • 是一个二元的目标变量

Logistic 回归模型可以理解为一个非常简单的神经网络:

  • 它有一个实值加权向量

  • 它有一个实值偏置量 b

  • 它使用 sigmoid 函数作为其激活函数

与线性回归不同,Logistic 回归没有封闭解。但由于损失函数是凸函数,因此我们可以使用梯度下降法来训练模型。事实上,在保证学习速率足够小且使用足够的训练迭代步数的前提下,梯度下降法(或任何其他优化算法)可以是能够找到全局最小值。

训练 Logistic 回归模型有不同的步骤。首先(在步骤 0 中),模型的参数将被初始化。在达到指定训练次数或参数收敛前,重复以下其他步骤。

第 0 步:用 0 (或小的随机值)来初始化权重向量和偏置值

第 1 步:计算输入的特征与权重值的线性组合,这可以通过矢量化和矢量传播来对所有训练样本进行处理:

其中 X 是所有训练样本的维度矩阵,其形式为·表示点积。

第 2 步:用 sigmoid 函数作为激活函数,其返回值介于0到1之间:

第 3 步:计算整个训练集的损失值。

我们希望模型得到的目标值概率落在 0 到 1 之间。因此在训练期间,我们希望调整参数,使得模型较大的输出值对应正标签(真实标签为 1),较小的输出值对应负标签(真实标签为 0  )。这在损失函数中表现为如下形式:

第 4 步:对权重向量和偏置量,计算其对损失函数的梯度。

关于这个导数实现的详细解释,可以参见这里(https://stats.stackexchange.com/questions/278771/how-is-the-cost-function-from-logistic-regression-derivated)。

一般形式如下:

对于偏置量的导数计算,此时为 1。

第 5 步:更新权重和偏置值。

其中,表示学习率。

In [24]:


 

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt

np.random.seed()

% matplotlib inline

数据集

In [25]:


 

# We will perform logistic regression using a simple toy dataset of two classes

X, y_true = make_blobs(n_samples= 1000, centers=2)

fig = plt.figure(figsize=(8,6))
plt.scatter(X[:,0], X[:,1], c=y_true)

plt.title("Dataset")

plt.xlabel("First feature")

plt.ylabel("Second feature")

plt.show()

In [26]:


 

# Reshape targets to get column vector with shape (n_samples, 1)

y_true = y_true[:, np.newaxis]
# Split the data into a training and test set

X_train, X_test, y_train, y_test = train_test_split(X, y_true)

print(f'Shape X_train: {X_train.shape}')

print(f'Shape y_train: {y_train.shape}')

print(f'Shape X_test: {X_test.shape}')

print(f'Shape y_test: {y_test.shape}')

Shape X_train: (750, 2)

Shape y_train: (750, 1)

Shape X_test: (250, 2)

Shape y_test: (250, 1)

Logistic回归分类

In [27]:


 

class LogisticRegression:

  

   def __init__(self):

       pass

   def sigmoid(self, a):

        / ( + np.exp(-a))

   def train(self, X, y_true, n_iters, learning_rate):

       """

       Trains the logistic regression model on given data X and targets y

       """

       # Step 0: Initialize the parameters

       n_samples, n_features = X.shape

       self.weights = np.zeros((n_features, ))

       self.bias =

       costs = []

  

       for i in range(n_iters):

           # Step 1 and 2: Compute a linear combination of the input features and weights,

           # apply the sigmoid activation function

           y_predict = self.sigmoid(np.dot(X, self.weights) + self.bias)

      

           # Step 3: Compute the cost over the whole training set.

           cost = (- / n_samples) * np.sum(y_true * np.log(y_predict) + ( - y_true) * (np.log( - y_predict)))

           # Step 4: Compute the gradients

           dw = ( / n_samples) * np.dot(X.T, (y_predict - y_true))

           db = ( / n_samples) * np.sum(y_predict - y_true)

           # Step 5: Update the parameters

           self.weights = self.weights - learning_rate * dw

           self.bias = self.bias - learning_rate * db

           costs.append(cost)

            == :

               print(f"Cost after iteration {i}: {cost}")

       return self.weights, self.bias, costs

   def predict(self, X):

       """

       Predicts binary labels for a set of examples X.

       """

       y_predict = self.sigmoid(np.dot(X, self.weights) + self.bias)

       y_predict_labels = [ for elem in y_predict]

       return np.array(y_predict_labels)[:, np.newaxis]

初始化并训练模型

In [29]:


 

regressor = LogisticRegression()

w_trained, b_trained, costs = regressor.train(X_train, y_train, n_iters=600, learning_rate=0.009)

fig = plt.figure(figsize=(8,6))

plt.plot(np.arange(600), costs)

plt.title("Development of cost over training")

plt.xlabel("Number of iterations")

plt.ylabel("Cost")

plt.show()

Cost after iteration 0: 0.6931471805599453

Cost after iteration 100: 0.046514002935609956

Cost after iteration 200: 0.02405337743999163

Cost after iteration 300: 0.016354408151412207

Cost after iteration 400: 0.012445770521974634

Cost after iteration 500: 0.010073981792906512

测试模型

In [31]:


 

y_p_train = regressor.predict(X_train)

y_p_test = regressor.predict(X_test)

print(f"train accuracy: {100 - np.mean(np.abs(y_p_train - y_train)) * 100}%")

print(f"test accuracy: {100 - np.mean(np.abs(y_p_test - y_test))}%")

train accuracy: 100.0%

test accuracy: 100.0%

03 感知器算法

感知器是一种简单的监督式的机器学习算法,也是最早的神经网络体系结构之一。它由 Rosenblatt 在 20 世纪 50 年代末提出。感知器是一种二元的线性分类器,其使用 d- 维超平面来将一组训练样本( d- 维输入向量)映射成二进制输出值。它的原理如下:

给定:

  • 数据集

  • 是d-维向量 

  • 是一个目标变量,它是一个标量

感知器可以理解为一个非常简单的神经网络:

  • 它有一个实值加权向量

  • 它有一个实值偏置量 b

  • 它使用 Heaviside step 函数作为其激活函数

感知器的训练可以使用梯度下降法,训练算法有不同的步骤。首先(在步骤0中),模型的参数将被初始化。在达到指定训练次数或参数收敛前,重复以下其他步骤。

第 0 步:用 0 (或小的随机值)来初始化权重向量和偏置值

第 1 步:计算输入的特征与权重值的线性组合,这可以通过矢量化和矢量传播法则来对所有训练样本进行处理:

其中 X 是所有训练示例的维度矩阵,其形式为·表示点积。

第 2 步:用 Heaviside step 函数作为激活函数,其返回一个二进制值:

第 3 步:使用感知器的学习规则来计算权重向量和偏置量的更新值。

其中,表示学习率。

第 4 步:更新权重向量和偏置量。

In [1]:


 

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split

np.random.seed()

% matplotlib inline

数据集

In [2]:


 

X, y = make_blobs(n_samples=1000, centers=2)

fig = plt.figure(figsize=(8,6))
plt.scatter(X[:,0], X[:,1], c=y)

plt.title("Dataset")

plt.xlabel("First feature")

plt.ylabel("Second feature")

plt.show()

In [3]:


 

y_true = y[:, np.newaxis]

X_train, X_test, y_train, y_test = train_test_split(X, y_true)

print(f'Shape X_train: {X_train.shape}')

print(f'Shape y_train: {y_train.shape})')

print(f'Shape X_test: {X_test.shape}')

print(f'Shape y_test: {y_test.shape}')

Shape X_train: (750, 2)

Shape y_train: (750, 1))

Shape X_test: (250, 2)

Shape y_test: (250, 1)

感知器分类

In [6]:


 

class Perceptron():

   def __init__(self):

       pass

   ., n_iters=):

       n_samples, n_features = X.shape

       # Step 0: Initialize the parameters

       ))

       

       for i in range(n_iters):

           # Step 1: Compute the activation

           a = np.dot(X, self.weights) + self.bias

           # Step 2: Compute the output

           y_predict = self.step_function(a)

           # Step 3: Compute weight updates

           delta_w = learning_rate * np.dot(X.T, (y - y_predict))

           delta_b = learning_rate * np.sum(y - y_predict)

           # Step 4: Update the parameters

           self.weights += delta_w

           self.bias += delta_b

       return self.weights, self.bias

   def step_function(self, x):

        for elem in x])[:, np.newaxis]

   def predict(self, X):

       a = np.dot(X, self.weights) + self.bias

       return self.step_function(a)

初始化并训练模型

In [7]:


 

p = Perceptron()

w_trained, b_trained = p.train(X_train, y_train,learning_rate=0.05, n_iters=500)

测试

In [10]:


 

y_p_train = p.predict(X_train)

y_p_test = p.predict(X_test)

print(f"training accuracy: {100 - np.mean(np.abs(y_p_train - y_train)) * 100}%")

print(f"test accuracy: {100 - np.mean(np.abs(y_p_test - y_test)) * 100}%")

training accuracy: 100.0%

test accuracy: 100.0%

可视化决策边界

In [13]:


 

def plot_hyperplane(X, y, weights, bias):

   """

   Plots the dataset and the estimated decision hyperplane

   """

   slope = - weights[]/weights[]

   intercept = - bias/weights[]

   x_hyperplane = np.linspace(,)

   y_hyperplane = slope * x_hyperplane + intercept

   fig = plt.figure(figsize=(,))

   plt.scatter(X[:,], X[:,], c=y)

   plt.plot(x_hyperplane, y_hyperplane, '-')

   plt.title("Dataset and fitted decision hyperplane")

   plt.xlabel("First feature")

   plt.ylabel("Second feature")

   plt.show()

In [14]:


 

plot_hyperplane(X, y, w_trained, b_trained)

04 K 最近邻算法

k-nn 算法是一种简单的监督式的机器学习算法,可以用于解决分类和回归问题。这是一个基于实例的算法,并不是估算模型,而是将所有训练样本存储在内存中,并使用相似性度量进行预测。

给定一个输入示例,k-nn 算法将从内存中检索 k 个最相似的实例。相似性是根据距离来定义的,也就是说,与输入示例之间距离最小(欧几里得距离)的训练样本被认为是最相似的样本。

输入示例的目标值计算如下:

分类问题:

a) 不加权:输出 k 个最近邻中最常见的分类

b) 加权:将每个分类值的k个最近邻的权重相加,输出权重最高的分类

回归问题:

a) 不加权:输出k个最近邻值的平均值

b) 加权:对于所有分类值,将分类值加权求和并将结果除以所有权重的总和

加权版本的 k-nn 算法是改进版本,其中每个近邻的贡献值根据其与查询点之间的距离进行加权。下面,我们在 sklearn 用 k-nn 算法的原始版本实现数字数据集的分类。

In [1]:


 

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split

np.random.seed()

% matplotlib inline

数据集

In [2]:


 

# We will use the digits dataset as an example. It consists of the 1797 images of hand-written digits. Each digit is
# represented by a 64-dimensional vector of pixel values.

digits = load_digits()

X, y = digits.data, digits.target

X_train, X_test, y_train, y_test = train_test_split(X, y)

print(f'X_train shape: {X_train.shape}')

print(f'y_train shape: {y_train.shape}')

print(f'X_test shape: {X_test.shape}')

print(f'y_test shape: {y_test.shape}')

# Example digits

fig = plt.figure(figsize=(,))
):

   ax = fig.add_subplot(, , i+)

   plt.imshow(X[i].reshape((,)), cmap='gray')

X_train shape: (1347, 64)

y_train shape: (1347,)

X_test shape: (450, 64)

y_test shape: (450,)

K 最邻近类别

In [3]:


 

class kNN():

   def __init__(self):

       pass

   def fit(self, X, y):

       self.data = X

       self.targets = y

   def euclidean_distance(self, X):

       """

       Computes the euclidean distance between the training data and

       a new input example or matrix of input examples X

       """

       # input: single data point

       :

           l2 = np.sqrt(np.sum((self.data - X)**, axis=))

       # input: matrix of data points

       :

           n_samples, _ = X.shape

           l2 = [np.sqrt(np.sum((self.data - X[i])**, axis=)) for i in range(n_samples)]

       return np.array(l2)

   ):

       """

       Predicts the classification for an input example or matrix of input examples X

       """

       # step 1: compute distance between input and training data

       dists = self.euclidean_distance(X)

       # step 2: find the k nearest neighbors and their classifications

       :

           :

               nn = np.argmin(dists)

               return self.targets[nn]

           else:

               knn = np.argsort(dists)[:k]

               y_knn = self.targets[knn]

               max_vote = max(y_knn, key=list(y_knn).count)

               return max_vote

       :

           knn = np.argsort(dists)[:, :k]

           y_knn = self.targets[knn]

           :

               return y_knn.T

           else:

               n_samples, _ = X.shape

               max_votes = [max(y_knn[i], key=list(y_knn[i]).count) for i in range(n_samples)]

               return max_votes

初始化并训练模型

In [11]:


 

knn = kNN()

knn.fit(X_train, y_train)

print("Testing one datapoint, k=1")

print(], k=)}")

print(]}")

print()

print("Testing one datapoint, k=5")

print(], k=)}")

print(]}")

print()

print("Testing 10 datapoint, k=1")

print(:], k=)}")

print(:]}")

print()

print("Testing 10 datapoint, k=4")

print(:], k=)}")

print(:]}")

print()

Testing one datapoint, k=1

Predicted label: 3

True label: 3

Testing one datapoint, k=5

Predicted label: 9

True label: 9

Testing 10 datapoint, k=1

Predicted labels: [[3 1 0 7 4 0 0 5 1 6]]

True labels: [3 1 0 7 4 0 0 5 1 6]

Testing 10 datapoint, k=4

Predicted labels: [3, 1, 0, 7, 4, 0, 0, 5, 1, 6]

True labels: [3 1 0 7 4 0 0 5 1 6]

测试集精度

In [12]:


 

# Compute accuracy on test set

y_p_test1 = knn.predict(X_test, k=1)

test_acc1= np.sum(y_p_test1[0] == y_test)/len(y_p_test1[0]) * 100

print(f"Test accuracy with k = 1: {format(test_acc1)}")

y_p_test8 = knn.predict(X_test, k=5)

test_acc8= np.sum(y_p_test8 == y_test)/len(y_p_test8) * 100

print(f"Test accuracy with k = 8: {format(test_acc8)}")

Test accuracy with k = 1: 97.77777777777777

Test accuracy with k = 8: 97.55555555555556

05  K均值聚类算法

K-Means 是一种非常简单的聚类算法(聚类算法都属于无监督学习)。给定固定数量的聚类和输入数据集,该算法试图将数据划分为聚类,使得聚类内部具有较高的相似性,聚类与聚类之间具有较低的相似性。

算法原理

1. 初始化聚类中心,或者在输入数据范围内随机选择,或者使用一些现有的训练样本(推荐)

2. 直到收敛

  • 将每个数据点分配到最近的聚类。点与聚类中心之间的距离是通过欧几里德距离测量得到的。

  • 通过将聚类中心的当前估计值设置为属于该聚类的所有实例的平均值,来更新它们的当前估计值。

目标函数

聚类算法的目标函数试图找到聚类中心,以便数据将划分到相应的聚类中,并使得数据与其最接近的聚类中心之间的距离尽可能小。

给定一组数据X1,...,Xn和一个正数k,找到k个聚类中心C1,...,Ck并最小化目标函数:

这里:

  • 决定了数据点是否属于类

  • 表示类的聚类中心

  • 表示欧几里得距离

K-Means 算法的缺点:

  • 聚类的个数在开始就要设定

  • 聚类的结果取决于初始设定的聚类中心

  • 对异常值很敏感

  • 不适合用于发现非凸聚类问题

  • 该算法不能保证能够找到全局最优解,因此它往往会陷入一个局部最优解

In [21]:


 

import numpy as np
import matplotlib.pyplot as plt
import random
from sklearn.datasets import make_blobs

np.random.seed()

% matplotlib inline

数据集

In [22]:


 

X, y = make_blobs(centers=4, n_samples=1000)

print(f'Shape of dataset: {X.shape}')

fig = plt.figure(figsize=(8,6))
plt.scatter(X[:,0], X[:,1], c=y)

plt.title("Dataset with 4 clusters")

plt.xlabel("First feature")

plt.ylabel("Second feature")

plt.show()

Shape of dataset: (1000, 2)

K均值分类

In [23]:


 

class KMeans():

   ):

       self.k = n_clusters

   def fit(self, data):

       """

       Fits the k-means model to the given dataset

       """

       n_samples, _ = data.shape

       # initialize cluster centers

       self.centers = np.array(random.sample(list(data), self.k))

       self.initial_centers = np.copy(self.centers)

       # We will keep track of whether the assignment of data points

       # to the clusters has changed. If it stops changing, we are

       # done fitting the model

       old_assigns = None

       n_iters =

       while True:

           new_assigns = [self.classify(datapoint) for datapoint in data]

           if new_assigns == old_assigns:

               print(f"Training finished after {n_iters} iterations!")

               return

           old_assigns = new_assigns

           n_iters +=

           # recalculate centers

           for id_ in range(self.k):

               points_idx = np.where(np.array(new_assigns) == id_)

               datapoints = data[points_idx]

               self.centers[id_] = datapoints.mean(axis=)

   def l2_distance(self, datapoint):

       dists = np.sqrt(np.sum((self.centers - datapoint)**, axis=))

       return dists

   def classify(self, datapoint):

       """

       Given a datapoint, compute the cluster closest to the

       datapoint. Return the cluster ID of that cluster.

       """

       dists = self.l2_distance(datapoint)

       return np.argmin(dists)

   def plot_clusters(self, data):

       plt.figure(figsize=(,))

       plt.title("Initial centers in black, final centers in red")

       plt.scatter(data[:, ], data[:, ], marker='.', c=y)

       plt.scatter(self.centers[:, ], self.centers[:,], c='r')

       plt.scatter(self.initial_centers[:, ], self.initial_centers[:,], c='k')

       plt.show()

初始化并调整模型


 

kmeans = KMeans(n_clusters=4)

kmeans.fit(X)

Training finished after 4 iterations!

描绘初始和最终的聚类中心


 

kmeans.plot_clusters(X)

06 简单的神经网络

在这一章节里,我们将实现一个简单的神经网络架构,将 2 维的输入向量映射成二进制输出值。我们的神经网络有 2 个输入神经元,含 6 个隐藏神经元隐藏层及 1 个输出神经元。

我们将通过层之间的权重矩阵来表示神经网络结构。在下面的例子中,输入层和隐藏层之间的权重矩阵将被表示为,隐藏层和输出层之间的权重矩阵为。除了连接神经元的权重向量外,每个隐藏和输出的神经元都会有一个大小为 1 的偏置量。

我们的训练集由 m = 750 个样本组成。因此,我们的矩阵维度如下:

  • 训练集维度: X = (750,2)

  • 目标维度: Y = (750,1)

  • 维度:(m,nhidden) = (2,6)

  • 维度:(bias vector):(1,nhidden) = (1,6)

  • 维度: (nhidden,noutput)= (6,1)

  • 维度:(bias vector):(1,noutput) = (1,1)

损失函数

我们使用与 Logistic 回归算法相同的损失函数:

对于多类别的分类任务,我们将使用这个函数的通用形式作为损失函数,称之为分类交叉熵函数。

训练

我们将用梯度下降法来训练我们的神经网络,并通过反向传播法来计算所需的偏导数。训练过程主要有以下几个步骤:

1. 初始化参数(即权重量和偏差量)

2. 重复以下过程,直到收敛:

  • 通过网络传播当前输入的批次大小,并计算所有隐藏和输出单元的激活值和输出值。

  • 针对每个参数计算其对损失函数的偏导数

  • 更新参数

前向传播过程

首先,我们计算网络中每个单元的激活值和输出值。为了加速这个过程的实现,我们不会单独为每个输入样本执行此操作,而是通过矢量化对所有样本一次性进行处理。其中:

  • 表示对所有训练样本激活隐层单元的矩阵

  • 表示对所有训练样本输出隐层单位的矩阵

隐层神经元将使用 tanh 函数作为其激活函数:

输出层神经元将使用 sigmoid 函数作为激活函数:

激活值和输出值计算如下(·表示点乘):

反向传播过程

为了计算权重向量的更新值,我们需要计算每个神经元对损失函数的偏导数。这里不会给出这些公式的推导,你会在其他网站上找到很多更好的解释(https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/)。

对于输出神经元,梯度计算如下(矩阵符号):

对于输入和隐层的权重矩阵,梯度计算如下:

权重更新

In [3]:


 

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_split

np.random.seed()

% matplotlib inline

数据集

In [4]:


 

X, y = make_circles(n_samples=1000, factor=0.5, noise=.1)

fig = plt.figure(figsize=(8,6))
plt.scatter(X[:,0], X[:,1], c=y)

plt.xlim([-1.5, 1.5])

plt.ylim([-1.5, 1.5])

plt.title("Dataset")

plt.xlabel("First feature")

plt.ylabel("Second feature")

plt.show()

In [5]:


 

# reshape targets to get column vector with shape (n_samples, 1)

y_true = y[:, np.newaxis]
# Split the data into a training and test set

X_train, X_test, y_train, y_test = train_test_split(X, y_true)

print(f'Shape X_train: {X_train.shape}')

print(f'Shape y_train: {y_train.shape}')

print(f'Shape X_test: {X_test.shape}')

print(f'Shape y_test: {y_test.shape}')

Shape X_train: (750, 2)

Shape y_train: (750, 1)

Shape X_test: (250, 2)

Shape y_test: (250, 1)

Neural Network Class

以下部分实现受益于吴恩达的课程

https://www.coursera.org/learn/neural-networks-deep-learning


 

class NeuralNet():

   def __init__(self, n_inputs, n_outputs, n_hidden):

       self.n_inputs = n_inputs

       self.n_outputs = n_outputs

       self.hidden = n_hidden

       # Initialize weight matrices and bias vectors

       self.W_h = np.random.randn(self.n_inputs, self.hidden)

       self.b_h = np.zeros((, self.hidden))

       self.W_o = np.random.randn(self.hidden, self.n_outputs)

       self.b_o = np.zeros((, self.n_outputs))

   def sigmoid(self, a):

        / ( + np.exp(-a))

   def forward_pass(self, X):

       """

       Propagates the given input X forward through the net.

       Returns:

           A_h: matrix with activations of all hidden neurons for all input examples

           O_h: matrix with outputs of all hidden neurons for all input examples

           A_o: matrix with activations of all output neurons for all input examples

           O_o: matrix with outputs of all output neurons for all input examples

       """

       # Compute activations and outputs of hidden units

       A_h = np.dot(X, self.W_h) + self.b_h

       O_h = np.tanh(A_h)

       # Compute activations and outputs of output units

       A_o = np.dot(O_h, self.W_o) + self.b_o

       O_o = self.sigmoid(A_o)

       outputs = {

               "A_h": A_h,

               "A_o": A_o,

               "O_h": O_h,

               "O_o": O_o,

               }

       return outputs

   def cost(self, y_true, y_predict, n_samples):

       """

       Computes and returns the cost over all examples

       """

       # same cost function as in logistic regression

       cost = (- / n_samples) * np.sum(y_true * np.log(y_predict) + ( - y_true) * (np.log( - y_predict)))

       cost = np.squeeze(cost)

       assert isinstance(cost, float)

       return cost

   def backward_pass(self,  X, Y, n_samples, outputs):

       """

       Propagates the errors backward through the net.

       Returns:

           dW_h: partial derivatives of loss function w.r.t hidden weights

           db_h: partial derivatives of loss function w.r.t hidden bias

           dW_o: partial derivatives of loss function w.r.t output weights

           db_o: partial derivatives of loss function w.r.t output bias

       """

       dA_o = (outputs["O_o"] - Y)

       dW_o = ( / n_samples) * np.dot(outputs["O_h"].T, dA_o)

       db_o = ( / n_samples) * np.sum(dA_o)

       dA_h = (np.dot(dA_o, self.W_o.T)) * ( - np.power(outputs[))

       dW_h = ( / n_samples) * np.dot(X.T, dA_h)

       db_h = ( / n_samples) * np.sum(dA_h)

       gradients = {

               "dW_o": dW_o,

               "db_o": db_o,

               "dW_h": dW_h,

               "db_h": db_h,

               }

       return gradients

   def update_weights(self, gradients, eta):

       """

       Updates the model parameters using a fixed learning rate

       """

       self.W_o = self.W_o - eta * gradients["dW_o"]

       self.W_h = self.W_h - eta * gradients["dW_h"]

       self.b_o = self.b_o - eta * gradients["db_o"]

       self.b_h = self.b_h - eta * gradients["db_h"]

   , eta=0.3):

       """

       Trains the neural net on the given input data

       """

       n_samples, _ = X.shape

       for i in range(n_iters):

           outputs = self.forward_pass(X)

           cost = self.cost(y, outputs["O_o"], n_samples=n_samples)

           gradients = self.backward_pass(X, y, n_samples, outputs)

            == :

               print()}')

           self.update_weights(gradients, eta)

   def predict(self, X):

       """

       Computes and returns network predictions for given dataset

       """

       outputs = self.forward_pass(X)

       y_pred = [ for elem in outputs["O_o"]]

       return np.array(y_pred)[:, np.newaxis]

初始化并训练神经网络


 

nn = NeuralNet(n_inputs=, n_hidden=, n_outputs=)

print("Shape of weight matrices and bias vectors:")

print(f'W_h shape: {nn.W_h.shape}')

print(f'b_h shape: {nn.b_h.shape}')

print(f'W_o shape: {nn.W_o.shape}')

print(f'b_o shape: {nn.b_o.shape}')

print()

print("Training:")

nn.train(X_train, y_train, n_iters=, eta=0.7)

Shape of weight matrices and bias vectors:

W_h shape: (2, 6)

b_h shape: (1, 6)

W_o shape: (6, 1)

b_o shape: (1, 1)

Training:

Cost at iteration 0: 1.0872

Cost at iteration 100: 0.2723

Cost at iteration 200: 0.1712

Cost at iteration 300: 0.1386

Cost at iteration 400: 0.1208

Cost at iteration 500: 0.1084

Cost at iteration 600: 0.0986

Cost at iteration 700: 0.0907

Cost at iteration 800: 0.0841

Cost at iteration 900: 0.0785

Cost at iteration 1000: 0.0739

Cost at iteration 1100: 0.0699

Cost at iteration 1200: 0.0665

Cost at iteration 1300: 0.0635

Cost at iteration 1400: 0.061

Cost at iteration 1500: 0.0587

Cost at iteration 1600: 0.0566

Cost at iteration 1700: 0.0547

Cost at iteration 1800: 0.0531

Cost at iteration 1900: 0.0515

测试神经网络


 

n_test_samples, _ = X_test.shape

y_predict = nn.predict(X_test)

print(f"Classification accuracy on test set: {(np.sum(y_predict == y_test)/n_test_samples)*100} %")


 

Classification accuracy on test set: 98.4 %

可视化决策边界


 

X_temp, y_temp = make_circles(n_samples=60000, noise=.5)

y_predict_temp = nn.predict(X_temp)

y_predict_temp = np.ravel(y_predict_temp)


 

fig = plt.figure(figsize=(8,12))

ax = fig.add_subplot(2,1,1)
plt.scatter(X[:,0], X[:,1], c=y)

plt.xlim([-1.5, 1.5])

plt.ylim([-1.5, 1.5])

plt.xlabel("First feature")

plt.ylabel("Second feature")

plt.title("Training and test set")

ax = fig.add_subplot(2,1,2)
plt.scatter(X_temp[:,0], X_temp[:,1], c=y_predict_temp)

plt.xlim([-1.5, 1.5])

plt.ylim([-1.5, 1.5])

plt.xlabel("First feature")

plt.ylabel("Second feature")

plt.title("Decision boundary")

Out[11]:Text(0.5,1,'Decision boundary')

07 Softmax  回归算法

Softmax 回归算法,又称为多项式或多类别的 Logistic 回归算法。

给定:

  • 数据集

  • 是d-维向量 

  • 是对应于的目标变量,例如对于K=3分类问题,

Softmax 回归模型有以下几个特点:

  • 对于每个类别,都存在一个独立的、实值加权向量

  • 这个权重向量通常作为权重矩阵中的行。

  • 对于每个类别,都存在一个独立的、实值偏置量b

  • 它使用 softmax 函数作为其激活函数

  • 它使用交叉熵( cross-entropy )作为损失函数

训练 Softmax 回归模型有不同步骤。首先(在步骤0中),模型的参数将被初始化。在达到指定训练次数或参数收敛前,重复以下其他步骤。

第 0 步:用 0 (或小的随机值)来初始化权重向量和偏置值

第 1 步:对于每个类别k,计算其输入的特征与权重值的线性组合,也就是说为每个类别的训练样本计算一个得分值。对于类别k,输入向量为,则得分值的计算如下:

其中表示类别k的权重矩阵·表示点积。

我们可以通过矢量化和矢量传播法则计算所有类别及其训练样本的得分值:

其中 X 是所有训练样本的维度矩阵,W 表示每个类别的权重矩阵维度,其形式为

第 2 步:用 softmax 函数作为激活函数,将得分值转化为概率值形式。属于类别 k 的输入向量的概率值为:

同样地,我们可以通过矢量化来对所有类别同时处理,得到其概率输出。模型预测出的表示的是该类别的最高概率。

第 3 步:计算整个训练集的损失值。

我们希望模型预测出的高概率值是目标类别,而低概率值表示其他类别。这可以通过以下的交叉熵损失函数来实现:

在上面公式中,目标类别标签表示成独热编码形式( one-hot )。因此为1时表示的目标类别是 k,反之则为 0。

第 4 步:对权重向量和偏置量,计算其对损失函数的梯度。

关于这个导数实现的详细解释,可以参见这里(http://ufldl.stanford.edu/tutorial/supervised/SoftmaxRegression/)。

一般形式如下:

对于偏置量的导数计算,此时为1。

第 5 步:对每个类别k,更新其权重和偏置值。

其中,表示学习率。

In [1]:


 

from sklearn.datasets import load_iris
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt

np.random.seed()

数据集

In [2]:


 

X, y_true = make_blobs(centers=4, n_samples = 5000)

fig = plt.figure(figsize=(8,6))
plt.scatter(X[:,0], X[:,1], c=y_true)

plt.title("Dataset")

plt.xlabel("First feature")

plt.ylabel("Second feature")

plt.show()

In [3]:


 

# reshape targets to get column vector with shape (n_samples, 1)

y_true = y_true[:, np.newaxis]
# Split the data into a training and test set

X_train, X_test, y_train, y_test = train_test_split(X, y_true)

print(f'Shape X_train: {X_train.shape}')

print(f'Shape y_train: {y_train.shape}')

print(f'Shape X_test: {X_test.shape}')

print(f'Shape y_test: {y_test.shape}')

Shape X_train: (3750, 2)

Shape y_train: (3750, 1)

Shape X_test: (1250, 2)

Shape y_test: (1250, 1)

Softmax回归分类


 

class SoftmaxRegressor:

   def __init__(self):

       pass

   , learning_rate=0.1):

       """

       Trains a multinomial logistic regression model on given set of training data

       """

       self.n_samples, n_features = X.shape

       self.n_classes = n_classes

       self.weights = np.random.rand(self.n_classes, n_features)

       self.bias = np.zeros((, self.n_classes))

       all_losses = []

       for i in range(n_iters):

           scores = self.compute_scores(X)

           probs = self.softmax(scores)

           y_predict = np.argmax(probs, axis=)[:, np.newaxis]

           y_one_hot = self.one_hot(y_true)

           loss = self.cross_entropy(y_one_hot, probs)

           all_losses.append(loss)

           dw = ( / self.n_samples) * np.dot(X.T, (probs - y_one_hot))

           db = ( / self.n_samples) * np.sum(probs - y_one_hot, axis=)

           self.weights = self.weights - learning_rate * dw.T

           self.bias = self.bias - learning_rate * db

            == :

               print()}')

       return self.weights, self.bias, all_losses

   def predict(self, X):

       """

       Predict class labels for samples in X.

       Args:

           X: numpy array of shape (n_samples, n_features)

       Returns:

           numpy array of shape (n_samples, 1) with predicted classes

       """

       scores = self.compute_scores(X)

       probs = self.softmax(scores)

       )[:, np.newaxis]

   def softmax(self, scores):

       """

       Tranforms matrix of predicted scores to matrix of probabilities

       Args:

           scores: numpy array of shape (n_samples, n_classes)

           with unnormalized scores

       Returns:

           softmax: numpy array of shape (n_samples, n_classes)

           with probabilities

       """

       exp = np.exp(scores)

       sum_exp = np.sum(np.exp(scores), axis=, keepdims=True)

       softmax = exp / sum_exp

       return softmax

   def compute_scores(self, X):

       """

       Computes class-scores for samples in X

       Args:

           X: numpy array of shape (n_samples, n_features)

       Returns:

           scores: numpy array of shape (n_samples, n_classes)

       """

       return np.dot(X, self.weights.T) + self.bias

   def cross_entropy(self, y_true, scores):

       loss = - ( / self.n_samples) * np.sum(y_true * np.log(scores))

       return loss

   def one_hot(self, y):

       """

       Tranforms vector y of labels to one-hot encoded matrix

       """

       one_hot = np.zeros((self.n_samples, self.n_classes))

       one_hot[np.arange(self.n_samples), y.T] =

       return one_hot

初始化并训练模型


 

regressor = SoftmaxRegressor()

w_trained, b_trained, loss = regressor.train(X_train, y_train, learning_rate=0.1, n_iters=800, n_classes=4)

fig = plt.figure(figsize=(8,6))

plt.plot(np.arange(800), loss)

plt.title("Development of loss during training")

plt.xlabel("Number of iterations")

plt.ylabel("Loss")

plt.show()Iteration number: 0, loss: 1.393

Iteration number: 100, loss: 0.2051

Iteration number: 200, loss: 0.1605

Iteration number: 300, loss: 0.1371

Iteration number: 400, loss: 0.121

Iteration number: 500, loss: 0.1087

Iteration number: 600, loss: 0.0989

Iteration number: 700, loss: 0.0909

测试模型


 

n_test_samples, _ = X_test.shape

y_predict = regressor.predict(X_test)

print(f"Classification accuracy on test set: {(np.sum(y_predict == y_test)/n_test_samples) * 100}%")

测试集分类准确率:99.03999999999999%

Python实现的各种机器学习算法的更多相关文章

  1. 小姐姐带你一起学:如何用Python实现7种机器学习算法(附代码)

    小姐姐带你一起学:如何用Python实现7种机器学习算法(附代码) Python 被称为是最接近 AI 的语言.最近一位名叫Anna-Lena Popkes的小姐姐在GitHub上分享了自己如何使用P ...

  2. 建模分析之机器学习算法(附python&R代码)

    0序 随着移动互联和大数据的拓展越发觉得算法以及模型在设计和开发中的重要性.不管是现在接触比较多的安全产品还是大互联网公司经常提到的人工智能产品(甚至人类2045的的智能拐点时代).都基于算法及建模来 ...

  3. 机器学习算法与Python实践之(四)支持向量机(SVM)实现

    机器学习算法与Python实践之(四)支持向量机(SVM)实现 机器学习算法与Python实践之(四)支持向量机(SVM)实现 zouxy09@qq.com http://blog.csdn.net/ ...

  4. 机器学习算法与Python实践之(三)支持向量机(SVM)进阶

    机器学习算法与Python实践之(三)支持向量机(SVM)进阶 机器学习算法与Python实践之(三)支持向量机(SVM)进阶 zouxy09@qq.com http://blog.csdn.net/ ...

  5. 机器学习算法与Python实践之(二)支持向量机(SVM)初级

    机器学习算法与Python实践之(二)支持向量机(SVM)初级 机器学习算法与Python实践之(二)支持向量机(SVM)初级 zouxy09@qq.com http://blog.csdn.net/ ...

  6. 【机器学习算法-python实现】KNN-k近邻算法的实现(附源代码)

    ,400],[200,5],[100,77],[40,300]]) shape:显示(行,列)例:shape(group)=(4,2) zeros:列出一个同样格式的空矩阵,例:zeros(group ...

  7. 机器学习算法与Python实践之(五)k均值聚类(k-means)

    机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学 ...

  8. 机器学习算法 Python&R 速查表

    sklearn实战-乳腺癌细胞数据挖掘( 博主亲自录制) https://study.163.com/course/introduction.htm?courseId=1005269003&u ...

  9. 10 种机器学习算法的要点(附 Python 和 R 代码)

    本文由 伯乐在线 - Agatha 翻译,唐尤华 校稿.未经许可,禁止转载!英文出处:SUNIL RAY.欢迎加入翻译组. 前言 谷歌董事长施密特曾说过:虽然谷歌的无人驾驶汽车和机器人受到了许多媒体关 ...

随机推荐

  1. poj3162 树形dp|树的直径 + 双单调队列|线段树,好题啊

    题解链接:https://blog.csdn.net/shiqi_614/article/details/8105149 用树形dp是超时的,, /* 先求出每个点可以跑的最长距离dp[i][0|1] ...

  2. php 重要函数归集

    1.json_encode 与 json_decode json_encode 把数组转化成字符串 json_encode(array) json_decode 把目标字符串转成数组json_deco ...

  3. 安装mysql后在/var/log/mysqld.log 中找不到临时密码

    centos7通过yum装完mysql,使用grep 'temporary password' /var/log/mysqld.log找不到root密码打开mysqld.log中根本没有tempora ...

  4. Python属性(@property)

    创建用于计算机的属性 在Python中,可以通过@property(装饰器)将一个方法转换为属性,从而实现用于计算的属性.将方法转换为属性后,可以直接通过方法名来访问方法,而不需要再添加一对小括号&q ...

  5. spring cloud 自定义ribbon客户端

    一.自定义Ribbon客户端-[方式一]配置类 1.1.自定义负载规则 增加RibbonConfiguration.java配置类 public class RibbonConfiguration { ...

  6. 20165206 实验一 Java开发环境的熟悉

    20165206 实验一 Java开发环境的熟悉 一.实验内容及步骤 实验一 Java开发环境的熟悉-1 建立有自己学号的实验目录. 通过vim Hello.java编辑代码. 编译.运行Hello. ...

  7. windows10的文件浏览器中无法搜索文件内容

    系统:更新到最新的win10(2018年8月23日 23:54:31) 重现步骤:git clone一个项目,然后切换到它的另一个分支:打开文件夹浏览器(explorer),在右上角里输入想要查找的字 ...

  8. Senparc.Weixin微信开发(2) 消息机制和上下文(Session)

    了解MessageHandler 为项目添加一个CustomMessageHandle.cs类 public class CustomMessageHandler : MessageHandler&l ...

  9. Elasticsearch集群

    详细Elasticsearch安装: https://www.cnblogs.com/littlehb/p/8406378.html 安装之前需先优化内核: https://www.cnblogs.c ...

  10. 利用 Windows API Code Pack 修改音乐的 ID3 信息

    朋友由于抠门 SD 卡买小了,结果音乐太多放不下,又不舍得再买新卡,不得已决定重新转码,把音乐码率压低一点,牺牲点音质来换空间(用某些人的话说,反正不是搞音乐的,听不出差别)… 结果千千静听(百度音乐 ...