手搓一个全连接神经网络

172 阅读3分钟

对于文本数据,一般使用全连接神经网络,我们的目标是对这样的一个数据进行一个二分类

image.png

第一步,查看数据的信息和基本内容

print("数据的前五行")  
print(data.head(5))  
print("数据的后五行")  
print(data.tail(5))  
print("数据的详细内容")  
print(data.describe())  
print("每列的数据集的类型")  
print(data.dtypes)

第二步,检查数据中是否出现空值对数据中的空值进行处理

print(data.shape)  
print(data.isnull().sum())

如果存在空值的话,使用平均数进行代替处理:

def null_num(string1,data):  
mean_area = data[string1].mean(skipna=True)  
data[string1].fillna(mean_area, inplace=True)

第三步,检查数据中是否存在异常值并对异常值进行处理

def yichang1(string1, data):  
'''检查数据trestbps中是否存在异常值'''  
'''异常值处理'''  
'''拉伊大准则'''  
'''箱型图分析'''  
'''2 7 4 1 5'''  
'''排序过后是:1 2 4 5 7'''  
'''1--2 2--4 4--5 5--7'''  
'''2是25分位数,4是50分位数,5是75分位数'''  
'''极差ior:75分位数-25分位数'''  
'''估计的最小值 :25分位数-1.5*ior=2-1.5*3=-2.5'''  
'''估计的最大值 :75分位数+1.5*ior=2-1.5*3=9.5'''  
data_info = data.describe()  
'''使用loc把25分位数取出来'''  
data_25 = data_info.loc['25%', string1]  
'''使用loc把75分位数取出来'''  
data_75 = data_info.loc['75%', string1]  
'''根据25分位数和75分位数求极差'''  
data_ior = data_75 - data_25  
'''估计最小值'''  
data_min = data_25 - 1.5 * data_ior  
data_max = data_75 + 1.5 * data_ior  
print(data_min)  
print(data_max)  
data_yichag = (90 <= data[string1]) & (data[string1] >= 170)  
data_yichag = sum(data_yichag)  
print(data_yichag)  
c2 = (data[string1] < data_min) | (data[string1] > data_max)  
'''把异常值的索引赋值为drop_index'''  
drop_index = data.loc[c2].index  
data = data.drop(labels=drop_index, axis=0)  
return data

利用箱型图分析把数据中存在的异常值进行删除

第四步,对文本数据中存在的文本类特征做一个映射

def yingshe(data,string2):  
value_counts_result = data[string2].value_counts()  
print(value_counts_result)  
def map_thal(x):  
if x[string2] == 'normal':  
return 1  
elif x[string2] == 'reversible':  
return 2  
elif x[string2] == 'fixed':  
return 3  
elif x[string2] == '1':  
return 4  
elif x[string2] == '2':  
return 5  
data[string2] = data.apply(map_thal, axis=1)  
print(data.describe)  
return data  
name='thal'  
yingshe(data,name)  
print(data.dtypes)

此时,data中的所有列都转化为了float和int类型

第五步,把数据转化成张量

import torch  
data_label = data.iloc[:,-1]  
print(data_label.dtype)  
numpy_data = data_label.to_numpy()  
print(type(numpy_data))  
data_label = torch.tensor(numpy_data, dtype=torch.int64)  
print(data_label)  
  
data_train = data.drop('target', axis=1)  
numpy_data1=data_train.to_numpy()  
print(type(numpy_data1))  
data_train=torch.tensor(numpy_data1)  
print(data_train)

第六步,建立模型

class my_model(nn.Module):
    def __init__(self):
        super(my_model, self).__init__()
        # 定义各个全连接层
        self.linear1 = nn.Linear(in_features=13, out_features=16)
        self.linear2 = nn.Linear(in_features=16, out_features=32)
        self.linear3 = nn.Linear(in_features=32, out_features=64)
        self.linear4 = nn.Linear(in_features=64, out_features=128)
        # 输出层,假设是一个二分类问题,输出为 2 个类别
        self.output = nn.Linear(128, 2)  # num_classes 是输出类别数,具体视情况而定

    def forward(self, x):
        # 定义前向传播过程
        x = self.linear1(x)
        x = torch.relu(x)  # 使用 ReLU 激活函数
        x = self.linear2(x)
        x = torch.relu(x)  # 使用 ReLU 激活函数
        x = self.linear3(x)
        x = torch.relu(x)  # 使用 ReLU 激活函数
        x = self.linear4(x)
        x = torch.relu(x)  # 使用 ReLU 激活函数
        x = self.output(x)  # 输出层,不使用激活函数(交叉熵损失会自动处理)
        return x

# 实例化模型
model = my_model()

第七步,训练模型

# 3. 定义损失函数和优化器  
criterion = nn.CrossEntropyLoss() # 对于分类任务使用交叉熵损失  
optimizer = optim.Adam(model.parameters(), lr=0.001) # Adam优化器,学习率0.001  
# 4. 训练过程  
epochs = 1000  
batch_size = 32  
for epoch in range(epochs):  
model.train() # 设置模型为训练模式  
# 按照 batch_size 分批次处理数据  
for i in range(0, len(data_train), batch_size):  
# 获取当前 batch  
inputs = data_train[i:i+batch_size]  
labels = data_label[i:i+batch_size]  
# 将输入和标签传入模型并计算输出  
optimizer.zero_grad() # 清除梯度  
outputs = model(inputs) # 前向传播  
loss = criterion(outputs, labels) # 计算损失  
loss.backward() # 反向传播  
optimizer.step() # 更新模型参数  
# 每隔一定轮次输出训练过程中的损失  
if (epoch+1) % 10 == 0:  
print(f"Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}")  
torch.save(model, 'model.pth')

第八步,模型评价

result = model(data_train)  
tmp_out = torch.softmax(result, dim=1)  
out = torch.argmax(tmp_out, dim=1)  
print(sum((out == data_label)) / len(out))

最后的准确率大概是----98%

image.png