Pytorch 创建数据和类型转换

数据类型:

Pytorch支持的数据类型有如下类型:

Torch 数据类型
名称dtype说明
int8 unsignedtorch.uint8Unsigned 8 bit int, value in [0:255]
int8 signedtorch.int8signed 8 bit int, value in [-127:127]
int16 signedtorch.int16 or torch.short16 bit signed integer
int32/inttorch.int32 or torch.int32 bit signed integer
int64torch.int64 or torch.long64 bit signed integer
float16torch.float16 or torch.half

16-bit float.

1-bit sign, 5 bit exponent.

10-bit fraction.

bf16torch.bfloat16

16-bit float.

1-bit sign, 8 bit exponent.

7-bit fraction.

float32/floattorch.float or torch.float32

32-bit float.

1 bit sign, 8 bit exponent.

23-bit fraction.

float64/doubletorch.double or torch.float64

64-bit float.

1 bit sign, 11 bit exponent.

52-bit fraction.

Booleantorch.bool

Boolean: True or False

0 or 1.

Q-uint8torch.quint8Quantized 8-bit integer (unsigned)
Q-int8torch.qint8Quantized 8-bit integer (signed)
Q-int32torch.qint32Quantized 32-bit integer (signed)
Q-int4torch.quint4x2Quantized 4-bit integer (unsigned)

创建不同数据类型的Tensor

从内置数据类型创建

import torch

size = [32, 32, 3] # 即将要创建的tensor size

t_example = torch.tensor(size, dtype=torch.int32)
print(f"Created t_example is: {t_example}")

## output is:
Created t_example is: tensor([32, 32,  3], dtype=torch.int32)



创建稀疏矩阵

By COO (Rdinate)

COO是一种很直观的稀疏矩阵描述方式,通过直接定义(行,列)坐标对,表示哪些(行,列)的坐标是有数值的,并且数值的value定义在values array里面,

下面的示意图很好的解释了Rdinate方式的稀疏矩阵创建方式。

创建稀疏矩阵by COO示意

Pytorch参考代码,

## spase tensor
import torch
i = torch.tensor([[0, 1, 1], [2, 0, 2]]) # 创建的稀疏矩阵,坐标索引为(0, 2), (1, 0), (1, 2) 的位置有值,其他位置为0
v = torch.tensor([3, 4, 5], dtype=torch.float32) # 值分别为3, 4, 5, 类型为float32
a= torch.sparse_coo_tensor(i, v, [2, 4]) # 创建稀疏矩阵,size为[2, 4]

print(f"{a}")
#-----------------------------------------------------

# 代码输出:
tensor(indices=tensor([[0, 1, 1],
                       [2, 0, 2]]),
       values=tensor([3., 4., 5.]),
       size=(2, 4), nnz=3, layout=torch.sparse_coo)


By CSR (Compressed Sparse Row)

COO方式描述的稀疏矩阵,每一行/列,坐标对都需要一一对应。假设对于二维数组size(m, n),需要存储空间最大为m*n,此种方式对于有效元素非常少的二维sparse Tensor来说,其需要的存储空间小。但是如果又要元素较多,worst case需要的存储是m*n。

CSR从Row方向上压缩了Row需要的存储大小。以如下array为例,

COO的描述方式为:

import torch

i = [[0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5],
        [0, 4, 0, 1, 5, 1, 2, 3, 0, 2, 3, 4, 1, 3, 4, 5, 1, 4, 5]]
value = [10, -2, 3, 9, 3, 7, 8, 7, 3, 8, 7, 5, 8, 9, 9, 13, 4, 2, -1]

size = [6, 6]

array = torch.sparse_coo_tensor(i, v, size)

Array[i] element 数量为: 19*2。即如果有效元素是19个,需要一个1x19的行矩阵和一个1x19的列矩阵来存储19个元素的(行,列)坐标对。nnz表示有效元素的个数的话,需要的存储空间为3*nnz.

CSR的方式Column array和COO方式一样,对于上图的稀疏矩阵,col_ptr array一模一样[0, 4, 0, 1, 5, 1, 2, 3, 0, 2, 3, 4, 1, 3, 4, 5, 1, 4, 5]。

上面的稀疏矩阵的value array,从element_ind来看,共计从0到18,共计有19个有效元素,

从col_ind_array的规律来看,0,4,0,1,5.。。。第一个0表示第0行的第0列元素,第二个0其实表示下一行(第一行)的第0列是有效元素。从这里我们可以看出,行矩阵不需要保存每一个有效元素的行id,其实只需要保存列矩阵里面哪个位置是“下一行”就可以了。

按照上面的array为例来看,element_ind表示元素的整体索引(递增),从0到18,共计19个元素,row_ptr[0]是0,表示从element_id0开始是第一行的,row_ptr[1]为2,表示element_ind为2的位置是下一行(第二行的第一个有效元素的列坐标),row_ptr[2]是5,表示element_ind为5的位置是再下一行(也就是第三行的第一个有效元素的列坐标),以此类推。row_ptr的最后一个元素表示“矩阵中共计多少个non-zero元素”

以上面的稀疏矩阵为例,需要的存储空间为,len(col_ind_array) = nnz, size of (value) = nnz, len(row_ptr) = n (line-no), 加上row_ptr的最后一个元素。共计需要存储空间 2* nnz + n + 1。相比于COO方式,节约了存储消耗。


By CSC (Comressed Sparse Column)

类似于CSR,此种方式压缩column数据。


By BSR (Block Compressed Sparse Row)

行坐标压缩和CSR一样,唯一的区别是data element的每个元素由0维变成了多维。类似于下图矩阵:


By BSC (Block Compressed Sparse Column)

跟BSR一样,压缩方向是列Block压缩。


numpy.array创建

#-----------------------------------------------------
import numpy as np
import torch
size = [32, 32, 3] # 即将要创建的tensor size
t_np_example = np.array(size)
t_example = torch.from_numpy(t_np_example)
print(f"Created t_example is: {t_example}")
#-----------------------------------------------------
Created t_example is: tensor([32, 32,  3], dtype=torch.int32)

From Others

asarray:

功能介绍:从其他“对象”或“类型”的数据创建tensor,典型用法是:

函数原型:array = torch.asarray(obj, *, dtype=None)

参数定义:参数obj可以是:tensor, numpy array或者scalar,DLPack,buffer,scalar,scalar序列,,etc.

Pytorch 的官方例程很好的说明了使用方法,参考如下:

Example: 

>>> a = torch.tensor([1, 2, 3])
>>> # Shares memory with tensor 'a'
>>> b = torch.asarray(a)
>>> a.data_ptr() == b.data_ptr()
True
>>> # Forces memory copy
>>> c = torch.asarray(a, copy=True)
>>> a.data_ptr() == c.data_ptr()
False

>>> a = torch.tensor([1., 2., 3.], requires_grad=True)
>>> b = a + 2
>>> b
tensor([3., 4., 5.], grad_fn=<AddBackward0>)
>>> # Shares memory with tensor 'b', with no grad
>>> c = torch.asarray(b)
>>> c
tensor([3., 4., 5.])
>>> # Shares memory with tensor 'b', retaining autograd history
>>> d = torch.asarray(b, requires_grad=True)
>>> d
tensor([3., 4., 5.], grad_fn=<AddBackward0>)

>>> array = numpy.array([1, 2, 3])
>>> # Shares memory with array 'array'
>>> t1 = torch.asarray(array)
>>> array.__array_interface__['data'][0] == t1.data_ptr()
True
>>> # Copies memory due to dtype mismatch
>>> t2 = torch.asarray(array, dtype=torch.float32)
>>> array.__array_interface__['data'][0] == t2.data_ptr()
False

>>> scalar = numpy.float64(0.5)
>>> torch.asarray(scalar)
tensor(0.5000, dtype=torch.float64)


as_tensor:

功能介绍:从一个tensor复制成另一个tensor,

函数原型:torch.as_tensor(data, dtype=None, device=None)

参数定义:

    data:如果data已经是tensor,并且数据类型和dtype匹配,则函数直接返回data tensor,如果数据类型不一致,则此函数先将数据类型转换成dtype并copy成一个新的tensor并返回。

        如果data是 numpy,则此函数直接call tensor.from_numpy生成并返回tensor。

Example:

>>> a = numpy.array([1, 2, 3])
>>> t = torch.as_tensor(a)
>>> t
tensor([ 1,  2,  3])
>>> t[0] = -1
>>> a
array([-1,  2,  3])

>>> a = numpy.array([1, 2, 3])
>>> t = torch.as_tensor(a, device=torch.device('cuda'))
>>> t
tensor([ 1,  2,  3])
>>> t[0] = -1
>>> a
array([1,  2,  3])

as_strided

功能介绍:从一个tensor按照定义的size和stride创建新的tensor,对应的value和原tensor保持一致。

函数原型:torch.as_strided(input, size, stride, storage_offset=None)

参数定义: input: 输入的原tensor;size:output tensor size;stride:output tensor的stride。

Example:

>>> x = torch.randn(3, 3)
>>> x
tensor([[ 0.9039,  0.6291,  1.0795],
        [ 0.1586,  2.1939, -0.4900],
        [-0.1909, -0.7503,  1.9355]])
>>> t = torch.as_strided(x, (2, 2), (1, 2))
>>> t
tensor([[0.9039, 1.0795],
        [0.6291, 0.1586]])
>>> t = torch.as_strided(x, (2, 2), (1, 2), 1)
tensor([[0.6291, 0.1586],
        [1.0795, 2.1939]])

from_numpy

功能介绍:从numpy.ndarray创建tensor,注意:返回的tensor和ndarray公用同一块memory。改变tensor某个位置的element值也会改变ndarray的对应位置元素的值。同样,改变ndarray内某个位置的value,tensor对应的位置value也会被修改。

函数原型: torch.from_numpy(ndarray)

参数定义:ndarray: numpy.array;

Example:

>>> a = numpy.array([1, 2, 3])
>>> t = torch.from_numpy(a)
>>> t
tensor([ 1,  2,  3])
>>> t[0] = -1
>>> a
array([-1,  2,  3])

from_dlpack

功能介绍:从符合dlpack协议的external library创建tensor。需要注意,用户需注意原library的数据属性,比如只读等属性可能会导致未期望的问题等。

函数原型:torch.from_dlpack(ext_tensor)

参数定义:ext_tensor: 具备__dlpack__ 属性或者DLPack封装的对象。

Example:

>>> import torch.utils.dlpack
>>> t = torch.arange(4)

# Convert a tensor directly (supported in PyTorch >= 1.10)
>>> t2 = torch.from_dlpack(t)
>>> t2[:2] = -1  # show that memory is shared
>>> t2
tensor([-1, -1,  2,  3])
>>> t
tensor([-1, -1,  2,  3])

# The old-style DLPack usage, with an intermediate capsule object
>>> capsule = torch.utils.dlpack.to_dlpack(t)
>>> capsule
<capsule object "dltensor" at ...>
>>> t3 = torch.from_dlpack(capsule)
>>> t3
tensor([-1, -1,  2,  3])
>>> t3[0] = -9  # now we're sharing memory between 3 tensors
>>> t3
tensor([-9, -1,  2,  3])
>>> t2
tensor([-9, -1,  2,  3])
>>> t
tensor([-9, -1,  2,  3])

frombuffer

功能介绍:从一段python buffer数据生成1维 tensor。

函数原型:torch.frombuffer(buffer, *, dtype, count=-1, offset=0, requires_grad=False)

参数定义:

  •         buffer: python buffer;
  •         dtype: 生成的Tensor的数据类型;
  •         count:表示1维tensor的元素个数,为正数表示从offset开始,创建多少个tensor元素。为负数表示从offset开始的整个buffer能创建的最大tensor元素个数,即 length/sizeof(dtype);
  •         offset:表示从buffer的第offset个bytes开始创建tensor。

注意:

  •         和前几个函数一样,生成的Tensor和buffer共享memory空间。
  •         此函数处理的buffer数据不在CPU上会导致发生异常segmentation fault。
  •         此函数不会转换数据类型,指定的dtype数据类型必须和原始输入的buffer的数据类型一致。

Example:

>>> import array
>>> a = array.array('i', [1, 2, 3])
>>> t = torch.frombuffer(a, dtype=torch.int32)
>>> t
tensor([ 1,  2,  3])
>>> t[0] = -1
>>> a
array([-1,  2,  3])

>>> # Interprets the signed char bytes as 32-bit integers.
>>> # Each 4 signed char elements will be interpreted as
>>> # 1 signed 32-bit integer.
>>> import array
>>> a = array.array('b', [-1, 0, 0, 0])
>>> torch.frombuffer(a, dtype=torch.int32)
tensor([255], dtype=torch.int32)

Tensor数据初始化

zeros

功能介绍:Tensor数据全部初始化为0

函数原型:torch.zeros(*size, *, out=None, dtype=None, layout=torch.strided, device=None)

参数定义:

  •         必选:size: tensor的大小和维度。
  •         可选:
  •                 out: 输出tensor。
  •                 dtype: 数据类型。
  •                 layout: 输出tensor的layout。
  •                 device: CPU or CUDA.

Example: 

>>> torch.zeros(2, 3)
tensor([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.]])

>>> torch.zeros(5)
tensor([ 0.,  0.,  0.,  0.,  0.])

zeros_like

功能介绍:从已知tensor创建输出tensor,并初始化数据为全0

函数原型:torch.zeros_like(input, *, dtype=None, layout, device=None, ,,)

参数定义:

        input: 输入tensor

        dtype:数据类型

Example:

>>> input = torch.empty(2, 3)
>>> torch.zeros_like(input)
tensor([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.]])

ones:

功能介绍:等同于zeros,唯一的区别是将tensor所有数据初始化为全1.

Example:

>>> torch.ones(2, 3)
tensor([[ 1.,  1.,  1.],
        [ 1.,  1.,  1.]])

>>> torch.ones(5)
tensor([ 1.,  1.,  1.,  1.,  1.])

ones_like

功能介绍: 等同于zeros_like, 区别同ones和zeros。

Example:

>>> input = torch.empty(2, 3)
>>> torch.ones_like(input)
tensor([[ 1.,  1.,  1.],
        [ 1.,  1.,  1.]])

arange

功能介绍:生成一个元素的值从start开始,到end(不包含)结束,size=(end-start)/step的1维tensor.

函数原型:torch.arange(start=0, end, step=1, *, out=None, dtype=None,,,)

关键参数定义:

        start: 开始的值。

        end:结束值

        step:递增步进值。 

注意:step必须是int类型。

Example:

>>> torch.arange(5)
tensor([ 0,  1,  2,  3,  4])
>>> torch.arange(1, 4)
tensor([ 1,  2,  3])
>>> torch.arange(1, 2.5, 0.5)
tensor([ 1.0000,  1.5000,  2.0000])

range

注意:Pytorch备注此函数将被废弃。


linspace

功能介绍:生成Tensor,其值为从start到end的线性数据(等差数列)。即

        start, start + (end-start)/(steps-1), ,,,, start + (steps - 2) * (end - start) / (steps - 1), end.

函数原型:torch.linspace(start, end, steps, *, out=None, dtype=None,,,)

关键参数定义:

        start: 开始的值。

        end:结束值

        step:递增步进值。 

注意:step必须是int类型。

Example:

>>> torch.linspace(3, 10, steps=5)
tensor([  3.0000,   4.7500,   6.5000,   8.2500,  10.0000])
>>> torch.linspace(-10, 10, steps=5)
tensor([-10.,  -5.,   0.,   5.,  10.])
>>> torch.linspace(start=-10, end=10, steps=5)
tensor([-10.,  -5.,   0.,   5.,  10.])
>>> torch.linspace(start=-10, end=10, steps=1)
tensor([-10.])

logspace

功能介绍:生成Tensor,其值为从以base为底的start到end的幂指数排列。即

(base^{start}, base^{(start+\frac{end-start}{steps-1})}, ,,,base^{(start + (steps-2) * \frac{end-start}{steps-1}))}, base^{end})

函数原型:torch.logspace(start, end, steps, base=10.0, *, out=None, dtype=None,,,)

关键参数定义:

        start: 开始的值。

        end:结束值

        step:递增步进值。 

        base: Log的底。

注意:step必须是int类型。

Example:

>>> torch.logspace(start=-10, end=10, steps=5)
tensor([ 1.0000e-10,  1.0000e-05,  1.0000e+00,  1.0000e+05,  1.0000e+10])
>>> torch.logspace(start=0.1, end=1.0, steps=5)
tensor([  1.2589,   2.1135,   3.5481,   5.9566,  10.0000])
>>> torch.logspace(start=0.1, end=1.0, steps=1)
tensor([1.2589])
>>> torch.logspace(start=2, end=2, steps=1, base=2)
tensor([4.0])

eye

功能介绍:生成对角线矩阵,对角线上的值为0,其他位置为0。

函数原型:torch.eye(*size, *, out=None, dtype=None,,,)

Example:

>>> torch.eye(3)
tensor([[ 1.,  0.,  0.],
        [ 0.,  1.,  0.],
        [ 0.,  0.,  1.]])

empty

功能介绍:生成Tensor,其数据未初始化。注意:未初始化不是0或者1的意思。

函数原型:torch.empty(*size, *, out=None, dtype=None,,,)

Example:

>>> torch.empty((2,3), dtype=torch.int64)
tensor([[ 9.4064e+13,  2.8000e+01,  9.3493e+13],
        [ 7.5751e+18,  7.1428e+18,  7.5955e+18]])

empty_like

功能介绍:和empty一样,只是需要提供一个参考输入tensor,此函数获取input tensor size,并产生一个empty的tensor返回。

函数原型:torch.empty_like(input, *, out=None, dtype=None,,,)

Example:

>>> a=torch.empty((2,3), dtype=torch.int32, device = 'cuda')
>>> torch.empty_like(a)
tensor([[0, 0, 0],
        [0, 0, 0]], device='cuda:0', dtype=torch.int32)

empty_strided

功能介绍:生成一个大小为size,指定stride的Tensor,数据未初始化。

函数原型:torch.empty_strided(size, stride, *, dtype=None,,,,)

Example: 

>>> a = torch.empty_strided((2, 3), (1, 2))
>>> a
tensor([[8.9683e-44, 4.4842e-44, 5.1239e+07],
        [0.0000e+00, 0.0000e+00, 3.0705e-41]])
>>> a.stride()
(1, 2)
>>> a.size()
torch.Size([2, 3])

full

功能介绍:创建一个符合参数size,值为指定的fill_value的Tensor。

函数原型:torch.full(size, fill_value, *, out=None, dtype=None,,,)

Example:

>>> torch.full((2, 3), 3.141592)
tensor([[ 3.1416,  3.1416,  3.1416],
        [ 3.1416,  3.1416,  3.1416]])

full_like

功能介绍:功能和full一样,输入的参数由size换成输入tensor。此函数创建的Tensor,size和input tensor一样,其他功能和full函数一致。

函数原型:torch.full_like(input, fill_value, *, out=None, dtype=None,,,)


Tensor数据类型转换

quantize_per_tensor

功能介绍:将Tensor内的元素“量化”操作成dtype类型(quint8, qint8, uint32)的数据。基本计算方式为:

 output[i] = (input[i] / scale) + zero_point

函数原型:torch.quantize_per_tensor(input, scale, zero_point, dtype)

Example:

>>> torch.quantize_per_tensor(torch.tensor([-1.0, 0.0, 1.0, 2.0]), 0.1, 10, torch.quint8)
tensor([-1.,  0.,  1.,  2.], size=(4,), dtype=torch.quint8,
       quantization_scheme=torch.per_tensor_affine, scale=0.1, zero_point=10)
>>> torch.quantize_per_tensor(torch.tensor([-1.0, 0.0, 1.0, 2.0]), 0.1, 10, torch.quint8).int_repr()
tensor([ 0, 10, 20, 30], dtype=torch.uint8)
>>> torch.quantize_per_tensor([torch.tensor([-1.0, 0.0]), torch.tensor([-2.0, 2.0])],
>>> torch.tensor([0.1, 0.2]), torch.tensor([10, 20]), torch.quint8)
(tensor([-1.,  0.], size=(2,), dtype=torch.quint8,
    quantization_scheme=torch.per_tensor_affine, scale=0.1, zero_point=10),
    tensor([-2.,  2.], size=(2,), dtype=torch.quint8,
    quantization_scheme=torch.per_tensor_affine, scale=0.2, zero_point=20))
>>> torch.quantize_per_tensor(torch.tensor([-1.0, 0.0, 1.0, 2.0]), torch.tensor(0.1), torch.tensor(10), torch.quint8)
tensor([-1.,  0.,  1.,  2.], size=(4,), dtype=torch.quint8,
   quantization_scheme=torch.per_tensor_affine, scale=0.10, zero_point=10)

quantize_per_channel

  • 功能介绍:将Tensor内的元素“量化”操作成dtype类型(quint8, qint8, qint32)的数据。和per tensor的区别是,此函数的scale和zero_point是1维数组,每个元素代表每个channel;基本计算方式为:
  •  output[i] = (input[i] / scale[c]) + zero_point[c]
  • 函数原型:torch.quantize_per_channel(input, scale, zero_point, axis, dtype)
    •         input: 要被量化的原始Float tensor.
    •         scale:量化的Scale,Per channel的1维数组。
    •         zero_points:量化参数zero-points,Per channel的1维数组。
    •         axis:Per-channel quantize的channel方向(0: 坐标轴X方向,1:坐标轴Y方向,2:坐标轴C方向,,以此类推tensor的维度,或者(WHC...)

Example:

>>> x = torch.tensor([[-1.0, 0.0], [1.0, 2.0]])
>>> torch.quantize_per_channel(x, torch.tensor([0.1, 0.01]), torch.tensor([10, 0]), 0, torch.quint8)
tensor([[-1.,  0.],
        [ 1.,  2.]], size=(2, 2), dtype=torch.quint8,
       quantization_scheme=torch.per_channel_affine,
       scale=tensor([0.1000, 0.0100], dtype=torch.float64),
       zero_point=tensor([10,  0]), axis=0)
>>> torch.quantize_per_channel(x, torch.tensor([0.1, 0.01]), torch.tensor([10, 0]), 0, torch.quint8).int_repr()
tensor([[  0,  10],
        [100, 200]], dtype=torch.uint8)

dequantize

  • 功能介绍:将经过量化之后的Tensor,反量化成fp32.
  • 函数原型:torch.dequantize(tensor)

complex

  • 功能介绍:根据输入的实部和虚部tensor,创建复数tensor。
  • 函数原型:torch.complex(real, imag, *, out=None)
  • 关键参数定义:
    • real:实部Tensor。dtype只能是:half/float/double
    • imag:虚部Tensor。dtype需要和real tensor保持一致。
    • out:如果input dtype是float32, 则output dtype必须是:complex64;如果input 的type是float64, 则output dtype必须是:complex128
  • Example:
    >>> real = torch.tensor([1, 2], dtype=torch.float32)
    >>> imag = torch.tensor([3, 4], dtype=torch.float32)
    >>> z = torch.complex(real, imag)
    >>> z
    tensor([(1.+3.j), (2.+4.j)])
    >>> z.dtype
    torch.complex64

polar

  • 功能介绍:创建极坐标系表述的复数Tensor
  • 函数原型:torch.polar(abs, angle, *, out=None)
    • out = abs * cos(angle) + abs * sin(angle) * j
  • Example:
>>> import numpy as np
>>> abs = torch.tensor([1, 2], dtype=torch.float64)
>>> angle = torch.tensor([np.pi / 2, 5 * np.pi / 4], dtype=torch.float64)
>>> z = torch.polar(abs, angle)
>>> z
tensor([(0.0000+1.0000j), (-1.4142-1.4142j)], dtype=torch.complex128)

heaviside

  • 功能介绍:计算阶跃函数(赫维赛德函数)

        \left\{\begin{matrix} 0,& input<0\\ values & input=0 \\ 1, & input>0 \end{matrix}\right.

  • 函数原型:torch.heaviside(input, values, *, out=None)
  • Example:

        

>>> input = torch.tensor([-1.5, 0, 2.0])
>>> values = torch.tensor([0.5])
>>> torch.heaviside(input, values)
tensor([0.0000, 0.5000, 1.0000])
>>> values = torch.tensor([1.2, -2.0, 3.5])
>>> torch.heaviside(input, values)
tensor([0., -2., 1.])

本篇结束

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值