如何自己创建一个简单的神经网络

这篇文章讲使用pytorch的。 

所以若没有安装 pytorch, 需要安装 pytorch。

更早一篇文章,点击进入。

写这篇博客的原因
本文主要目的通过我的第一个神经网络二分类器的创建过程,来帮助我自己了解搭建一个简单神经网络的过程,也希望能够帮助到寻找搭建简单的神经网络而遇到困难的人。

下面是一个简单的神经网络二分类器:

若有不足,欢迎建议。

一、引入库:

import numpy 
import torch 
import datetime
import math


 设置输入,以21个输入为例,使用CPU :

shuru=21
device = torch.device('cpu')  # 使用CPU


二、准备工作 

定义一个MoXing类

MoXing: 模型

定义你想要的神经网络模型

class MoXing(torch.nn.Module):
  def __init__(self):
    super(MoXing, self).__init__()
    self.hid1 = torch.nn.Linear(shuru,59)#定义第一个隐藏层(可无)
    #第一个参数输入(一般为上一层神经元数),这里shuru就是刚才定义的输入数
    #第一个参数输出(一般为下一层神经元数)
    self.hid2 = torch.nn.Linear(59, 59)#第二层(可无),同理
    self.oupt = torch.nn.Linear(59, 1)
    torch.nn.init.xavier_uniform_(self.hid1.weight)#第一层w
    torch.nn.init.zeros_(self.hid1.bias)#第一层b
    torch.nn.init.xavier_uniform_(self.hid2.weight)
    torch.nn.init.zeros_(self.hid2.bias)
    torch.nn.init.xavier_uniform_(self.oupt.weight)
    torch.nn.init.zeros_(self.oupt.bias)
  def forward(self, x):
    z = torch.tanh(self.hid1(x))#第一层激活函数tanh
    z = torch.tanh(self.hid2(z))#同理
    z = torch.sigmoid(self.oupt(z))  #输出层激活函数sigmoid
    return z

定义一个ShuJuJi类

ShuJuJi:数据集

方便一会处理测试数据和训练数据,本文主要用csv表格中的数据。

数据集第一列为要预测的y,其他列为输入的特征,可根据自己需要改。

class ShuJuJi(torch.utils.data.Dataset):
  def __init__(self, src_file):
    all_data = numpy.loadtxt(src_file, usecols=range(0,shuru+1),delimiter=",", comments="#",  dtype="float",skiprows=1)
    self.y_data = torch.tensor(all_data[:,0],dtype=torch.float32).to(device) 
    #第一列为y 
    self.y_data = self.y_data.reshape(-1,1)  
    self.x_data = torch.tensor(all_data[:,1:shuru+1],dtype=torch.float32).to(device)
    #之后第二列到第shuru+1列shuru个列为x
  def __len__(self):
    return len(self.x_data)
  def __getitem__(self, hang):
    x = self.x_data[hang,:]  # 第hang+1行的x
    y = self.y_data[hang,:]    # 第hang+1行的y
    return x, y  # 返回 x, y


 定义ping_gu函数 

ping_gu: 评估

用来评估神经网络效果

#预测值大于分界,将预测值视为1类,否则为0类
def ping_gu(moxing, shujuji, fenjie=0.5):
  a = 0; b = 0; c = 0; d = 0
  for i in range(len(shujuji)):
    x = shujuji[i][0]
    y = shujuji[i][1]
    y = y.type(torch.int64)  #y 化为整数
    with torch.no_grad():
        y_yuce = moxing(x)      
    if y == 1 and y_yuce >= fenjie:
        a += 1
    elif y == 0 and y_yuce < fenjie:
        b += 1
    elif y == 0 and y_yuce >= fenjie:
        c += 1
    elif y == 1 and y_yuce < fenjie:
        d += 1
  N = a + c + b + d
  if N = len(shujuji) and N != 0:
      zb1 = (a + b) / (N * 1.0)
      #指标1: 预测的准确率
      if a+c != 0:
            zb2= (1.0 * a) / (a + c)
            #指标2: 预测为1类中真实值为1的概率
      else:
            zb2=0.0
      if a+d != 0:
            zb3 = (1.0 * a) / (a + d)
            #指标3: 真实值为1中指标2预测为1类的概率
      else:
            zb3=0.0
      if zb3 != 0 and zb2!= 0:
            zb_four = 2.0 / ((1.0 / zb2) + (1.0 / zb3))
            #指标_four: 指标2和指标3的调和平均数
      else:
            zb_four = 0
      return zb1, zb2, zb3, zb_four
  else:
      return 0, 0, 0, 0

三、开始 :


(为了运行后的显示效果,下面print中部分文字可能与代码不太对应,不要在意。) 

 启动!

print("\t\t\t神经网络:\t\t (名字)")#(名字): 神经网路名字,自己取
print('---启动!---启动!---启动!'*2+'---')
torch.manual_seed(1)
numpy.random.seed(1)

初始化数据和神经网络 :

print('\n|' + '-' * 80 + '\n')
print('开始初始化数据和神经网络:\n')
batch_size = 8             
print("\t开始读取用来训练 (名字) 的训练集......")
train_shuju = ShuJuJi("训练数据.csv")
xun_lian = torch.utils.data.DataLoader(train_shuju, batch_size=batch_size, shuffle=True)
print('\n\t\t OK!读取完成!')
print("\n\t开始读取用来测试(名字)的测试集......")
test_shuju = ShuJuJi("测试数据.csv")
ce_shi = torch.utils.data.DataLoader(test_shuju, batch_size=batch_size, shuffle=True)
print('\n\t\t OK!读取完成!')
print("\n\t激活(名字)全连接BP神经网络二分类器......")
moxing = MoXing().to(device)

初始化训练模式 :

print('\n|' + '-' * 80+'\n')
print('初始化训练模式:\n')
moxing.train()  # 设置训练模式
xuexilv = 0 #学习率根据需求自己设置
loss_func = torch.nn.BCELoss()  #损失函数
yiuhuaqi = torch.optim.SGD(moxing.parameters(),lr=xuexilv)
epochs = 0 #根据需求自己设置
xianshi = 0    #根据需求自己设置,即每xianshi个epoch显示一次
print(f"\t损失函数: {loss_func}")
print(f"\n\t优化器: {yiuhuaqi.__class__.__name__}")
print(f"\n\t学习率:   {xuexilv}")
print(f"\n\tBatch size(每次迭代样本数): {batch_size}")
print(f"\n\tepochs(预遍历次数): {epochs}")

训练神经网络:

print('\n|' + '-' * 80+'\n')
print("开始训练(名字)神经网络:\n")
for epoch in range(0, epochs):
    train_loss = 0.0  
    test_loss = 0.0
    for (batch_index, batch) in enumerate(ce_shi):
        X2 = batch[0]             
        Y2 = batch[1]            
        Y_yuce2 = moxing(X2)           
        loss_zhi2 = loss_func(Y_yuce2, Y2)   
        test_loss += loss_zhi2.item()
    loss_test = test_loss/len(ce_shi) # 计算平均测试损失
    pinggu_test = ping_gu(moxing, test_shuju, fenjie=0.5)
    for (batch_index, batch) in enumerate(xun_lian):
        X = batch[0]            
        Y = batch[1]             
        Y_yuce = moxing(X)            
        loss_zhi = loss_func(Y_yuce, Y)  
        train_loss += loss_zhi.item()  # 累加张量的值
        yiuhuaqi.zero_grad()  # 重置所有梯度
        loss_zhi.backward()   # 计算新梯度
        yiuhuaqi.step()      # 更新所有权重
    loss_train = train_loss/len(xun_lian)  # 计算平均训练损失
    if 0 < pinggu_test[1] < 200:
        # 当神经网络的测试指标满足一定条件时保存神经网络
        banben = str(datetime.datetime.today()).replace('-', '').replace(':', '').replace(' ', '')[:12]
        path = f".\\Models\\T_{int(pinggu_test[1])}_{int(1000 * pinggu_test[2])}_{int(100000 * pinggu_test[2] / pinggu_test[1])}.pt"
        torch.save(moxing.state_dict(), path)
        print(f'\tOK! 已保存完成! 保存于  {path} ')
    if epoch % xianshi == 0:
        # 每进行xianshi个epoch进行显示
        print("epoch = %5d       loss_train = %8.7f       loss_test = %8.7f" %(epoch,loss_train,loss_test),end='')
        print("       zb1 = %0.5f       zb2 = %5.1f       zb3 = %0.5f       zb_four = %0.5f" % (pinggu_test[0], pinggu_test[1], pinggu_test[2], pinggu_test[3]))        
print("\t训练完成")

评估神经网络 :

print('\n|' + '-' * 80+'\n')
print("开始评估(名字)神经网络:\n")
moxing.eval()
pinggu_train = ping_gu(moxing, train_shuju, fenjie=0.5)
print("\t训练数据分类效果指标: ")
print("\t\t zb1    = %0.5f " % pinggu_train[0])
print("\t\t zb2    = %5.1f " % pinggu_train[1])
print("\t\t zb3    = %0.5f " % pinggu_train[2])
print("\t\t zb_four= %0.5f " % pinggu_train[3])
pinggu_test = ping_gu(moxing, test_shuju, fenjie=0.5)
print("\t测试数据分类效果指标: ")
print("\t\t zb1    = %0.5f " % pinggu_test[0])
print("\t\t zb2    = %5.1f " % pinggu_test[1])
print("\t\t zb3    = %0.5f " % pinggu_test[2])
print("\t\t zb_four= %0.5f " % pinggu_test[3])

保存神经网络 :

print('\n|' + '-' * 80+'\n')
print("开始保存训练后的 T 二分类器(保存 T 二分类器的训练状态):\n ")
banben=str(datetime.datetime.today()).replace('-','').replace(':','').replace(' ','')[:12]
#获取当前时间精确到分钟
path = f".\\Models\\T_model1.0_{banben}.pt"
#保存路径,也可以自己定名字或命名方法
torch.save(moxing.state_dict(), path)
print(f'\tOK! 已保存完成! 保存于  {path} ')

使用神经网络进行二分类 :

print('\n|'+'-'*80+'\n')
print("尝试使用(名字)二分类器分类预测:\n")
yorn = input('是否开始预测( y 或 n ):')
if yorn == 'y':
    while True:
        print('(x的各列列名)')
        print('请按上述顺序输入特征参数(参数间以单个空格隔开):')
        shu_ru_ji = [float(i) for i in input().split()]
        if len(shu_ru_ji) == shuru:
            xx = numpy.array([shu_ru_ji],dtype=numpy.float32)
            xx = torch.tensor(xx, dtype=torch.float32).to(device)
            moxing.eval()
            with torch.no_grad():
                Y_yuce = moxing(xx)    # a Tensor
            y_yucei = Y_yuce.item()  # scalar, [0.0, 1.0]
            print("输出结果:  %0.5f " % y_yucei)
            if y_yucei < 0.5:
                print("\t预测为: 0")
            else:
                print("\t预测为: 1")
            mmn = input('是否继续(输入 y 或 n ):')
            if mmn == 'n':
                break
    print('分类结束.')
    print("\n(名字)二分类器  当前进程结束.")
else:
    print('\n(名字)二分类器  当前进程结束.')

备注:

 使用保存的神经网络 :

def yuce(model_path,shu_ru):
    model = MoXing().to(device)
    model.load_state_dict(torch.load(mo_xing))
    model.eval()
    xx = torch.tensor(shu_ru, dtype=torch.float32).to(device)
    with torch.no_grad():
        yy = model(xx)  
    y_yuce = yy.item()  
    return int(y_yuce+0.5) #四舍五入,也可直接y_yuce
cd = pandas.read_csv('要用模型预测的表.csv', encoding="utf-8")
y=list(cd['y'])
models_list=[]
model_name=''
yuce=[]
for hang in range(len(y)):
    shuRu = cd[hang:hang + 1] #第hang+1行的数据
    shuRu = numpy.array(shuRu, dtype=numpy.float32)[:,1:]
    #我的文件,第一列是y,特征从第二列开始,所以是[:,1:]
    y_yuce=yuce(model_name, shuRu)
    yuce.append(y_yuce)
    #y_yuce为预测值
cd[model_name+'预测']=yuce
cd.to_csv('要用模型预测的表.csv',index=False)


训练模式二:  神经网路可视化训练

随着训练动态显示神经网络评估指标变化

即随着训练,动态显示神经效果变化

(这种模式更直观显示训练过程, 但会降低训练速度,且不再需要xianshi这个参数)

  先引入plt :
( 要在上面“引入库”中多引入一个plt来画图 )

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False


动态可视化训练 :
(可将下文tu_.....列表换成你要画的数据列表)

print('\n|' + '-' * 80+'\n')
print("开始训练(名字)神经网络:\n")
tu_test_loss=[]
tu_train_loss=[]
tu_train_yuce=[]
tu_test_yuce=[]
tu_train_day=[]
tu_test_day=[]
tu_train_re=[]
tu_test_re=[]
tu_x=[]
for epoch in range(0, epochs):
    tu_x.append(epoch)
    train_loss = 0.0  # 一次完整迭代 enumerate将值变为索引:值
    test_loss = 0.0
    for (batch_index, batch) in enumerate(ce_shi):
        X2 = batch[0]
        Y2 = batch[1]
        Y_yuce2 = moxing(X2)
        loss_zhi2 = loss_func(Y_yuce2, Y2)   # y 与 Y_yuce 仅有1个值,loss_zhi为仅有1值的张量
        test_loss += loss_zhi2.item()
    loss_test = test_loss/len(ce_shi) # 计算平均测试损失
    tu_test_loss.append(loss_test)
    pinggu_test = ping_gu(moxing, test_shuju, fenjie=0.5)
    tu_test_yuce.append(pinggu_test[1])
    tu_test_day.append(pinggu_test[2])
    tu_test_re.append(pinggu_test[3])
    for (batch_index, batch) in enumerate(xun_lian):
        X = batch[0]
        Y = batch[1]
        Y_yuce = moxing(X)
        loss_zhi = loss_func(Y_yuce, Y)   # y 与 Y_yuce 仅有1个值,loss_zhi为仅有1值的张量
        train_loss += loss_zhi.item()  # 累加张量的值
        yiuhuaqi.zero_grad()  # 重置所有梯度
        loss_zhi.backward()   # 计算新梯度
        yiuhuaqi.step()      # 更新所有权重
    loss_train = train_loss/len(xun_lian)  # 计算平均训练损失
    pinggu_train = ping_gu(moxing, train_shuju, fenjie=0.5)
    tu_train_loss.append(loss_train)
    tu_train_yuce.append(pinggu_train[1])
    tu_train_day.append(pinggu_train[2])
    tu_train_re.append(pinggu_train[3])
    if epoch > 0:
        plt.clf()
        plt.subplot(2, 2, 1)
        plt.plot(tu_x[1:], tu_train_loss[1:], label="训练误差", linestyle='-')
        plt.plot(tu_x[1:], tu_test_loss[1:], label="测试误差", linestyle='-')
        # plt.xlabel("遍历次数")
        # plt.ylabel("误差", fontsize=16)
        plt.title(f"训练误差  vs  测试误差")
        plt.legend(loc='center left')
        plt.subplot(2, 2, 2)
        plt.plot(tu_x[1:], tu_train_day[1:], label="训练指标3", linestyle='-')
        plt.plot(tu_x[1:], tu_test_day[1:], label="测试指标3", linestyle='-')
        # plt.xlabel("遍历次数")
        # plt.ylabel("指标3", fontsize=16)
        plt.title(f"训练指标3  vs  测试指标3")
        plt.tight_layout()
        plt.legend(loc='center left')
        plt.subplot(2, 2, 3)
        plt.plot(tu_x[1:], tu_train_yuce[1:], label="训练预测", linestyle='-')
        plt.plot(tu_x[1:], tu_test_yuce[1:], label="测试预测", linestyle='-')
        # plt.xlabel("遍历次数")
        # plt.ylabel("预测", fontsize=16)
        plt.title(f"训练预测  vs  测试预测")
        plt.tight_layout()
        plt.legend(loc='center left')
        plt.subplot(2, 2, 4)
        plt.plot(tu_x[1:], tu_train_re[1:], label="训练占比率", linestyle='-')
        plt.plot(tu_x[1:], tu_test_re[1:], label="测试占比率", linestyle='-')
        # plt.xlabel("遍历次数")
        # plt.ylabel("占比率", fontsize=16)
        plt.title(f"训练占比率  vs  测试占比率")
        plt.tight_layout()
        plt.legend(loc='center left')
        plt.pause(0.5)  # 暂停一段时间,不然画的太快会卡住显示不出来
        plt.ioff()  # 关闭画图窗口

未完待续   (未来可能添加基因组来优化)

如果对您有帮助,请多多支持。

  • 32
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的前馈神经网络的示例代码: ``` import numpy as np class FeedforwardNeuralNetwork: def __init__(self, input_size, output_size, hidden_layers=[10, 10], activation_function='sigmoid'): self.input_size = input_size self.output_size = output_size self.hidden_layers = hidden_layers self.activation_function = activation_function # Initialize weights and biases for hidden layers self.weights = [] self.biases = [] input_layer_size = input_size for layer_size in hidden_layers: weight_matrix = np.random.randn(layer_size, input_layer_size) bias_vector = np.random.randn(layer_size, 1) self.weights.append(weight_matrix) self.biases.append(bias_vector) input_layer_size = layer_size # Initialize weights and biases for output layer weight_matrix = np.random.randn(output_size, input_layer_size) bias_vector = np.random.randn(output_size, 1) self.weights.append(weight_matrix) self.biases.append(bias_vector) def sigmoid(self, z): return 1 / (1 + np.exp(-z)) def relu(self, z): return np.maximum(0, z) def forward(self, X): A = X for i in range(len(self.weights)): Z = np.dot(self.weights[i], A) + self.biases[i] if self.activation_function == 'sigmoid': A = self.sigmoid(Z) elif self.activation_function == 'relu': A = self.relu(Z) return A ``` 以上代码定义了一个类 `FeedforwardNeuralNetwork`,它接受输入大小、输出大小和隐藏层大小的参数,并且可以指定使用 `sigmoid` 或 `ReLU` 作为激活函数。通过 `weights` 和 `biases` 属性存储所有隐藏层和输出层的权重和偏置。`sigmoid` 和 `relu` 方法分别实现了 `sigmoid` 和 `ReLU` 激活函数。`forward` 方法接受输入 `X` 并计算网络输出。在每个隐藏层和输出层中,我们首先计算加权输入 `Z`,然后应用激活函数 `A`。最后,返回输出层的值。 你可以创建一个实例并使用 `forward` 方法计算输出,例如: ``` # Create a neural network with 2 input neurons, 1 output neuron, and 1 hidden layer with 3 neurons network = FeedforwardNeuralNetwork(2, 1, [3]) # Compute the output for an input of [1, 2] output = network.forward(np.array([1, 2]).reshape(-1, 1)) print(output) ``` 输出将是一个表示网络预测的单个值。请注意,这个神经网络是非常简单的,并且仅用于演示目的。在实际应用中,你需要考虑更复杂的结构、更多的层和更多的神经元。同时,还需要进行更复杂的训练和调优过程来获得预期的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值