如何转换带有两个标签的数据集+;1和-1在Python中以向量化的方式转换为热单向量表示?

如何转换带有两个标签的数据集+;1和-1在Python中以向量化的方式转换为热单向量表示?,python,numpy,vector,Python,Numpy,Vector,我有一个numpy格式的数据集,有一个x向量和一个y向量。y向量只有两个值+1或-1(或0或1),因为它是一个二值函数。我知道我可以在数据集上循环,如果我看到+1将其映射到1,如果我看到和-1将其逐个映射到0。然而,我希望给定整个向量y=[nx1]一步将其映射到一个向量y=[nx2],因为它可能非常大,所以我希望尽快完成(我也不想将数据集的副本保存两次) 在python中有没有一种矢量化的方法可以快速进行这种转换 以下是循环代码供参考: def transform_data_to_one_ho

我有一个numpy格式的数据集,有一个x向量和一个y向量。y向量只有两个值+1或-1(或0或1),因为它是一个二值函数。我知道我可以在数据集上循环,如果我看到+1将其映射到1,如果我看到和-1将其逐个映射到0。然而,我希望给定整个向量
y=[nx1]
一步将其映射到一个向量
y=[nx2]
,因为它可能非常大,所以我希望尽快完成(我也不想将数据集的副本保存两次)

在python中有没有一种矢量化的方法可以快速进行这种转换


以下是循环代码供参考:

def transform_data_to_one_hot(X,Y):
    N,D = Y.size
    Y_new = np.zeros(N,D)
    for i in range(N):
        if y == -1:
            Y_new[i] = np.array([1,0])
        else:
            Y_new[i] = np.array([0,1])
    return Y_new

让我们使用Radamacher变量(即+1,-1而不是0和1)执行奇偶校验函数。在这种情况下,奇偶函数只是乘积函数:

>>> X = np.array([[-1,-1],[-1,1],[1,-1],[1,1]])
>>> X
array([[-1, -1],
       [-1,  1],
       [ 1, -1],
       [ 1,  1]])

>>> Y = np.reshape(np.prod(X,axis=1),[4,1])
>>> Y
array([[ 1],
       [-1],
       [-1],
       [ 1]])
当Y向量为1热时,应为:

>>> Y
array([[ 0,1],
       [1,0],
       [1,0],
       [ 0,1]])

以下是一些简单的观察结果,有助于提高效率:

  • 预先分配结果,而不是使用
    串联
  • 如果要覆盖那些零,
    empty
    zero
  • 使用
    out
    参数避免临时性

仔细选择您的数据类型-由于您选择了错误的数据类型,因此强制转换将产生副本-

def initialization_based(y):
    out = np.zeros((len(y),2),dtype=int)
    out[np.arange(out.shape[0]), (y==1).astype(int)] = 1
    return out
样本运行-

In [244]: y
Out[244]: array([ 1, -1,  1,  1, -1,  1, -1,  1])

In [245]: initialization_based(y)
Out[245]: 
array([[0, 1],
       [1, 0],
       [0, 1],
       [0, 1],
       [1, 0],
       [0, 1],
       [1, 0],
       [0, 1]])
使用
初始化
方法的其他方法-

def initialization_based_v2(y):
    out = np.zeros((len(y),2),dtype=int)
    out[np.arange(out.shape[0]), (y+1)//2] = 1
    return out

def initialization_based_v3(y):
    yc = y.copy()
    yc[yc==-1] = 0
    out = np.zeros((len(y),2),dtype=int)
    out[np.arange(out.shape[0]), yc] = 1
    return out
这两个新添加的内容只是在设置列索引的方式上有所不同。对于版本2,我们使用以下公式计算:
(y+1)//2
,而对于版本
3
,则使用:
yc=y.copy();yc[yc==-1]=0

另一个非常接近,但使用布尔数组-

def initialization_based_v4(y):
    out = np.empty((len(y),2),dtype=int)
    mask = y == 1    
    out[:,0] = mask
    out[:,1] = ~mask
    return out

运行时测试-

In [320]: y = 2*np.random.randint(0,2,(1000000))-1

In [321]: %timeit sign_to_one_hot(y, dtype=int)
     ...: %timeit initialization_based(y)
     ...: %timeit initialization_based_v2(y)
     ...: %timeit initialization_based_v3(y)
     ...: %timeit initialization_based_v4(y)
     ...: 
100 loops, best of 3: 3.16 ms per loop
100 loops, best of 3: 8.39 ms per loop
10 loops, best of 3: 27.2 ms per loop
100 loops, best of 3: 13.8 ms per loop
100 loops, best of 3: 3.11 ms per loop

In [322]: from sklearn.preprocessing import OneHotEncoder

In [323]: enc = OneHotEncoder(sparse=False)

In [324]: %timeit enc.fit_transform(np.where(y>=0, y, 0))
10 loops, best of 3: 77.3 ms per loop
您也可以使用这个方法

注意:它不接受负数,所以我们必须替换它们

演示:

结果:

In [140]: rslt
Out[140]:
array([[ 0.,  1.],
       [ 1.,  0.],
       [ 1.,  0.],
       [ 0.,  1.]])
源阵列:

In [141]: Y
Out[141]:
array([[ 1],
       [-1],
       [-1],
       [ 1]])

熊猫解决方案:

In [148]: pd.get_dummies(Y.ravel())
Out[148]:
   -1   1
0   0   1
1   1   0
2   1   0
3   0   1

你要找的是
a[a==-1]=0
?(其中
a
是你的数组…@MaxU我想我是!但是你的意思是
a[a==-1]=np.array([1,0])
你能提供一个小的可复制的输入数据集和所需的数据集吗?@MaxU是的。给我一秒钟我试着使用你的函数来理解你想要的数据集应该是什么样子,但是你的函数对我不起作用。。。你能发布所需的数据集吗?Divakar的答案有什么不同?@Pinocchio:这个答案没有分配额外的内存,而其他答案与你的答案和eric的答案有什么不同?你能评论一下你的不同版本有什么不同吗?你确定第一个答案是正确的吗?我编写的单元测试表明,它总是返回包含所有1的矩阵。@Pinocchio由第一个返回,你的意思是
初始化\u-based
?是的,没有v-name的那个。maskl one也有广播错误。
In [141]: Y
Out[141]:
array([[ 1],
       [-1],
       [-1],
       [ 1]])
In [148]: pd.get_dummies(Y.ravel())
Out[148]:
   -1   1
0   0   1
1   1   0
2   1   0
3   0   1