BP反向传播
【摘要】 """案例:研究生学院录取数据,用梯度下降训练一个网络。数据有三个输入特征:GRE 分数、GPA 分数和本科院校排名(从 1 到 4)。排名 1 代表最好,排名 4 代表最差。"""# ----------分隔线-------------"""数据解读说明:admit 0未录取 1 录取gre分数 gpa绩点分数 rank 本科院校等级#数据预处理admit --目标标签ran...
"""
案例:研究生学院录取数据,用梯度下降训练一个网络。
数据有三个输入特征:GRE 分数、GPA 分数和本科院校排名(从 1 到 4)。排名 1 代表最好,排名 4 代表最差。
"""
# ----------分隔线-------------
"""
数据解读说明:
admit 0未录取 1 录取
gre分数 gpa绩点分数 rank 本科院校等级
#数据预处理
admit --目标标签
rank ---分类变量--》亚编码|one-hot独热编码,相当于去除量纲的影响
gre,gpa ---连续变量---》标准化,去除量纲影响
"""
import numpy as np
import pandas as pd
# 设置显示内容属性,防止pandas打印不全
pd.set_option('display.max_columns', 1000)
pd.set_option('display.width', 1000)
pd.set_option('display.max_colwidth', 1000)
admissions = pd.read_csv('./datas/11.csv')
def data_explore(admissions):
print(admissions.head(n=10))
print(admissions.info()) # 查看是否有空值,以及数据类型
print(admissions.describe()) # 再次可以看到是否有空值,以及值范围,需要考虑做数据变换。
print('各个样本相应的数量为:{}'.format(admissions['admit'].value_counts())) # 查看样本是否均衡
# 100:1是不均衡的,1的样本是学不会的
"""
一、数据清理
1、分类变量哑编码
rank 是类别特征,其中的数字并不表示任何相对的值。排名第 2 并不是排名第 1 的两倍;
排名第 3 也不是排名第 2 的 1.5 倍。因此,我们需要用哑变量 来对 rank 进行编码。
把数据分成 4 个新列,用 0 或 1 表示。排名为 1 的行对应 rank_1 列的值为 1 ,其余三列的值为 0;
排名为 2 的行对应 rank_2 列的值为 1 ,其余三列的值为 0,以此类推。
2、连续变量标准化
把 GRE 和 GPA 数据标准化,变成均值为 0,标准偏差为 1。因为 sigmoid 函数会挤压很大或者很小的输入。
很大或者很小输入的梯度为 0,这意味着梯度下降的步长也会是 0。
"""
def data_transform(admissions):
"""
一 rank代表学校等级(1--4),转成哑变量
1、 用pd.get_dummies 将rank列,转成哑变量,新变量名前缀为:prefix='rank'
2、将原数据集admissions 和 1 进行列拼接;
3、drop原始的rank列。
"""
data = pd.concat([admissions, pd.get_dummies(admissions['rank'], prefix='rank')], axis=1)
data = data.drop('rank', axis=1)
"""
二、gre和gpa变量的标准化
标准做法:先拆分数据集--使用训练数据集的统计量 去标准化 验证和测试。
"""
for field in ['gre', 'gpa']:
mean, std = data[field].mean(), data[field].std()
data.loc[:, field] = (data[field] - mean) / std
"""
三、数据拆分:分成训练 和 测试数据集
1、设置随机数种子,确保大家执行和我们这里演示的结果一致;
2、使用np.random.choice,随机选择数据集中90% 数据的index
"""
# 随机打乱,并将数据集拆分为 90%训练---10%测试数据集。
np.random.seed(42)
sample = np.random.choice(data.index, size=int(len(data) * 0.9), replace=False)
train_data, test_data = data.iloc[sample], data.drop(sample)
"""
四、 将自变量(features)和目标值分离
"""
features_train, targets_train = train_data.drop('admit', axis=1), train_data['admit']
features_test, targets_test = test_data.drop('admit', axis=1), test_data['admit']
return features_train, targets_train, features_test, targets_test
# ***************************************
"""
GRE带隐藏层反向传播案例
先介绍 伪代码 和 梯度求导 流程
"""
# ***************************************
def sigmoid(x):
# 激活函数 1/(1+e^(-z))
return 1 / (1 + np.exp(-x))
def gre_bp_answer(features_train, targets_train, features_test, targets_test):
"""
gre反向传播函数
:return:
"""
# 1、设置超参数
n_hidden = 2 # 隐藏层节点数量
epochs = 1000 # 迭代的次数
learning_rate = 0.05 # 学习率
# 2、获取样本的数量和特征数量
n_reords, n_features = features_train.shape
last_loss = None
# 3、构建模型权重(2个权重)--无偏置项,因为数据是标准化后的,偏置项为0
weights_input_hidden = np.random.normal(
loc=0.0, scale=1 / n_features ** 0.5, size=(n_features, n_hidden) # loc 均值 scale标准差 1/根号下n_features
)
weights_hidden_output = np.random.normal(
scale=1 / n_hidden ** 0.5, size=n_hidden
)
# 4、构建模型循环
for e in range(1, epochs):
# 定义2个del_w 并初始化为0,用于存储梯度值的
del_w_input_hidden = np.zeros(weights_input_hidden.shape)
del_w_hidden_output = np.zeros(weights_hidden_output.shape)
# 构建遍历数据集的循环
for x, y in zip(features_train.values, targets_train):
# 5、正向传播
hidden_input = np.matmul(x, weights_input_hidden)
hidden_output = sigmoid(hidden_input)
output = sigmoid(np.matmul(hidden_output, weights_hidden_output))
# 6、反向传播
error = output - y
output_error_term = error * output * (1 - output) # 标量
hidden_error = output_error_term * weights_hidden_output # (n_hidden, ) 向量
hidden_error_term = hidden_error * hidden_output * (1-hidden_output) # (n_hidden, ) 向量
del_w_input_hidden += x[:, None] * hidden_error_term
del_w_hidden_output += hidden_output * output_error_term
# 7、执行梯度下降,更新权重
weights_hidden_output -= del_w_hidden_output * learning_rate/n_reords
weights_input_hidden -= del_w_input_hidden * learning_rate/n_reords
# 8、每20个迭代,打印1次模型损失
if e % 20 == 0:
hidden_output = sigmoid(np.dot(features_train, weights_input_hidden))
out = sigmoid(np.dot(hidden_output, weights_hidden_output)) # out就是预测值
loss = np.mean((out - targets_train)**2)
if last_loss and last_loss < loss:
print('警告,模型损失在上升')
else:
print('Epoch:{} — Train Loss:{}'.format(e, loss))
last_loss = loss
# 9、计算测试集准确率
hidden = sigmoid(np.matmul(features_test.values, weights_input_hidden))
out = sigmoid(np.matmul(hidden, weights_hidden_output)) # 测试数据集的预测值
predictions = out > 0.5
accuracy = np.mean(predictions == targets_test)
print("Test ACC:{}".format(accuracy))
if __name__ == '__main__':
features_train, targets_train, features_test, targets_test = data_transform(admissions)
# data_explore(admissions)
gre_bp_answer(features_train, targets_train, features_test, targets_test)
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)