前 言
随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。主要是利用BP神经网络来实现数据的二分类。
提示:以下是本篇文章正文内容,下面案例可供参考
一、BP神经网络的推导
二、使用步骤
导入数据集:训练集x_train、y_train和测试集x_test、y_test。进行训练并输出结果。
三、完整代码
import numpy as np
import pandas as pd
import scipy.io as sio
import matplotlib.pyplot as plt
def load_dataset():
# 读取.mat文件
x_train = u'x_train.mat'
x_train = sio.loadmat(x_train)
x_test = u'x_test.mat'
x_test = sio.loadmat(x_test)
y_train = u'y_train.mat'
y_train = sio.loadmat(y_train)
y_test = u'y_test.mat'
y_test = sio.loadmat(y_test)
# 拆分训练数据与测试数据
x_train = x_train['x_train']
y_train = y_train['y_train']
x_test = x_test['x_test']
y_test = y_test['y_test']
# 将训练和测试数据分别用表格的形式查看
print("训练集:", pd.concat([pd.DataFrame(x_train), pd.DataFrame(y_train)], axis=1))
print("测试集:", pd.concat([pd.DataFrame(x_test), pd.DataFrame(y_test)], axis=1))
return x_train, y_train, x_test, y_test
def sigmoid(x):
# Sigmoid activation function: f(x) = 1 / (1 + e^(-x))
return 1 / (1 + np.exp(-x))
def deriv_sigmoid(x):
# Derivative of sigmoid: f'(x) = f(x) * (1 - f(x))
fx = sigmoid(x)
return fx * (1 - fx)
def mse_loss(y_true, y_pred):
# MSE:平均方差损失(即为所有方差((y_true - y_pred)^2) 的平均值)
# y_true and y_pred are numpy arrays of the same length.
return ((y_true - y_pred) ** 2).mean()
class OurNeuralNetwork:
'''
A neural network with:
- 2 inputs
- a hidden layer with 2 neurons (h1, h2)
- an output layer with 1 neuron (o1)
'''
def __init__(self):
# 权重,Weights
self.w1 = np.random.normal()
self.w2 = np.random.normal()
self.w3 = np.random.normal()
self.w4 = np.random.normal()
self.w5 = np.random.normal()
self.w6 = np.random.normal()
# 截距项,Biases
self.b1 = np.random.normal()
self.b2 = np.random.normal()
self.b3 = np.random.normal()
def feedforward(self, x):
# x is a numpy array with 2 elements.
h1 = sigmoid(self.w1 * x[0] + self.w2 * x[1] + self.b1)
h2 = sigmoid(self.w3 * x[0] + self.w4 * x[1] + self.b2)
o1 = sigmoid(self.w5 * h1 + self.w6 * h2 + self.b3)
return o1
def train(self, data, all_y_trues):
'''
- data is a (n x 2) numpy array, n = # of samples in the dataset.
- all_y_trues is a numpy array with n elements.
Elements in all_y_trues correspond to those in data.
'''
learn_rate = 0.1
epochs = 1000 # number of times to loop through the entire dataset
list_epoch = []
list_loss = []
w1 = []
w2 = []
w3 = []
w4 = []
w5 = []
w6 = []
b1 = []
b2 = []
b3 = []
for epoch in range(epochs):
for x, y_true in zip(data, all_y_trues):
# Do a feedforward (we'll need these values later)
sum_h1 = self.w1 * x[0] + self.w2 * x[1] + self.b1
h1 = sigmoid(sum_h1)
sum_h2 = self.w3 * x[0] + self.w4 * x[1] + self.b2
h2 = sigmoid(sum_h2)
sum_o1 = self.w5 * h1 + self.w6 * h2 + self.b3
o1 = sigmoid(sum_o1)
y_pred = o1
# --- Calculate partial derivatives.
# --- Naming: d_L_d_w1 represents "partial L / partial w1"
d_L_d_ypred = -2 * (y_true - y_pred)
# Neuron o1
d_ypred_d_w5 = h1 * deriv_sigmoid(sum_o1)
d_ypred_d_w6 = h2 * deriv_sigmoid(sum_o1)
d_ypred_d_b3 = deriv_sigmoid(sum_o1)
d_ypred_d_h1 = self.w5 * deriv_sigmoid(sum_o1)
d_ypred_d_h2 = self.w6 * deriv_sigmoid(sum_o1)
# Neuron h1
d_h1_d_w1 = x[0] * deriv_sigmoid(sum_h1)
d_h1_d_w2 = x[1] * deriv_sigmoid(sum_h1)
d_h1_d_b1 = deriv_sigmoid(sum_h1)
# Neuron h2
d_h2_d_w3 = x[0] * deriv_sigmoid(sum_h2)
d_h2_d_w4 = x[1] * deriv_sigmoid(sum_h2)
d_h2_d_b2 = deriv_sigmoid(sum_h2)
# --- Update weights and biases
# Neuron h1
w1.append(self.w1)
w2.append(self.w2)
b1.append(self.b1)
self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w1
self.w2 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w2
self.b1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_b1
# Neuron h2
w3.append(self.w3)
w4.append(self.w4)
b2.append(self.b2)
self.w3 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w3
self.w4 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w4
self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_b2
# Neuron o1
w5.append(self.w5)
w6.append(self.w6)
b3.append(self.b3)
self.w5 -= learn_rate * d_L_d_ypred * d_ypred_d_w5
self.w6 -= learn_rate * d_L_d_ypred * d_ypred_d_w6
self.b3 -= learn_rate * d_L_d_ypred * d_ypred_d_b3
# --- Calculate total loss at the end of each epoch
if epoch % 10 == 0:
y_preds = np.apply_along_axis(self.feedforward, 1, data) #np.apply_along_axis(function,aixs,data):将一个函数沿一个轴作用到数组中
loss = mse_loss(all_y_trues, y_preds)
print("Epoch %d loss: %.3f" % (epoch, loss))
list_epoch.append(epoch)
list_loss.append(loss)
return list_epoch,list_loss,w1,w2,w3,w4,w5,w6,b1,b2,b3
def predict(self, data, all_y_trues):
# 计算将测试集带入模型后得到的预测值
y_preds = []
for i in range(len(data)):
y_pre = self.feedforward(data[i])[0]
y_preds.append(y_pre)
# 利用不同的阈值对y_preds进行分割,找到num_normal、num_normal_correct、num_freeze和num_freeze_correct
x = []
num_normal = []
num_normal_correct = []
num_freeze = []
num_freeze_correct = []
for i in range(1, 10):
num1 = 0
num2 = 0
num3 = 0
num4 = 0
i /= 200
x.append(i)
for j in range(len(y_preds)):
if y_preds[j] < i:
num1 += 1
for k in range(len(all_y_trues)):
if all_y_trues[k] == 0 and j == k:
num2 += 1
for j in range(len(y_preds)):
if y_preds[j] >= i:
num3 += 1
for k in range(len(all_y_trues)):
if all_y_trues[k] == 1 and j == k:
num4 += 1
num_normal.append(num3)
num_normal_correct.append(num4)
num_freeze.append(num1)
num_freeze_correct.append(num2)
print("num_freeze:", num_freeze)
print("num_freeze_correct:", num_freeze_correct)
print("num_normal:", num_normal)
print("num_normal_correct:", num_normal_correct)
# 根据不同的阈值对预测准确率{(TP+FN)/(TP+TN+FP+FN)}的影响
y = []
for i, j in zip(num_normal_correct, num_freeze_correct):
y.append((i + j) / len(all_y_trues))
plt.plot(x, y)
plt.xlabel('阈值', fontproperties="SimHei", fontsize=14)
plt.ylabel('准确率', fontproperties="SimHei", fontsize=14)
plt.title("不同的阈值对预测准确率的影响", fontproperties="SimHei", fontsize=14)
plt.show()
# 利用找到的最佳的阈值,进行分类,并得到预测标签test_predict_labels
test_predict_labels = []
accuracy = max(y)
thresh = x[y.index(max(y))]
for j in range(len(y_preds)):
if y_preds[j] < thresh:
test_predict_labels.append(0)
else:
test_predict_labels.append(1)
return thresh, accuracy, test_predict_labels
def main():
# load dataset
[x_train, y_train, x_test, y_test] = load_dataset()
# Define train set
data_train = x_train[:, 1:3]
all_y_trues_train = y_train
# Train our neural network!
network = OurNeuralNetwork()
[list_epoch, list_loss, w1, w2, w3, w4, w5, w6, b1, b2, b3] = network.train(data_train, all_y_trues_train)
plt.plot(list_epoch, list_loss)
plt.xlabel('epoch')
plt.ylabel('loss')
plt.title('Neural network loss vs epoch')
plt.show()
print(">>>>>>开始预测>>>>>>>")
# get the predicted result of x_test
data_test = x_test[:, 1:3] # 测试集,并用测试集的wind_speed和power进行预测
all_y_trues_test = y_test
[thresh, accuracy, test_predict_labels] = network.predict(data_test, all_y_trues_test)
print("根据阈值:{},得到的预测准确率:{}".format(thresh, accuracy))
print("x_test的预测标签:", test_predict_labels)
plt.scatter(range(len(x_test)), test_predict_labels)
plt.xlabel('测试数据位数', fontproperties="SimHei", fontsize=14)
plt.ylabel('标签', fontproperties="SimHei", fontsize=14)
plt.title("测试集的预测分类图", fontproperties="SimHei", fontsize=14)
plt.show()
if __name__ == '__main__':
main()
四、实验结果
预测准确率accuracy = (TP+FN)/(TP+TN+FP+FN),其中num_freeze = TN+FN ,num_normal =TP+FP,分别表示利用训练的网络模型预测结冰和未结冰的数据点的个数; num_freeze_correct = TN, num_normal_correct =TP, 分别表示预测正常的结冰和为结冰的数据点的个数。