<commit_before>{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "moGQn-psFggi"
      },
      "source": [
        "##### Copyright 2020 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "cUGG66UTFwJ-"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "YpbnPF_MEv4h"
      },
      "source": [
        "# Model Remediation Case Study\n",
        "\n",
        "\u003cdiv class=\"devsite-table-wrapper\"\u003e\u003ctable class=\"tfo-notebook-buttons\" align=\"left\"\u003e\n",
        "  \u003ctd\u003e\u003ca target=\"_blank\" href=\"https://colab.sandbox.google.com/github/tensorflow/fairness-indicators/blob/master/fairness_indicators/documentation/examples/Fairness_Indicators_Lineage_Case_Study.ipynb\"\u003e\n",
        "  \u003cimg src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" /\u003eView on TensorFlow.org\u003c/a\u003e\n",
        "\u003c/td\u003e\n",
        "\u003ctd\u003e\n",
        "  \u003ca target=\"_blank\" href=\"https://colab.sandbox.google.com/github/tensorflow/tensorflow/model-remediation/blob/master/docs/examples/min_diff_keras.ipynb\"\u003e\n",
        "  \u003cimg src=\"https://www.tensorflow.org/images/colab_logo_32px.png\"\u003eRun in Google Colab\u003c/a\u003e\n",
        "\u003c/td\u003e\n",
        "\u003ctd\u003e\n",
        "  \u003ca target=\"_blank\" href=\"https://github.com/tensorflow/model-remediation\"\u003e\n",
        "  \u003cimg width=32px src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\"\u003eView source on GitHub\u003c/a\u003e\n",
        "\u003c/td\u003e\n",
        "\u003ctd\u003e\n",
        "    \u003ca target=\"_blank\" href=\"https://storage.googleapis.com/tensorflow_docs/docs/examples/min_diff_keras.ipynb\"\u003e\u003cimg src=\"https://www.tensorflow.org/images/download_logo_32px.png\" /\u003eDownload notebook\u003c/a\u003e\n",
        "\u003c/td\u003e\n",
        "\u003c/table\u003e\u003c/div\u003e"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "both",
        "id": "WoA7i_6ShG6Y"
      },
      "outputs": [],
      "source": [
        "#@title Installs\n",
        "#!pip install --upgrade tensorflow-model-remediation\n",
        "#!pip install --upgrade fairness-indicators"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "JYLW8UIsIMrE"
      },
      "outputs": [],
      "source": [
        "#@title Imports\n",
        "import copy\n",
        "import os\n",
        "import requests\n",
        "import tempfile\n",
        "\n",
        "import tensorflow_model_remediation.min_diff as md\n",
        "from google.protobuf import text_format\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "import tensorflow as tf\n",
        "import tensorflow_hub as hub\n",
        "import tensorflow_model_analysis as tfma\n",
        "import tensorflow_data_validation as tfdv\n",
        "from tensorflow_model_analysis.addons.fairness.post_export_metrics import fairness_indicators\n",
        "from tensorflow_model_analysis.addons.fairness.view import widget_view"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "both",
        "id": "Zo3Dkbtsqx-e"
      },
      "outputs": [],
      "source": [
        "#@title Import Util\n",
        "%load -r 16: min_diff_keras_util.py\n",
        "",
        "",
        ""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "both",
        "id": "-Hw5HdppwuBs"
      },
      "outputs": [],
      "source": [
        "#@title Preprocess Data\n",
        "# We use a helper utility to preprocessed data for convenience and speed.\n",
        "data_train, data_validate, validate_tfrecord_file, labels_train, labels_validate = download_and_process_civil_comments_data()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "Ular7EPMU_Y1"
      },
      "outputs": [],
      "source": [
        "#@title Constants\n",
        "TEXT_FEATURE = 'comment_text'\n",
        "LABEL = 'toxicity'\n",
        "BATCH_SIZE = 128"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "taGEqZGB_FWN"
      },
      "outputs": [],
      "source": [
        "#@title Seeds\n",
        "np.random.seed(1)\n",
        "tf.random.set_seed(1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "KcRceFceKyE_"
      },
      "outputs": [],
      "source": [
        "#@title Train Model\n",
        "\n",
        "use_pretrained_model = True #@param {type:\"boolean\"}\n",
        "\n",
        "if use_pretrained_model:\n",
        "  URL = 'https://storage.googleapis.com/civil_comments_model/baseline_model.h5'\n",
        "  FILEPATH = 'baseline_pretrained_model.h5'\n",
        "  r = requests.get(URL, allow_redirects=True)\n",
        "  open(FILEPATH, 'wb').write(r.content)\n",
        "  baseline_model = tf.keras.models.load_model(FILEPATH, custom_objects={'KerasLayer' : hub.KerasLayer})\n",
        "\n",
        "else:\n",
        "  optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)\n",
        "  loss = tf.keras.losses.BinaryCrossentropy(from_logits=True)\n",
        "\n",
        "  baseline_model = create_keras_sequential_model()\n",
        "  \n",
        "  baseline_model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])\n",
        "\n",
        "  baseline_model.fit(x=data_train[TEXT_FEATURE],\n",
        "                     y=labels_train, batch_size=BATCH_SIZE,\n",
        "                     epochs=10)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "DRLTXwDfN6a7"
      },
      "outputs": [],
      "source": [
        "#@title Save Model\n",
        "base_dir = tempfile.mkdtemp(prefix='saved_models')\n",
        "baseline_model_location = os.path.join(base_dir, 'model_export_baseline')\n",
        "baseline_model.save(baseline_model_location, save_format='tf')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "both",
        "id": "4d6CZj2d-jrw"
      },
      "outputs": [],
      "source": [
        "#@title Run Model Analysis\n",
        "\n",
        "# We use a helper utility to hide the evaluation logic for readability.\n",
        "base_dir = tempfile.mkdtemp(prefix='eval') \n",
        "eval_subdir = 'eval_results_baseline'\n",
        "eval_result = get_eval_results(baseline_model_location, base_dir,\n",
        "                               eval_subdir, validate_tfrecord_file)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "ynbJR3Qc-j0D"
      },
      "outputs": [],
      "source": [
        "#@title Render Evaluation Results\n",
        "\n",
        "widget_view.render_fairness_indicator(eval_result)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "jj4dychpyrqM"
      },
      "outputs": [],
      "source": [
        "#@title Create Mindiff DataFrames\n",
        "\n",
        "# Create masks for the sensitive and nonsensitive groups\n",
        "minority_mask = data_train.religion.apply(\n",
        "    lambda x: any(religion in x for religion in \n",
        "                  ('atheist', 'jewish', 'muslim')))\n",
        "majority_mask = data_train.religion.apply(lambda x: x == \"['christian']\")\n",
        "\n",
        "# Select nontoxic examples, so Mindiff will be able to reduce sensitive FP rate.\n",
        "true_negative_mask = data_train['toxicity'] == 0\n",
        "\n",
        "data_train_main = copy.copy(data_train)\n",
        "data_train_sensitive = data_train[minority_mask \u0026 true_negative_mask]\n",
        "data_train_nonsensitive = data_train[majority_mask \u0026 true_negative_mask]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "both",
        "id": "C0DkFMTOuIQT"
      },
      "outputs": [],
      "source": [
        "#@title Create Mindiff Datasets\n",
        "\n",
        "# Convert the pandas DataFrames to Datasets.\n",
        "dataset_train_main = tf.data.Dataset.from_tensor_slices(\n",
        "    (data_train_main['comment_text'].values, \n",
        "     data_train_main.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)\n",
        "dataset_train_sensitive = tf.data.Dataset.from_tensor_slices(\n",
        "    (data_train_sensitive['comment_text'].values, \n",
        "     data_train_sensitive.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)\n",
        "dataset_train_nonsensitive = tf.data.Dataset.from_tensor_slices(\n",
        "    (data_train_nonsensitive['comment_text'].values, \n",
        "     data_train_nonsensitive.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "both",
        "id": "xutVGl9fyikP"
      },
      "outputs": [],
      "source": [
        "#@title Train Model\n",
        "\n",
        "use_pretrained_model = True #@param {type:\"boolean\"}\n",
        "\n",
        "base_dir = tempfile.mkdtemp(prefix='saved_models')\n",
        "min_diff_model_location = os.path.join(base_dir, 'model_export_min_diff')\n",
        "\n",
        "if use_pretrained_model:\n",
        "  URL = 'https://storage.googleapis.com/civil_comments_model/min_diff_model.h5'\n",
        "  FILEPATH = 'min_diff_pretrained_model.h5'\n",
        "  r = requests.get(URL, allow_redirects=True)\n",
        "  open(FILEPATH, 'wb').write(r.content)\n",
        "  min_diff_model = tf.keras.models.load_model(FILEPATH, custom_objects={'KerasLayer' : hub.KerasLayer})\n",
        "  \n",
        "  min_diff_model.save(min_diff_model_location, save_format='tf')\n",
        "\n",
        "else:\n",
        "  # Create the dataset that will be passed to the MinDiffModel during training.\n",
        "  dataset = md.keras.utils.input_utils.pack_min_diff_data(\n",
        "      dataset_train_main, dataset_train_sensitive, dataset_train_nonsensitive)\n",
        "\n",
        "  # Create the original model.\n",
        "  original_model = create_keras_sequential_model()\n",
        "  \n",
        "  # Wrap the original model in a MinDiffModel, passing in one of the min diff\n",
        "  # losses and using a moderately high strength.\n",
        "  min_diff_strength = 1.5\n",
        "  min_diff_loss = md.losses.MMDLoss('gauss') # TODO:  try AbsCorrLoss()\n",
        "  min_diff_model = md.keras.MinDiffModel(original_model, min_diff_loss, min_diff_strength)\n",
        "\n",
        "  # Compile the model normally after wrapping the original model.  Note that\n",
        "  # this means we use the baseline's model's loss here.\n",
        "  optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)\n",
        "  loss = tf.keras.losses.BinaryCrossentropy(from_logits=True)\n",
        "  min_diff_model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])\n",
        "\n",
        "  min_diff_model.fit(dataset, epochs=10)\n",
        "\n",
        "  min_diff_model.save_original_model(min_diff_model_location, save_format='tf')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "both",
        "id": "0CBdOQCH5IR6"
      },
      "outputs": [],
      "source": [
        "#@title Run Model Analysis\n",
        "min_diff_eval_subdir = 'eval_results_min_diff'\n",
        "min_diff_eval_result = get_eval_results(min_diff_model_location, base_dir,\n",
        "                               min_diff_eval_subdir, validate_tfrecord_file)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "A3_PEjYBO3Dq"
      },
      "outputs": [],
      "source": [
        "#@title Render Evaluation Results\n",
        "\n",
        "widget_view.render_fairness_indicator(min_diff_eval_result)"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [
        "moGQn-psFggi"
      ],
      "name": "min_diff_keras.ipynb",
      "provenance": [],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },<commit_msg>internal<commit_after>{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "moGQn-psFggi"
      },
      "source": [
        "##### Copyright 2020 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "cUGG66UTFwJ-"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "YpbnPF_MEv4h"
      },
      "source": [
        "# Model Remediation Case Study\n",
        "\n",
        "\u003cdiv class=\"devsite-table-wrapper\"\u003e\u003ctable class=\"tfo-notebook-buttons\" align=\"left\"\u003e\n",
        "  \u003ctd\u003e\u003ca target=\"_blank\" href=\"https://colab.sandbox.google.com/github/tensorflow/fairness-indicators/blob/master/fairness_indicators/documentation/examples/Fairness_Indicators_Lineage_Case_Study.ipynb\"\u003e\n",
        "  \u003cimg src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" /\u003eView on TensorFlow.org\u003c/a\u003e\n",
        "\u003c/td\u003e\n",
        "\u003ctd\u003e\n",
        "  \u003ca target=\"_blank\" href=\"https://colab.sandbox.google.com/github/tensorflow/tensorflow/model-remediation/blob/master/docs/examples/min_diff_keras.ipynb\"\u003e\n",
        "  \u003cimg src=\"https://www.tensorflow.org/images/colab_logo_32px.png\"\u003eRun in Google Colab\u003c/a\u003e\n",
        "\u003c/td\u003e\n",
        "\u003ctd\u003e\n",
        "  \u003ca target=\"_blank\" href=\"https://github.com/tensorflow/model-remediation\"\u003e\n",
        "  \u003cimg width=32px src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\"\u003eView source on GitHub\u003c/a\u003e\n",
        "\u003c/td\u003e\n",
        "\u003ctd\u003e\n",
        "    \u003ca target=\"_blank\" href=\"https://storage.googleapis.com/tensorflow_docs/docs/examples/min_diff_keras.ipynb\"\u003e\u003cimg src=\"https://www.tensorflow.org/images/download_logo_32px.png\" /\u003eDownload notebook\u003c/a\u003e\n",
        "\u003c/td\u003e\n",
        "\u003c/table\u003e\u003c/div\u003e"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "WoA7i_6ShG6Y"
      },
      "outputs": [],
      "source": [
        "#@title Installs\n",
        "#!pip install --upgrade tensorflow-model-remediation\n",
        "#!pip install --upgrade fairness-indicators"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "JYLW8UIsIMrE"
      },
      "outputs": [],
      "source": [
        "#@title Imports\n",
        "import copy\n",
        "import os\n",
        "import requests\n",
        "import tempfile\n",
        "import zipfile\n",
        "\n",
        "import tensorflow_model_remediation.min_diff as md\n",
        "from google.protobuf import text_format\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "import tensorflow as tf\n",
        "import tensorflow_hub as hub\n",
        "import tensorflow_model_analysis as tfma\n",
        "import tensorflow_data_validation as tfdv\n",
        "from tensorflow_model_analysis.addons.fairness.post_export_metrics import fairness_indicators\n",
        "from tensorflow_model_analysis.addons.fairness.view import widget_view"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "Zo3Dkbtsqx-e"
      },
      "outputs": [],
      "source": [
        "#@title Import Util\n",
        "%load -r 16: min_diff_keras_util.py\n",
        "",
        "",
        ""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "-Hw5HdppwuBs"
      },
      "outputs": [],
      "source": [
        "#@title Preprocess Data\n",
        "# We use a helper utility to preprocessed data for convenience and speed.\n",
        "data_train, data_validate, validate_tfrecord_file, labels_train, labels_validate = download_and_process_civil_comments_data()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "Ular7EPMU_Y1"
      },
      "outputs": [],
      "source": [
        "#@title Constants\n",
        "TEXT_FEATURE = 'comment_text'\n",
        "LABEL = 'toxicity'\n",
        "BATCH_SIZE = 128"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "taGEqZGB_FWN"
      },
      "outputs": [],
      "source": [
        "#@title Seeds\n",
        "np.random.seed(1)\n",
        "tf.random.set_seed(1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "KcRceFceKyE_"
      },
      "outputs": [],
      "source": [
        "#@title Train Model\n",
        "\n",
        "use_pretrained_model = True #@param {type:\"boolean\"}\n",
        "\n",
        "if use_pretrained_model:\n",
        "  URL = 'https://storage.googleapis.com/civil_comments_model/baseline_model.zip'\n",
        "  ZIPPATH = 'baseline_model.zip'\n",
        "  DIRPATH = '/tmp/baseline_model'\n",
        "  r = requests.get(URL, allow_redirects=True)\n",
        "  open(ZIPPATH, 'wb').write(r.content)\n",
        "\n",
        "  with zipfile.ZipFile(ZIPPATH, 'r') as zip_ref:\n",
        "    zip_ref.extractall('')\n",
        "\n",
        "  baseline_model = tf.keras.models.load_model(DIRPATH, custom_objects={'KerasLayer' : hub.KerasLayer})\n",
        "\n",
        "else:\n",
        "  optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)\n",
        "  loss = tf.keras.losses.BinaryCrossentropy(from_logits=True)\n",
        "\n",
        "  baseline_model = create_keras_sequential_model()\n",
        "  \n",
        "  baseline_model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])\n",
        "\n",
        "  baseline_model.fit(x=data_train[TEXT_FEATURE],\n",
        "                     y=labels_train, batch_size=BATCH_SIZE,\n",
        "                     epochs=10)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "DRLTXwDfN6a7"
      },
      "outputs": [],
      "source": [
        "#@title Save Model\n",
        "base_dir = tempfile.mkdtemp(prefix='saved_models')\n",
        "baseline_model_location = os.path.join(base_dir, 'model_export_baseline')\n",
        "baseline_model.save(baseline_model_location, save_format='tf')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "4d6CZj2d-jrw"
      },
      "outputs": [],
      "source": [
        "#@title Run Model Analysis\n",
        "\n",
        "# We use a helper utility to hide the evaluation logic for readability.\n",
        "base_dir = tempfile.mkdtemp(prefix='eval') \n",
        "eval_subdir = 'eval_results_baseline'\n",
        "eval_result = get_eval_results(baseline_model_location, base_dir,\n",
        "                               eval_subdir, validate_tfrecord_file)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "ynbJR3Qc-j0D"
      },
      "outputs": [],
      "source": [
        "#@title Render Evaluation Results\n",
        "\n",
        "widget_view.render_fairness_indicator(eval_result)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "jj4dychpyrqM"
      },
      "outputs": [],
      "source": [
        "#@title Create Mindiff DataFrames\n",
        "\n",
        "# Create masks for the sensitive and nonsensitive groups\n",
        "minority_mask = data_train.religion.apply(\n",
        "    lambda x: any(religion in x for religion in \n",
        "                  ('atheist', 'jewish', 'muslim')))\n",
        "majority_mask = data_train.religion.apply(lambda x: x == \"['christian']\")\n",
        "\n",
        "# Select nontoxic examples, so Mindiff will be able to reduce sensitive FP rate.\n",
        "true_negative_mask = data_train['toxicity'] == 0\n",
        "\n",
        "data_train_main = copy.copy(data_train)\n",
        "data_train_sensitive = data_train[minority_mask \u0026 true_negative_mask]\n",
        "data_train_nonsensitive = data_train[majority_mask \u0026 true_negative_mask]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "C0DkFMTOuIQT"
      },
      "outputs": [],
      "source": [
        "#@title Create Mindiff Datasets\n",
        "\n",
        "# Convert the pandas DataFrames to Datasets.\n",
        "dataset_train_main = tf.data.Dataset.from_tensor_slices(\n",
        "    (data_train_main['comment_text'].values, \n",
        "     data_train_main.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)\n",
        "dataset_train_sensitive = tf.data.Dataset.from_tensor_slices(\n",
        "    (data_train_sensitive['comment_text'].values, \n",
        "     data_train_sensitive.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)\n",
        "dataset_train_nonsensitive = tf.data.Dataset.from_tensor_slices(\n",
        "    (data_train_nonsensitive['comment_text'].values, \n",
        "     data_train_nonsensitive.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "xutVGl9fyikP"
      },
      "outputs": [],
      "source": [
        "#@title Train Model\n",
        "\n",
        "use_pretrained_model = True #@param {type:\"boolean\"}\n",
        "min_diff_strength = 1.5 #@param {type:\"number\"}\n",
        "\n",
        "base_dir = tempfile.mkdtemp(prefix='saved_models')\n",
        "min_diff_model_location = os.path.join(base_dir, 'model_export_min_diff')\n",
        "\n",
        "if use_pretrained_model:\n",
        "  URL = 'https://storage.googleapis.com/civil_comments_model/min_diff_model.zip'\n",
        "  ZIPPATH = 'min_diff_model.zip'\n",
        "  DIRPATH = '/tmp/min_diff_model'\n",
        "  r = requests.get(URL, allow_redirects=True)\n",
        "  open(ZIPPATH, 'wb').write(r.content)\n",
        "\n",
        "  with zipfile.ZipFile(ZIPPATH, 'r') as zip_ref:\n",
        "    zip_ref.extractall('')\n",
        "\n",
        "  min_diff_model = tf.keras.models.load_model(DIRPATH, custom_objects={'KerasLayer' : hub.KerasLayer})\n",
        "  \n",
        "  min_diff_model.save(min_diff_model_location, save_format='tf')\n",
        "\n",
        "else:\n",
        "  # Create the dataset that will be passed to the MinDiffModel during training.\n",
        "  dataset = md.keras.utils.input_utils.pack_min_diff_data(\n",
        "      dataset_train_main, dataset_train_sensitive, dataset_train_nonsensitive)\n",
        "\n",
        "  # Create the original model.\n",
        "  original_model = create_keras_sequential_model()\n",
        "  \n",
        "  # Wrap the original model in a MinDiffModel, passing in one of the min diff\n",
        "  # losses and using a moderately high strength.\n",
        "  min_diff_loss = md.losses.MMDLoss()\n",
        "  min_diff_model = md.keras.MinDiffModel(original_model, min_diff_loss, min_diff_strength)\n",
        "\n",
        "  # Compile the model normally after wrapping the original model.  Note that\n",
        "  # this means we use the baseline's model's loss here.\n",
        "  optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)\n",
        "  loss = tf.keras.losses.BinaryCrossentropy(from_logits=True)\n",
        "  min_diff_model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])\n",
        "\n",
        "  min_diff_model.fit(dataset, epochs=10)\n",
        "\n",
        "  min_diff_model.save_original_model(min_diff_model_location, save_format='tf')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "0CBdOQCH5IR6"
      },
      "outputs": [],
      "source": [
        "#@title Run Model Analysis\n",
        "min_diff_eval_subdir = 'eval_results_min_diff'\n",
        "min_diff_eval_result = util.get_eval_results(min_diff_model_location, base_dir,\n",
        "                                    min_diff_eval_subdir, validate_tfrecord_file,\n",
        "                                    slice_selection='religion')\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "A3_PEjYBO3Dq"
      },
      "outputs": [],
      "source": [
        "#@title Render Evaluation Results\n",
        "\n",
        "widget_view.render_fairness_indicator(min_diff_eval_result)"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [
        "moGQn-psFggi"
      ],
      "name": "min_diff_keras.ipynb",
      "provenance": [],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
{'fraction_non_alphanumeric': 0.162882315020414, 'fraction_numerical': 0.016760977007377695, 'mean_word_length': 2.179209837185472, 'pattern_counts': {'":': 258, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 22, 'lorem ipsum': 0, 'www.': 10, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 13, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '800728', 'n_tokens_mistral': 9979, 'n_tokens_neox': 9592, 'n_words': 1532}