{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":30894,"databundleVersionId":3147400,"sourceType":"competition"}],"dockerImageVersionId":30587,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport numpy as np\nfrom torch.utils.data import Dataset, DataLoader\nimport pandas as pd","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:45:45.827390Z","iopub.execute_input":"2023-12-05T12:45:45.827788Z","iopub.status.idle":"2023-12-05T12:45:49.014120Z","shell.execute_reply.started":"2023-12-05T12:45:45.827745Z","shell.execute_reply":"2023-12-05T12:45:49.013342Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(f\"Using device: {device}\")","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:45:51.537513Z","iopub.execute_input":"2023-12-05T12:45:51.538007Z","iopub.status.idle":"2023-12-05T12:45:51.570643Z","shell.execute_reply.started":"2023-12-05T12:45:51.537976Z","shell.execute_reply":"2023-12-05T12:45:51.569704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_set = pd.read_csv(r'/kaggle/input/g-research-crypto-forecasting/train.csv')\ntrain_set['Close'] = np.log(train_set['Close'])\ntrain_set['Volume'] = np.log(train_set['Volume'])","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:45:54.829337Z","iopub.execute_input":"2023-12-05T12:45:54.829688Z","iopub.status.idle":"2023-12-05T12:46:56.579306Z","shell.execute_reply.started":"2023-12-05T12:45:54.829658Z","shell.execute_reply":"2023-12-05T12:46:56.578334Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"close_mean = train_set.groupby('timestamp')[['Close','Volume']].mean().reset_index()\nclose_mean.columns = ['timestamp','Close_mean','Volume_mean']\nclose_mean","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:46:56.583175Z","iopub.execute_input":"2023-12-05T12:46:56.583486Z","iopub.status.idle":"2023-12-05T12:46:57.898936Z","shell.execute_reply.started":"2023-12-05T12:46:56.583460Z","shell.execute_reply":"2023-12-05T12:46:57.898073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_set = train_set[train_set['Asset_ID'] ==  2]\ntrain_set = train_set[['timestamp','Close','Volume']]\ntrain_set = close_mean.merge(train_set,on = 'timestamp',how = 'left')\ntrain_set['target'] = train_set['Close']/train_set['Close'].shift(1) - 1\ntrain_set['target'] = train_set['target'].shift(-1)\ntrain_set = train_set.ffill()\ntrain_set = train_set.replace(np.inf,np.nan).replace(-np.inf,np.nan).replace(np.nan,0)\ntrain_set","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:46:57.900181Z","iopub.execute_input":"2023-12-05T12:46:57.900539Z","iopub.status.idle":"2023-12-05T12:46:59.240254Z","shell.execute_reply.started":"2023-12-05T12:46:57.900504Z","shell.execute_reply":"2023-12-05T12:46:59.239357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_set.describe()","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:46:59.242697Z","iopub.execute_input":"2023-12-05T12:46:59.242996Z","iopub.status.idle":"2023-12-05T12:46:59.648606Z","shell.execute_reply.started":"2023-12-05T12:46:59.242971Z","shell.execute_reply":"2023-12-05T12:46:59.647722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CorrelationLoss(nn.Module):\n    def __init__(self):\n        super(CorrelationLoss, self).__init__()\n\n    def forward(self, predictions, targets):\n        # 计算相关系数\n        predictions_mean = torch.mean(predictions)\n        targets_mean = torch.mean(targets)\n        numerator = torch.sum((predictions - predictions_mean) * (targets - targets_mean))\n        denominator_pred = torch.sqrt(torch.sum((predictions - predictions_mean)**2))\n        denominator_target = torch.sqrt(torch.sum((targets - targets_mean)**2))\n        correlation = numerator / (denominator_pred * denominator_target)\n\n        # 使用相关系数的负值作为损失\n        loss = 1 - correlation\n\n        return loss\n","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:46:59.649906Z","iopub.execute_input":"2023-12-05T12:46:59.650573Z","iopub.status.idle":"2023-12-05T12:46:59.658577Z","shell.execute_reply.started":"2023-12-05T12:46:59.650534Z","shell.execute_reply":"2023-12-05T12:46:59.657693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 定义数据集类\nclass TimeSeriesDataset(Dataset):\n    def __init__(self, features, target, seq_length):\n        self.features = features\n        self.target = target\n        self.seq_length = seq_length\n\n    def __len__(self):\n        return len(self.features) - self.seq_length + 1\n\n    def __getitem__(self, idx):\n        features = self.features[idx:idx+self.seq_length]\n        target = self.target[idx+self.seq_length-1]\n\n        if not torch.is_tensor(features):\n            features = torch.FloatTensor(features).to(device)\n        if not torch.is_tensor(target):\n            target = torch.FloatTensor([target]).to(device)\n\n        return features, target","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:46:59.659801Z","iopub.execute_input":"2023-12-05T12:46:59.660168Z","iopub.status.idle":"2023-12-05T12:46:59.668702Z","shell.execute_reply.started":"2023-12-05T12:46:59.660136Z","shell.execute_reply":"2023-12-05T12:46:59.667767Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 定义LSTM模型\nclass LSTMModel(nn.Module):\n#     def __init__(self, input_size, hidden_size, output_size):\n#         super(LSTMModel, self).__init__()\n#         self.lstm = nn.LSTM(input_size, hidden_size, batch_first=True)\n#         self.fc = nn.Linear(hidden_size, output_size)\n\n#     def forward(self, x):\n#         out, _ = self.lstm(x)\n#         out = self.fc(out[:, -1, :])  # 取最后一个时间步的输出\n#         return out\n    \n    def __init__(self, input_size, hidden_size, output_size):\n        super(LSTMModel, self).__init__()\n        self.lstm = nn.LSTM(input_size, hidden_size, batch_first=True)\n        self.fc1 = nn.Linear(hidden_size, 64)  # 第一个全连接层\n        self.relu = nn.Tanh()  # Tanh 激活函数\n        self.fc2 = nn.Linear(64, output_size)  # 第二个全连接层\n\n    def forward(self, x):\n        out, _ = self.lstm(x)\n        out = self.fc1(out[:, -1, :])  # 第一个全连接层\n        out = self.relu(out)  # ReLU 激活函数\n        out = self.fc2(out)  # 第二个全连接层\n        return out","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:46:59.670125Z","iopub.execute_input":"2023-12-05T12:46:59.670772Z","iopub.status.idle":"2023-12-05T12:46:59.683188Z","shell.execute_reply.started":"2023-12-05T12:46:59.670740Z","shell.execute_reply":"2023-12-05T12:46:59.682411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"features_np = train_set[['Close','Volume','Close_mean','Volume_mean']].values\ntarget_np = train_set[['target']].values\n\nfeatures_np = (features_np - features_np.min()) / (features_np.max() - features_np.min())\ntarget_np = (target_np - target_np.min()) / (target_np.max() - target_np.min())\n\n\nfeatures_tensor = torch.FloatTensor(features_np).to(device)\ntarget_tensor = torch.FloatTensor(target_np).to(device)\n","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:46:59.684339Z","iopub.execute_input":"2023-12-05T12:46:59.685122Z","iopub.status.idle":"2023-12-05T12:47:02.526579Z","shell.execute_reply.started":"2023-12-05T12:46:59.685089Z","shell.execute_reply":"2023-12-05T12:47:02.525719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 定义超参数\ninput_size =4  # 特征数量\nhidden_size = 50  # 隐层大小\noutput_size = 1  # 输出大小\nseq_length = 900  # 序列长度\nbatch_size = 256","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:47:02.527698Z","iopub.execute_input":"2023-12-05T12:47:02.527979Z","iopub.status.idle":"2023-12-05T12:47:02.532546Z","shell.execute_reply.started":"2023-12-05T12:47:02.527954Z","shell.execute_reply":"2023-12-05T12:47:02.531589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 创建数据集和数据加载器\ndataset = TimeSeriesDataset(features_tensor, target_tensor, seq_length)\ndataloader = DataLoader(dataset, batch_size=batch_size, shuffle=False)\n\n# 初始化模型、损失函数和优化器\nmodel = LSTMModel(input_size, hidden_size, output_size).to(device)\ncriterion = CorrelationLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=0.001)\n\n# 训练过程\nnum_epochs = 100\n\nfor epoch in range(num_epochs):\n    print(epoch)\n    for batch_features, batch_target in dataloader:\n        # 前向传播\n        output = model(batch_features)\n\n        # 计算损失\n        loss = criterion(output, batch_target)\n\n        # 反向传播和优化\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n    # 打印损失\n    print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss.item()}')\n\n# # 模型训练完成，你可以使用它进行预测\n# # 例如，使用最后50天的数据进行预测\n# last_50_days = features_tensor[-50:]\n# last_50_days = last_50_days.unsqueeze(0)  # 添加 batch 维度\n# prediction = model(last_50_days)\n# print(f'Predicted value for the next day: {prediction.item()}')\n","metadata":{"execution":{"iopub.status.busy":"2023-12-05T12:47:02.535509Z","iopub.execute_input":"2023-12-05T12:47:02.535841Z"},"trusted":true},"execution_count":null,"outputs":[]}]}