python搭建 ADLINE 网络判断男女 (MBGD)
小记
2022.4.16
把上篇从SGD改成了MBGD
SGD (Stochastic Gradient Descent 随机梯度下降法),是用训练集中每个样本的损失值对参数的梯度来更新参数。
MBGD (Mini Batch Gradient Descent 小批量梯度下降法),是以一部分样本的平均损失值为损失值。
题目
训练一个模型, 给出一个人的身高、体重和体脂率,判断男女。
相比上篇SGD增加了
- 引入ones,bias=b* ones, (b是1*1,ones是1*10,bias是1*10)
- 点乘,计算loss的时候是label和ouput对应位置相乘。
- 引入B,损失值从loss变成meanloss, meanloss=B*loss ,(B是1*10,loss是10*1,meanloss是1*1)
判断思路
男性的label=1,女性label=-1,
得出的predict,predict=1判断为男性,predict=-1判断为女性
代码框架
代码
主要改在main
main.py
import numpy as np
from icecream import ic
import node
import ope
import loss
from graph import default_graph
def make_test():
# 生产测试数据
m_h = np.random.normal(171, 6, 500)
f_h = np.random.normal(168, 5, 500)
m_w = np.random.normal(70, 10, 500)
f_w = np.random.normal(57, 8, 500)
m_bfrs = np.random.normal(16, 2, 500)
f_bfrs = np.random.normal(22, 2, 500)
m_labels = [1] * 500
f_labels = [-1] * 500
train_set = np.array([np.concatenate((m_h, f_h)),
np.concatenate((m_w, f_w)),
np.concatenate((m_bfrs, f_bfrs)),
np.concatenate((m_labels, f_labels))
]).T
np.random.shuffle(train_set)
return train_set
if __name__=='__main__':
train_set=make_test()
bacth_size=10
x=node.Variable(shape=(bacth_size,3))
w=node.Variable(shape=(3,1))
b=node.Variable(shape=(1,1))
label=node.Variable(shape=(bacth_size,1))
w.set_value(np.mat(np.random.normal(0,0.001,(3,1))))
b.set_value(np.mat(np.random.normal(0,0.001,(1,1))))
#全1向量
ones=node.Variable(shape=(bacth_size,1))
ones.set_value(np.mat(np.ones(bacth_size)).T)
bias=ope.MatMul(ones,b)
y=ope.Add(ope.MatMul(x,w),bias)
predict=ope.Step(y)
loss=loss.PerceptionLoss(ope.Multiply(label,y))
B=node.Variable(shape=(1,bacth_size))
B.set_value(1/bacth_size*np.mat(np.ones(bacth_size)))
mean_loss=ope.MatMul(B,loss)
learning_rate=0.001
for epoch in range(100):
for i in np.arange(0,len(train_set),bacth_size):
# 输入数据
x.set_value(np.mat(train_set[i:i+bacth_size, :-1]))
label.set_value(np.mat(train_set[i:i+bacth_size,-1]).T)
mean_loss.forward()
w.backward(mean_loss)
b.backward(mean_loss)
# 想优化的结点都是标量结点,即都是1*n,
w.set_value(w.value - learning_rate * w.jacobi.T.reshape(w.shape()))
b.set_value(b.value - learning_rate * b.jacobi.T.reshape(b.shape()))
default_graph.clear_jacobi() #要清理每一次的雅可比矩阵,否则递归时会因为雅可比矩阵含有值而不重新计算
if epoch%10==0:
pred = []
for i in np.arange(0, len(train_set), bacth_size):
# 输入数据
x.set_value(np.mat(train_set[i:i + bacth_size, :-1]))
label.set_value(np.mat(train_set[i:i + bacth_size, -1]).T)
predict.forward()
#对一个mini batch的样本的预测结果
pred.extend(predict.value.A.ravel())
pred = np.array(pred) * 2 - 1
accuracy = (train_set[:, -1] == pred).astype(np.int).sum() / len(train_set)
print("训练次数为:",epoch,"时,准确率为:",accuracy)