[PYTHON] Ich habe AdaNet gegen Tabellendaten ausprobiert

Einführung

Kürzlich habe ich von AdaNet (https://github.com/tensorflow/adanet) erfahren, einer automatischen Konstruktionsbibliothek für tiefes Lernen. Da das Beispiel jedoch viele Bilddaten enthielt und das Beispiel für die Tabellendaten klein war, habe ich ein Memorandum erstellt. Ich werde auch eine Notiz machen.

Die folgenden Programme basieren auf diesem Artikel. https://towardsdatascience.com/modeling-banks-churn-rate-with-adanet-a-scalable-flexible-auto-ensemble-learning-framework-700fa1e6df74

Umgebung

Ich habe Google Colaboratory verwendet.

Was ich getan habe

Bibliotheksinstallation

Installiere mit pip und du bist fertig.

! pip install adanet

In der Ausgabe habe ich einen FEHLER bekommen, aber am Ende hat es ohne Probleme funktioniert.

(Kürzung)
Successfully built rednose termstyle
ERROR: datascience 0.10.6 has requirement coverage==3.7.1, but you'll have coverage 4.5.4 which is incompatible.
ERROR: datascience 0.10.6 has requirement folium==0.2.1, but you'll have folium 0.8.3 which is incompatible.
ERROR: coveralls 0.5 has requirement coverage<3.999,>=3.6, but you'll have coverage 4.5.4 which is incompatible.
Installing collected packages: nose, termstyle, colorama, rednose, coverage, mock, adanet
  Found existing installation: coverage 3.7.1
    Uninstalling coverage-3.7.1:
      Successfully uninstalled coverage-3.7.1
Successfully installed adanet-0.8.0 colorama-0.4.3 coverage-4.5.4 mock-3.0.5 nose-1.3.7 rednose-1.3.0 termstyle-0.1.11

Vorbereitung

Erstellen Sie ein Verzeichnis, um Modellinformationen beim Erstellen des Modells zu speichern.

!mkdir ./models

Bibliothek importieren

Importieren Sie zunächst die erforderlichen Bibliotheken.

from __future__ import division
from __future__ import print_function

import functools
import os
import shutil

import adanet
from adanet.examples import simple_dnn
import matplotlib.pyplot as plt
import tensorflow as tf
import pandas as pd
from sklearn.model_selection import train_test_split


# The random seed to use.
RANDOM_SEED = 42

LOG_DIR = './models'

Lade Daten

Dieses Mal werden wir den Brustkrebs-Datensatz verwenden, der von scicit-learn bereitgestellt wird. Anweisungen finden Sie auf der sklearn-Seite. https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_breast_cancer.html#sklearn.datasets.load_breast_cancer


from sklearn.datasets import load_breast_cancer
data = load_breast_cancer()
df_X = pd.DataFrame(data.data, columns=data.feature_names)
df_y = pd.DataFrame(data.target, columns=['target'])
x_train, x_test, y_train, y_test = train_test_split(df_X, df_y, test_size=0.2, random_state=100)

In diesen Daten ist die Zielvariable 0 oder 1, es handelt sich also um eine binäre Klassifizierung.

df_y['target'].unique()
array([0, 1])

Vorbereitung der in AdaNet verwendeten Funktionen

Schreiben Sie eine Funktion, um die Daten an AdaNet zu übergeben. Daten werden im Diktattyp an "from_tensor_slices" von "tensorflow" übergeben.

FEATURES_KEY = "x"
_NUM_LAYERS_KEY = "num_layers"

def input_fn(partition, training, batch_size):
  """Generate an input function for the Estimator."""

  def _input_fn():

    if partition == "train":
      dataset = tf.data.Dataset.from_tensor_slices(({FEATURES_KEY: x_train}, y_train))
    else:
      dataset = tf.data.Dataset.from_tensor_slices(({FEATURES_KEY: x_test},  y_test))

    # repeat is called after shuffling,to prevent separate epochs from blending together.
    if training:
      dataset = dataset.shuffle(10 * batch_size, seed=RANDOM_SEED).repeat()

    dataset = dataset.batch(batch_size)
    iterator = dataset.make_one_shot_iterator()
    features, labels = iterator.get_next()
    return features, labels

  return _input_fn

Bereiten Sie eine Klasse für Deep Learning vor.


class _SimpleDNNBuilder(adanet.subnetwork.Builder):
  """Builds a DNN subnetwork for AdaNet."""

  def __init__(self, optimizer, layer_size, num_layers, learn_mixture_weights,
               seed):

    self._optimizer = optimizer
    self._layer_size = layer_size
    self._num_layers = num_layers
    self._learn_mixture_weights = learn_mixture_weights
    self._seed = seed

  def build_subnetwork(self,
                       features,
                       labels,
                       logits_dimension,
                       training,
                       iteration_step,
                       summary,
                       previous_ensemble=None):

    input_layer = tf.to_float(features[FEATURES_KEY])
    kernel_initializer = tf.glorot_uniform_initializer(seed=self._seed)
    last_layer = input_layer
    for _ in range(self._num_layers):
      last_layer = tf.layers.dense(
          last_layer,
          units=self._layer_size,
          activation=tf.nn.relu,
          kernel_initializer=kernel_initializer)
    logits = tf.layers.dense(
        last_layer,
        units=logits_dimension,
        kernel_initializer=kernel_initializer)
    persisted_tensors = {_NUM_LAYERS_KEY: tf.constant(self._num_layers)}
    return adanet.Subnetwork(
        last_layer=last_layer,
        logits=logits,
        complexity=self._measure_complexity(),
        persisted_tensors=persisted_tensors)

  def _measure_complexity(self):
    """Approximates Rademacher complexity as the square-root of the depth."""
    return tf.sqrt(tf.to_float(self._num_layers))

  def build_subnetwork_train_op(self, subnetwork, loss, var_list, labels,
                                iteration_step, summary, previous_ensemble):
    return self._optimizer.minimize(loss=loss, var_list=var_list)

  def build_mixture_weights_train_op(self, loss, var_list, logits, labels,
                                     iteration_step, summary):
    if not self._learn_mixture_weights:
      return tf.no_op()
    return self._optimizer.minimize(loss=loss, var_list=var_list)

  @property
  def name(self):
    if self._num_layers == 0:
      # A DNN with no hidden layers is a linear model.
      return "linear"
    return "{}_layer_dnn".format(self._num_layers)  

class SimpleDNNGenerator(adanet.subnetwork.Generator):
  """Generates a two DNN subnetworks at each iteration.
  """

  def __init__(self,
               optimizer,
               layer_size=32,
               learn_mixture_weights=False,
               seed=None):

    self._seed = seed
    self._dnn_builder_fn = functools.partial(
        _SimpleDNNBuilder,
        optimizer=optimizer,
        layer_size=layer_size,
        learn_mixture_weights=learn_mixture_weights)
  def generate_candidates(self, previous_ensemble, iteration_number,
                          previous_ensemble_reports, all_reports, config):
    """See `adanet.subnetwork.Generator`."""

    num_layers = 0
    seed = self._seed
    if previous_ensemble:
      num_layers = tf.contrib.util.constant_value(
          previous_ensemble.weighted_subnetworks[
              -1].subnetwork.persisted_tensors[_NUM_LAYERS_KEY])
    if seed is not None:
      seed += iteration_number
    return [
        self._dnn_builder_fn(num_layers=num_layers, seed=seed),
        self._dnn_builder_fn(num_layers=num_layers + 1, seed=seed),
    ]

Ich werde den Ausführungsteil beschreiben. Die Parameter am Anfang legen den "RMSPropOptimizer" fest, mit dem die Lernrate und die Gesamtzahl der Trainings angepasst werden. Da es sich diesmal um eine binäre Klassifizierung handelt, wird für den Kopf von "adanet.Estimator" "binary_classification_head" verwendet.


# AdaNet parameters
LEARNING_RATE = 0.001
TRAIN_STEPS = 100000 
BATCH_SIZE = 32 

LEARN_MIXTURE_WEIGHTS = False
ADANET_LAMBDA = 0 
BOOSTING_ITERATIONS = 5

def train_and_evaluate(learn_mixture_weights=LEARN_MIXTURE_WEIGHTS,
                       adanet_lambda=ADANET_LAMBDA):
  """Trains an `adanet.Estimator` to predict churn yes/no."""

  estimator = adanet.Estimator(
      # Since we are predicting churn, we'll use a regression
      # head that optimizes for MSE.
      head=tf.contrib.estimator.binary_classification_head(
          loss_reduction=tf.losses.Reduction.SUM_OVER_BATCH_SIZE),

      # Define the generator, which defines our search space of subnetworks
      # to train as candidates to add to the final AdaNet model.
      subnetwork_generator=SimpleDNNGenerator(
          optimizer=tf.train.RMSPropOptimizer(learning_rate=LEARNING_RATE),
          learn_mixture_weights=learn_mixture_weights,
          seed=RANDOM_SEED),

  
      adanet_lambda=adanet_lambda,
      # The number of train steps per iteration.
      max_iteration_steps=TRAIN_STEPS // BOOSTING_ITERATIONS,

      # The evaluator will evaluate the model on the full training set to
      # compute the overall AdaNet loss (train loss + complexity
      # regularization) to select the best candidate to include in the
      # final AdaNet model.
      evaluator=adanet.Evaluator(
          input_fn=input_fn("train", training=False, batch_size=BATCH_SIZE)),

      # The report materializer will evaluate the subnetworks' metrics
      # using the full training set to generate the reports that the generator
      # can use in the next iteration to modify its search space.
      report_materializer=adanet.ReportMaterializer(
          input_fn=input_fn("train", training=False, batch_size=BATCH_SIZE)),

      # Configuration for Estimators.
      config=tf.estimator.RunConfig(
          save_checkpoints_steps=50000,
          save_summary_steps=50000,
          tf_random_seed=RANDOM_SEED))

  # Train and evaluate using using the tf.estimator tooling.
  train_spec = tf.estimator.TrainSpec(
      input_fn=input_fn("train", training=True, batch_size=BATCH_SIZE),
      max_steps=TRAIN_STEPS)
  eval_spec = tf.estimator.EvalSpec(
      input_fn=input_fn("test", training=False, batch_size=BATCH_SIZE),
      steps=None)
  return tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)

def ensemble_architecture(result):
  """Extracts the ensemble architecture from evaluation results."""

  architecture = result["architecture/adanet/ensembles"]
  # The architecture is a serialized Summary proto for TensorBoard.
  summary_proto = tf.summary.Summary.FromString(architecture)
  return summary_proto.value[0].tensor.string_val[0]


results, _ = train_and_evaluate()
print("Loss:", results["average_loss"])
print("Results:", results)
print("Architecture:", ensemble_architecture(results))

Das Ausführungsergebnis ist wie folgt. Da es viele Standardausgaben gibt, wird nur der letzte Teil angezeigt. Die Genauigkeit beträgt ca. 93%.

(Kürzung)
Loss: 0.1722714
Results: {'accuracy': 0.9298246, 'accuracy_baseline': 0.5701754, 'architecture/adanet/ensembles': b'\n1\n\x13architecture/adanetB\x10\x08\x07\x12\x00B\n| linear |J\x08\n\x06\n\x04text', 'auc': 0.99623233, 'auc_precision_recall': 0.9973264, 'average_loss': 0.1722714, 'best_ensemble_index_0': 0, 'iteration': 0, 'label/mean': 0.5701754, 'loss': 0.16755146, 'precision': 1.0, 'prediction/mean': 0.49755728, 'recall': 0.8769231, 'global_step': 20000}
Architecture: b'| linear |'

Zusammenfassung

Ich habe AdaNet gegen Tabellendaten ausprobiert. Ich hatte das Gefühl, dass es ein Bild war, in ein Programm zu schreiben, mit Ausnahme der Deep-Learning-Schicht und des Implementierungsteils des Knotens.

Recommended Posts

Ich habe AdaNet gegen Tabellendaten ausprobiert
Ich habe MLflow auf Databricks ausprobiert
Ich habe Cython unter Ubuntu auf VirtualBox ausprobiert
Ich habe versucht, BigQuery-Daten mit Jupyter Lab mit GCP zu visualisieren
Ich habe versucht, Konversationsdaten von ASKfm zu kratzen
Ich habe versucht, YOUTUBE Data API V3 zu verwenden
Ich habe versucht, Faktoren mit Titanic-Daten zu analysieren!
Ich habe versucht zu kratzen
Ich habe PyQ ausprobiert
Ich habe AutoKeras ausprobiert
Ich habe es mit Papiermühle versucht
Ich habe versucht, Django-Slack
Ich habe es mit Django versucht
Ich habe es mit Spleeter versucht
Ich habe es mit cgo versucht
Ich habe die Pivot-Table-Funktion von Pandas ausprobiert
Ich habe versucht, Remote API mit GAE / J zu verwenden
Ich habe versucht, die Daten mit Zwietracht zu speichern
Ich habe versucht, YOLO v3 mit Google Colab auszuführen
Ich habe versucht, die Hauptkomponenten mit Titanic-Daten zu analysieren!
Ich habe versucht, CloudWatch-Daten mit Python abzurufen
Ich habe versucht, jupyter nteract auf dem Heroku-Server zu starten
[Pythonocc] Ich habe versucht, CAD auf einem Jupyter-Notebook zu verwenden
Ich habe LINE Message API (line-bot-sdk-python) mit GAE ausprobiert
Ich habe DBM mit Pylearn 2 unter Verwendung künstlicher Daten ausprobiert
Ich habe versucht, mit tkinter mit dem Taschenrechner zu spielen
[IBM Cloud] Ich habe versucht, über Cloud Funtions (Python) auf die Tabelle Db2 on Cloud zuzugreifen.
Ich habe versucht, die Daten des Laptops durch Booten unter Ubuntu zu retten
Ich habe versucht, parametrisiert zu verwenden
Ich habe versucht, Argparse zu verwenden
Ich habe versucht, Mimesis zu verwenden
Ich habe versucht, anytree zu verwenden
Ich habe versucht, Pymc auszuführen
Ich habe Python zum ersten Mal auf dem Mac ausprobiert.
Ich habe ARP-Spoofing ausprobiert
Ich habe versucht, die App auf der IoT-Plattform "Rimotte" auszuführen.
Ich habe versucht, Mine Sweeper auf dem Terminal mit Python zu implementieren
Ich habe versucht, aiomysql zu verwenden
Ich habe versucht, Summpy zu verwenden
Ich habe versucht, das Spiel in der J League vorherzusagen (Datenanalyse)
Ich habe Python> autopep8 ausprobiert
Ich habe Python zum ersten Mal mit Heroku ausprobiert
Ich habe versucht, Coturn zu verwenden
Ich habe versucht, Pipenv zu verwenden
Ich habe versucht, Matplotlib zu verwenden
Ich habe versucht, "Anvil" zu verwenden.
Ich habe versucht, Hubot zu verwenden
Ich habe versucht, ESPCN zu verwenden
Ich habe PyCaret2.0 (pycaret-nightly) ausprobiert.
Ich habe versucht, openpyxl zu verwenden
Ich habe einen visuellen Regressionstest auf GitHub Pages versucht
Ich habe versucht, EKG-Daten mit der K-Shape-Methode zu gruppieren
Ich habe versucht, tief zu lernen
Ich habe AWS CDK ausprobiert!
Ich habe versucht, Ipython zu verwenden
Ich habe versucht zu debuggen.
Ich habe versucht, PyCaret zu verwenden
Ich habe versucht, Cron zu verwenden