Dataset and DataLoader 加载数据集

news2024/11/15 19:23:23

文章目录

    • 7、Dataset and DataLoader 加载数据集
      • 7.1 Revision
        • 7.1.1 Manual data feed 手动数据输入
        • 7.1.2 Epoch, Batch-Size, Iterations
      • 7.2 DataLoader 数据加载器
      • 7.3 Dataset 数据集
        • 7.3.1 import
        • 7.3.2 class
        • 7.3.3 DataLoader
      • 7.4 Example: Diabetes Dataset
        • 7.4.1 Prepare dataset
        • 7.4.2 Design model
        • 7.4.3 Construct loss and optimizer
        • 7.4.4 Training cycle
        • 7.4.5 num_workers in Windows
        • 7.4.6 代码
      • 7.5 Datasets
        • 7.5.1 MNIST Dataset
      • 7.6 Kaggle Exercise
        • 7.6.1 Prepare dataset
        • 7.6.2 Design model
        • 7.6.3 Construct loss and optimizer
        • 7.6.4 Training cycle
        • 7.6.5 Test and Output
        • 7.6.6 完整代码

7、Dataset and DataLoader 加载数据集

B站视频教程传送门:PyTorch深度学习实践 - 加载数据集

7.1 Revision

我们就拿上节的糖尿病的例子来做个引入。

7.1.1 Manual data feed 手动数据输入

先回顾一下上一节的代码片段:

xy = np.loadtxt('../data/diabetes.csv.gz', delimiter=',', dtype=np.float32)

x_data = torch.from_numpy(xy[:, :-1])
y_data = torch.from_numpy(xy[:, [-1]])

...

for epoch in range(100):
    # Forward
    y_pred = model(x_data)
    loss = criterion(y_pred, y_data)
    print(epoch, loss.item())

    # Backward
    optimizer.zero_grad()
    loss.backward()

    # Update
    optimizer.step()

注意:在做前馈(Forward:model(x_data))时,是将所有数据全部送入模型中。在使用梯度下降有以下两种选择:

  • 全部样本 Batch

    • 可以最大化的利用向量计算的优势来提升计算速度。
    • 性能上会有一点问题。
  • 单个样本 随机梯度下降

    • 会得到一个比较好的随机性,会跨越将来我们在优化当中遇到的鞍点,即克服鞍点问题,训练出的模型性能会较好。

    • 会导致在优化过程中时间过长。

所以我们在深度学习中,会使用 Mini-Batch 的方法,来均衡我们在性能和训练时间上的需求。

7.1.2 Epoch, Batch-Size, Iterations

# Training cycle
for epoch in range(training_epochs):
    # Loop over all batches
    for i in range(total_batch):

嵌套循环:

  1. for:每一次循环是一个 epoch,即训练周期
  2. for:每一次迭代执行一次 Mini-Batch

7.2 DataLoader 数据加载器

batch-size=2, shuffle=True

参数说明:

  • batch_size:每2个为一组,即 I t e r a t i o n s = S a m p l e B a c t h − S i z e Iterations = \frac {Sample} {Bacth-Size} Iterations=BacthSizeSample
  • shuffle:是否打乱顺序

7.3 Dataset 数据集

import torch
from torch.utils.data import Dataset
from torch.utils.data import DataLoader


class DiabetesDataset(Dataset):
    def __init__(self):
        pass

    def __getitem__(self, index):
        pass

    def __len__(self):
        pass


dataset = DiabetesDataset()
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)

7.3.1 import

import torch
from torch.utils.data import Dataset
from torch.utils.data import DataLoader

Dataset:抽象类,不能实例化,只能被其他子类继承

DataLoader:加载数据,可以实例化

7.3.2 class

class DiabetesDataset(Dataset):
    def __init__(self):
        pass

    def __getitem__(self, index):
        pass

    def __len__(self):
        pass

(Dataset):表示该类(DiabetesDataset)继承自 Dataset

__getitem__:实例化类之后,该类支持下标操作,可以通过索引 dataset[index] 拿出数据

__len__:返回数据条数

7.3.3 DataLoader

train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)

num_workers:并行线程数

7.4 Example: Diabetes Dataset

# 导入需要的包
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader

7.4.1 Prepare dataset

class DiabetesDataset(Dataset):
    def __init__(self, filepath):
        xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32)
        self.len = xy.shape[0]
        self.x_data = torch.from_numpy(xy[:, :-1])
        self.y_data = torch.from_numpy(xy[:, [-1]])

    def __getitem__(self, index):
        return self.x_data[index], self.y_data[index]

    def __len__(self):
        return self.len


dataset = DiabetesDataset('../data/diabetes.csv.gz')
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)

7.4.2 Design model

class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = torch.nn.Linear(8, 6)
        self.linear2 = torch.nn.Linear(6, 4)
        self.linear3 = torch.nn.Linear(4, 1)
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self, x):
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        x = self.sigmoid(self.linear3(x))
        return x


model = Model()

7.4.3 Construct loss and optimizer

criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

7.4.4 Training cycle

for epoch in range(100):
    for i, data in enumerate(train_loader, 0):
        # 1. Prepare data
        inputs, labels = data
        # 2. Forward
        y_pred = model(inputs)
        loss = criterion(y_pred, labels)
        print(epoch, i, loss.item())
        # 3. Backward
        optimizer.zero_grad()
        loss.backward()
        # 4. Update
        optimizer.step()

7.4.5 num_workers in Windows

当我们在PyCharm执行上述代码时,会报出如下错误:

RuntimeError: 
        An attempt has been made to start a new process before the
        current process has finished its bootstrapping phase.

        This probably means that you are not using fork to start your
        child processes and you have forgotten to use the proper idiom
        in the main module:

            if __name__ == '__main__':
                freeze_support()
                ...

        The "freeze_support()" line can be omitted if the program
        is not going to be frozen to produce an executable.

在不同操作系统中,多进程的实现方式也不同,LinuxMac OS 使用的是fork,而 Windows 则使用spawn

所以我们需在training cycle前添加如下代码:

if __name__ == '__main__':

7.4.6 代码

import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
import matplotlib.pyplot as plt


class DiabetesDataset(Dataset):
    def __init__(self, filepath):
        xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32)
        self.len = xy.shape[0]
        self.x_data = torch.from_numpy(xy[:, :-1])
        self.y_data = torch.from_numpy(xy[:, [-1]])

    def __getitem__(self, index):
        return self.x_data[index], self.y_data[index]

    def __len__(self):
        return self.len


dataset = DiabetesDataset('../data/diabetes.csv.gz')
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=0)


class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = torch.nn.Linear(8, 6)
        self.linear2 = torch.nn.Linear(6, 4)
        self.linear3 = torch.nn.Linear(4, 1)
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self, x):
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        x = self.sigmoid(self.linear3(x))
        return x


model = Model()

criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

epoch_list = []
loss_list = []

if __name__ == '__main__':
    for epoch in range(100):

        epoch_list.append(epoch)

        for i, data in enumerate(train_loader, 0):
            # 1. Prepare data
            inputs, labels = data
            # 2. Forward
            y_pred = model(inputs)
            loss = criterion(y_pred, labels)
            print(epoch, i, loss.item())
            # 3. Backward
            optimizer.zero_grad()
            loss.backward()
            # 4. Update
            optimizer.step()
            
        loss_list.append(loss.item())

plt.plot(epoch_list, loss_list)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.show()

训练次数:100

训练次数:1000

7.5 Datasets

The following dataset loaders are available:https://pytorch.org/vision/stable/datasets.html

All datasets are subclasses of torch.utils.data.Dataset i.e, they have __getitem__ and __len__ methods implemented. Hence, they can all be passed to a torch.utils.data.DataLoader which can load multiple samples in parallel using torch.multiprocessing workers. For example:

imagenet_data = torchvision.datasets.ImageNet('path/to/imagenet_root/')
data_loader = torch.utils.data.DataLoader(imagenet_data, batch_size=4, shuffle=True, num_workers=args.nThreads)

All the datasets have almost similar API. They all have two common arguments: transform and target_transform to transform the input and target respectively. You can also create your own datasets using the provided base classes.

7.5.1 MNIST Dataset

以下列 MNIST 数据集为例:

import torch
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets

train_dataset = datasets.MNIST(root='../dataset/mnist', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root='../dataset/mnist', train=False, transform=transforms.ToTensor(), download=True)

train_loader = DataLoader(dataset=train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=32, shuffle=False)

for batch_idx, (inputs, target) in enumerate(train_loader):
    ......

7.6 Kaggle Exercise

  • 注册并登录 Kaggle
  • 进入 Titanic 竞赛,下载 test.csvtrain.csv

7.6.1 Prepare dataset

class TitanicDataset(Dataset):
    def __init__(self, filepath):
        xy = pd.read_csv(filepath)
        self.len = xy.shape[0]
        feature = ["Pclass", "Sex", "SibSp", "Parch", "Fare"]
        self.x_data = torch.from_numpy(np.array(pd.get_dummies(xy[feature])))
        self.y_data = torch.from_numpy(np.array(xy["Survived"]))

    def __getitem__(self, index):
        return self.x_data[index], self.y_data[index]

    def __len__(self):
        return self.len


dataset = TitanicDataset('../data/train.csv')
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=0)

7.6.2 Design model

class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = torch.nn.Linear(6, 3)
        self.linear2 = torch.nn.Linear(3, 1)
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self, x):
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        return x

    def test(self, x):
        with torch.no_grad():
            x = self.sigmoid(self.linear1(x))
            x = self.sigmoid(self.linear2(x))
            y = []
            for i in x:
                if i > 0.5:
                    y.append(1)
                else:
                    y.append(0)
            return y


model = Model()

7.6.3 Construct loss and optimizer

criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

7.6.4 Training cycle

if __name__ == '__main__':
    for epoch in range(100):
        for i, (inputs, labels) in enumerate(train_loader, 0):
            inputs = inputs.float()
            labels = labels.float()
            y_pred = model(inputs)
            y_pred = y_pred.squeeze(-1)
            loss = criterion(y_pred, labels)
            print(epoch, i, loss.item())

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

7.6.5 Test and Output

test_data = pd.read_csv('../data/test.csv')
feature = ["Pclass", "Sex", "SibSp", "Parch", "Fare"]
test = torch.from_numpy(np.array(pd.get_dummies(test_data[feature])))
y = model.test(test.float())

output = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': y})
output.to_csv('../data/my_predict.csv', index=False)

7.6.6 完整代码

import numpy as np
import pandas as pd
import torch
from torch.utils.data import Dataset, DataLoader
import matplotlib.pyplot as plt


class TitanicDataset(Dataset):
    def __init__(self, filepath):
        xy = pd.read_csv(filepath)
        self.len = xy.shape[0]  # xy.shape()可以得到xy的行列数
        feature = ["Pclass", "Sex", "SibSp", "Parch", "Fare"]  # 选取相关的数据特征
        # 要先进行独热表示,然后转化成ndarray,最后再转换成tensor矩阵
        self.x_data = torch.from_numpy(np.array(pd.get_dummies(xy[feature])))
        self.y_data = torch.from_numpy(np.array(xy["Survived"]))

    # 使用索引拿到数据
    def __getitem__(self, index):
        return self.x_data[index], self.y_data[index]

    # 返回数据的条数/长度
    def __len__(self):
        return self.len


# 实例化自定义类,并传入数据地址
dataset = TitanicDataset('../data/train.csv')
# 采用Mini-Batch的训练方法
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=0)  # num_workers是否要进行多线程服务


# 定义模型
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = torch.nn.Linear(6, 3)
        self.linear2 = torch.nn.Linear(3, 1)
        self.sigmoid = torch.nn.Sigmoid()

    # 前馈
    def forward(self, x):
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        return x

    # 测试
    def test(self, x):
        with torch.no_grad():
            x = self.sigmoid(self.linear1(x))
            x = self.sigmoid(self.linear2(x))
            y = []
            # 根据二分法原理,划分y的值
            for i in x:
                if i > 0.5:
                    y.append(1)
                else:
                    y.append(0)
            return y


# 实例化模型
model = Model()

# 定义损失函数
criterion = torch.nn.BCELoss(reduction='mean')
# 定义优化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

# 防止windows系统报错
if __name__ == '__main__':
    loss_list = []
    # 采用Mini-Batch的方法训练要采用多层嵌套循环
    # 所有数据都跑100遍
    for epoch in range(100):
        # data从train_loader中取出数据(取出的是一个元组数据):(x,y)
        # enumerate可以获得当前是第几次迭代,内部迭代每一次跑一个Mini-Batch
        for i, (inputs, labels) in enumerate(train_loader, 0):
            # inputs获取到data中的x的值,labels获取到data中的y值
            inputs = inputs.float()
            labels = labels.float()
            y_pred = model(inputs)
            y_pred = y_pred.squeeze(-1)
            loss = criterion(y_pred, labels)
            print(epoch, i, loss.item())

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        loss_list.append(loss.item())

    plt.plot(range(100), loss_list)
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.show()

# 测试
test_data = pd.read_csv('../data/test.csv')
feature = ["Pclass", "Sex", "SibSp", "Parch", "Fare"]
test = torch.from_numpy(np.array(pd.get_dummies(test_data[feature])))
y = model.test(test.float())

# 输出预测结果
output = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': y})
output.to_csv('../data/my_predict.csv', index=False)
0 0 0.756897509098053
0 1 0.7051487565040588
0 2 0.6766899228096008
0 3 0.658218502998352
0 4 0.6307331919670105
0 5 0.7304965257644653
0 6 0.644881010055542
0 7 0.6831851601600647
0 8 0.8197712302207947
0 9 0.7180750966072083
0 10 0.7203354835510254
0 11 0.6558003425598145
0 12 0.6053438782691956
0 13 0.5872318744659424
0 14 0.7021993398666382
0 15 0.705322265625
0 16 0.8232700824737549
0 17 0.651711642742157
0 18 0.674558162689209
0 19 0.6497538685798645
0 20 0.6709573864936829
0 21 0.6553310751914978
0 22 0.6533945798873901
0 23 0.6815280318260193
0 24 0.6963645815849304
0 25 0.727899968624115
0 26 0.6275196075439453
0 27 0.6709432005882263
...
99 0 0.6080023050308228
99 1 0.4668632447719574
99 2 0.544707179069519
99 3 0.5396970510482788
99 4 0.616457462310791
99 5 0.536240816116333
99 6 0.5226209163665771
99 7 0.595719575881958
99 8 0.5522709488868713
99 9 0.5529608726501465
99 10 0.6031484603881836
99 11 0.6390214562416077
99 12 0.5860381126403809
99 13 0.5921188592910767
99 14 0.6553858518600464
99 15 0.4729886054992676
99 16 0.6547493934631348
99 17 0.5085688829421997
99 18 0.5744019746780396
99 19 0.5622053146362305
99 20 0.49595993757247925
99 21 0.4467465877532959
99 22 0.5766837000846863
99 23 0.6239879131317139
99 24 0.6590874195098877
99 25 0.6569676995277405
99 26 0.516386866569519
99 27 0.49393993616104126

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/190391.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【微服务】Seata的部署和集成

Seata的部署和集成一、部署Seata的tc-server1.下载2.解压3.修改配置4.在nacos添加配置5.创建数据库表6.启动TC服务二、微服务集成seata1.引入依赖2.修改配置文件三、TC服务的高可用和异地容灾1.模拟异地容灾的TC集群2.将事务组映射配置到nacos3.微服务读取nacos配置一、部署Sea…

【Redis】.net core 3.1 Redis安装和简单使用

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 简单来说,就是一个键值对数据库。 Redis支持的…

DynaSLAM-5 DynaSLAM中Mask R-CNN部分源码解析(Ⅳ)

目录 1.ROIAlign层 2.Mask分支 3.整体框架回顾 1.ROIAlign层 在上文中,我们现在手里已经有了正负样本数据以及它们对应的标签。接下来我们就要进行预测的操作了! 但在预测之前,还有些小问题: ①每个ROI大小也不一样&#xff0c…

Biotin-SS-Sulfo-NHS;CAS:325143-98-4;生物素-二硫键-磺酸-活性酯

名称:生物素-二硫键-磺酸-活性酯 英文名称:Biotin-SS-Sulfo-NHS CAS:325143-98-4 分子式:C19H27N4NaO9S4 分子量:606.67 外观:白色固体或粘稠液体,取决于分子量大小 溶剂:溶于大部分有机溶…

JVM自动内存管理核心知识速览

目录运行时数据区程序计数器Java虚拟机栈本地方法栈Java堆方法区运行时常量池直接内存对象对象的创建类加载检查分配内存指针碰撞(Bump The Pointer)空闲列表(Free List)内存分配并发问题初始化值设置对象头执行init方法对象的内存…

一、Qt汽车仪表盘之绘制背景-绘制饼图

一、绘图坐标系分析 1、坐标系平移 1、从原来的坐标系中心移动到矩形仪表盘中心,相对应的坐标会发生变化。 2、了解绘制饼图的含义 (1)坐标系平移之后坐标变化 (2)绘制第一个饼图效果 第一个饼图:坐标…

[COMST 2022] 元宇宙的安全隐私问题

A Survey on Metaverse: Fundamentals, Security, and Privacyhttps://ieeexplore.ieee.org/abstract/document/9880528摘要元宇宙,作为下一代互联网的一个不断发展的范式,旨在建立一个完全沉浸式、超时空、自我维持的虚拟共享空间,供人类玩耍…

进销存ERP源码/ 进销存APP源码/小程序ERP系统/Thinkphp+Uniapp全开源销售进库出入库

框架:ThinkPHP5.0.24 uniapp 包含:服务端php全套开源源码,uniapp前端全套开源源码(可发布H5/android/iod/微信小程序/抖音小程序/支付宝/百度小程序) 注:这个是全开源,随便你怎么开,怎么来&…

JUC并发编程之SynchronousQueue的底层原理

作者简介:专注于研究Linux内核、Hotspot虚拟机、汇编语言、JDK源码、各大中间件源码等等喜欢的话,可以三连关注~SynchronousQueue是什么在JDK源码中JUC包下的并发编程阻塞/同步队列实现各种花样,但是队列的实现无非是。先进先出,后…

程序员必备的Linux命令——文件及目录命令

Linux命令就是我们对Linux系统进行管理的操作指令。类似于我们操作windows系统中可视化的各种操作动作。 在Linux系统中,我们任何东西都被认做是文件,比如cpu、内存、键盘以及用户全是文件。Linux命令类似于之前的DOS命令。 Linux系统中命令分为两种&a…

ORB-SLAM3算法和代码学习——系统初始化浅谈

总述 先放一张LocalMapping的代码结构图 相比于ORB-SLAM2,ORB-SLAM3的系统初始化分成了三个主要的模块:纯视觉初始化、纯IMU初始化、视觉和IMU联合优化。 纯视觉初始化和之前一样就是单目或者双目初始化,在Tracking线程中进行&#xff1b…

js数据结构之栈

1.栈数据结构 栈是一种遵从后进先出(LIFO)原则的有序集合。新添加或待删除的元素都保存在栈的同一端,称作栈顶,另一端就叫栈底。在栈里,新元素都靠近栈顶,旧元素都接近栈底。 在现实生活中也能发现许多栈的…

【服务器数据恢复】Raid5崩溃导致EMC存储不可用的数据恢复案例

服务器数据恢复环境: EMC存储,多块stat硬盘组建raid5磁盘阵列,两块热备盘,上层采用zfs文件系统。 服务器故障&检测&分析: EMC存储中的raid5磁盘阵列有2块硬盘出现故障,但是只有一块热备盘被激活&am…

关于原型和原型链的整理学习

关于原型和原型链是很多人学习或面试时遇到的问题,可能部分不懂,部分懂但不会说,下面关于原型和原型链进行简单的整理总结,希望可以帮助到大家。 一、JS中的原型和原型链 1、原型说明 所有的引用类型(数组、函数、对…

【Tools】Git和VS Code配置

文章目录0 前期教程1 前言2 基本使用2.1 配置2.2 获取帮助3 GitHub仓库和git3.1 新建一个GitHub仓库3.2 删除一个仓库(repository)3.3 上传项目代码4 git常用指令4.1 创建分支4.2 合并分支4.3 在git提交记录上移动4.4 撤销变更4.5 整理提交记录5 在VS Co…

蓝桥杯 stm32 DAC

文章代码使用 HAL 库。 文章目录前言一、根据手册了解 DAC 重要特性 :二、CubeMX 创建工程:三、DAC 代码:1. 设置DAC输出值函数。2. 开启DAC输出函数。3. DAC 输出电压。总结前言 DAC 就是 数字模拟信号转换器 ,也就是把 数字信号转变成模拟…

实施MES系统前,先想清楚首先用来解决什么问题

MES系统首先用来解决什么问题? 很多人会自然而然地认为,MES系统是用来解决管理问题的,是为了明确管理流程的,是为了建立管控标准的…… 甲方会有很多很多想解决的问题,甚至在系统导入过程中,各个部门也会…

vue中安装与引用echarts示例

第002个点击查看专栏目录Echarts发展到现在,已经陆续经过了很多版本,越来越完善,现在主要研究5.0以上的功能。这里是介绍在vue项目中,如果全局或者局部引用echarts,对项目初装echarts会起到非常大的帮助。 NPM 安装 E…

电脑文件如何自动备份?

电脑文件如何自动备份?计算机的出现是人类科技发展的重要标志,电脑已经成为我们工作、生活以及学习中必不可少的工具,尤其是在工作中的应用,它改变了以前传统的工作方式。电脑的使用给我们带来极大方便的同时,也带来了…

mPEG-SS-NH2 ;mPEG-SS-Amine;甲氧基聚乙二醇-双硫键-氨基-科研用试剂简介

mPEG-SS-NH2 甲氧基聚乙二醇-双硫键-氨基 英文名称:mPEG-SS-NH2 英文别名:mPEG-SS-Amine 存储条件:-20C,避光,避湿 用 途:仅供科研实验使用,不用于诊治 外观: 固体或粘性液体,取…