{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import re\nimport os\nimport gc\nimport pandas as pd\nimport numpy as np\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom tqdm.notebook import tqdm\n\nfrom bs4 import BeautifulSoup\n\n\nimport tensorflow as tf\nfrom tensorflow.keras.layers import Dense, Dropout, Input, Concatenate, Average, GlobalAveragePooling1D, GlobalMaxPooling1D\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.models import Model, load_model\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau, LearningRateScheduler, EarlyStopping, ModelCheckpoint\n\nimport transformers\nfrom transformers import TFAutoModel, AutoTokenizer\nfrom tokenizers import Tokenizer, models, pre_tokenizers, decoders, processors\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","papermill":{"duration":8.250954,"end_time":"2020-09-14T10:32:32.953612","exception":false,"start_time":"2020-09-14T10:32:24.702658","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-05-30T01:44:01.264555Z","iopub.execute_input":"2022-05-30T01:44:01.264908Z","iopub.status.idle":"2022-05-30T01:44:10.354519Z","shell.execute_reply.started":"2022-05-30T01:44:01.264825Z","shell.execute_reply":"2022-05-30T01:44:10.353648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## [What do you predict with this data?](https://www.kaggle.com/c/jigsaw-multilingual-toxic-comment-classification/data)\n- Predicts the probability that a comment is toxic. A toxic comment is 1.0; a benign, non-toxic comment is 0.0.\n- In the test set, all comments are classified as either 1.0 or 0.0.\n\n## 列\n- id-Identifier in each file.\n- comment_text-The text of the comment to be classified.\n- lang-The language of the comment.\n- toxic-Whether the comment is classified as toxic (not present in test.csv.)\n### Train1\n- severe_toxic \t\n- obscene\n- threat\n- insult\n- identity_hate","metadata":{}},{"cell_type":"markdown","source":"# data loading","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv(\"../input/jigsaw-multilingual-toxic-comment-classification/jigsaw-toxic-comment-train.csv\")\n\nvalid = pd.read_csv('../input/jigsaw-multilingual-toxic-comment-classification/validation.csv')\n\ntest = pd.read_csv('../input/jigsaw-multilingual-toxic-comment-classification/test.csv')\n\nsub = pd.read_csv('../input/jigsaw-multilingual-toxic-comment-classification/sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2022-05-30T01:44:10.356295Z","iopub.execute_input":"2022-05-30T01:44:10.357197Z","iopub.status.idle":"2022-05-30T01:44:14.753333Z","shell.execute_reply.started":"2022-05-30T01:44:10.357152Z","shell.execute_reply":"2022-05-30T01:44:14.752605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train","metadata":{"execution":{"iopub.status.busy":"2022-05-30T01:44:14.754506Z","iopub.execute_input":"2022-05-30T01:44:14.75473Z","iopub.status.idle":"2022-05-30T01:44:14.780508Z","shell.execute_reply.started":"2022-05-30T01:44:14.754707Z","shell.execute_reply":"2022-05-30T01:44:14.779726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['comment_text'][223545]","metadata":{"execution":{"iopub.status.busy":"2022-05-30T01:44:14.782111Z","iopub.execute_input":"2022-05-30T01:44:14.782415Z","iopub.status.idle":"2022-05-30T01:44:14.791558Z","shell.execute_reply.started":"2022-05-30T01:44:14.782386Z","shell.execute_reply":"2022-05-30T01:44:14.790807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Helper Functions","metadata":{"papermill":{"duration":0.016745,"end_time":"2020-09-14T10:32:32.989209","exception":false,"start_time":"2020-09-14T10:32:32.972464","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def text_preprocessing(text):\n    \n    def cleaning_text(text):\n        text = str(text)\n        text = re.sub(r'[0-9\"]', '', text) # number\n        text = re.sub(r'#[\\S]+\\b', '', text) # hash\n        text = re.sub(r'@[\\S]+\\b', '', text) # mention\n        text = re.sub(r'https?\\S+', '', text) # link\n        text = re.sub(r'\\s+', ' ', text) # multiple white spaces\n        \n        return text.strip()\n    \n    def sub_text(text):\n        template = re.compile(r'https?://\\S+|www\\.\\S+') #Removes website links\n        text = template.sub(r'', text)\n        \n        text = BeautifulSoup(text, 'lxml').get_text() #Removes HTML tags\n        only_text = soup.get_text()\n        text = only_text\n    \n        emoji_pattern = re.compile(\"[\"\n                                   u\"\\U0001F600-\\U0001F64F\"  # emoticons\n                                   u\"\\U0001F300-\\U0001F5FF\"  # symbols & pictographs\n                                   u\"\\U0001F680-\\U0001F6FF\"  # transport & map symbols\n                                   u\"\\U0001F1E0-\\U0001F1FF\"  # flags (iOS)\n                                   u\"\\U00002702-\\U000027B0\"\n                                   u\"\\U000024C2-\\U0001F251\" \"]+\")\n        text = emoji_pattern.sub(r'', text)\n    \n        text = re.sub(r\"[^a-zA-Z\\d]\", \" \", text) #Remove special Charecters\n        text = re.sub(' +', ' ', text) #Remove Extra Spaces\n        text = text.strip() # remove spaces at the beginning and at the end of string\n\n        return text\n    \n    def text_split(text):\n        split_line = text.split(' ')\n        if(len(split_line) > 160):\n            text = ' '.join(split_line[:160]) + ' ' + ' '.join(split_line[-32:])\n            \n        return text\n    \n    process_text = sub_text(text)\n    process_text = text_split(process_text)\n    \n    return process_text","metadata":{"execution":{"iopub.status.busy":"2022-05-30T01:44:14.793072Z","iopub.execute_input":"2022-05-30T01:44:14.793389Z","iopub.status.idle":"2022-05-30T01:44:14.806643Z","shell.execute_reply.started":"2022-05-30T01:44:14.793359Z","shell.execute_reply":"2022-05-30T01:44:14.805845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def tk_encode(texts, tokenizer, maxlen=512):\n    \"\"\"\n    return_tensors : {\"PyTorch\" : 'pt'}, {\"TensorFlow\": 'tf'}, {\"NumPy\": 'np'} \n    \"\"\"\n    enc_di = tokenizer.batch_encode_plus(\n        texts, \n        return_attention_mask=True, \n        return_token_type_ids=False,\n        pad_to_max_length=True,\n        max_length=maxlen,\n        truncation=True,\n        return_tensors='tf'\n    )\n    \n    return {\n        \"input_ids\": enc_di['input_ids'],\n        \"attention_mask\": enc_di['attention_mask']\n    }","metadata":{"papermill":{"duration":0.026944,"end_time":"2020-09-14T10:32:33.120544","exception":false,"start_time":"2020-09-14T10:32:33.0936","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-05-30T01:44:14.80789Z","iopub.execute_input":"2022-05-30T01:44:14.808217Z","iopub.status.idle":"2022-05-30T01:44:14.820226Z","shell.execute_reply.started":"2022-05-30T01:44:14.808187Z","shell.execute_reply":"2022-05-30T01:44:14.819431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## TPU configs\n- Use of TPU","metadata":{"papermill":{"duration":0.019688,"end_time":"2020-09-14T10:32:35.727854","exception":false,"start_time":"2020-09-14T10:32:35.708166","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Detect hardware, return appropriate distribution strategy\ntry:\n    # TPU detection. No parameters necessary if TPU_NAME environment variable is\n    # set: this is always the case on Kaggle.\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n    print('Running on TPU ', tpu.master())\nexcept ValueError:\n    tpu = None\n\nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\nelse:\n    # Default distribution strategy in Tensorflow. Works on CPU and single GPU.\n    strategy = tf.distribute.get_strategy()\n\nprint(\"REPLICAS: \", strategy.num_replicas_in_sync)","metadata":{"papermill":{"duration":5.350186,"end_time":"2020-09-14T10:32:41.097859","exception":false,"start_time":"2020-09-14T10:32:35.747673","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-05-30T01:44:14.821725Z","iopub.execute_input":"2022-05-30T01:44:14.822065Z","iopub.status.idle":"2022-05-30T01:44:21.225521Z","shell.execute_reply.started":"2022-05-30T01:44:14.82203Z","shell.execute_reply":"2022-05-30T01:44:21.224371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Configuration\nMODEL = 'jplu/tf-xlm-roberta-large' # bert-base-uncased\nAUTO = tf.data.experimental.AUTOTUNE\nSEED = 42\nEPOCHS_1 = 20\nEPOCHS_0 = 100\nEPOCHS_2 = 2\nBATCH_SIZE = 16 * strategy.num_replicas_in_sync\nMAX_LEN = 192\nSHUFFLE = 2048\nVERBOSE = 1","metadata":{"papermill":{"duration":0.030241,"end_time":"2020-09-14T10:32:41.149549","exception":false,"start_time":"2020-09-14T10:32:41.119308","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-05-30T01:44:21.226932Z","iopub.execute_input":"2022-05-30T01:44:21.227155Z","iopub.status.idle":"2022-05-30T01:44:21.233348Z","shell.execute_reply.started":"2022-05-30T01:44:21.22713Z","shell.execute_reply":"2022-05-30T01:44:21.232358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Conversion\n\nConsider garbage collection.","metadata":{"papermill":{"duration":0.020699,"end_time":"2020-09-14T10:32:41.19124","exception":false,"start_time":"2020-09-14T10:32:41.170541","status":"completed"},"tags":[]}},{"cell_type":"code","source":"train.toxic = train.toxic.round().astype(int)\ntrain = train.sample(frac=1, random_state=SEED)\nvalid = valid.sample(frac=1, random_state=SEED)","metadata":{"execution":{"iopub.status.busy":"2022-05-30T01:44:21.234961Z","iopub.execute_input":"2022-05-30T01:44:21.235273Z","iopub.status.idle":"2022-05-30T01:44:21.309523Z","shell.execute_reply.started":"2022-05-30T01:44:21.235234Z","shell.execute_reply":"2022-05-30T01:44:21.308621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\ntrain['comment_text'] = train['comment_text'].apply(lambda x: text_preprocessing(x))\nvalid['comment_text'] = valid['comment_text'].apply(lambda x: text_preprocessing(x))\ntest['content'] = test['content'].apply(lambda x: text_preprocessing(x))","metadata":{"execution":{"iopub.status.busy":"2022-05-30T01:44:21.312425Z","iopub.execute_input":"2022-05-30T01:44:21.312726Z","iopub.status.idle":"2022-05-30T01:44:21.828724Z","shell.execute_reply.started":"2022-05-30T01:44:21.312695Z","shell.execute_reply":"2022-05-30T01:44:21.827787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import psutil \nfrom termcolor import colored\n\n# Obtain memory capacity\nmem = psutil.virtual_memory() \nprint(f\"total_memory: {colored(mem.total, 'yellow')}, memory_used: {colored(mem.used, 'yellow')}, memory_available, {colored(mem.available, 'yellow')}\")\nprint(f\"memory_used_per: {((mem.used / mem.total) * 100) :.0f}%\")\nprint(f\"available_memory: {((mem.available / mem.total) * 100) :.0f}%\")","metadata":{"execution":{"iopub.status.busy":"2022-05-30T01:44:21.829856Z","iopub.execute_input":"2022-05-30T01:44:21.830124Z","iopub.status.idle":"2022-05-30T01:44:21.837247Z","shell.execute_reply.started":"2022-05-30T01:44:21.830095Z","shell.execute_reply":"2022-05-30T01:44:21.836366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_train_steps = train.shape[0] // (BATCH_SIZE * 8)\nn_valid_steps = valid.shape[0] // (BATCH_SIZE)\n\n\n#del train1\n#gc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-05-30T01:44:21.838062Z","iopub.execute_input":"2022-05-30T01:44:21.83827Z","iopub.status.idle":"2022-05-30T01:44:21.851462Z","shell.execute_reply.started":"2022-05-30T01:44:21.838246Z","shell.execute_reply":"2022-05-30T01:44:21.85057Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# First load the real tokenizer\ntokenizer = AutoTokenizer.from_pretrained('jplu/tf-xlm-roberta-large') # bert-base-uncased","metadata":{"execution":{"iopub.status.busy":"2022-05-30T01:44:21.85248Z","iopub.execute_input":"2022-05-30T01:44:21.852814Z","iopub.status.idle":"2022-05-30T01:44:26.110275Z","shell.execute_reply.started":"2022-05-30T01:44:21.852773Z","shell.execute_reply":"2022-05-30T01:44:26.109286Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time \nx_train = tk_encode(list(train.comment_text.values), tokenizer, maxlen=MAX_LEN)\nx_valid = tk_encode(list(valid.comment_text.values), tokenizer, maxlen=MAX_LEN)\nx_test = tk_encode(list(test.content.values), tokenizer, maxlen=MAX_LEN)\n\ny_train = train.toxic.values\ny_valid = valid.toxic.values\n\ndel train, valid\ngc.collect()","metadata":{"papermill":{"duration":324.393881,"end_time":"2020-09-14T10:39:25.086531","exception":false,"start_time":"2020-09-14T10:34:00.69265","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-05-30T01:44:26.113738Z","iopub.execute_input":"2022-05-30T01:44:26.114006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dataset objects\n- If the data set is small enough to fit in memory, caching it in RAM using the cache() method of the data set will save a lot of time.\n- Caching in RAM should be done after pre-processing the data before loading, shuffling, repeating, splitting into batches, and prefetching.","metadata":{"papermill":{"duration":0.021058,"end_time":"2020-09-14T10:39:25.128116","exception":false,"start_time":"2020-09-14T10:39:25.107058","status":"completed"},"tags":[]}},{"cell_type":"code","source":"train_dataset = (\n    tf.data.Dataset.from_tensor_slices((x_train, y_train))\n    .repeat()\n    .shuffle(SHUFFLE)\n    .batch(BATCH_SIZE)\n    .prefetch(AUTO)\n)\n\n\nvalid_dataset = (\n    tf.data.Dataset.from_tensor_slices((x_valid, y_valid))\n    .batch(BATCH_SIZE)\n    .cache()\n    .prefetch(AUTO)\n)\n\n\ntest1_dataset = (\n    tf.data.Dataset.from_tensor_slices(x_test)\n    .batch(BATCH_SIZE)\n)\n\ndel x_train, x_valid, y_train, y_valid, x_test, \ngc.collect()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Callbacks\n\n* Create custom callbacks and introduce over-learning sensing","metadata":{"papermill":{"duration":0.020471,"end_time":"2020-09-14T10:39:30.869121","exception":false,"start_time":"2020-09-14T10:39:30.84865","status":"completed"},"tags":[]}},{"cell_type":"code","source":"class ValTrainRatioCustomCallback(tf.keras.callbacks.Callback):\n    def on_epoch_end(self, epoch, logs):\n        print(\"\\nval/train: {:.2f}\".format(logs[\"val_loss\"] / logs[\"loss\"]))\n        \ncustom_call = ValTrainRatioCustomCallback()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learning_rate_reducation = ReduceLROnPlateau(monitor=\"val_accuracy\", patience=2, mode=\"max\", verbose=0, factor=0.7, min_lr=1e-7)\nearly_stopping = EarlyStopping(monitor=\"val_accuracy\", patience=5, mode=\"max\", verbose=0, restore_best_weights=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callbacks_list = [learning_rate_reducation, early_stopping, custom_call]","metadata":{"papermill":{"duration":0.03098,"end_time":"2020-09-14T10:39:30.920611","exception":false,"start_time":"2020-09-14T10:39:30.889631","status":"completed"},"tags":[],"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Build model\n- When classifying, problems may occur in internal tracking and model storage, so it is better to use the sequential or functional API unless this flexibility is absolutely necessary.\n- In the following, the functional API is used to connect each layer.","metadata":{"papermill":{"duration":0.020872,"end_time":"2020-09-14T10:39:30.962458","exception":false,"start_time":"2020-09-14T10:39:30.941586","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def build_model(transformer, max_len=512):\n    input_word_ids = Input(shape=(max_len,), dtype=tf.int32, name=\"input_ids\")\n    attention_mask = Input(shape=(max_len,), dtype=tf.int32, name=\"attention_mask\")\n    sequence_output = transformer({\"input_ids\": input_word_ids, \"attention_mask\": attention_mask})[0]\n\n    avg_pool = GlobalAveragePooling1D()(sequence_output)\n    max_pool = GlobalMaxPooling1D()(sequence_output)\n    cls_token = Concatenate()([avg_pool, max_pool])\n    \n    samples = []\n    for n in range(2):\n        sample = Dropout(0.4)(cls_token)\n        sample = Dense(1, activation='sigmoid', name=f'sample_{n}')(sample)\n        samples.append(sample)\n    \n    out = Average(name='output')(samples)\n    model = Model(inputs={\n                \"input_ids\": input_word_ids,\n                \"attention_mask\": attention_mask\n                }, \n                outputs=out,\n                name='XLM-R')\n    model.compile(Adam(lr=1e-5), loss='binary_crossentropy', metrics=[tf.keras.metrics.AUC(name='auc'), 'accuracy'])\n    \n    return model","metadata":{"papermill":{"duration":0.034992,"end_time":"2020-09-14T10:39:31.018124","exception":false,"start_time":"2020-09-14T10:39:30.983132","status":"completed"},"tags":[],"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load to TPU","metadata":{"papermill":{"duration":0.020645,"end_time":"2020-09-14T10:39:31.059685","exception":false,"start_time":"2020-09-14T10:39:31.03904","status":"completed"},"tags":[]}},{"cell_type":"code","source":"%%time\nwith strategy.scope():\n    transformer_layer = TFAutoModel.from_pretrained(MODEL)\n    model = build_model(transformer_layer, max_len=MAX_LEN)\nmodel.summary()","metadata":{"papermill":{"duration":142.229783,"end_time":"2020-09-14T10:41:53.30972","exception":false,"start_time":"2020-09-14T10:39:31.079937","status":"completed"},"tags":[],"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Run model","metadata":{"papermill":{"duration":0.024162,"end_time":"2020-09-14T10:41:53.360801","exception":false,"start_time":"2020-09-14T10:41:53.336639","status":"completed"},"tags":[]}},{"cell_type":"code","source":"model_history_1 = model.fit(\n    train_dataset,\n    steps_per_epoch=n_train_steps,\n    validation_data=valid_dataset,\n    epochs=EPOCHS_1,\n    callbacks=callbacks_list,\n    verbose=VERBOSE\n )","metadata":{"papermill":{"duration":2129.665644,"end_time":"2020-09-14T11:17:23.051354","exception":false,"start_time":"2020-09-14T10:41:53.38571","status":"completed"},"tags":[],"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Blending","metadata":{"papermill":{"duration":1.510705,"end_time":"2020-09-14T11:19:24.617701","exception":false,"start_time":"2020-09-14T11:19:23.106996","status":"completed"},"tags":[]}},{"cell_type":"code","source":"#Blending\nmulti_sub = model.predict(test1_dataset, verbose=1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub['toxic'] = multi_sub * 1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**[Post-processing](https://www.kaggle.com/c/jigsaw-multilingual-toxic-comment-classification/discussion/160980)**\n* Reasons for the following processes","metadata":{}},{"cell_type":"code","source":"sub.loc[test[\"lang\"] == \"es\", \"toxic\"] *= 1.11\nsub.loc[test[\"lang\"] == \"fr\", \"toxic\"] *= 1.06\nsub.loc[test[\"lang\"] == \"it\", \"toxic\"] *= 0.93\nsub.loc[test[\"lang\"] == \"pt\", \"toxic\"] *= 0.92\nsub.loc[test[\"lang\"] == \"tr\", \"toxic\"] *= 0.94","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# min-max normalize\nsub.toxic -= sub.toxic.min()\nsub.toxic /= (sub.toxic.max() - sub.toxic.min())\nsub.toxic.hist(bins=100, log=False, alpha=1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#test = pd.read_csv('../input/jigsaw-multilingual-toxic-comment-classification/test.csv')\npred_test = pd.merge(test, sub)\npred_test.sort_values(by='toxic', ascending=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Submission","metadata":{"papermill":{"duration":1.794411,"end_time":"2020-09-14T11:21:52.125678","exception":false,"start_time":"2020-09-14T11:21:50.331267","status":"completed"},"tags":[]}},{"cell_type":"code","source":"sub.to_csv('submission.csv', index=False)","metadata":{"papermill":{"duration":2.126567,"end_time":"2020-09-14T11:21:55.986587","exception":false,"start_time":"2020-09-14T11:21:53.86002","status":"completed"},"tags":[],"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import psutil \nfrom termcolor import colored\n\n# メモリ容量を取得\nmem = psutil.virtual_memory() \nprint(f\"total_memory: {colored(mem.total, 'yellow')}, memory_used: {colored(mem.used, 'yellow')}, memory_available, {colored(mem.available, 'yellow')}\")\nprint(f\"memory_used_per: {((mem.used / mem.total) * 100) :.0f}%\")\nprint(f\"available_memory: {((mem.available / mem.total) * 100) :.0f}%\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}