首页 > 编程问答 >PyTorch LSTM 模型上的 CrossEntropyLoss,每个时间步一分类

PyTorch LSTM 模型上的 CrossEntropyLoss,每个时间步一分类

时间:2024-07-23 10:18:50浏览次数:13  
标签:python machine-learning pytorch neural-network lstm

我正在尝试创建一个 LSTM 模型来检测时间序列数据中的异常情况。它需要 5 个输入并产生 1 个布尔输出(如果检测到异常则为 True/False)。异常模式通常连续 3 - 4 个时间步长。与大多数 LSTM 示例不同,它们预测未来数据或对整个数据序列进行分类,我尝试在每个时间步输出 True/False 检测标志(如果检测到,则在模式的最后一个时间步点处为 True) )。

不幸的是,CrossEntropyLoss 似乎不允许超过 1D 的输出张量,在这种情况下,它将是 2D [num 个序列,带有布尔数据的序列长度]

这里是一些示例代码我想要生成什么:

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np

# Define LSTM classifier model
class LSTMClassifier(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size):
        super(LSTMClassifier, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        out, _ = self.lstm(x, (h0, c0))
        out = self.fc(out[:, -1, :])
        return out

# Input - 100 examples containing 5 data points per timestep (where there are 10 timesteps)
X_train = np.random.rand(100, 10, 5)
# Output - 100 examples containing 1 True/False output per timestep to match the input
y_train = np.random.choice(a=[True, False], size=(100, 10))  # Binary labels (True or False)

# Convert data to PyTorch tensors
X_train_tensor = torch.tensor(X_train, dtype=torch.float32)
y_train_tensor = torch.tensor(y_train, dtype=torch.bool)

# Define model parameters
input_size = X_train.shape[2] # 5 inputs per timestep
hidden_size = 4 # Pattern we are trying to detect is usually 4 timesteps long
num_layers = 1
output_size = 1 # True/False

# Instantiate the model
model = LSTMClassifier(input_size, hidden_size, num_layers, output_size)

# Define loss function and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# Train the model
num_epochs = 10
for epoch in range(num_epochs):
    optimizer.zero_grad()
    outputs = model(X_train_tensor)
    loss = criterion(outputs, y_train_tensor)
    loss.backward()
    optimizer.step()
    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item()}')

# Test the model
X_test = np.random.rand(10, 10, 5) # Generate some test data - same dimensions as input
X_test_tensor = torch.tensor(X_test, dtype=torch.float32)
with torch.no_grad():
    predictions = model(X_test_tensor)
    predicted_outputs = torch.argmax(predictions, dim=1)
    print("Predicted Outputs:", predicted_outputs)

我是否需要重新调整输出,或者可能使用不同的损失函数,或者 LSTM 以外的模型?


你遇到的问题是你的LSTM模型在每个时间步都输出一个预测,而 CrossEntropyLoss 希望有一个单一预测的张量(对于每个序列)。你有几个选择来解决这个问题:

1. 使用BCELoss和sigmoid输出:

  • 修改你的LSTM模型,使其在 fc 层后输出一个介于0和1之间的值。你可以通过在 fc 层后添加一个 sigmoid 激活函数来实现这一点:
    def forward(self, x):
        # ... your existing code ...
        out = self.fc(out)
        out = torch.sigmoid(out) # Apply sigmoid activation
        return out
  • 使用 BCELoss (二元交叉熵损失)作为你的损失函数,它适用于二元分类问题:
criterion = nn.BCELoss()
  • 在训练过程中,你需要将你的 y_train_tensor 转换为 float 类型:
y_train_tensor = torch.tensor(y_train, dtype=torch.float32)

2. 为每个时间步计算损失,然后汇总:

  • 保持你的模型输出为每个时间步的预测。
  • 使用 BCELoss 计算每个时间步的损失。
  • 对所有时间步的损失求平均值,得到一个单一损失值用于反向传播。
criterion = nn.BCELoss(reduction='none') # Do not reduce across time steps

# ... inside the training loop:
    outputs = model(X_train_tensor)
    loss = criterion(outputs, y_train_tensor.float())  # Calculate loss for each time step
    loss = loss.mean() # Average the loss over all time steps
    loss.backward()
    # ...

3. 使用LSTM进行序列分类:

  • 如果你只关心整个序列是否包含异常,而不是每个时间步的具体预测,你可以使用LSTM进行序列分类。
  • 修改你的模型,只在最后一个时间步输出一个预测。
  • 使用 BCELoss CrossEntropyLoss (如果你输出的是类概率),并使用一个单一标签来指示整个序列是否包含异常。

以下是如何实现选项2的示例代码:

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np

# ... (Your LSTMClassifier class remains the same) ...

# ... (Your data generation remains the same) ...

# ... (Your model parameters remain the same) ...

# Instantiate the model
model = LSTMClassifier(input_size, hidden_size, num_layers, output_size)

# Define loss function and optimizer
criterion = nn.BCELoss(reduction='none') # Don't reduce loss across time steps
optimizer = optim.Adam(model.parameters(), lr=0.001)

# Train the model
num_epochs = 10
for epoch in range(num_epochs):
    optimizer.zero_grad()
    outputs = model(X_train_tensor)
    loss = criterion(outputs, y_train_tensor.float()) # Calculate loss for each time step
    loss = loss.mean() # Average the loss over all time steps
    loss.backward()
    optimizer.step()
    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item()}')

# Test the model
# ... (Your test code remains similar, but you'll get predictions for each time step) ...

请记住,为你的特定问题选择最佳方法取决于你的目标和数据的特征。

标签:python,machine-learning,pytorch,neural-network,lstm
From: 78781313

相关文章

  • 我如何为 yolov5 制作 gui,从 pytorch 和 opencv 加载到 tkinker?
    请帮助我,我不明白如何使用yolo和tkinker作为gui来制作用于实时检测的gui。以及如何将边界框从pytorch渲染到tkinker?这里是代码:importtorchfrommatplotlibimportpyplotaspltimportnumpyasnpimportcv2model=torch.hub.load('ultralytics/yolov5......
  • 强制从当前包自动导入的 Python 以此包的名称为前缀
    我在VSCode中使用Python和Pylance扩展。在我正在编辑的自己的包中,自动添加的导入(设置“导入格式:绝对”)如下所示:frommydirectory.myfileimportmyclass但是,我的Python包正在被被一个(非常愚蠢且不可协商的)外部系统消耗,该系统拒绝正确解释它,除非导入的格式特别......
  • Python语言-面向对象
    知识代码classJobSalary(object):job=''def__init__(self,city):self.jobname="数据分析师"self.exp=''self.city=city#方法defdata_normalize(self,data):print(f'正在规范化......
  • 需要帮助使用 Selenium Python 单击 Microsoft Teams 按钮
    我将Python与Selenium结合使用,并自动登录MicrosoftTeams。进入后,弹出窗口显示我需要单击“立即切换”以切换到V2版本。我似乎无法使用SeleniumPython成功单击此按钮。谁能帮我自动点击这个按钮?这是我不成功的尝试:self.driver.find_element(By.CLASS_NAME,......
  • python接口自动化(四十)- logger 日志 - 下(超详解)
    宏哥微信粉丝群:https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1.简介按照上一篇的计划,这一篇给小伙伴们讲解一下:(1)多模块使用logging,(2)通过文件配置logging模块,(3)自己封装一个日志(logging)类。可能有的小伙伴在这里会有个疑问一个logging为什么分两篇的篇幅......
  • Python面试题:使用NumPy进行高效数组运算
    NumPy是Python中进行高效数组运算的基础库。以下是一些示例,展示了如何使用NumPy进行高效的数组运算,包括创建数组、数组操作、数学运算以及一些高级操作。安装NumPy如果你还没有安装NumPy,可以通过以下命令进行安装:pipinstallnumpy示例代码1.创建数组import......
  • Python面试题:使用Matplotlib和Seaborn进行数据可视化
    使用Matplotlib和Seaborn进行数据可视化是数据分析中非常重要的一部分。以下示例展示了如何使用这两个库来创建各种图表,包括基本的线图、柱状图、散点图和高级的分类数据可视化图表。安装Matplotlib和Seaborn如果你还没有安装这两个库,可以使用以下命令进行安装:pipins......
  • 20、Python之容器:红楼主角都有谁?10行代码生成《红楼梦》词云图
    引言Python系列前面的文章中,我们介绍了Python中容器的基本使用,上一篇中,我们又重点介绍了Counter计数器的使用。这些介绍,应该足以应付日常的工作需求了。在今天的文章中,我想以词云图的生成这个综合案例,巩固一下前面关于容器、字典推导式、Counter的使用。同时,介绍两个比较好......
  • 使用snowflake.connector 3.0.3上的密钥对从python连接到snowflake
    我正在尝试使用Snowflake.connector包从我的Python代码连接到Snowflake。不幸的是,由于遗留代码,我只能在python3.7.3上使用Snowflake连接器版本3.0.3,并且无法升级我确实设法从我自己的计算机进行连接,使用:con=Snowflake.connector。连接(...私有密钥文件=......
  • python 文件(txt)操作
    我有一个txt文件,其中包含一列(大约2000个)单词。每个单词只用一个新行分隔。我想将所有这些单词存储在一个数组中words.txt文件的示例:applebananaorange我尝试过的代码:importrandomwithopen('E:/Code/learn/Projects/word-guessing-game/words.txt','r')a......