Praxiseinstieg Machine Learning mit Scikit-Learn, Keras und TensorFlow. Aurélien Géron

Praxiseinstieg Machine Learning mit Scikit-Learn, Keras und TensorFlow - Aurélien Géron


Скачать книгу
für Merkmale mit einer Ordnung wie »schlecht«, »durchschnittlich«, »gut« und »ausgezeichnet«), aber es ist offensichtlich nicht der Fall für die Spalte ocean_proximity (beispielsweise sind die Kategorien 0 und 4 einander ähnlicher als die Kategorien 0 und 1). Um dieses Problem zu beheben, ist es üblich, ein binäres Merkmal pro Kategorie zu erstellen: Ein Merkmal beträgt 1, wenn die Kategorie »<1H OCEAN« ist (und andernfalls 0), ein weiteres Merkmal beträgt 1, wenn die Kategorie »INLAND« ist (und andernfalls 0) und so weiter. Dies nennt man One-Hot-Codierung, weil nur jeweils ein Merkmal 1 beträgt (heiß) und die anderen 0 betragen (kalt). Die neuen Merkmale werden manchmal als Dummy-Merkmale bezeichnet. Scikit-Learn bietet eine Klasse OneHotEncoder an, um kategorische Merkmalswerte in One-Hot-Vektoren umzuwandeln:20

      >>> from sklearn.preprocessing import OneHotEncoder

      >>> cat_encoder = OneHotEncoder()

      >>> housing_cat_1hot = cat_encoder.fit_transform(housing_cat)

      >>> housing_cat_1hot

      <16512x5 sparse matrix of type '<class 'numpy.float64'>'

      with 16512 stored elements in Compressed Sparse Row format>

      Beachten Sie, dass die Ausgabe kein NumPy-Array, sondern eine Sparse-Matrix aus SciPyi ist. Dies ist sehr hilfreich, wenn Sie kategorische Merkmale mit mehreren Tausend Kategorien haben. Nach der One-Hot-Codierung erhalten wir eine Matrix mit Tausenden Spalten, und die gesamte Matrix ist voller Nullen, bis auf eine 1 pro Zeile. Alle Nullen zu speichern, wäre extreme Speicherverschwendung. Die Sparse-Matrix speichert daher nur die Stellen der Elemente ungleich null. Sie können sie mehr oder weniger wie ein gewöhnliches 2-D-Array verwenden,21 aber wenn Sie sie wirklich in ein (dichtes) NumPy-Array umwandeln möchten, rufen Sie die Methode toarray() auf:

      >>> housing_cat_1hot.toarray()

      array([[1., 0., 0., 0., 0.],

      [1., 0., 0., 0., 0.],

      [0., 0., 0., 0., 1.],

      ...,

      [0., 1., 0., 0., 0.],

      [1., 0., 0., 0., 0.],

      [0., 0., 0., 1., 0.]])

      Wieder erhalten Sie eine Liste der Merkmale über die Instanzvariable categories_ des Encoders:

      >>> cat_encoder.categories_

      [array(['<1H OCEAN', 'INLAND', 'ISLAND', 'NEAR BAY', 'NEAR OCEAN'],

      dtype=object)]

      Beide Transformationen (von textbasierten Kategorien zu Integer-Kategorien, anschließend von Integer-Kategorien zu One-Hot-Vektoren) lassen sich in einem Schritt mit der Klasse CategoricalEncoder durchführen. Diese ist kein Teil von Scikit-Learn 0.19.0 und früher, aber wird in Kürze hinzugefügt. Sie sollte also verfügbar sein, sobald Sie diese Zeilen lesen. Falls nicht, können Sie sich den Code aus dem Jupyter-Notebook für dieses Kapitel abholen (der Code wurde aus PullRequest #9151 kopiert). So lässt er sich verwenden:

      >>> from sklearn.preprocessing import CategoricalEncoder # oder aus dem Notebook

      >>> cat_encoder = CategoricalEncoder()

      >>> housing_cat_reshaped = housing_cat.values.reshape(-1, 1)

      >>> housing_cat_1hot = cat_encoder.fit_transform(housing_cat_reshaped)

      >>> housing_cat_1hot

      <16512x5 sparse matrix of type '<class 'numpy.float64'>'

      with 16512 stored elements in Compressed Sparse Row format>

      Standardmäßig gibt der CategoricalEncoder eine Sparse-Matrix aus, Sie können die Codierung aber auf "onehot-dense" setzen, wenn Sie eine dichtere Matrix bevorzugen:

      >>> cat_encoder = CategoricalEncoder(encoding="onehot-dense")

      >>> housing_cat_1hot = cat_encoder.fit_transform(housing_cat_reshaped)

      >>> housing_cat_1hot

      array([[ 1., 0., 0., 0., 0.],

      [ 1., 0., 0., 0., 0.],

      [ 0., 0., 0., 0., 1.],

      ...,

      [ 0., 1., 0., 0., 0.],

      [ 1., 0., 0., 0., 0.],

      [ 0., 0., 0., 1., 0.]])

      Sie können die Liste der Kategorien über die Instanzvariable des Encoders catego ries_ einsehen. Sie ist eine Liste mit einem 1-D-Array von Kategorien für jedes kategorische Merkmal (in diesem Fall eine Liste mit einem einzelnen Array, da es nur ein kategorisches Merkmal gibt):

      >>> cat_encoder.categories_

      [array(['<1H OCEAN', 'INLAND', 'ISLAND', 'NEAR BAY', 'NEAR OCEAN'], dtype=object)]

image Wenn ein kategorisches Merkmal eine große Anzahl möglicher Kategorien aufweist (z.B. Ländercode, Beruf, Spezies und so weiter), führt die One-Hot-Codierung zu einer großen Zahl von Eingabemerkmalen. Dies kann das Trainieren verlangsamen und die Leistung verringern. In diesem Fall können Sie die kategorischen Eingabewerte durch sinnvolle numerische Merkmale ersetzen, die damit in Zusammenhang stehen: Beispielsweise könnten Sie das Merkmal ocean_proximity durch den Abstand zum Ozean ersetzen (genauso ließe sich ein Ländercode durch die Bevölkerungszahl und das BSP pro Einwohner ersetzen). Alternativ könnten Sie jedes Merkmal durch einen erlernbaren, niedriger dimensionalen Vektor namens Embedding austauschen. Jede Repräsentation eines Merkmals würde während des Trainings gelernt werden. Dies ist ein Beispiel für Representation Learning (siehe die Kapitel 13 und 17).

       Eigene Transformer

      Obwohl Scikit-Learn viele nützliche Transformer bereitstellt, werden Sie für bestimmte Aufgaben bei der Datenaufbereitung oder zum Kombinieren bestimmter Merkmale Ihre eigenen schreiben müssen. Ihre Transformer sollten nahtlos mit den übrigen Funktionen von Scikit-Learn zusammenarbeiten (z.B. Pipelines), und da Scikit-Learn auf Duck Typing (anstelle von Vererbung) aufbaut, müssen Sie lediglich eine Klasse definieren und drei Methoden implementieren: fit() (die self zurückgibt), transform() und fit_transform().

      Sie können die letzte automatisch erhalten, indem Sie als Oberklasse Transformer Mixin wählen. Wenn Sie außerdem BaseEstimator als Oberklasse wählen (und die Verwendung der Parameter *args und **kargs im Konstruktor vermeiden), erhalten Sie die zusätzlichen Methoden (get_params() und set_params()), die beim automatischen Einstellen der Hyperparameter hilfreich sind.

      Als Beispiel ist hier eine kleine Transformer-Klasse angegeben, die die zuvor besprochenen kombinierten Merkmale hinzufügt:

      from sklearn.base import BaseEstimator, TransformerMixin

      rooms_ix, bedrooms_ix, population_ix, households_ix = 3, 4, 5, 6

      class CombinedAttributesAdder(BaseEstimator, TransformerMixin):

      def __init__(self, add_bedrooms_per_room = True): # weder *args noch **kargs

      self.add_bedrooms_per_room = add_bedrooms_per_room

      def fit(self, X, y=None):

      return self # sonst nichts zu tun

      def transform(self, X, y=None):

      rooms_per_household = X[:, rooms_ix] / X[:, households_ix]

      population_per_household = X[:, population_ix] / X[:, households_ix]


Скачать книгу