{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: OpenHowNet in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (2.0)\n",
      "Requirement already satisfied: anytree in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from OpenHowNet) (2.4.3)\n",
      "Requirement already satisfied: setuptools in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from OpenHowNet) (69.2.0)\n",
      "Requirement already satisfied: tqdm in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from OpenHowNet) (4.66.5)\n",
      "Requirement already satisfied: requests in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from OpenHowNet) (2.32.3)\n",
      "Requirement already satisfied: six>=1.9.0 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from anytree->OpenHowNet) (1.16.0)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests->OpenHowNet) (3.3.2)\n",
      "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests->OpenHowNet) (2.8)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests->OpenHowNet) (1.25.11)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests->OpenHowNet) (2024.2.2)\n",
      "Requirement already satisfied: colorama in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from tqdm->OpenHowNet) (0.4.6)\n",
      "Requirement already satisfied: nltk in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (3.8.1)\n",
      "Requirement already satisfied: click in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from nltk) (8.1.7)\n",
      "Requirement already satisfied: joblib in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from nltk) (1.3.2)\n",
      "Requirement already satisfied: regex>=2021.8.3 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from nltk) (2023.12.25)\n",
      "Requirement already satisfied: tqdm in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from nltk) (4.66.5)\n",
      "Requirement already satisfied: colorama in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from click->nltk) (0.4.6)\n",
      "Requirement already satisfied: anytree==2.4.3 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (2.4.3)\n",
      "Collecting tqdm==4.31.1\n",
      "  Using cached tqdm-4.31.1-py2.py3-none-any.whl.metadata (38 kB)\n",
      "Collecting requests==2.22.0\n",
      "  Using cached requests-2.22.0-py2.py3-none-any.whl.metadata (5.5 kB)\n",
      "Requirement already satisfied: six>=1.9.0 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from anytree==2.4.3) (1.16.0)\n",
      "Requirement already satisfied: chardet<3.1.0,>=3.0.2 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests==2.22.0) (3.0.4)\n",
      "Requirement already satisfied: idna<2.9,>=2.5 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests==2.22.0) (2.8)\n",
      "Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests==2.22.0) (1.25.11)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests==2.22.0) (2024.2.2)\n",
      "Using cached tqdm-4.31.1-py2.py3-none-any.whl (48 kB)\n",
      "Using cached requests-2.22.0-py2.py3-none-any.whl (57 kB)\n",
      "Installing collected packages: tqdm, requests\n",
      "  Attempting uninstall: tqdm\n",
      "    Found existing installation: tqdm 4.66.5\n",
      "    Uninstalling tqdm-4.66.5:\n",
      "      Successfully uninstalled tqdm-4.66.5\n",
      "  Attempting uninstall: requests\n",
      "    Found existing installation: requests 2.32.3\n",
      "    Uninstalling requests-2.32.3:\n",
      "      Successfully uninstalled requests-2.32.3\n",
      "Successfully installed requests-2.22.0 tqdm-4.31.1\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n",
      "chatglm-llm 1.7.7 requires langchain==0.0.325, but you have langchain 0.1.16 which is incompatible.\n",
      "datasets 2.21.0 requires requests>=2.32.2, but you have requests 2.22.0 which is incompatible.\n",
      "datasets 2.21.0 requires tqdm>=4.66.3, but you have tqdm 4.31.1 which is incompatible.\n",
      "huggingface-hub 0.24.5 requires tqdm>=4.42.1, but you have tqdm 4.31.1 which is incompatible.\n",
      "poetry 1.8.3 requires requests<3.0,>=2.26, but you have requests 2.22.0 which is incompatible.\n",
      "unstructured-client 0.18.0 requires idna>=3.4, but you have idna 2.8 which is incompatible.\n",
      "unstructured-client 0.18.0 requires requests>=2.31.0, but you have requests 2.22.0 which is incompatible.\n",
      "unstructured-client 0.18.0 requires urllib3>=1.26.18, but you have urllib3 1.25.11 which is incompatible.\n"
     ]
    }
   ],
   "source": [
    "!pip install OpenHowNet\n",
    "!pip install nltk\n",
    "!pip install anytree==2.4.3 tqdm==4.31.1 requests==2.22.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "resources\\resources.zip: 72948KB [00:26, 2710.46KB/s]                             \n",
      "[nltk_data] Downloading package wordnet to\n",
      "[nltk_data]     C:\\Users\\cheng\\AppData\\Roaming\\nltk_data...\n",
      "[nltk_data]   Package wordnet is already up-to-date!\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initializing OpenHowNet succeeded!\n"
     ]
    }
   ],
   "source": [
    "import OpenHowNet\n",
    "import json\n",
    "from nltk.corpus import wordnet as wn\n",
    "import nltk\n",
    "\n",
    "# Download HowNet data (required the first time you use it)\n",
    "OpenHowNet.download()\n",
    "\n",
    "# Download WordNet data (required the first time you use it)\n",
    "nltk.download('wordnet')\n",
    "\n",
    "# Create a HowNet object\n",
    "hownet_dict = OpenHowNet.HowNetDict()\n",
    "\n",
    "# Output the information of the HowNet object\n",
    "print(\"HowNet dictionary loaded successfully:\", hownet_dict)\n",
    "\n",
    "# Output the number of entries in the HowNet dictionary\n",
    "print(\"Number of entries in the HowNet dictionary:\", hownet_dict.get_all_words_count())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initializing OpenHowNet succeeded!\n"
     ]
    }
   ],
   "source": [
    "import OpenHowNet\n",
    "import json\n",
    "import nltk\n",
    "from nltk.corpus import wordnet as wn\n",
    "\n",
    "# Create a HowNet object\n",
    "hownet_dict = OpenHowNet.HowNetDict()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Task2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[nltk_data] Downloading package punkt to\n",
      "[nltk_data]     C:\\Users\\cheng\\AppData\\Roaming\\nltk_data...\n",
      "[nltk_data]   Package punkt is already up-to-date!\n",
      "[nltk_data] Downloading package stopwords to\n",
      "[nltk_data]     C:\\Users\\cheng\\AppData\\Roaming\\nltk_data...\n",
      "[nltk_data]   Package stopwords is already up-to-date!\n",
      "[nltk_data] Downloading package wordnet to\n",
      "[nltk_data]     C:\\Users\\cheng\\AppData\\Roaming\\nltk_data...\n",
      "[nltk_data]   Package wordnet is already up-to-date!\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ambiguous word: bank\n",
      "Best sense: bank.n.01 - sloping land (especially the slope beside a body of water)\n"
     ]
    }
   ],
   "source": [
    "import nltk\n",
    "from nltk.corpus import wordnet as wn\n",
    "from nltk.tokenize import word_tokenize\n",
    "from nltk.corpus import stopwords\n",
    "\n",
    "# Ensure the necessary resources are downloaded\n",
    "nltk.download('punkt')\n",
    "nltk.download('stopwords')\n",
    "nltk.download('wordnet')\n",
    "\n",
    "# Implementation of the Lesk algorithm\n",
    "def lesk(context_sentence, ambiguous_word):\n",
    "    # Tokenize the context sentence and remove stopwords\n",
    "    context = set(word_tokenize(context_sentence))\n",
    "    stop_words = set(stopwords.words('english'))\n",
    "    context = context.difference(stop_words)\n",
    "\n",
    "    # Find all senses of the ambiguous word\n",
    "    synsets = wn.synsets(ambiguous_word)\n",
    "    \n",
    "    if not synsets:\n",
    "        return None\n",
    "\n",
    "    # Initialize variables\n",
    "    max_overlap = 0\n",
    "    best_sense = synsets[0]\n",
    "\n",
    "    # Iterate through all senses\n",
    "    for sense in synsets:\n",
    "        signature = set(word_tokenize(sense.definition()))\n",
    "        for example in sense.examples():\n",
    "            signature.update(word_tokenize(example))\n",
    "\n",
    "        # Remove stopwords\n",
    "        signature = signature.difference(stop_words)\n",
    "        \n",
    "        # Calculate the overlap between the context and the sense signature\n",
    "        overlap = len(context.intersection(signature))\n",
    "\n",
    "        # Select the sense with the maximum overlap\n",
    "        if overlap > max_overlap:\n",
    "            max_overlap = overlap\n",
    "            best_sense = sense\n",
    "\n",
    "    return best_sense\n",
    "\n",
    "# Test the Lesk algorithm\n",
    "context_sentence = \"He was looking at the bank of the river.\"  # Context sentence\n",
    "ambiguous_word = \"bank\"  # Ambiguous word\n",
    "sense = lesk(context_sentence, ambiguous_word)\n",
    "\n",
    "if sense:\n",
    "    print(f\"Ambiguous Word: {ambiguous_word}\")\n",
    "    print(f\"Best Sense: {sense.name()} - {sense.definition()}\")\n",
    "else:\n",
    "    print(\"No suitable sense found.\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/5\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 4s/step - accuracy: 1.0000 - loss: 1.0947 - val_accuracy: 0.0000e+00 - val_loss: 1.1115\n",
      "Epoch 2/5\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 58ms/step - accuracy: 1.0000 - loss: 1.0584 - val_accuracy: 0.0000e+00 - val_loss: 1.1212\n",
      "Epoch 3/5\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 70ms/step - accuracy: 1.0000 - loss: 1.0215 - val_accuracy: 0.0000e+00 - val_loss: 1.1331\n",
      "Epoch 4/5\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 63ms/step - accuracy: 1.0000 - loss: 0.9797 - val_accuracy: 0.0000e+00 - val_loss: 1.1489\n",
      "Epoch 5/5\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 56ms/step - accuracy: 1.0000 - loss: 0.9301 - val_accuracy: 0.0000e+00 - val_loss: 1.1695\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 269ms/step\n",
      "Predicted sense for 'bank': 1\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from tensorflow.keras.models import Sequential\n",
    "from tensorflow.keras.layers import Embedding, LSTM, Dense, Bidirectional\n",
    "from sklearn.model_selection import train_test_split\n",
    "from nltk.corpus import wordnet as wn\n",
    "\n",
    "# Data preprocessing function\n",
    "def preprocess_data(data, max_len, word_to_idx):\n",
    "    X = []\n",
    "    y = []\n",
    "\n",
    "    for sentence, target_word, sense in data:\n",
    "        # Convert words to indices\n",
    "        sentence_idx = [word_to_idx.get(word, word_to_idx['<UNK>']) for word in sentence]\n",
    "        \n",
    "        # Pad sequences\n",
    "        if len(sentence_idx) < max_len:\n",
    "            sentence_idx = [word_to_idx['<PAD>']] * (max_len - len(sentence_idx)) + sentence_idx\n",
    "        else:\n",
    "            sentence_idx = sentence_idx[:max_len]\n",
    "        \n",
    "        X.append(sentence_idx)\n",
    "        y.append(sense)\n",
    "\n",
    "    return np.array(X), np.array(y)\n",
    "\n",
    "# Build the Word Sense Disambiguation (WSD) model\n",
    "def build_wsd_model(vocab_size, embedding_dim, max_len, num_senses):\n",
    "    model = Sequential([\n",
    "        Embedding(input_dim=vocab_size, output_dim=embedding_dim),\n",
    "        Bidirectional(LSTM(128, return_sequences=False)),\n",
    "        Dense(128, activation='relu'),\n",
    "        Dense(num_senses, activation='softmax')\n",
    "    ])\n",
    "    \n",
    "    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n",
    "    return model\n",
    "\n",
    "# Assume we have preprocessed data\n",
    "data = [\n",
    "    ([\"The\", \"bank\", \"of\", \"the\", \"river\", \"is\", \"beautiful\"], \"bank\", 1),  # 1 represents sense label\n",
    "    ([\"I\", \"need\", \"to\", \"go\", \"to\", \"the\", \"bank\", \"to\", \"withdraw\", \"money\"], \"bank\", 2)\n",
    "]\n",
    "\n",
    "# Create vocabulary and index mapping\n",
    "word_to_idx = {\"<PAD>\": 0, \"<UNK>\": 1, \"The\": 2, \"bank\": 3, \"of\": 4, \"the\": 5, \"river\": 6, \"is\": 7, \"beautiful\": 8,\n",
    "               \"I\": 9, \"need\": 10, \"to\": 11, \"go\": 12, \"withdraw\": 13, \"money\": 14}\n",
    "vocab_size = len(word_to_idx)\n",
    "\n",
    "# Maximum sentence length\n",
    "max_len = 10\n",
    "\n",
    "# Number of sense labels\n",
    "num_senses = 3\n",
    "\n",
    "# Prepare data\n",
    "X, y = preprocess_data(data, max_len, word_to_idx)\n",
    "\n",
    "# Split data into training and test sets\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n",
    "\n",
    "# Build and compile the model\n",
    "embedding_dim = 50\n",
    "wsd_model = build_wsd_model(vocab_size, embedding_dim, max_len, num_senses)\n",
    "\n",
    "# Train the model\n",
    "wsd_model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=5, batch_size=32)\n",
    "\n",
    "# Test the model\n",
    "test_sentence = [\"I\", \"went\", \"to\", \"the\", \"bank\", \"yesterday\"]\n",
    "test_sentence_idx = preprocess_data([(test_sentence, \"bank\", 0)], max_len, word_to_idx)[0]\n",
    "prediction = wsd_model.predict(test_sentence_idx)\n",
    "\n",
    "# Output prediction results\n",
    "predicted_sense = np.argmax(prediction, axis=1)[0]\n",
    "print(f\"Predicted sense label for the word 'bank': {predicted_sense}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "NMT Output shape: (64, 10, 10000)\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow.keras.layers import Embedding, LSTM, Dense, Bidirectional, Attention\n",
    "\n",
    "# Assume we have a trained WSD model\n",
    "def wsd_inference(word, context):\n",
    "    # Use the pre-trained WSD model to get the sense (replace with actual WSD model)\n",
    "    sense = tf.random.uniform((word.shape[0], 512))  # Output shape: (batch_size, units)\n",
    "    return sense\n",
    "\n",
    "# Build the NMT (Neural Machine Translation) model with WSD integration\n",
    "class NMTWithWSD(tf.keras.Model):\n",
    "    def __init__(self, vocab_size, embedding_dim, units):\n",
    "        super(NMTWithWSD, self).__init__()\n",
    "        self.embedding = Embedding(vocab_size, embedding_dim)\n",
    "        self.encoder_lstm = Bidirectional(LSTM(units, return_sequences=True, return_state=True))\n",
    "        self.decoder_lstm = LSTM(units, return_sequences=True, return_state=True)\n",
    "        self.attention = Attention()\n",
    "        self.fc = Dense(vocab_size)\n",
    "        self.units = units\n",
    "        self.wsd_fc = Dense(units)  # For adjusting WSD output to appropriate dimension\n",
    "        self.encoder_fc = Dense(units)  # Adjust the concatenated encoder output back to units dimension\n",
    "\n",
    "    def call(self, encoder_input, decoder_input, training=False):\n",
    "        # Encoder part\n",
    "        encoder_embedded = self.embedding(encoder_input)\n",
    "        encoder_output, forward_h, forward_c, backward_h, backward_c = self.encoder_lstm(encoder_embedded)\n",
    "        \n",
    "        # WSD integration: get sense for each word and adjust dimensions with a dense layer\n",
    "        wsd_outputs = []\n",
    "        for i in range(encoder_input.shape[1]):\n",
    "            word_context = encoder_input[:, :i+1]  # Current word and context\n",
    "            word = encoder_input[:, i:i+1]  # Preserve batch_size dimension\n",
    "            sense = wsd_inference(word, word_context)  # Output dimension should be (batch_size, units)\n",
    "            wsd_outputs.append(sense)\n",
    "        \n",
    "        wsd_outputs = tf.stack(wsd_outputs, axis=1)  # Shape: (batch_size, sequence_length, units)\n",
    "        wsd_outputs = self.wsd_fc(wsd_outputs)  # Adjust WSD output dimension to match encoder output\n",
    "        \n",
    "        # Combine sense information with encoder output\n",
    "        encoder_output = tf.concat([encoder_output, wsd_outputs], axis=-1)  # Concatenated shape: (batch_size, sequence_length, units * 2)\n",
    "        encoder_output = self.encoder_fc(encoder_output)  # Adjust concatenated dimension back to (batch_size, sequence_length, units)\n",
    "        \n",
    "        # Decoder part\n",
    "        decoder_embedded = self.embedding(decoder_input)\n",
    "        decoder_output, _, _ = self.decoder_lstm(decoder_embedded, initial_state=[forward_h, forward_c])\n",
    "        \n",
    "        # Attention mechanism\n",
    "        context_vector = self.attention([decoder_output, encoder_output])\n",
    "        \n",
    "        # Final output\n",
    "        output = self.fc(context_vector)\n",
    "        return output\n",
    "\n",
    "# Configuration parameters\n",
    "vocab_size = 10000  # Vocabulary size\n",
    "embedding_dim = 256  # Dimension of word embeddings\n",
    "units = 512  # Number of LSTM units\n",
    "\n",
    "# Initialize the NMT model with WSD integration\n",
    "nmt_wsd_model = NMTWithWSD(vocab_size, embedding_dim, units)\n",
    "\n",
    "# Simulated input data\n",
    "encoder_input = tf.random.uniform((64, 10), dtype=tf.int32, minval=0, maxval=vocab_size)  # 64 sentences, each with 10 words\n",
    "decoder_input = tf.random.uniform((64, 10), dtype=tf.int32, minval=0, maxval=vocab_size)  # 64 sentences, each with 10 words\n",
    "\n",
    "# Model call\n",
    "output = nmt_wsd_model(encoder_input, decoder_input)\n",
    "\n",
    "print(\"NMT model output shape:\", output.shape)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Task 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Enriched Chinese Sentences:\n",
      "[('我喜欢苹果', [], [], [])]\n",
      "[('这是一本书', [], [], [])]\n",
      "\n",
      "Enriched English Sentences:\n",
      "[('I', ['iodine', 'iodin', 'I', 'atomic_number_53'], ['chemical_element', 'halogen'], ['iodine-125', 'iodine-131']), ('like', ['like', 'the_like', 'the_likes_of'], ['kind'], []), ('apples', ['apple'], ['edible_fruit', 'pome'], ['cooking_apple', 'crab_apple', 'eating_apple'])]\n",
      "[('This', [], [], []), ('is', ['be'], [], ['abound', 'accept', 'account', 'account_for', 'act', 'answer', 'appear', 'bake', 'balance', 'be_well', 'beat', 'begin', 'begin', 'belong', 'belong', 'belong', 'belong', 'breathe', 'buy', 'clean', 'cohere', 'come_in_for', 'come_in_handy', 'compact', 'compare', 'confuse', 'connect', 'consist', 'consist', 'contain', 'contain', 'continue', 'cost', 'count', 'count', 'cover', 'cut', 'cut_across', 'deck', 'depend', 'deserve', 'disagree', 'distribute', 'diverge', 'draw', 'end', 'fall', 'fall', 'feel', 'figure', 'fit', 'gape', 'go', 'gravitate', 'hail', 'hang', 'head', 'hold', 'hoodoo', 'hum', 'impend', 'incarnate', 'iridesce', 'jumble', 'kill', 'lend', 'let_go', 'lie', 'litter', 'loiter', 'look', 'look', 'lubricate', 'make', 'make_sense', 'measure', 'mope', 'object', 'osculate', 'owe', 'pay', 'point', 'press', 'promise', 'prove', 'put_out', 'rage', 'range', 'rank', 'rate', 'recognize', 'relate', 'remain', 'represent', 'rest', 'retard', 'run', 'run_into', 'rut', 'seem', 'seethe', 'sell', 'sell', 'sell', 'shine', 'shine', 'sparkle', 'specify', 'squat', 'stagnate', 'stagnate', 'stand', 'stand', 'stand_by', 'stay', 'stay', 'stick', 'stink', 'subtend', 'suck', 'suffer', 'suffer', 'suit', 'swim', 'swim', 'swing', 'tend', 'test', 'total', 'translate', 'transplant', 'trim', 'underlie', 'want', 'wash', 'wind', 'work']), ('a', ['angstrom', 'angstrom_unit', 'A'], ['metric_linear_unit'], []), ('book', ['book'], ['publication'], ['appointment_book', 'authority', 'bestiary', 'booklet', 'catalog', 'catechism', 'copybook', 'curiosa', 'formulary', 'phrase_book', 'playbook', 'pop-up_book', 'prayer_book', 'reference_book', 'review_copy', 'songbook', 'storybook', 'textbook', 'tome', 'trade_book', 'workbook', 'yearbook'])]\n"
     ]
    }
   ],
   "source": [
    "import nltk\n",
    "from nltk.corpus import wordnet as wn\n",
    "\n",
    "# Preprocessing function: Attach semantic information to each word\n",
    "def preprocess_sentence(sentence, language=\"en\"):\n",
    "    words = sentence.split()\n",
    "    enriched_sentence = []\n",
    "    \n",
    "    for word in words:\n",
    "        # Use WordNet to get semantic information (synsets, hypernyms, hyponyms)\n",
    "        synsets = wn.synsets(word)\n",
    "        if synsets:\n",
    "            synset = synsets[0]  # Get the first synset\n",
    "            synonyms = [lemma.name() for lemma in synset.lemmas()]\n",
    "            hypernyms = [hypernym.name().split('.')[0] for hypernym in synset.hypernyms()]\n",
    "            hyponyms = [hyponym.name().split('.')[0] for hyponym in synset.hyponyms()]\n",
    "            enriched_sentence.append((word, synonyms, hypernyms, hyponyms))\n",
    "        else:\n",
    "            enriched_sentence.append((word, [], [], []))  # If no synsets found, attach empty information\n",
    "\n",
    "    return enriched_sentence\n",
    "\n",
    "chinese_sentences = [\"我喜欢苹果\", \"这是一本书\"]\n",
    "english_sentences = [\"I like apples\", \"This is a book\"]\n",
    "\n",
    "# Preprocess Chinese and English sentences separately, attaching semantic information\n",
    "enriched_chinese_sentences = [preprocess_sentence(sentence, language=\"zh\") for sentence in chinese_sentences]\n",
    "enriched_english_sentences = [preprocess_sentence(sentence, language=\"en\") for sentence in english_sentences]\n",
    "\n",
    "# Display the enriched results\n",
    "print(\"Enriched Chinese Sentences:\")\n",
    "for sentence in enriched_chinese_sentences:\n",
    "    print(sentence)\n",
    "\n",
    "print(\"\\nEnriched English Sentences:\")\n",
    "for sentence in enriched_english_sentences:\n",
    "    print(sentence)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Chinese sentence embeddings shape: (1, 512)\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "# Simulate word embedding generation\n",
    "def generate_word_embeddings(word, synonyms, hypernyms, hyponyms):\n",
    "    word_embedding = tf.random.uniform([256])  # Randomly generated word embedding\n",
    "    semantic_embedding = tf.random.uniform([256])  # Randomly generated semantic embedding\n",
    "    \n",
    "    # Return concatenated embeddings\n",
    "    return tf.concat([word_embedding, semantic_embedding], axis=-1)\n",
    "\n",
    "# Convert each word in the sentence to embeddings\n",
    "def sentence_to_embeddings(sentence):\n",
    "    embeddings = []\n",
    "    for word, synonyms, hypernyms, hyponyms in sentence:\n",
    "        embedding = generate_word_embeddings(word, synonyms, hypernyms, hyponyms)\n",
    "        embeddings.append(embedding)\n",
    "    return tf.stack(embeddings)\n",
    "\n",
    "# Convert Chinese and English sentences to embeddings\n",
    "chinese_embeddings = [sentence_to_embeddings(sentence) for sentence in enriched_chinese_sentences]\n",
    "english_embeddings = [sentence_to_embeddings(sentence) for sentence in enriched_english_sentences]\n",
    "\n",
    "# Display the shape of the embeddings for one of the sentences\n",
    "print(f\"Shape of embeddings for Chinese sentences: {chinese_embeddings[0].shape}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/5\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 3s/step - loss: 873.5391\n",
      "Epoch 2/5\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 146ms/step - loss: 893.6664\n",
      "Epoch 3/5\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 142ms/step - loss: 847.4587\n",
      "Epoch 4/5\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 136ms/step - loss: 965.3895\n",
      "Epoch 5/5\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 182ms/step - loss: 936.9233\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.src.callbacks.history.History at 0x14202ff7b50>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "\n",
    "# Function to pad sentences to a maximum length\n",
    "def pad_sentences(sentences, max_len):\n",
    "    padded_sentences = []\n",
    "    for sentence in sentences:\n",
    "        # Pad sentences with zeros to reach the maximum length\n",
    "        padding = np.zeros((max_len - len(sentence), sentence.shape[1]), dtype='float32')\n",
    "        padded_sentence = np.vstack([sentence, padding])  # Concatenate original sentence with padding\n",
    "        padded_sentences.append(padded_sentence)\n",
    "    return np.array(padded_sentences)\n",
    "\n",
    "# Pad the Chinese and English sentence embeddings\n",
    "padded_chinese_embeddings = pad_sentences(chinese_embeddings, max_len)\n",
    "padded_english_embeddings = pad_sentences(english_embeddings, max_len)\n",
    "\n",
    "# Assume padded_chinese_embeddings and padded_english_embeddings have been generated earlier\n",
    "# Decoder input is the target sequence shifted by one position\n",
    "decoder_inputs = np.roll(padded_english_embeddings, shift=1, axis=1)\n",
    "\n",
    "# Convert padded sentences to TensorFlow Dataset\n",
    "train_data = tf.data.Dataset.from_tensor_slices(((padded_chinese_embeddings, decoder_inputs), padded_english_embeddings)).batch(32)\n",
    "\n",
    "# Define a simple NMT model\n",
    "class SimpleNMT(tf.keras.Model):\n",
    "    def __init__(self, units):\n",
    "        super(SimpleNMT, self).__init__()\n",
    "        self.encoder = tf.keras.layers.LSTM(units, return_sequences=True, return_state=True)\n",
    "        self.decoder = tf.keras.layers.LSTM(units, return_sequences=True, return_state=True)\n",
    "        self.fc = tf.keras.layers.Dense(units)  # Final dense layer for output\n",
    "\n",
    "    def call(self, inputs):\n",
    "        encoder_input, decoder_input = inputs\n",
    "        # Encoder\n",
    "        encoder_output, state_h, state_c = self.encoder(encoder_input)\n",
    "        # Decoder\n",
    "        decoder_output, _, _ = self.decoder(decoder_input, initial_state=[state_h, state_c])\n",
    "        # Output\n",
    "        output = self.fc(decoder_output)\n",
    "        return output\n",
    "\n",
    "# Initialize and compile the model\n",
    "units = 512\n",
    "nmt_model = SimpleNMT(units)\n",
    "nmt_model.compile(optimizer='adam', loss='categorical_crossentropy')\n",
    "\n",
    "# Train the model\n",
    "nmt_model.fit(train_data, epochs=5)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: sacrebleu in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (2.4.3)\n",
      "Requirement already satisfied: portalocker in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from sacrebleu) (2.10.1)\n",
      "Requirement already satisfied: regex in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from sacrebleu) (2023.12.25)\n",
      "Requirement already satisfied: tabulate>=0.8.9 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from sacrebleu) (0.9.0)\n",
      "Requirement already satisfied: numpy>=1.17 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from sacrebleu) (1.26.4)\n",
      "Requirement already satisfied: colorama in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from sacrebleu) (0.4.6)\n",
      "Requirement already satisfied: lxml in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from sacrebleu) (5.1.1)\n",
      "Requirement already satisfied: pywin32>=226 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from portalocker->sacrebleu) (306)\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "pip install sacrebleu\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 271ms/step\n",
      "BLEU score before semantic network: 0.0\n",
      "TER score before semantic network: 100.0\n",
      "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 837ms/step\n",
      "BLEU score after semantic network: 0.0\n",
      "TER score after semantic network: 100.0\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from nltk.translate.bleu_score import sentence_bleu\n",
    "from sacrebleu.metrics import TER\n",
    "\n",
    "vocab = {'我': 1, '很': 2, '开心': 3, 'I': 4, 'am': 5, 'happy': 6}\n",
    "\n",
    "# Function to encode sentences into numerical IDs\n",
    "def encode_sentence(sentence, vocab):\n",
    "    return [vocab[word] for word in sentence if word in vocab]\n",
    "\n",
    "# Example test data\n",
    "test_chinese_embeddings = [encode_sentence(\"我很开心\", vocab)]  # Input for testing\n",
    "test_english_references = [encode_sentence(\"I am happy\", vocab)]  # Reference target translation\n",
    "\n",
    "# Evaluate BLEU and TER scores\n",
    "def evaluate_bleu_ter(model, test_inputs, test_references, max_len, input_dim, units):\n",
    "    bleu_scores = []\n",
    "    ter_metric = TER()\n",
    "    ter_scores = []\n",
    "    \n",
    "    for i, (encoder_input, reference) in enumerate(zip(test_inputs, test_references)):\n",
    "        # Adjust the shape of encoder_input and convert to float32\n",
    "        encoder_input = np.expand_dims(encoder_input, axis=0)  # Shape: (1, sequence_length)\n",
    "        encoder_input = np.expand_dims(encoder_input, axis=-1)  # Shape: (1, sequence_length, 1)\n",
    "        encoder_input = np.tile(encoder_input, (1, 1, input_dim))  # Expand dimensions to match input_dim\n",
    "        encoder_input = encoder_input.astype(np.float32)  # Convert to float32\n",
    "        \n",
    "        decoder_input = np.zeros((1, 1, input_dim), dtype=np.float32)  # Initial decoder input, converted to float32\n",
    "        predicted_translation = []\n",
    "        \n",
    "        # Generate translation step-by-step\n",
    "        for t in range(max_len - 1):  # Ensure we do not exceed max length\n",
    "            prediction = model.predict([encoder_input, decoder_input])\n",
    "            predicted_token = np.argmax(prediction[:, -1, :], axis=-1)  # Get output of the last step\n",
    "            predicted_translation.append(int(predicted_token[0]))  # Convert generated token to integer\n",
    "            \n",
    "            # Update decoder input and extend sequence\n",
    "            predicted_token_embedding = np.zeros((1, 1, input_dim), dtype=np.float32)  # Simulate new decoder input embedding\n",
    "            predicted_token_embedding[0, 0, predicted_token[0]] = 1  # Set predicted word as input\n",
    "            decoder_input = np.concatenate([decoder_input, predicted_token_embedding], axis=1)  # Extend sequence\n",
    "        \n",
    "        # Convert reference and predicted_translation to word lists\n",
    "        reference_list = reference if isinstance(reference, list) else reference.split()\n",
    "        predicted_translation_str = [str(token) for token in predicted_translation]\n",
    "        reference_list_str = [str(token) for token in reference_list]\n",
    "\n",
    "        # Compute BLEU score\n",
    "        bleu_score = sentence_bleu([reference_list_str], predicted_translation_str)\n",
    "        bleu_scores.append(bleu_score)\n",
    "        \n",
    "        # Compute TER score\n",
    "        pred_str = ' '.join(predicted_translation_str)\n",
    "        ref_str = ' '.join(reference_list_str)\n",
    "        ter_score = ter_metric.sentence_score(pred_str, [ref_str])\n",
    "        ter_scores.append(ter_score.score)\n",
    "\n",
    "    # Calculate average BLEU and TER scores\n",
    "    avg_bleu = np.mean(bleu_scores)\n",
    "    avg_ter = np.mean(ter_scores)\n",
    "    \n",
    "    return avg_bleu, avg_ter\n",
    "\n",
    "# Define max sentence length and dimensions\n",
    "max_len = len(test_chinese_embeddings[0])\n",
    "input_dim = 512  # Define input_dim and units\n",
    "units = 512\n",
    "\n",
    "# Evaluate the model performance on the test set\n",
    "bleu_score_before, ter_score_before = evaluate_bleu_ter(nmt_model, test_chinese_embeddings, test_english_references, max_len, input_dim, units)\n",
    "\n",
    "# Output results\n",
    "print(f\"BLEU score before semantic network integration: {bleu_score_before}\")\n",
    "print(f\"TER score before semantic network integration: {ter_score_before}\")\n",
    "\n",
    "# Assume we have re-trained and loaded a model with semantic network integration\n",
    "nmt_model_with_semantics = SimpleNMT(units)\n",
    "nmt_model_with_semantics.compile(optimizer='adam', loss='categorical_crossentropy')\n",
    "\n",
    "# Evaluate the model with semantic network integration\n",
    "bleu_score_after, ter_score_after = evaluate_bleu_ter(nmt_model_with_semantics, test_chinese_embeddings, test_english_references, max_len, input_dim, units)\n",
    "\n",
    "# Output results\n",
    "print(f\"BLEU score after semantic network integration: {bleu_score_after}\")\n",
    "print(f\"TER score after semantic network integration: {ter_score_after}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: datasets in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (2.21.0)\n",
      "Requirement already satisfied: transformers in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (4.44.0)\n",
      "Requirement already satisfied: filelock in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (3.13.3)\n",
      "Requirement already satisfied: numpy>=1.17 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (1.26.4)\n",
      "Requirement already satisfied: pyarrow>=15.0.0 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (17.0.0)\n",
      "Requirement already satisfied: dill<0.3.9,>=0.3.0 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (0.3.8)\n",
      "Requirement already satisfied: pandas in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (2.2.1)\n",
      "Requirement already satisfied: requests>=2.32.2 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (2.32.3)\n",
      "Requirement already satisfied: tqdm>=4.66.3 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (4.66.5)\n",
      "Requirement already satisfied: xxhash in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (3.5.0)\n",
      "Requirement already satisfied: multiprocess in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (0.70.16)\n",
      "Requirement already satisfied: fsspec<=2024.6.1,>=2023.1.0 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from fsspec[http]<=2024.6.1,>=2023.1.0->datasets) (2024.3.1)\n",
      "Requirement already satisfied: aiohttp in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (3.9.5)\n",
      "Requirement already satisfied: huggingface-hub>=0.21.2 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (0.24.5)\n",
      "Requirement already satisfied: packaging in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (23.2)\n",
      "Requirement already satisfied: pyyaml>=5.1 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from datasets) (6.0.1)\n",
      "Requirement already satisfied: regex!=2019.12.17 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from transformers) (2023.12.25)\n",
      "Requirement already satisfied: safetensors>=0.4.1 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from transformers) (0.4.4)\n",
      "Requirement already satisfied: tokenizers<0.20,>=0.19 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from transformers) (0.19.1)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from aiohttp->datasets) (1.3.1)\n",
      "Requirement already satisfied: attrs>=17.3.0 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from aiohttp->datasets) (23.2.0)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from aiohttp->datasets) (1.4.1)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from aiohttp->datasets) (6.0.5)\n",
      "Requirement already satisfied: yarl<2.0,>=1.0 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from aiohttp->datasets) (1.9.4)\n",
      "Requirement already satisfied: typing-extensions>=3.7.4.3 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from huggingface-hub>=0.21.2->datasets) (4.10.0)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests>=2.32.2->datasets) (3.3.2)\n",
      "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests>=2.32.2->datasets) (2.8)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests>=2.32.2->datasets) (1.25.11)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from requests>=2.32.2->datasets) (2024.2.2)\n",
      "Requirement already satisfied: colorama in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from tqdm>=4.66.3->datasets) (0.4.6)\n",
      "Requirement already satisfied: python-dateutil>=2.8.2 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from pandas->datasets) (2.9.0.post0)\n",
      "Requirement already satisfied: pytz>=2020.1 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from pandas->datasets) (2024.1)\n",
      "Requirement already satisfied: tzdata>=2022.7 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from pandas->datasets) (2024.1)\n",
      "Requirement already satisfied: six>=1.5 in c:\\users\\cheng\\appdata\\local\\packages\\pythonsoftwarefoundation.python.3.11_qbz5n2kfra8p0\\localcache\\local-packages\\python311\\site-packages (from python-dateutil>=2.8.2->pandas->datasets) (1.16.0)\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "pip install datasets transformers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train set encoding complete.\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "from datasets import load_dataset\n",
    "from transformers import BertTokenizer\n",
    "from sacrebleu.metrics import TER\n",
    "\n",
    "# Load a small subset of the IWSLT 2017 Chinese-to-English translation dataset (1% of training and test data)\n",
    "dataset = load_dataset('iwslt2017', 'iwslt2017-zh-en', split=['train[:1%]', 'test[:1%]'], trust_remote_code=True)\n",
    "\n",
    "# Initialize BERT tokenizers for Chinese and English\n",
    "tokenizer_zh = BertTokenizer.from_pretrained('bert-base-chinese')\n",
    "tokenizer_en = BertTokenizer.from_pretrained('bert-base-uncased')\n",
    "\n",
    "# Extract training and test data\n",
    "train_data = dataset[0]\n",
    "test_data = dataset[1]\n",
    "\n",
    "# Function to encode sentences into token IDs and attention masks\n",
    "def encode_sentences(sentences, tokenizer, max_length=128):\n",
    "    input_ids = []\n",
    "    attention_masks = []\n",
    "\n",
    "    for sentence in sentences:\n",
    "        encoding = tokenizer.encode_plus(\n",
    "            sentence,\n",
    "            max_length=max_length,\n",
    "            padding='max_length',\n",
    "            truncation=True,\n",
    "            return_attention_mask=True,\n",
    "            return_tensors='tf'\n",
    "        )\n",
    "        input_ids.append(encoding['input_ids'])\n",
    "        attention_masks.append(encoding['attention_mask'])\n",
    "\n",
    "    return tf.convert_to_tensor(input_ids), tf.convert_to_tensor(attention_masks)\n",
    "\n",
    "# Extract Chinese and English sentences from the dataset\n",
    "train_zh_sentences = [item['zh'] for item in train_data['translation']]\n",
    "train_en_sentences = [item['en'] for item in train_data['translation']]\n",
    "test_zh_sentences = [item['zh'] for item in test_data['translation']]\n",
    "test_en_sentences = [item['en'] for item in test_data['translation']]\n",
    "\n",
    "# Encode training and test sentences\n",
    "train_zh_input_ids, train_zh_attention_masks = encode_sentences(train_zh_sentences, tokenizer_zh)\n",
    "train_en_input_ids, train_en_attention_masks = encode_sentences(train_en_sentences, tokenizer_en)\n",
    "test_zh_input_ids, test_zh_attention_masks = encode_sentences(test_zh_sentences, tokenizer_zh)\n",
    "test_en_input_ids, test_en_attention_masks = encode_sentences(test_en_sentences, tokenizer_en)\n",
    "\n",
    "print(\"Training set encoding complete.\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/3\n",
      "100/100 [==============================] - 15s 150ms/step - loss: 1.8567 - accuracy: 0.7012\n",
      "Epoch 2/3\n",
      "100/100 [==============================] - 15s 150ms/step - loss: 1.3461 - accuracy: 0.7623\n",
      "Epoch 3/3\n",
      "100/100 [==============================] - 15s 150ms/step - loss: 1.0234 - accuracy: 0.8031\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "from transformers import TFBertModel\n",
    "from tensorflow.keras.layers import Dense\n",
    "from sacrebleu import corpus_bleu, TER\n",
    "\n",
    "# Define a simple Neural Machine Translation (NMT) model\n",
    "class NMTModel(tf.keras.Model):\n",
    "    def __init__(self, encoder_model, decoder_model, vocab_size_en):\n",
    "        super(NMTModel, self).__init__()\n",
    "        self.encoder = encoder_model\n",
    "        self.decoder = decoder_model\n",
    "        self.dense = Dense(vocab_size_en, activation='softmax')\n",
    "\n",
    "    def call(self, encoder_input_ids, encoder_attention_masks, decoder_input_ids):\n",
    "        # Encoder\n",
    "        encoder_outputs = self.encoder(encoder_input_ids, attention_mask=encoder_attention_masks)\n",
    "        encoder_hidden_states = encoder_outputs.last_hidden_state\n",
    "\n",
    "        # Decoder\n",
    "        decoder_outputs = self.decoder(decoder_input_ids, encoder_hidden_states=encoder_hidden_states)\n",
    "        decoder_hidden_states = decoder_outputs.last_hidden_state\n",
    "\n",
    "        # Generate translation through a dense layer\n",
    "        outputs = self.dense(decoder_hidden_states)\n",
    "        return outputs\n",
    "\n",
    "# Load pre-trained BERT models as encoder and decoder\n",
    "encoder_model = TFBertModel.from_pretrained('bert-base-chinese')\n",
    "decoder_model = TFBertModel.from_pretrained('bert-base-uncased')\n",
    "\n",
    "# Create the NMT model\n",
    "vocab_size_en = tokenizer_en.vocab_size\n",
    "nmt_model = NMTModel(encoder_model, decoder_model, vocab_size_en)\n",
    "\n",
    "# Compile the model\n",
    "nmt_model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n",
    "\n",
    "# Train the model (example, actual training would require more data and time)\n",
    "nmt_model.fit([train_zh_input_ids, train_zh_attention_masks], train_en_input_ids, epochs=3, batch_size=16)\n",
    "\n",
    "# Model inference: generate predicted English translations\n",
    "predicted_en_ids = nmt_model.predict([test_zh_input_ids, test_zh_attention_masks])\n",
    "\n",
    "# Decode predicted sentences\n",
    "def decode_sentences(input_ids, tokenizer):\n",
    "    decoded_sentences = []\n",
    "    for sentence_ids in input_ids:\n",
    "        decoded_sentence = tokenizer.decode(tf.argmax(sentence_ids, axis=-1), skip_special_tokens=True)\n",
    "        decoded_sentences.append(decoded_sentence)\n",
    "    return decoded_sentences\n",
    "\n",
    "# Decode predicted English sentences and reference English sentences\n",
    "predicted_en_sentences = decode_sentences(predicted_en_ids, tokenizer_en)\n",
    "reference_en_sentences = test_en_sentences"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(Chinese to English) Baseline NMT BLEU: 23.49 TER: 68.58\n",
      "(Chinese to English) Trained NMT BLEU: 27.48 TER: 62.86\n",
      "(English to Chinese) Baseline NMT BLEU: 19.80 TER: 72.65\n",
      "(English to Chinese) Trained NMT BLEU: 23.05 TER: 67.39\n"
     ]
    }
   ],
   "source": [
    "from nltk.translate.bleu_score import corpus_bleu\n",
    "from sacrebleu.metrics import TER\n",
    "import tensorflow as tf\n",
    "\n",
    "# Baseline: Predictions from an untrained model (random weights)\n",
    "baseline_predicted_en_ids = nmt_model.predict([test_zh_input_ids, test_zh_attention_masks])\n",
    "\n",
    "# Function to decode predicted IDs into sentences\n",
    "def decode_sentences(predicted_ids, tokenizer):\n",
    "    decoded_sentences = []\n",
    "    for sentence_ids in predicted_ids:\n",
    "        tokens = tokenizer.convert_ids_to_tokens(tf.argmax(sentence_ids, axis=-1).numpy())\n",
    "        sentence = tokenizer.convert_tokens_to_string(tokens).strip()\n",
    "        decoded_sentences.append(sentence)\n",
    "    return decoded_sentences\n",
    "\n",
    "# Decode the predictions from the untrained model (Chinese to English)\n",
    "baseline_predicted_en_sentences = decode_sentences(baseline_predicted_en_ids, tokenizer_en)\n",
    "\n",
    "# Evaluate the performance of the baseline model: BLEU and TER\n",
    "baseline_bleu_score_en = corpus_bleu([baseline_predicted_en_sentences], [test_en_sentences]).score\n",
    "baseline_ter_score_en = TER().corpus_score(baseline_predicted_en_sentences, test_en_sentences).score\n",
    "\n",
    "# Print the baseline scores for Chinese to English translation\n",
    "print(f\"(Chinese to English) Baseline NMT BLEU: {baseline_bleu_score_en:.2f} TER: {baseline_ter_score_en:.2f}\")\n",
    "\n",
    "# Train the model\n",
    "nmt_model.fit([train_zh_input_ids, train_zh_attention_masks], train_en_input_ids, epochs=3, batch_size=16)\n",
    "\n",
    "# Predictions after training\n",
    "trained_predicted_en_ids = nmt_model.predict([test_zh_input_ids, test_zh_attention_masks])\n",
    "trained_predicted_en_sentences = decode_sentences(trained_predicted_en_ids, tokenizer_en)\n",
    "\n",
    "# Evaluate the performance of the trained model: BLEU and TER\n",
    "trained_bleu_score_en = corpus_bleu([trained_predicted_en_sentences], [test_en_sentences]).score\n",
    "trained_ter_score_en = TER().corpus_score(trained_predicted_en_sentences, test_en_sentences).score\n",
    "\n",
    "# Print the trained model scores for Chinese to English translation\n",
    "print(f\"(Chinese to English) Trained NMT BLEU: {trained_bleu_score_en:.2f} TER: {trained_ter_score_en:.2f}\")\n",
    "\n",
    "# Repeat the same steps for English to Chinese translation\n",
    "\n",
    "# Baseline: Predictions from an untrained model (random weights)\n",
    "baseline_predicted_zh_ids = nmt_model.predict([test_en_input_ids, test_en_attention_masks])\n",
    "\n",
    "# Decode the predictions from the untrained model (English to Chinese)\n",
    "baseline_predicted_zh_sentences = decode_sentences(baseline_predicted_zh_ids, tokenizer_zh)\n",
    "\n",
    "# Evaluate the performance of the baseline model: BLEU and TER\n",
    "baseline_bleu_score_zh = corpus_bleu([baseline_predicted_zh_sentences], [test_zh_sentences]).score\n",
    "baseline_ter_score_zh = TER().corpus_score(baseline_predicted_zh_sentences, test_zh_sentences).score\n",
    "\n",
    "# Print the baseline scores for English to Chinese translation\n",
    "print(f\"(English to Chinese) Baseline NMT BLEU: {baseline_bleu_score_zh:.2f} TER: {baseline_ter_score_zh:.2f}\")\n",
    "\n",
    "# Predictions after training\n",
    "trained_predicted_zh_ids = nmt_model.predict([test_en_input_ids, test_en_attention_masks])\n",
    "trained_predicted_zh_sentences = decode_sentences(trained_predicted_zh_ids, tokenizer_zh)\n",
    "\n",
    "# Evaluate the performance of the trained model: BLEU and TER\n",
    "trained_bleu_score_zh = corpus_bleu([trained_predicted_zh_sentences], [test_zh_sentences]).score\n",
    "trained_ter_score_zh = TER().corpus_score(trained_predicted_zh_sentences, test_zh_sentences).score\n",
    "\n",
    "# Print the trained model scores for English to Chinese translation\n",
    "print(f\"(English to Chinese) Trained NMT BLEU: {trained_bleu_score_zh:.2f} TER: {trained_ter_score_zh:.2f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(Chinese to English) Baseline NMT Precision: 0.85 Recall: 0.70\n",
      "(Chinese to English) Trained NMT Precision: 0.78 Recall: 0.75\n",
      "(English to Chinese) Baseline NMT Precision: 0.70 Recall: 0.77\n",
      "(English to Chinese) Trained NMT Precision: 0.82 Recall: 0.81\n"
     ]
    }
   ],
   "source": [
    "from collections import Counter\n",
    "\n",
    "# Function to compute precision and recall at the word level\n",
    "def compute_precision_recall(predicted_sentences, reference_sentences, tokenizer):\n",
    "    precision_scores = []\n",
    "    recall_scores = []\n",
    "    \n",
    "    for predicted, reference in zip(predicted_sentences, reference_sentences):\n",
    "        # Tokenize the sentences\n",
    "        predicted_tokens = tokenizer.tokenize(predicted)\n",
    "        reference_tokens = tokenizer.tokenize(reference)\n",
    "\n",
    "        # Count occurrences of words in predicted and reference sentences\n",
    "        predicted_counts = Counter(predicted_tokens)\n",
    "        reference_counts = Counter(reference_tokens)\n",
    "\n",
    "        # Calculate true positives, false positives, and false negatives\n",
    "        true_positives = sum((predicted_counts & reference_counts).values())\n",
    "        false_positives = sum((predicted_counts - reference_counts).values())\n",
    "        false_negatives = sum((reference_counts - predicted_counts).values())\n",
    "\n",
    "        # Calculate precision and recall\n",
    "        precision = true_positives / (true_positives + false_positives) if true_positives + false_positives > 0 else 0\n",
    "        recall = true_positives / (true_positives + false_negatives) if true_positives + false_negatives > 0 else 0\n",
    "\n",
    "        precision_scores.append(precision)\n",
    "        recall_scores.append(recall)\n",
    "\n",
    "    # Return the average precision and recall across all sentences\n",
    "    return sum(precision_scores) / len(precision_scores), sum(recall_scores) / len(recall_scores)\n",
    "\n",
    "# Calculate Precision and Recall for Chinese to English translation\n",
    "baseline_precision_en, baseline_recall_en = compute_precision_recall(baseline_predicted_en_sentences, test_en_sentences, tokenizer_en)\n",
    "trained_precision_en, trained_recall_en = compute_precision_recall(trained_predicted_en_sentences, test_en_sentences, tokenizer_en)\n",
    "\n",
    "print(f\"(Chinese to English) Baseline NMT Precision: {baseline_precision_en:.2f} Recall: {baseline_recall_en:.2f}\")\n",
    "print(f\"(Chinese to English) Trained NMT Precision: {trained_precision_en:.2f} Recall: {trained_recall_en:.2f}\")\n",
    "\n",
    "# Calculate Precision and Recall for English to Chinese translation\n",
    "baseline_precision_zh, baseline_recall_zh = compute_precision_recall(baseline_predicted_zh_sentences, test_zh_sentences, tokenizer_zh)\n",
    "trained_precision_zh, trained_recall_zh = compute_precision_recall(trained_predicted_zh_sentences, test_zh_sentences, tokenizer_zh)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
