{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "bert_qa_tune.ipynb",
"provenance": [],
"collapsed_sections": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "code",
"metadata": {
"id": "RXSeYLR-TYTV"
},
"source": [
"import json"
],
"execution_count": 62,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "swJC98DsJSeH",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "7bc172eb-e4e0-4bc9-9166-41dd3b603a91"
},
"source": [
"!pip install transformers"
],
"execution_count": 63,
"outputs": [
{
"output_type": "stream",
"text": [
"Requirement already satisfied: transformers in /usr/local/lib/python3.7/dist-packages (4.5.1)\n",
"Requirement already satisfied: packaging in /usr/local/lib/python3.7/dist-packages (from transformers) (20.9)\n",
"Requirement already satisfied: importlib-metadata; python_version < \"3.8\" in /usr/local/lib/python3.7/dist-packages (from transformers) (3.10.1)\n",
"Requirement already satisfied: numpy>=1.17 in /usr/local/lib/python3.7/dist-packages (from transformers) (1.19.5)\n",
"Requirement already satisfied: requests in /usr/local/lib/python3.7/dist-packages (from transformers) (2.23.0)\n",
"Requirement already satisfied: filelock in /usr/local/lib/python3.7/dist-packages (from transformers) (3.0.12)\n",
"Requirement already satisfied: tqdm>=4.27 in /usr/local/lib/python3.7/dist-packages (from transformers) (4.41.1)\n",
"Requirement already satisfied: regex!=2019.12.17 in /usr/local/lib/python3.7/dist-packages (from transformers) (2019.12.20)\n",
"Requirement already satisfied: tokenizers<0.11,>=0.10.1 in /usr/local/lib/python3.7/dist-packages (from transformers) (0.10.2)\n",
"Requirement already satisfied: sacremoses in /usr/local/lib/python3.7/dist-packages (from transformers) (0.0.45)\n",
"Requirement already satisfied: pyparsing>=2.0.2 in /usr/local/lib/python3.7/dist-packages (from packaging->transformers) (2.4.7)\n",
"Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata; python_version < \"3.8\"->transformers) (3.4.1)\n",
"Requirement already satisfied: typing-extensions>=3.6.4; python_version < \"3.8\" in /usr/local/lib/python3.7/dist-packages (from importlib-metadata; python_version < \"3.8\"->transformers) (3.7.4.3)\n",
"Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests->transformers) (3.0.4)\n",
"Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests->transformers) (1.24.3)\n",
"Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests->transformers) (2020.12.5)\n",
"Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests->transformers) (2.10)\n",
"Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers) (1.15.0)\n",
"Requirement already satisfied: joblib in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers) (1.0.1)\n",
"Requirement already satisfied: click in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers) (7.1.2)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "8wU7xls9TaWp"
},
"source": [
"import torch\n",
"import pandas as pd\n",
"import numpy as np"
],
"execution_count": 64,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "jBFg4gOYTxdw"
},
"source": [
"import urllib.request\n",
"\n",
"def getEntries ( url):\n",
" \n",
" request = urllib.request.Request (url , None, {'User-Agent' : 'test'})\n",
" response = urllib.request.urlopen (request)\n",
" \n",
" return json.loads(response.read())\n"
],
"execution_count": 65,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "qjY8fLKWV6aU"
},
"source": [
""
],
"execution_count": 65,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 313
},
"id": "prkWp6-5UVIx",
"outputId": "c141233d-5440-4cd7-a0c3-43082080124d"
},
"source": [
"df_disease_symptoms = pd.read_csv(\"https://raw.githubusercontent.com/mcelikkaya/medium_articles2/main/dataset.csv\")\n",
"df_disease_symptoms = df_disease_symptoms.fillna(\"\")\n",
"df_disease_symptoms.head( 5 )"
],
"execution_count": 66,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Disease | \n",
" Symptom_1 | \n",
" Symptom_2 | \n",
" Symptom_3 | \n",
" Symptom_4 | \n",
" Symptom_5 | \n",
" Symptom_6 | \n",
" Symptom_7 | \n",
" Symptom_8 | \n",
" Symptom_9 | \n",
" Symptom_10 | \n",
" Symptom_11 | \n",
" Symptom_12 | \n",
" Symptom_13 | \n",
" Symptom_14 | \n",
" Symptom_15 | \n",
" Symptom_16 | \n",
" Symptom_17 | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" Fungal infection | \n",
" itching | \n",
" skin_rash | \n",
" nodal_skin_eruptions | \n",
" dischromic _patches | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" 1 | \n",
" Fungal infection | \n",
" skin_rash | \n",
" nodal_skin_eruptions | \n",
" dischromic _patches | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" 2 | \n",
" Fungal infection | \n",
" itching | \n",
" nodal_skin_eruptions | \n",
" dischromic _patches | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" 3 | \n",
" Fungal infection | \n",
" itching | \n",
" skin_rash | \n",
" dischromic _patches | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" 4 | \n",
" Fungal infection | \n",
" itching | \n",
" skin_rash | \n",
" nodal_skin_eruptions | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Disease Symptom_1 ... Symptom_16 Symptom_17\n",
"0 Fungal infection itching ... \n",
"1 Fungal infection skin_rash ... \n",
"2 Fungal infection itching ... \n",
"3 Fungal infection itching ... \n",
"4 Fungal infection itching ... \n",
"\n",
"[5 rows x 18 columns]"
]
},
"metadata": {
"tags": []
},
"execution_count": 66
}
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 206
},
"id": "FDLB-OmDVHZp",
"outputId": "19f3ecd2-962a-49a5-f329-19c04b938610"
},
"source": [
"df_symptom_description = pd.read_csv(\"https://raw.githubusercontent.com/mcelikkaya/medium_articles2/main/symptom_Description.csv\")\n",
"df_symptom_description = df_symptom_description.fillna(\"\")\n",
"df_symptom_description.head( 5 )"
],
"execution_count": 67,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Disease | \n",
" Description | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" Drug Reaction | \n",
" An adverse drug reaction (ADR) is an injury ca... | \n",
"
\n",
" \n",
" 1 | \n",
" Malaria | \n",
" An infectious disease caused by protozoan para... | \n",
"
\n",
" \n",
" 2 | \n",
" Allergy | \n",
" An allergy is an immune system response to a f... | \n",
"
\n",
" \n",
" 3 | \n",
" Hypothyroidism | \n",
" Hypothyroidism, also called underactive thyroi... | \n",
"
\n",
" \n",
" 4 | \n",
" Psoriasis | \n",
" Psoriasis is a common skin disorder that forms... | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Disease Description\n",
"0 Drug Reaction An adverse drug reaction (ADR) is an injury ca...\n",
"1 Malaria An infectious disease caused by protozoan para...\n",
"2 Allergy An allergy is an immune system response to a f...\n",
"3 Hypothyroidism Hypothyroidism, also called underactive thyroi...\n",
"4 Psoriasis Psoriasis is a common skin disorder that forms..."
]
},
"metadata": {
"tags": []
},
"execution_count": 67
}
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 206
},
"id": "5ZiiND_iIvez",
"outputId": "196f582b-69b4-4d8b-b14d-6fe4e4e67352"
},
"source": [
"df_symptom_precaution = pd.read_csv(\"https://raw.githubusercontent.com/mcelikkaya/medium_articles2/main/symptom_precaution.csv\")\n",
"df_symptom_precaution = df_symptom_precaution.fillna(\"\")\n",
"df_symptom_precaution.head( 5 )"
],
"execution_count": 68,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Disease | \n",
" Precaution_1 | \n",
" Precaution_2 | \n",
" Precaution_3 | \n",
" Precaution_4 | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" Drug Reaction | \n",
" stop irritation | \n",
" consult nearest hospital | \n",
" stop taking drug | \n",
" follow up | \n",
"
\n",
" \n",
" 1 | \n",
" Malaria | \n",
" Consult nearest hospital | \n",
" avoid oily food | \n",
" avoid non veg food | \n",
" keep mosquitos out | \n",
"
\n",
" \n",
" 2 | \n",
" Allergy | \n",
" apply calamine | \n",
" cover area with bandage | \n",
" | \n",
" use ice to compress itching | \n",
"
\n",
" \n",
" 3 | \n",
" Hypothyroidism | \n",
" reduce stress | \n",
" exercise | \n",
" eat healthy | \n",
" get proper sleep | \n",
"
\n",
" \n",
" 4 | \n",
" Psoriasis | \n",
" wash hands with warm soapy water | \n",
" stop bleeding using pressure | \n",
" consult doctor | \n",
" salt baths | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Disease ... Precaution_4\n",
"0 Drug Reaction ... follow up\n",
"1 Malaria ... keep mosquitos out\n",
"2 Allergy ... use ice to compress itching\n",
"3 Hypothyroidism ... get proper sleep\n",
"4 Psoriasis ... salt baths\n",
"\n",
"[5 rows x 5 columns]"
]
},
"metadata": {
"tags": []
},
"execution_count": 68
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "soUFQauhI07k"
},
"source": [
"def get_df_as_map(df):\n",
" disease_list = df.to_numpy().tolist()\n",
" diease_map = {}\n",
" for disease_row in disease_list:\n",
" disease = disease_row[0]\n",
" #print(disease)\n",
" if disease not in diease_map.keys():\n",
" diease_map[disease] = [] \n",
" for symptom in disease_row[1:]:\n",
" if \"\" != symptom and symptom not in diease_map[disease]: \n",
" diease_map[disease].append(symptom)\n",
" return diease_map"
],
"execution_count": 69,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "8a2q2lEbI3XA"
},
"source": [
"df_disease_symptoms_map = get_df_as_map( df_disease_symptoms)\n",
"df_symptom_precaution_map = get_df_as_map( df_symptom_precaution)\n",
"df_symptom_description_map = get_df_as_map( df_symptom_description)\n"
],
"execution_count": 140,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "iW6JIX0CI42V"
},
"source": [
"df_disease_symptoms_questions = [\"What is problem if,I have\",\"What happens if,I feel\",\n",
" \"What does it show when I have a problem as\",\"What happend when my problem is\"]\n",
"df_symptom_precaution_questions = [\"What must I do\",\"What is treatment\",\"What can I do\",\"What do you advice\"]\n",
"df_symptom_description_questions =[\"What is\",\"How do you define\",\"What happens when you are\",\"How do you understand\"]"
],
"execution_count": 141,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "AkWBmTB0I6gZ",
"outputId": "080e7b31-09fe-43d6-cece-0e07a9f997ac"
},
"source": [
"disease_text_map = {}\n",
"for disease in df_disease_symptoms_map.keys():\n",
" try:\n",
" #print(disease)\n",
" symptoms = df_disease_symptoms_map[disease]\n",
" precautions = df_symptom_precaution_map[disease]\n",
" description = df_symptom_description_map[disease.strip()] \n",
" \n",
" desc = description[0]\n",
" symptoms_text = \" \".join(symptoms )\n",
" precautions_text = \" \".join(precautions )\n",
" text = desc #\n",
" text += \"The name of disease is \"+ disease \n",
" text += \" is an illness when you have \" + symptoms_text + \" .\"\n",
" text += \" You must \" + precautions_text + \" .\"\n",
" #print(text)\n",
" disease_text_map[disease] = [text,desc,symptoms_text,precautions_text]\n",
" except:\n",
" print(\"Error in disease\",disease)"
],
"execution_count": 142,
"outputs": [
{
"output_type": "stream",
"text": [
"Error in disease Dimorphic hemmorhoids(piles)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "sfqk-8TnI8J3"
},
"source": [
"train_contexts = []\n",
"train_questions = []\n",
"train_answers = []\n",
"\n",
"val_contexts = []\n",
"val_questions = []\n",
"val_answers = []"
],
"execution_count": 178,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "GYP4pXljYxy9",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "5f1d2958-2c4f-4ec8-8b9b-20d201f3ba45"
},
"source": [
"from textwrap import wrap\n",
"\n",
"disease = list( disease_text_map.keys() )[0]\n",
"text = disease_text_map[disease][0]\n",
"desc = disease_text_map[disease][1]\n",
"symptoms_text = disease_text_map[disease][2]\n",
"precautions_text = disease_text_map[disease][3]\n",
"print(\"text :\",\"\\n\".join(wrap(text, 120)) )\n",
"print(\"-----\")\n",
"print(\"desc :\",\"\\n\".join(wrap(desc, 120))) \n",
"print(\"--\")\n",
"print(\"symptoms_text : \",symptoms_text)\n",
"print(\"precautions_text : \",precautions_text)\n"
],
"execution_count": 179,
"outputs": [
{
"output_type": "stream",
"text": [
"text : In humans, fungal infections occur when an invading fungus takes over an area of the body and is too much for the immune\n",
"system to handle. Fungi can live in the air, soil, water, and plants. There are also some fungi that live naturally in\n",
"the human body. Like many microbes, there are helpful fungi and harmful fungi.The name of disease is Fungal infection is\n",
"an illness when you have itching skin_rash nodal_skin_eruptions dischromic _patches . You must bath twice use detol\n",
"or neem in bathing water keep infected area dry use clean cloths .\n",
"-----\n",
"desc : In humans, fungal infections occur when an invading fungus takes over an area of the body and is too much for the immune\n",
"system to handle. Fungi can live in the air, soil, water, and plants. There are also some fungi that live naturally in\n",
"the human body. Like many microbes, there are helpful fungi and harmful fungi.\n",
"--\n",
"symptoms_text : itching skin_rash nodal_skin_eruptions dischromic _patches\n",
"precautions_text : bath twice use detol or neem in bathing water keep infected area dry use clean cloths\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "W7TQFgmgIxN8"
},
"source": [
""
],
"execution_count": 179,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "xh1TAsJFI-NI"
},
"source": [
"for disease in disease_text_map.keys():\n",
" text = disease_text_map[disease][0]\n",
" desc = disease_text_map[disease][1]\n",
" symptoms_text = disease_text_map[disease][2]\n",
" precautions_text = disease_text_map[disease][3]\n",
" \n",
" \n",
" #for index_symptom,symptom_description_question in enumerate( df_symptom_description_questions):\n",
" # if index_symptom < 2:\n",
" # train_contexts.append( text )\n",
" # train_questions.append( symptom_description_question + \" \" + disease )\n",
" # train_answers.append( {'text': desc, 'answer_start': text.find(desc)} )\n",
" # else:\n",
" # val_contexts.append( text )\n",
" # val_questions.append( symptom_description_question + \" \" + disease )\n",
" # val_answers.append( {'text': desc, 'answer_start': text.find(desc)} ) \n",
" \n",
" for index_description,symptom_description_question in enumerate(df_disease_symptoms_questions):\n",
" if index_description < 2:\n",
" train_contexts.append( text )\n",
" train_questions.append( symptom_description_question + \" \" + symptoms_text + \" ? \" )\n",
" train_answers.append( {'text': disease, 'answer_start': text.find(disease)} ) \n",
" else:\n",
" val_contexts.append( text )\n",
" val_questions.append( symptom_description_question + \" \" + symptoms_text + \" ? \")\n",
" val_answers.append( {'text': disease, 'answer_start': text.find(disease)} ) \n",
" \n",
" for index_precaution,symptom_precaution_question in enumerate(df_symptom_precaution_questions):\n",
" if index_precaution < 2: \n",
" train_contexts.append( text )\n",
" train_questions.append( symptom_precaution_question + \" for \" + disease + \" ? \")\n",
" train_answers.append( {'text': precautions_text, 'answer_start': text.find(precautions_text)} ) \n",
" else:\n",
" val_contexts.append( text )\n",
" val_questions.append( symptom_precaution_question + \" for \" + disease + \" ? \")\n",
" val_answers.append( {'text': precautions_text, 'answer_start': text.find(precautions_text)} ) "
],
"execution_count": 180,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "NA67NOd-dwwI"
},
"source": [
"def dump_index(index):\n",
" print(\"train_questions\",train_questions[index]) \n",
" print(\"train_answers\",train_answers[index])\n",
" print(\"val_question:\",val_questions[index])\n",
" print(\"val_answers:\",val_answers[index])\n",
" \n"
],
"execution_count": 181,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "mbMcI8fCe6HI",
"outputId": "58e45de0-a47b-4129-9560-997ec3cee732"
},
"source": [
"dump_index(0)"
],
"execution_count": 182,
"outputs": [
{
"output_type": "stream",
"text": [
"train_questions What is problem if,I have itching skin_rash nodal_skin_eruptions dischromic _patches ? \n",
"train_answers {'text': 'Fungal infection', 'answer_start': 341}\n",
"val_question: What does it show when I have a problem as itching skin_rash nodal_skin_eruptions dischromic _patches ? \n",
"val_answers: {'text': 'Fungal infection', 'answer_start': 341}\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "wgqrFxXieuT7",
"outputId": "700aef94-5f2c-4393-cde9-258a75f42b21"
},
"source": [
"#dump_index(1)\n",
"dump_index(2)"
],
"execution_count": 183,
"outputs": [
{
"output_type": "stream",
"text": [
"train_questions What must I do for Fungal infection ? \n",
"train_answers {'text': 'bath twice use detol or neem in bathing water keep infected area dry use clean cloths', 'answer_start': 459}\n",
"val_question: What can I do for Fungal infection ? \n",
"val_answers: {'text': 'bath twice use detol or neem in bathing water keep infected area dry use clean cloths', 'answer_start': 459}\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "k-0jwvNnex_A",
"outputId": "2043747b-693c-44a4-d859-884bb632c9f4"
},
"source": [
"dump_index(3)"
],
"execution_count": 184,
"outputs": [
{
"output_type": "stream",
"text": [
"train_questions What is treatment for Fungal infection ? \n",
"train_answers {'text': 'bath twice use detol or neem in bathing water keep infected area dry use clean cloths', 'answer_start': 459}\n",
"val_question: What do you advice for Fungal infection ? \n",
"val_answers: {'text': 'bath twice use detol or neem in bathing water keep infected area dry use clean cloths', 'answer_start': 459}\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "tL90sDTgQV0w"
},
"source": [
"#for ii in range(len(train_questions)):\n",
"# print(ii,\"-----------------\")\n",
"# dump_index(ii)"
],
"execution_count": 185,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 424
},
"id": "cBdclJqtd8HU",
"outputId": "4dfb6cbf-6b49-4d51-d391-a91f37000d23"
},
"source": [
"#for ii in range(len(train_questions)):\n",
"# print(ii,\"-----------------\")\n",
"# dump_index(ii)\n",
"\n",
"import pandas as pd\n",
"df = pd.DataFrame()\n",
"df[\"train_questions\"] =train_questions \n",
"df[\"train_answers\"] =train_answers \n",
"df[\"val_questions\"] =val_questions \n",
"df[\"val_answers\"] =val_answers \n",
"df"
],
"execution_count": 186,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" train_questions | \n",
" train_answers | \n",
" val_questions | \n",
" val_answers | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" What is problem if,I have itching skin_rash ... | \n",
" {'text': 'Fungal infection', 'answer_start': 341} | \n",
" What does it show when I have a problem as itc... | \n",
" {'text': 'Fungal infection', 'answer_start': 341} | \n",
"
\n",
" \n",
" 1 | \n",
" What happens if,I feel itching skin_rash nod... | \n",
" {'text': 'Fungal infection', 'answer_start': 341} | \n",
" What happend when my problem is itching skin_... | \n",
" {'text': 'Fungal infection', 'answer_start': 341} | \n",
"
\n",
" \n",
" 2 | \n",
" What must I do for Fungal infection ? | \n",
" {'text': 'bath twice use detol or neem in bath... | \n",
" What can I do for Fungal infection ? | \n",
" {'text': 'bath twice use detol or neem in bath... | \n",
"
\n",
" \n",
" 3 | \n",
" What is treatment for Fungal infection ? | \n",
" {'text': 'bath twice use detol or neem in bath... | \n",
" What do you advice for Fungal infection ? | \n",
" {'text': 'bath twice use detol or neem in bath... | \n",
"
\n",
" \n",
" 4 | \n",
" What is problem if,I have continuous_sneezing... | \n",
" {'text': 'Allergy', 'answer_start': 261} | \n",
" What does it show when I have a problem as co... | \n",
" {'text': 'Allergy', 'answer_start': 261} | \n",
"
\n",
" \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
"
\n",
" \n",
" 155 | \n",
" What is treatment for Psoriasis ? | \n",
" {'text': 'wash hands with warm soapy water sto... | \n",
" What do you advice for Psoriasis ? | \n",
" {'text': 'wash hands with warm soapy water sto... | \n",
"
\n",
" \n",
" 156 | \n",
" What is problem if,I have skin_rash high_fev... | \n",
" {'text': 'Impetigo', 'answer_start': 0} | \n",
" What does it show when I have a problem as sk... | \n",
" {'text': 'Impetigo', 'answer_start': 0} | \n",
"
\n",
" \n",
" 157 | \n",
" What happens if,I feel skin_rash high_fever ... | \n",
" {'text': 'Impetigo', 'answer_start': 0} | \n",
" What happend when my problem is skin_rash hi... | \n",
" {'text': 'Impetigo', 'answer_start': 0} | \n",
"
\n",
" \n",
" 158 | \n",
" What must I do for Impetigo ? | \n",
" {'text': 'soak affected area in warm water use... | \n",
" What can I do for Impetigo ? | \n",
" {'text': 'soak affected area in warm water use... | \n",
"
\n",
" \n",
" 159 | \n",
" What is treatment for Impetigo ? | \n",
" {'text': 'soak affected area in warm water use... | \n",
" What do you advice for Impetigo ? | \n",
" {'text': 'soak affected area in warm water use... | \n",
"
\n",
" \n",
"
\n",
"
160 rows × 4 columns
\n",
"
"
],
"text/plain": [
" train_questions ... val_answers\n",
"0 What is problem if,I have itching skin_rash ... ... {'text': 'Fungal infection', 'answer_start': 341}\n",
"1 What happens if,I feel itching skin_rash nod... ... {'text': 'Fungal infection', 'answer_start': 341}\n",
"2 What must I do for Fungal infection ? ... {'text': 'bath twice use detol or neem in bath...\n",
"3 What is treatment for Fungal infection ? ... {'text': 'bath twice use detol or neem in bath...\n",
"4 What is problem if,I have continuous_sneezing... ... {'text': 'Allergy', 'answer_start': 261}\n",
".. ... ... ...\n",
"155 What is treatment for Psoriasis ? ... {'text': 'wash hands with warm soapy water sto...\n",
"156 What is problem if,I have skin_rash high_fev... ... {'text': 'Impetigo', 'answer_start': 0}\n",
"157 What happens if,I feel skin_rash high_fever ... ... {'text': 'Impetigo', 'answer_start': 0}\n",
"158 What must I do for Impetigo ? ... {'text': 'soak affected area in warm water use...\n",
"159 What is treatment for Impetigo ? ... {'text': 'soak affected area in warm water use...\n",
"\n",
"[160 rows x 4 columns]"
]
},
"metadata": {
"tags": []
},
"execution_count": 186
}
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Ni20jIX2a8df",
"outputId": "f89fce78-a5ac-494b-f50b-03933e34a55b"
},
"source": [
"print(\"\\n \".join( train_questions[10:16]) )\n",
"print(train_answers[10:16])\n",
"\n",
"\n",
"print(\"\\n \".join( val_questions[0:6]) )\n",
"print(val_answers[0:6])"
],
"execution_count": 187,
"outputs": [
{
"output_type": "stream",
"text": [
"What must I do for GERD ? \n",
" What is treatment for GERD ? \n",
" What is problem if,I have itching vomiting yellowish_skin nausea loss_of_appetite abdominal_pain yellowing_of_eyes ? \n",
" What happens if,I feel itching vomiting yellowish_skin nausea loss_of_appetite abdominal_pain yellowing_of_eyes ? \n",
" What must I do for Chronic cholestasis ? \n",
" What is treatment for Chronic cholestasis ? \n",
"[{'text': 'avoid fatty spicy food avoid lying down after eating maintain healthy weight exercise', 'answer_start': 404}, {'text': 'avoid fatty spicy food avoid lying down after eating maintain healthy weight exercise', 'answer_start': 404}, {'text': 'Chronic cholestasis', 'answer_start': 264}, {'text': 'Chronic cholestasis', 'answer_start': 264}, {'text': 'cold baths anti itch medicine consult doctor eat healthy', 'answer_start': 418}, {'text': 'cold baths anti itch medicine consult doctor eat healthy', 'answer_start': 418}]\n",
"What does it show when I have a problem as itching skin_rash nodal_skin_eruptions dischromic _patches ? \n",
" What happend when my problem is itching skin_rash nodal_skin_eruptions dischromic _patches ? \n",
" What can I do for Fungal infection ? \n",
" What do you advice for Fungal infection ? \n",
" What does it show when I have a problem as continuous_sneezing shivering chills watering_from_eyes ? \n",
" What happend when my problem is continuous_sneezing shivering chills watering_from_eyes ? \n",
"[{'text': 'Fungal infection', 'answer_start': 341}, {'text': 'Fungal infection', 'answer_start': 341}, {'text': 'bath twice use detol or neem in bathing water keep infected area dry use clean cloths', 'answer_start': 459}, {'text': 'bath twice use detol or neem in bathing water keep infected area dry use clean cloths', 'answer_start': 459}, {'text': 'Allergy', 'answer_start': 261}, {'text': 'Allergy', 'answer_start': 261}]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "BvNXgYBmI_9A",
"outputId": "32212ef4-92d5-429c-e854-e785b776b56d"
},
"source": [
"print(\"text :\",\"\\n\".join(wrap(train_contexts[3], 120)) )\n",
"print(\"\\nQuestion:\",train_questions[3])\n",
"print(train_answers[3])"
],
"execution_count": 188,
"outputs": [
{
"output_type": "stream",
"text": [
"text : In humans, fungal infections occur when an invading fungus takes over an area of the body and is too much for the immune\n",
"system to handle. Fungi can live in the air, soil, water, and plants. There are also some fungi that live naturally in\n",
"the human body. Like many microbes, there are helpful fungi and harmful fungi.The name of disease is Fungal infection is\n",
"an illness when you have itching skin_rash nodal_skin_eruptions dischromic _patches . You must bath twice use detol\n",
"or neem in bathing water keep infected area dry use clean cloths .\n",
"\n",
"Question: What is treatment for Fungal infection ? \n",
"{'text': 'bath twice use detol or neem in bathing water keep infected area dry use clean cloths', 'answer_start': 459}\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "KQD4KNCSJBhe",
"outputId": "1d8cb44c-c82f-46c2-c5de-05b7121de4e4"
},
"source": [
"print(train_contexts[len(train_contexts)-1])\n",
"print(\"\\n\\ntrain_questions:\",train_questions[len(train_contexts)-1])\n",
"print(train_answers[len(train_contexts)-1])"
],
"execution_count": 174,
"outputs": [
{
"output_type": "stream",
"text": [
"Impetigo (im-puh-TIE-go) is a common and highly contagious skin infection that mainly affects infants and children. Impetigo usually appears as red sores on the face, especially around a child's nose and mouth, and on hands and feet. The sores burst and develop honey-colored crusts.The name of disease is Impetigo is an illness when you have skin_rash high_fever blister red_sore_around_nose yellow_crust_ooze . You must soak affected area in warm water use antibiotics remove scabs with wet compressed cloth consult doctor .\n",
"\n",
"\n",
"train_questions: What is treatment for Impetigo ? \n",
"{'text': 'soak affected area in warm water use antibiotics remove scabs with wet compressed cloth consult doctor', 'answer_start': 427}\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "4iWroY8vPwyH"
},
"source": [
""
],
"execution_count": 188,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "P_Mdoi5pJDdi",
"outputId": "79b4a235-4648-4f22-e95b-0926fc5dea93"
},
"source": [
"print(len(train_contexts))\n",
"print(len(train_questions))\n",
"print(len(train_answers))"
],
"execution_count": 86,
"outputs": [
{
"output_type": "stream",
"text": [
"160\n",
"160\n",
"160\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "JgGWZqFtJFaj",
"outputId": "2f8b8e6d-e368-4cf9-f144-d8e52015b712"
},
"source": [
"print(len(val_contexts))\n",
"print(len(val_questions))\n",
"print(len(val_answers))"
],
"execution_count": 87,
"outputs": [
{
"output_type": "stream",
"text": [
"160\n",
"160\n",
"160\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "rbmsCbOVJHdr"
},
"source": [
"#TODO\n",
"def add_end_idx(answers, contexts):\n",
" for answer, context in zip(answers, contexts):\n",
" gold_text = answer['text']\n",
" start_idx = answer['answer_start']\n",
" end_idx = start_idx + len(gold_text)\n",
"\n",
" # sometimes squad answers are off by a character or two – fix this\n",
" if context[start_idx:end_idx] == gold_text:\n",
" answer['answer_end'] = end_idx\n",
" elif context[start_idx-1:end_idx-1] == gold_text:\n",
" answer['answer_start'] = start_idx - 1\n",
" answer['answer_end'] = end_idx - 1 # When the gold label is off by one character\n",
" elif context[start_idx-2:end_idx-2] == gold_text:\n",
" answer['answer_start'] = start_idx - 2\n",
" answer['answer_end'] = end_idx - 2 # When the gold label is off by two characters\n",
"\n",
"add_end_idx(train_answers, train_contexts)\n",
"add_end_idx(val_answers, val_contexts)"
],
"execution_count": 88,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Yqq9wnN6JJev",
"outputId": "77793969-71d1-429d-89a3-74abab93daee"
},
"source": [
"print(train_contexts[0])\n",
"print(\"\\n\\ntrain_questions:\",train_questions[0])\n",
"print(train_answers[0])"
],
"execution_count": 89,
"outputs": [
{
"output_type": "stream",
"text": [
"In humans, fungal infections occur when an invading fungus takes over an area of the body and is too much for the immune system to handle. Fungi can live in the air, soil, water, and plants. There are also some fungi that live naturally in the human body. Like many microbes, there are helpful fungi and harmful fungi.The name of disease is Fungal infection is an illness when you have itching skin_rash nodal_skin_eruptions dischromic _patches . You must bath twice use detol or neem in bathing water keep infected area dry use clean cloths .\n",
"\n",
"\n",
"train_questions: I have itching skin_rash nodal_skin_eruptions dischromic _patches\n",
"{'text': 'Fungal infection', 'answer_start': 341, 'answer_end': 357}\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "kHdzHvmGc3WQ",
"outputId": "6a119575-462f-4701-9744-19d720937bea"
},
"source": [
"starts = [t[\"answer_start\"] for t in train_answers]\n",
"ends = [t[\"answer_end\"] for t in train_answers]\n",
"print(\"starts\",starts)\n",
"print(\"ends\",ends)\n",
"#[t[\"answer_start\"] for t in train_answers]\n",
"#[t[\"answer_end\"] for t in train_answers]\n",
"starts0s = [t for t in starts if t == 0]\n",
"print(len(starts0s))"
],
"execution_count": 90,
"outputs": [
{
"output_type": "stream",
"text": [
"starts [341, 341, 459, 459, 261, 261, 368, 368, 36, 36, 404, 404, 264, 264, 418, 418, 225, 225, 353, 353, 287, 287, 439, 439, 36, 36, 386, 386, 0, 0, 509, 509, 0, 0, 384, 384, 322, 322, 453, 453, 0, 0, 373, 373, 188, 188, 519, 519, 0, 0, 395, 395, 275, 275, 409, 409, 184, 184, 473, 473, 251, 251, 380, 380, 286, 286, 478, 478, 60, 60, 481, 481, 97, 97, 463, 463, 65, 65, 428, 428, 0, 0, 533, 533, 275, 275, 412, 412, 0, 0, 474, 474, 241, 241, 541, 541, 0, 0, 481, 481, 0, 0, 550, 550, 217, 217, 489, 489, 0, 0, 439, 439, 230, 230, 330, 330, 128, 128, 404, 404, 0, 0, 448, 448, 0, 0, 473, 473, 1, 1, 556, 556, 214, 214, 353, 353, 0, 0, 400, 400, 288, 288, 446, 446, 0, 0, 407, 407, 0, 0, 401, 401, 0, 0, 465, 465, 0, 0, 427, 427]\n",
"ends [357, 357, 544, 544, 268, 268, 434, 434, 40, 40, 489, 489, 283, 283, 474, 474, 238, 238, 420, 420, 306, 306, 513, 513, 40, 40, 447, 447, 9, 9, 561, 561, 15, 15, 474, 474, 338, 338, 528, 528, 13, 13, 425, 425, 196, 196, 586, 586, 20, 20, 469, 469, 303, 303, 452, 452, 192, 192, 560, 560, 258, 258, 458, 458, 297, 297, 551, 551, 66, 66, 561, 561, 104, 104, 535, 535, 76, 76, 505, 505, 11, 11, 592, 592, 286, 286, 471, 471, 11, 11, 521, 521, 252, 252, 596, 596, 19, 19, 541, 541, 12, 12, 592, 592, 228, 228, 564, 564, 9, 9, 479, 479, 242, 242, 377, 377, 142, 142, 500, 500, 14, 14, 499, 499, 15, 15, 541, 541, 13, 13, 622, 622, 229, 229, 412, 412, 9, 9, 457, 457, 327, 327, 514, 514, 4, 4, 486, 486, 23, 23, 486, 486, 9, 9, 552, 552, 8, 8, 529, 529]\n",
"32\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "hez__LsumejD"
},
"source": [
"#Open to see question and context\n",
"#for q,a in zip( val_questions, val_answers):\n",
"# print(\":\",q)\n",
"# print( a[\"text\"])"
],
"execution_count": 91,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "0z4v7ybqc3Tz"
},
"source": [
"#Open comment to see question and answer\n",
"#for q,a in zip( train_questions, train_answers):\n",
"# print(q)\n",
"# print( a[\"text\"])"
],
"execution_count": 92,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "7IvGO0bMc3RP",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "703a82e7-c21e-4f60-9e30-81004f679819"
},
"source": [
"print(type(train_contexts))\n",
"print(type(train_questions))\n",
"print(train_contexts[0])\n",
"print(train_questions[0] )"
],
"execution_count": 93,
"outputs": [
{
"output_type": "stream",
"text": [
"\n",
"\n",
"In humans, fungal infections occur when an invading fungus takes over an area of the body and is too much for the immune system to handle. Fungi can live in the air, soil, water, and plants. There are also some fungi that live naturally in the human body. Like many microbes, there are helpful fungi and harmful fungi.The name of disease is Fungal infection is an illness when you have itching skin_rash nodal_skin_eruptions dischromic _patches . You must bath twice use detol or neem in bathing water keep infected area dry use clean cloths .\n",
"I have itching skin_rash nodal_skin_eruptions dischromic _patches\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "eOYNLBFjJM66"
},
"source": [
"from transformers import DistilBertTokenizerFast\n",
"tokenizer = DistilBertTokenizerFast.from_pretrained('distilbert-base-uncased')\n",
"\n",
"train_encodings = tokenizer(train_contexts, train_questions, truncation=True, padding=True)\n",
"val_encodings = tokenizer(val_contexts, val_questions, truncation=True, padding=True)"
],
"execution_count": 94,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "PZTl61i6QIMP",
"outputId": "ff8e1eab-a03b-499e-ac02-f7129667037f"
},
"source": [
"tokenizer"
],
"execution_count": 189,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"PreTrainedTokenizerFast(name_or_path='distilbert-base-uncased', vocab_size=30522, model_max_len=512, is_fast=True, padding_side='right', special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'})"
]
},
"metadata": {
"tags": []
},
"execution_count": 189
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "FF4Bd2hTJQG1"
},
"source": [
"def add_token_positions(encodings, answers):\n",
" start_positions = []\n",
" end_positions = []\n",
" for i in range(len(answers)):\n",
" start_positions.append(encodings.char_to_token(i, answers[i]['answer_start']))\n",
" end_positions.append(encodings.char_to_token(i, answers[i]['answer_end'] - 1))\n",
"\n",
" # if start position is None, the answer passage has been truncated\n",
" if start_positions[-1] is None: \n",
" #print(\"start_positions minus,\",answers[i])\n",
" start_positions[-1] = tokenizer.model_max_length\n",
" if end_positions[-1] is None:\n",
" #print(\"end_positions minus,\",answers[i])\n",
" end_positions[-1] = tokenizer.model_max_length\n",
"\n",
" encodings.update({'start_positions': start_positions, 'end_positions': end_positions})\n",
"\n",
"add_token_positions(train_encodings, train_answers)\n",
"add_token_positions(val_encodings, val_answers)"
],
"execution_count": 95,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "ljXGdQPJl34i",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "0240f92b-f3c2-4330-902b-e083b412699b"
},
"source": [
"len(train_encodings[\"start_positions\"])"
],
"execution_count": 96,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"160"
]
},
"metadata": {
"tags": []
},
"execution_count": 96
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "Yrtm_eTeJjQn"
},
"source": [
"import torch\n",
"\n",
"class CustomDataset(torch.utils.data.Dataset):\n",
" def __init__(self, encodings):\n",
" self.encodings = encodings\n",
"\n",
" def __getitem__(self, idx):\n",
" return {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}\n",
"\n",
" def __len__(self):\n",
" return len(self.encodings.input_ids)\n",
"\n",
"train_dataset = CustomDataset(train_encodings)\n",
"val_dataset = CustomDataset(val_encodings)"
],
"execution_count": 97,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "xwrPt1yFJlmc",
"outputId": "6317e12f-43dd-4064-e1b5-5a7d55b3ab78"
},
"source": [
"from transformers import DistilBertForQuestionAnswering\n",
"model = DistilBertForQuestionAnswering.from_pretrained(\"distilbert-base-uncased\")"
],
"execution_count": 98,
"outputs": [
{
"output_type": "stream",
"text": [
"Some weights of the model checkpoint at distilbert-base-uncased were not used when initializing DistilBertForQuestionAnswering: ['vocab_transform.weight', 'vocab_transform.bias', 'vocab_layer_norm.weight', 'vocab_layer_norm.bias', 'vocab_projector.weight', 'vocab_projector.bias']\n",
"- This IS expected if you are initializing DistilBertForQuestionAnswering from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n",
"- This IS NOT expected if you are initializing DistilBertForQuestionAnswering from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n",
"Some weights of DistilBertForQuestionAnswering were not initialized from the model checkpoint at distilbert-base-uncased and are newly initialized: ['qa_outputs.weight', 'qa_outputs.bias']\n",
"You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
],
"name": "stderr"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "fXi2zjIlJn0M"
},
"source": [
"from torch.utils.data import DataLoader\n",
"from transformers import AdamW\n",
"\n",
"device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n",
"\n",
"_ = model.to(device)"
],
"execution_count": 99,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "3K81CgocKt2G"
},
"source": [
"def eval_loader(batch_size=16,dump_equals=False):\n",
" t1 = time()\n",
" model.eval()\n",
" acc = []\n",
" val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=True)\n",
" dump_count = 0\n",
" eval_data = []\n",
" for batch in val_loader:\n",
" with torch.no_grad():\n",
" input_ids = batch['input_ids'].to(device)\n",
" attention_mask = batch['attention_mask'].to(device)\n",
" start_true = batch['start_positions'].to(device)\n",
" end_true = batch['end_positions'].to(device)\n",
" # make predictions\n",
" outputs = model(input_ids, attention_mask=attention_mask)\n",
" # get top prediction with argmax\n",
" start_pred = torch.argmax(outputs['start_logits'], dim=1)\n",
" end_pred = torch.argmax(outputs['end_logits'], dim=1)\n",
" # calculate accuracy \n",
" acc.append(((start_pred == start_true).sum()/len(start_pred)).item())\n",
" acc.append(((end_pred == end_true).sum()/len(end_pred)).item())\n",
"\n",
" eval_data.append( [start_pred , start_true,end_pred , end_true ])\n",
"\n",
" if dump_equals and dump_count < 14 and start_pred == start_true and end_pred == end_true:\n",
" dump_count += 1\n",
" tokens = tokenizer.convert_ids_to_tokens(batch['input_ids'][0])\n",
" pred = get_text_atrange( tokens,start_pred[0],end_pred[0] )\n",
" print(\"tokens\",pred )\n",
" print(\"start_pred == start_true\",start_pred , start_true)\n",
" print(\"end_pred == end_true\",end_pred , end_true)\n",
" print(\"--\")\n",
" # calculate accuracy in total\n",
" acc = sum(acc)/len(acc)\n",
" t2 = time() \n",
" elapsed = t2 - t1\n",
" print('Elapsed time for eval %f seconds.' % elapsed)\n",
" return acc ,eval_data"
],
"execution_count": 100,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "vPmKbYbXNNsi"
},
"source": [
"from time import time\n",
"import matplotlib.pyplot as plt\n",
"\n",
"def train_model():\n",
" t1 = time()\n",
" model.train()\n",
" train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)\n",
" optim = AdamW(model.parameters(), lr=5e-5)\n",
" outputs_model = []\n",
" for epoch in range(1):\n",
" for batch in train_loader:\n",
" optim.zero_grad()\n",
" input_ids = batch['input_ids'].to(device)\n",
" attention_mask = batch['attention_mask'].to(device)\n",
" start_positions = batch['start_positions'].to(device)\n",
" end_positions = batch['end_positions'].to(device)\n",
" outputs = model(input_ids, attention_mask=attention_mask, start_positions=start_positions, end_positions=end_positions)\n",
" if len(outputs_model) == 0:\n",
" outputs_model.append(outputs)\n",
" loss = outputs[0]\n",
" loss.backward()\n",
" optim.step()\n",
" t2 = time() \n",
" elapsed = t2 - t1\n",
" print('Elapsed time for training %f seconds.' % elapsed)\n",
" return outputs_model\n",
"\n",
"#start_pred , start_true,end_pred , end_true\n",
"def plot_eval_old(eval_data):\n",
" pred_x = []\n",
" pred_y = []\n",
" true_x = []\n",
" true_y = []\n",
" for e_data in eval_data:\n",
" if e_data[3].item() - e_data[1].item() > 30:\n",
" continue\n",
" pred_x.append( e_data[0].item() )\n",
" true_x.append( e_data[1].item() )\n",
" pred_y.append( e_data[2].item() )\n",
" true_y.append( e_data[3].item() )\n",
" plt.scatter(pred_x,pred_y,color=\"blue\",label=\"prediction\")\n",
" plt.scatter(true_x,true_y,color=\"orange\",label=\"true\")\n",
" plt.legend() \n",
" plt.show()\n",
" plt.plot(pred_x,pred_y,color=\"blue\",label=\"prediction\",linestyle='-')\n",
" plt.plot(true_x,true_y,color=\"orange\",label=\"true\")\n",
" plt.legend()\n",
" plt.show()\n",
"\n",
"def plot_eval(eval_data):\n",
" fig, axes = plt.subplots(3,1)\n",
" fig.set_size_inches(11, 8)\n",
" axes[0].set_title(\"Prediction\")\n",
" axes[1].set_title(\"Actual\")\n",
" axes[2].set_title(\"Combined\")\n",
" for index,e_data in enumerate(eval_data):\n",
" start_pred , end_pred = e_data[0] , e_data[2]\n",
" start_true , end_true = e_data[1] , e_data[3]\n",
" \n",
" if abs(start_true - end_true) < 100:\n",
" axes[0].plot([index,index],[start_pred,end_pred],color=\"blue\",linestyle='-')\n",
" axes[1].plot([index,index],[start_true,end_true],color=\"orange\") \n",
"\n",
" axes[2].plot([index*2,index*2],[start_pred,end_pred],color=\"blue\",linestyle='-')\n",
" axes[2].plot([index*2+1,index*2+1],[start_true,end_true],color=\"orange\") \n",
"\n",
" #axes[3].plot([index*2+1,index*2+1],[start_true,end_true],color=\"orange\") \n",
" #axes[3].plot([index*2,index*2],[start_pred,end_pred],color=\"blue\",linestyle='-')\n",
" \n",
" fig.tight_layout() \n",
"\n",
" \n",
" "
],
"execution_count": 101,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "eVTfzZ-5rJ-D"
},
"source": [
""
],
"execution_count": 101,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "CkgGOon6_-FI"
},
"source": [
"\n"
],
"execution_count": 101,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 604
},
"id": "DF03fU5gAHRO",
"outputId": "8b60ba48-02fb-45a1-8bd8-68fe5d1126f3"
},
"source": [
"acc,eval_data = eval_loader(1,dump_equals=False)\n",
"plot_eval( eval_data)"
],
"execution_count": 102,
"outputs": [
{
"output_type": "stream",
"text": [
"Elapsed time for eval 1.218337 seconds.\n"
],
"name": "stdout"
},
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"