सूचकांकों की सरणी को 1-हॉट एन्कोडेड सुन्न सरणी में बदलें


227

मान लीजिए कि मेरे पास 1d अंक है

a = array([1,0,3])

मैं इसे 2d 1-हॉट एरे के रूप में एनकोड करना चाहूंगा

b = array([[0,1,0,0], [1,0,0,0], [0,0,0,1]])

क्या ऐसा करने का कोई त्वरित तरीका है? के aतत्वों को सेट करने के लिए सिर्फ लूपिंग की तुलना में तेज b, जो है।

जवाबों:


395

आपका सरणी aआउटपुट सरणी में गैर-अक्षीय तत्वों के कॉलम को परिभाषित करता है। आपको पंक्तियों को भी परिभाषित करना होगा और फिर फैंसी इंडेक्सिंग का उपयोग करना होगा:

>>> a = np.array([1, 0, 3])
>>> b = np.zeros((a.size, a.max()+1))
>>> b[np.arange(a.size),a] = 1
>>> b
array([[ 0.,  1.,  0.,  0.],
       [ 1.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.]])

111
सुंदर। इसे थोड़ा सामान्य करना: b = np.zeros((a.size, a.max()+1))फिर `b [np.arange (a.size), a] = 1`
James Atwood

10
@JamesAtwood यह एप्लिकेशन पर निर्भर करता है, लेकिन मैं अधिकतम पैरामीटर बनाऊंगा और डेटा से इसकी गणना नहीं करूंगा।
मोहम्मद मोघिमी

1
@ मोहम्मदमोहिमी ज़रूर, मुझे समझ में आता है।
जेम्स एटवुड

7
क्या हुआ अगर 'a' 2d था? और आप 3-डी वन-हॉट मैट्रिक्स चाहते हैं?
ई।

8
क्या कोई इस बात की व्याख्या कर सकता है कि यह क्यों काम करता है, लेकिन स्लाइस: [, ए] नहीं करता है?
एन। मैक।

168
>>> values = [1, 0, 3]
>>> n_values = np.max(values) + 1
>>> np.eye(n_values)[values]
array([[ 0.,  1.,  0.,  0.],
       [ 1.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.]])

9
यह समाधान इनपुट एनडी मैट्रिक्स से वन-हॉट एन + 1 डी मैट्रिक्स के लिए एकमात्र उपयोगी है। उदाहरण: input_matrix = np.asarray ([[0,1,1], [1,1,2]]); np.eye (3) [input_matrix] # उत्पादन 3 डी टेन्सर
Isaías

5
+1 क्योंकि स्वीकृत समाधान पर इसे प्राथमिकता दी जानी चाहिए। हालांकि एक अधिक सामान्य समाधान के valuesलिए, पायथन सूची के बजाय एक Numpy सरणी होना चाहिए, फिर यह केवल 1D में ही नहीं, सभी आयामों में काम करता है।
एलेक्स

8
ध्यान दें कि np.max(values) + 1यदि आपके डेटा सेट को बेतरतीब ढंग से नमूना कहा गया है तो केवल बाल्टी की संख्या के रूप में लेना वांछनीय नहीं हो सकता है और बस संयोग से यह अधिकतम मूल्य नहीं हो सकता है। बाल्टियों की संख्या एक पैरामीटर होनी चाहिए और यह सुनिश्चित करने के लिए कि प्रत्येक मान 0 (incl) और बाल्टियों की गिनती (excl) के भीतर होने के लिए एक पैरामीटर और अभिकथन / चेक होना चाहिए।
नाइटलाइफ़

2
मेरे लिए यह समाधान सबसे अच्छा है और किसी भी टेंसर को आसानी से सामान्यीकृत किया जा सकता है: one_hot (x, गहराई = 10) को परिभाषित करें: np.eye (गहराई) [x] लौटें। ध्यान दें कि अनुक्रमणिका के रूप में टेंसर x देने से x.shape आई पंक्तियों का एक टेंसर वापस आ जाता है।
केकेनोनेउरले

4
इस समाधान को "समझने" का आसान तरीका और यह एन-डिम्स ( numpyडॉक्स पढ़ने के बिना ) के लिए काम क्यों करता है : मूल मैट्रिक्स में प्रत्येक स्थान पर ( values), हमारे पास एक पूर्णांक है k, और हम eye(n)[k]उस स्थान में 1-हॉट वेक्टर को "डाल" देते हैं। । यह एक आयाम जोड़ता है क्योंकि हम मूल मैट्रिक्स में एक स्केलर के स्थान पर एक वेक्टर को "डाल" रहे हैं।
14

35

यदि आप केरस का उपयोग कर रहे हैं, तो उसके लिए एक उपयोगिता है:

from keras.utils.np_utils import to_categorical   

categorical_labels = to_categorical(int_labels, num_classes=3)

और यह @ YXD के उत्तर ( स्रोत-कोड देखें ) के समान ही बहुत कुछ करता है ।


32

यहाँ मुझे उपयोगी मिल रहा है:

def one_hot(a, num_classes):
  return np.squeeze(np.eye(num_classes)[a.reshape(-1)])

यहां num_classesआपके पास कई कक्षाएं हैं। इसलिए यदि आपके पास (10000)a आकार के साथ वेक्टर है , तो यह फ़ंक्शन इसे (10000, C) में बदल देता है । ध्यान दें कि aशून्य-अनुक्रमित है, अर्थात one_hot(np.array([0, 1]), 2)देगा [[1, 0], [0, 1]]

वास्तव में आप क्या चाहते थे कि मुझे विश्वास हो।

पुनश्च: स्रोत अनुक्रम मॉडल है - deeplearning.ai


यह भी कि, np.squeeze करने के कारण क्या है (क्योंकि वेक्टर का आकार मिलता है) np.eye(num_classes)[a.reshape(-1)]. What you are simply doing is using np.eye का उपयोग करके कई एक गर्म एन्कोडेड सरणियाँ हैं। आप प्रत्येक वर्ग सूचकांक के साथ 1 शेष शून्य के रूप में एक विकर्ण मैट्रिक्स बना रहे हैं और बाद में प्रदान किए गए इंडेक्स का उपयोग कर रहे हैं। a.reshape(-1)सूचकांक में इसी उत्पादन का उत्पादन करके np.eye()। मुझे इसकी आवश्यकता समझ में नहीं आई np.sqeezeक्योंकि हम इसका उपयोग केवल एक आयाम को हटाने के लिए करते हैं जो हमारे पास कभी नहीं होगा जैसा कि आउटपुट के आयाम में हमेशा रहेगा(a_flattened_size, num_classes)
अनु

27

आप उपयोग कर सकते हैं sklearn.preprocessing.LabelBinarizer:

उदाहरण:

import sklearn.preprocessing
a = [1,0,3]
label_binarizer = sklearn.preprocessing.LabelBinarizer()
label_binarizer.fit(range(max(a)+1))
b = label_binarizer.transform(a)
print('{0}'.format(b))

उत्पादन:

[[0 1 0 0]
 [1 0 0 0]
 [0 0 0 1]]

अन्य चीजों के बीच, आप इसे आरंभ कर सकते हैं sklearn.preprocessing.LabelBinarizer()ताकि transformविरल का उत्पादन हो ।


21

तुम भी सुन्न के नेत्र समारोह का उपयोग कर सकते हैं :

numpy.eye(number of classes)[vector containing the labels]


1
अधिक स्पष्टता के लिए उपयोग np.identity(num_classes)[indices]करना बेहतर हो सकता है। अच्छा उत्तर!
ओलिवर

5

यहां एक फ़ंक्शन है जो 1-डी वेक्टर को 2-डी एक-गर्म सरणी में परिवर्तित करता है।

#!/usr/bin/env python
import numpy as np

def convertToOneHot(vector, num_classes=None):
    """
    Converts an input 1-D vector of integers into an output
    2-D array of one-hot vectors, where an i'th input value
    of j will set a '1' in the i'th row, j'th column of the
    output array.

    Example:
        v = np.array((1, 0, 4))
        one_hot_v = convertToOneHot(v)
        print one_hot_v

        [[0 1 0 0 0]
         [1 0 0 0 0]
         [0 0 0 0 1]]
    """

    assert isinstance(vector, np.ndarray)
    assert len(vector) > 0

    if num_classes is None:
        num_classes = np.max(vector)+1
    else:
        assert num_classes > 0
        assert num_classes >= np.max(vector)

    result = np.zeros(shape=(len(vector), num_classes))
    result[np.arange(len(vector)), vector] = 1
    return result.astype(int)

नीचे कुछ उदाहरण उपयोग है:

>>> a = np.array([1, 0, 3])

>>> convertToOneHot(a)
array([[0, 1, 0, 0],
       [1, 0, 0, 0],
       [0, 0, 0, 1]])

>>> convertToOneHot(a, num_classes=10)
array([[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]])

ध्यान दें कि यह केवल वैक्टर पर काम करता है (और assertवेक्टर आकार की जांच करने के लिए नहीं है;))।
जॉन्डोडो

1
सामान्यीकृत दृष्टिकोण और मापदंडों की जांच के लिए +1। हालांकि, एक सामान्य अभ्यास के रूप में, मैं इनपुट पर जांच करने के लिए जोर लगाने का उपयोग नहीं करने का सुझाव देता हूं। केवल आंतरिक मध्यवर्ती स्थितियों को सत्यापित करने के लिए जोर का प्रयोग करें। बल्कि, सभी assert ___में परिवर्तित करें if not ___ raise Exception(<Reason>)
fnunnari

3

1-गर्म-एन्कोडिंग के लिए

   one_hot_encode=pandas.get_dummies(array)

उदाहरण के लिए

आनंद लें


टिप्पणी के लिए धन्यवाद, लेकिन कोड क्या कर रहा है का एक संक्षिप्त विवरण बहुत उपयोगी होगा!
क्लूर्स

कृपया उदाहरण देखें
शुभम मिश्रा

@Clarus नीचे दिए गए उदाहरण की जाँच करें। आप अपने np सरणी में प्रत्येक मूल्य के एक हॉट एन्कोडिंग को one_hot_encode [मान] करके एक्सेस कर सकते हैं। >>> import numpy as np >>> import pandas >>> a = np.array([1,0,3]) >>> one_hot_encode=pandas.get_dummies(a) >>> print(one_hot_encode) 0 1 3 0 0 1 0 1 1 0 0 2 0 0 1 >>> print(one_hot_encode[1]) 0 1 1 0 2 0 Name: 1, dtype: uint8 >>> print(one_hot_encode[0]) 0 0 1 1 2 0 Name: 0, dtype: uint8 >>> print(one_hot_encode[3]) 0 0 1 0 2 1 Name: 3, dtype: uint8
दीपक

2

मुझे लगता है कि संक्षिप्त उत्तर नहीं है। nआयामों में अधिक सामान्य मामले के लिए , मैं इसके साथ आया:

# For 2-dimensional data, 4 values
a = np.array([[0, 1, 2], [3, 2, 1]])
z = np.zeros(list(a.shape) + [4])
z[list(np.indices(z.shape[:-1])) + [a]] = 1

मैं सोच रहा हूँ कि क्या कोई बेहतर उपाय है - मुझे यह पसंद नहीं है कि मुझे उन सूचियों को अंतिम दो पंक्तियों में बनाना है। वैसे भी, मैंने कुछ माप किए timeitऔर ऐसा लगता है कि numpy-based ( indices/ arange) और पुनरावृत्त संस्करण उसी के बारे में प्रदर्शन करते हैं।


2

K3 --- rnc के उत्कृष्ट उत्तर के बारे में विस्तार से बताने के लिए , यहाँ एक अधिक सामान्य संस्करण दिया गया है:

def onehottify(x, n=None, dtype=float):
    """1-hot encode x with the max value n (computed from data if n is None)."""
    x = np.asarray(x)
    n = np.max(x) + 1 if n is None else n
    return np.eye(n, dtype=dtype)[x]

इसके अलावा, इस विधि का एक त्वरित और गंदा बेंचमार्क है और वर्तमान में YXD द्वारा स्वीकार किए गए उत्तर से एक विधि है (थोड़ा बदल गया है, ताकि वे एक ही एपीआई की पेशकश करें सिवाय इसके कि बाद में केवल 1 डी ndarrays के साथ काम करता है):

def onehottify_only_1d(x, n=None, dtype=float):
    x = np.asarray(x)
    n = np.max(x) + 1 if n is None else n
    b = np.zeros((len(x), n), dtype=dtype)
    b[np.arange(len(x)), x] = 1
    return b

बाद की विधि ~ 35% तेज (मैकबुक प्रो 13 2015) है, लेकिन पूर्व अधिक सामान्य है:

>>> import numpy as np
>>> np.random.seed(42)
>>> a = np.random.randint(0, 9, size=(10_000,))
>>> a
array([6, 3, 7, ..., 5, 8, 6])
>>> %timeit onehottify(a, 10)
188 µs ± 5.03 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit onehottify_only_1d(a, 10)
139 µs ± 2.78 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

2

आप निम्न कोड को एक-गर्म वेक्टर में परिवर्तित करने के लिए उपयोग कर सकते हैं:

आज्ञा देना x सामान्य वर्ग वेक्टर है जिसमें एकल कॉलम 0 से कुछ संख्याओं के साथ होता है:

import numpy as np
np.eye(x.max()+1)[x]

यदि 0 एक वर्ग नहीं है; फिर +1 निकालें।


1

मैं हाल ही में एक ही तरह की समस्या में भाग गया और कहा समाधान पाया गया जो केवल संतोषजनक है अगर आपके पास संख्याएं हैं जो एक निश्चित गठन के भीतर जाती हैं। उदाहरण के लिए यदि आप सूची में एक-हॉट एनकोड चाहते हैं:

all_good_list = [0,1,2,3,4]

आगे बढ़ो, पोस्ट किए गए समाधान पहले से ही ऊपर वर्णित हैं। लेकिन अगर इस आंकड़े पर विचार किया जाए तो:

problematic_list = [0,23,12,89,10]

यदि आप इसे ऊपर वर्णित विधियों के साथ करते हैं, तो आप संभवतः 90 एक-गर्म कॉलम के साथ समाप्त हो जाएंगे। ऐसा इसलिए है क्योंकि सभी उत्तरों में कुछ ऐसा शामिल है n = np.max(a)+1। मुझे एक और सामान्य समाधान मिला जो मेरे लिए काम करता था और आपके साथ साझा करना चाहता था:

import numpy as np
import sklearn
sklb = sklearn.preprocessing.LabelBinarizer()
a = np.asarray([1,2,44,3,2])
n = np.unique(a)
sklb.fit(n)
b = sklb.transform(a)

मुझे उम्मीद है कि किसी ने उपरोक्त समाधानों पर समान प्रतिबंधों का सामना किया और यह काम आ सकता है


1

इस तरह के एन्कोडिंग आमतौर पर सुन्न सरणी का हिस्सा होते हैं। यदि आप इस तरह एक संख्यात्मक सरणी का उपयोग कर रहे हैं:

a = np.array([1,0,3])

फिर इसे 1-हॉट एन्कोडिंग में बदलने का बहुत सरल तरीका है

out = (np.arange(4) == a[:,None]).astype(np.float32)

बस।


1
  • p एक 2d ndarray होगा।
  • हम जानना चाहते हैं कि कौन सी वैल्यू एक पंक्ति में सबसे अधिक है, वहां 1 और हर जगह 0 को डालना है।

स्वच्छ और आसान समाधान:

max_elements_i = np.expand_dims(np.argmax(p, axis=1), axis=1)
one_hot = np.zeros(p.shape)
np.put_along_axis(one_hot, max_elements_i, 1, axis=1)

1

एक न्यूरल पाइप लाइन चरण का उपयोग करना :

  1. अपना उदाहरण स्थापित करें
import numpy as np
a = np.array([1,0,3])
b = np.array([[0,1,0,0], [1,0,0,0], [0,0,0,1]])
  1. वास्तविक रूपांतरण करें
from neuraxle.steps.numpy import OneHotEncoder
encoder = OneHotEncoder(nb_columns=4)
b_pred = encoder.transform(a)
  1. यह काम करता है जोर देते हैं
assert b_pred == b

दस्तावेज़ से लिंक करें: neuraxle.steps.numpy.OneHotEncoder


0

यहाँ एक उदाहरण फ़ंक्शन है जो मैंने ऊपर दिए गए उत्तरों और अपने स्वयं के उपयोग के मामले के आधार पर करने के लिए लिखा था:

def label_vector_to_one_hot_vector(vector, one_hot_size=10):
    """
    Use to convert a column vector to a 'one-hot' matrix

    Example:
        vector: [[2], [0], [1]]
        one_hot_size: 3
        returns:
            [[ 0.,  0.,  1.],
             [ 1.,  0.,  0.],
             [ 0.,  1.,  0.]]

    Parameters:
        vector (np.array): of size (n, 1) to be converted
        one_hot_size (int) optional: size of 'one-hot' row vector

    Returns:
        np.array size (vector.size, one_hot_size): converted to a 'one-hot' matrix
    """
    squeezed_vector = np.squeeze(vector, axis=-1)

    one_hot = np.zeros((squeezed_vector.size, one_hot_size))

    one_hot[np.arange(squeezed_vector.size), squeezed_vector] = 1

    return one_hot

label_vector_to_one_hot_vector(vector=[[2], [0], [1]], one_hot_size=3)

0

मैं एक साधारण फ़ंक्शन को पूरा करने के लिए जोड़ रहा हूं, केवल खस्ता ऑपरेटरों का उपयोग करके:

   def probs_to_onehot(output_probabilities):
        argmax_indices_array = np.argmax(output_probabilities, axis=1)
        onehot_output_array = np.eye(np.unique(argmax_indices_array).shape[0])[argmax_indices_array.reshape(-1)]
        return onehot_output_array

यह इनपुट को प्रायिकता मैट्रिक्स के रूप में लेता है: जैसे:

[[0.03038822 0.65810204 0.16549407 0.3797123] ... [0.02771272 0.2760752 0.3280924 0.33458805]]

और वापस लौट आएगा

[[० १ ० ०] ... [० ० १ १]]


0

यहाँ एक आयामी-स्वतंत्र स्टैंडअलोन समाधान है।

यह किसी भी एन-डायमेंशनल सरणी arrको नॉन - नेटिव पूर्णांकों के एक-हॉट एन + 1-आयामी एरे में बदल देगा one_hot, जहाँ one_hot[i_1,...,i_N,c] = 1इसका अर्थ है arr[i_1,...,i_N] = c। आप इनपुट के माध्यम से पुनर्प्राप्त कर सकते हैंnp.argmax(one_hot, -1)

def expand_integer_grid(arr, n_classes):
    """

    :param arr: N dim array of size i_1, ..., i_N
    :param n_classes: C
    :returns: one-hot N+1 dim array of size i_1, ..., i_N, C
    :rtype: ndarray

    """
    one_hot = np.zeros(arr.shape + (n_classes,))
    axes_ranges = [range(arr.shape[i]) for i in range(arr.ndim)]
    flat_grids = [_.ravel() for _ in np.meshgrid(*axes_ranges, indexing='ij')]
    one_hot[flat_grids + [arr.ravel()]] = 1
    assert((one_hot.sum(-1) == 1).all())
    assert(np.allclose(np.argmax(one_hot, -1), arr))
    return one_hot

0

निम्नलिखित कोड का उपयोग करें। यह सबसे अच्छा काम करता है।

def one_hot_encode(x):
"""
    argument
        - x: a list of labels
    return
        - one hot encoding matrix (number of labels, number of class)
"""
encoded = np.zeros((len(x), 10))

for idx, val in enumerate(x):
    encoded[idx][val] = 1

return encoded

यह यहाँ पाया PS आपको लिंक में जाने की आवश्यकता नहीं है।


5
आपको खामियों के साथ छोरों का उपयोग करने से बचना चाहिए
केनन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.