init
This commit is contained in:
113
grasp_network_model.py
Normal file
113
grasp_network_model.py
Normal file
@ -0,0 +1,113 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import torch.nn.functional as F
|
||||
|
||||
|
||||
class CondGraspNet(nn.Module):
|
||||
def __init__(self):
|
||||
super(CondGraspNet, self).__init__()
|
||||
|
||||
# === 1. 定义输入维度 ===
|
||||
# 触觉特征: 12维 (3指 * 2单元 * 2分量)
|
||||
self.tactile_dim = 12
|
||||
# 构型特征: 3维 (One-Hot编码: [1,0,0], [0,1,0], [0,0,1])
|
||||
self.config_dim = 3
|
||||
|
||||
input_total_dim = self.tactile_dim + self.config_dim # 15维
|
||||
|
||||
# === 2. 定义网络层 (MLP结构) ===
|
||||
|
||||
# Layer 1: 特征融合层
|
||||
# 将触觉信息和构型信息混合
|
||||
self.fc1 = nn.Linear(input_total_dim, 64)
|
||||
self.bn1 = nn.BatchNorm1d(64) # 批归一化: 防止梯度消失,加速训练
|
||||
|
||||
# Layer 2: 非线性映射层
|
||||
# 增加网络宽度,拟合复杂的力学关系
|
||||
self.fc2 = nn.Linear(64, 128)
|
||||
self.bn2 = nn.BatchNorm1d(128)
|
||||
|
||||
# Layer 3: 特征压缩层
|
||||
self.fc3 = nn.Linear(128, 64)
|
||||
|
||||
# Layer 4: 输出层 (Regression Head)
|
||||
# 输出3个值: [Delta_X, Delta_Y, Delta_Theta]
|
||||
self.output = nn.Linear(64, 3)
|
||||
|
||||
# === 3. 权重初始化 (Xavier) ===
|
||||
# 这一步对小数据集训练非常重要,能让模型收敛得更快
|
||||
self._init_weights()
|
||||
|
||||
def _init_weights(self):
|
||||
for m in self.modules():
|
||||
if isinstance(m, nn.Linear):
|
||||
nn.init.xavier_uniform_(m.weight)
|
||||
if m.bias is not None:
|
||||
nn.init.constant_(m.bias, 0)
|
||||
|
||||
def forward(self, tactile_data, config_id_idx):
|
||||
"""
|
||||
前向传播函数
|
||||
:param tactile_data: [Batch_Size, 12] 的触觉数据张量
|
||||
:param config_id_idx: [Batch_Size] 的构型索引 (例如 [0, 2, 1...])
|
||||
:return: [Batch_Size, 3] 的预测偏差
|
||||
"""
|
||||
|
||||
# Step 1: 处理构型 ID (One-Hot Encoding)
|
||||
# 必须把整数 ID (0,1,2) 变成向量 ([1,0,0]...) 才能喂给神经网络
|
||||
batch_size = tactile_data.size(0)
|
||||
|
||||
# 创建一个全0的容器
|
||||
config_one_hot = torch.zeros(batch_size, self.config_dim).to(tactile_data.device)
|
||||
|
||||
# 使用 scatter_ 方法进行填充
|
||||
# config_id_idx 需要升维: [Batch] -> [Batch, 1]
|
||||
config_one_hot.scatter_(1, config_id_idx.unsqueeze(1).long(), 1)
|
||||
|
||||
# Step 2: 特征拼接 (Concatenate)
|
||||
# 将触觉数据和构型向量拼在一起 -> [Batch, 15]
|
||||
x = torch.cat((tactile_data, config_one_hot), dim=1)
|
||||
|
||||
# Step 3: 通过隐藏层
|
||||
x = F.relu(self.bn1(self.fc1(x))) # Linear -> BN -> ReLU
|
||||
x = F.relu(self.bn2(self.fc2(x))) # Linear -> BN -> ReLU
|
||||
x = F.relu(self.fc3(x)) # Linear -> ReLU (最后一层通常不用BN)
|
||||
|
||||
# Step 4: 输出结果
|
||||
prediction = self.output(x)
|
||||
|
||||
return prediction
|
||||
|
||||
|
||||
# === 单元测试 (Unit Test) ===
|
||||
# 运行此文件,检查网络结构和输入输出形状是否正确
|
||||
if __name__ == "__main__":
|
||||
print("Testing CondGraspNet Model...")
|
||||
|
||||
# 1. 实例化模型
|
||||
model = CondGraspNet()
|
||||
print(f"Model Structure:\n{model}")
|
||||
|
||||
# 2. 创建模拟输入数据 (Batch Size = 8)
|
||||
# 模拟8条触觉数据 (随机数)
|
||||
fake_tactile = torch.randn(8, 12)
|
||||
# 模拟8个构型ID (随机 0, 1, 2)
|
||||
fake_config = torch.tensor([0, 0, 1, 1, 2, 2, 0, 2], dtype=torch.long)
|
||||
|
||||
# 3. 前向推理
|
||||
print("\nProcessing forward pass...")
|
||||
try:
|
||||
output = model(fake_tactile, fake_config)
|
||||
|
||||
# 4. 验证结果
|
||||
print("Input Shape (Tactile):", fake_tactile.shape)
|
||||
print("Output Shape (Pred): ", output.shape) # 期望是 [8, 3]
|
||||
print("\nSample Prediction (Row 0):")
|
||||
print(f"Delta X: {output[0][0].item():.4f} mm")
|
||||
print(f"Delta Y: {output[0][1].item():.4f} mm")
|
||||
print(f"Delta θ: {output[0][2].item():.4f} deg")
|
||||
|
||||
if output.shape == (8, 3):
|
||||
print("\n✅ 测试通过:网络维度正确!")
|
||||
except Exception as e:
|
||||
print(f"\n❌ 测试失败:{e}")
|
||||
Reference in New Issue
Block a user