WordPress.com で次のようなサイトをデザイン
始めてみよう

【AWS】 Lambdaレイヤーでnumpy・pandasを追加

こんにちは、薬学生です。今回は、AWSのLambdaでnumpy・pandasをレイヤーとして追加するのに結構手間取ったため、どのようにしてレイヤーを追加したかを紹介していきたいと思います…

目次

はじめに

こんにちは、薬学生です。

今回は、AWSのLambdaでnumpy・pandasをレイヤーとして追加するのに結構手間取ったため、どのようにしてレイヤーを追加したかを紹介していきたいと思います。

なお、ここではPythonのデフォルトのライブラリではなく、pandasやnumpyといった、pipなどを利用してインストールする必要があるライブラリを想定しています。

全体の流れ

まず、全体としてどのような流れで実行したかを紹介します。

  1. Dockerを利用して、Lambdaが動作する環境を構築する
  2. Docker内でレイヤーに必要なライブラリをインストール・zip化する
  3. Dockerからローカルにzipフォルダを移行する
  4. zipフォルダをAWS上でアップロードしてレイヤーを作る

個人的にDockerを使い慣れていなかったり、アップロードするファイルの決まりがあることに気が付かなかったため、1~3に時間がかかってしまいました。それでは順を追って見ていきます。

手順1:DockerでLambda環境を構築

まず最初に、DockerでLambdaの環境を構築します。そもそもローカルではなくDockerで環境を構築する必要がある理由としましては、ローカルでライブラリを用意した場合、「invalid ELF header」とエラーが出てしまったからです。このエラーについては、「インストール時に環境に応じてheaderの情報が異なる」ことが原因のため起きるとのことです(こちらの記事を参考にさせていただいております。また、Lambdaで正しく動作すれば良いというスタンスですので、細かい部分は気にし過ぎす進めています)。

という訳で、Dockerを使ってLambdaと同じ環境を構築していくこととしました。先ほどの記事では「lambci/lambda」利用していましたが、この記事を書いている2022年3月現在、Python3.9はまだ非対応でした。

そのためこちらの記事を参考に、Amazon Linux2・Python3.9のDockerイメージ※を用意しました。

※こちらの組み合わせがLambdaの実行環境とのことです。なお、Amazon Linux2ではなく、LinuxがLambdaの実行環境だと述べている記事もあり、どちらが正確かは分かりません。私自身はAmazon Linux2の環境で用意したライブラリで正しく動作したため、ひとまずここではLunux2で話を進めていきます。

詳しくは先ほど紹介した記事の通りですが、コマンドを紹介しておきます。

$ docker pull amazonlinux:latest

Dockerfileを用意する。先ほど紹介したサイトからダウンロードできます。ファイルの中身は以下です。

FROM amazonlinux:latest
 
RUN yum install -y gcc openssl-devel bzip2-devel libffi-devel wget zip tar gzip make && \
    cd /opt && \
    wget https://www.python.org/ftp/python/3.9.6/Python-3.9.6.tgz && \
    tar xzf Python-3.9.6.tgz && \
    /opt/Python-3.9.6/configure --enable-optimizations && \
    make altinstall && \
    rm -f /opt/Python-3.9.6.tgz && \
    python3.9 -m pip install --upgrade pip

上記のDockerfileがあるディレクトリに移動して、以下3行を実行。なお、1行目の最後のピリオドは入力ミスではなく必要ですので注意です。

$ docker build -t amazonlin2_py39 .

$ docker run -it -d --name amznlin2_py39_cont amazonlin2_py39
$ docker exec -it amznlin2_py39_cont bash

これでDockerの環境構築は完了です。

手順2:Dockerでライブラリをインストール・zip化

次に、Docker内でレイヤーとして組み込みたいライブラリをインストール・zip化していきます。なお、こちらで注意してほしいのが、ディレクトリ名を「python」または「python/lib/python3.●/site-packages」にする必要がある点です(●は利用したいpythonのバージョン)。

サイトによってはこの点を全く触れていなかったりするので、かなり躓きやすいポイントかと思います。(事実、私はここでかなり苦戦しました)

$ mkdir python

$ pip install -t ./python pandas
$ zip -r pandas.zip python

手順3:Dockerからzipファイルをローカルへ移動

zip化まで終わったら、Docker内のファイルをローカルに移動させましょう。まず、手順2ではDockerの環境内で操作をしていたと思いますので、「Ctrl + p, q」と入力してコンテナからログアウトします。

そして以下のコマンドを入力することで、コンテナのIDを確認します。

$ docker ps

確認したコンテナIDを利用して、ローカルにコンテナ内のファイルを移動します。

$ docker cp コンテナID:/pandas.zip ./

手順4:AWSでレイヤーを作成

ここまでくると、あとはAWS上でzipファイルをアップロードしてレイヤーを作成するだけですので簡単です。こちらのサイトなどでやり方が紹介されていますので参考にしてみてください。

おわりに

以上、AWSのLambdaでレイヤーを追加する方法でした。個人的に、pandasとかnumpyとかは用意しておいてくれてもいいのでは??と感じました(記事によってはデフォルトでnumpyはあると書いていましたが分かりませんでした)。この調子でAWSを使っていこうと思います。それではまた〜

参考文献

【参考】これまで読んできたPython参考書紹介

はじめに 今回は、これまでPythonの関係で読んできた本を紹介したいと思います。なお、もし購入される場合には、こちらのリンクから購入いただけますと幸いです…

目次

はじめに

今回は、これまでPythonの関係で読んできた本を紹介したいと思います。なお、もし購入される場合には、こちらのリンクから購入いただけますと幸いです。

Python基礎

独学プログラマー Python言語の基本から仕事のやり方まで

初めに読んだのはこの書籍でした。とても初歩的な内容をカバーしてくれているので、最初の一冊に向いている印象です。

ニューラルネットワーク

最短コースでわかる PyTorch &深層学習プログラミング

こちらはPytorchの入門書になります。Pytorchの中でどのような処理が行われているのかを理解することができ、脱ブラックボックス化が図れると思います。個人的に、Pytorch公式のチュートリアルやQiitaで断片的な知識しか身についていなかったため、とても重宝しております。

つくりながら学ぶ! PyTorchによる発展ディープラーニング

こちらは、上記のPytorchの入門書と比べると、圧倒的に上級者向けの内容になっています。フルスクラッチでニューラルネットワークを作れるようになりたい方はこちらを参考にすると良いかと思います。

コンペ特化

Kaggleで勝つデータ分析の技術

こちらの書籍は、SINGATEやKaggleに参加するようになってから、購入しました。精度を上げるためのチップスが多数掲載されておりますので、コンペで行き詰まった時などにお世話になっています。

そのほか

図解即戦力 Google Cloudのしくみと技術がこれ1冊でしっかりわかる教科書

こちらについては、今後読む予定の書籍になります。

おわりに

以上がこれまでに読んできた書籍になります。こうして振り返ると、インターネットで多くの情報を入手できるためというのはありますが、ほとんど書籍を読んでいませんね。。精進していきたいと思います。もしも参考になるようでしたら嬉しいです。これからも読んだ本をここに追加していきたいと思います。

【銀メダル獲得】SIGNATE医学論文の自動仕分けチャレンジの振り返り

はじめに 今回、SIGNATEの『医学論文の自動仕分けチャレンジ』に参加いたしました。こちらのコンペは、論文のタイトル・アブストラクトのテキストデータを用いて…

目次

はじめに

今回、SIGNATEの『医学論文の自動仕分けチャレンジ』に参加いたしました。こちらのコンペは、論文のタイトル・アブストラクトのテキストデータを用いて、システマティックレビューの対象となる文献か否か(2値)を判定するアルゴリズムを作成し、その精度を競うコンペでした。詳しいルールや評価方法などは、公式サイトをご確認ください。

コンペ終了に関する SIGNATEの公式Twitter 2021/10/05

こちらのコンペはリーダーボードスコアと最終スコアの乖離が大きく、順位のシャッフルが結構あるコンペでした。私自身は、リーダーボードスコアでは60位くらいでしたが、最終的に638人中40位で銀メダルを獲得することができました。大体上位6%程度ですかね。まずまずの結果を出せたのかと思います。

今回は、このコンペに参加する中で実践したこと、気づいたことを簡単に書き留めておこうと思います。

モデルの作成

今回はpytorchでニューラルネットワークモデルを構築しました。TensorFlow(keras)でも問題ないかと思うのですが、利用できる事前学習済みのBERT(Bidirectional Encoder Representations from Transformers)モデルの種類がpytorchの方が多いとの話でしたので、pytorchを利用しました。なお、コードの直感的な理解のしやすさで言うと、圧倒的にkerasがオススメです。レイヤーを積み重ねていく感じがとてもわかりやすいと思います。

なお、実際にモデルを作成するときは、こちらのフォーラムを大変参考にさせていただきました。その他、参考にさせていただいた記事を紹介しておきます。

Kaggle : CommonLit Readability Prizeコンペ
こちらはKaggleで開催された自然言語に関するコンペです。同じように文書の分類問題であり、pytorch・TensorFlowを利用してモデルを作成している方が多く、評価が高いものを中心にモデルを真似させていただきました。KaggleではSIGNATEと比べて多くの方がコードを公開してくれているのでとても参考になりますよね。

BERTのfine-tuningに関する記事
こちらの記事はBERTのfine-tuningに関する記事です。記事の後編が9月初め頃に公開されており、事前学習モデルの精度を向上させるための手法を掲載してくれています。こちらの手法を上から順に真似して利用させていただきました。

以上の記事を参考にしつつ、9月中はGoogle Colaboratoryでひたすらモデルを回し続けました。アーリーストップを何回に設定するかにもよりますが、場合によっては1モデルの学習に7時間以上かかることがあるため作業の合間にモデルを回す感じでした。Colab Proを利用していましたが、場合によってはColab Pro+に課金するのもありですね。

結果として、個別のモデルではリーダーボードのスコアで0.915台が限界でした。なお、最終結果を見るとアンダーサンプリングを実施したモデルなどで0.936台になっていました。ただ、リーダーボードスコアは0.90台でしたのでそのモデルを最終提出用に選ぶのは現実的ではありませんね。難しい。。

アンサンブル

パラメータや、モデルのレイヤーを変更したりして、ある程度モデルを作り終えた後に、アンサンブルを実施しました。実はアンサンブルの効果を甘く見ていたのですが、アンサンブルのおかげで安定して高精度の予測を出力することができました。考えてみるとモデルの数が増えれば増えるほどばらつきは小さくなるため、安定して真値に近い予測を出力できますね

ただ、1回モデルを学習させるにつきGoogleドライブが2GB程度圧迫される状況だったため、何も考えずに生成したモデルの大半を削除してしまっていました、、。とりあえず出力結果は全て保存しておくことが無難ですね。結果として20以上のモデルを生成していたのにも関わらず、最終的には5つのモデルのアンサンブルを提出して終了することとなりました。

また、アンサンブルを甘く見ていたため、アンサンブルに費やす時間を十分に確保していなかったことも失敗でした。今回は、5モデルの多数決で判定を行うこととしましたが、スタッキングなどの手法を試すための時間をとっておくべきでした。

反省点

今回のコンペでは、以下の点が甘かったなとつくづく感じています。

  • 探索的データ分析(EDA)・モデル学習・アンサンブルの時間配分・スケジュール管理
  • アンサンブルの過小評価

1つ目の時間配分・スケジュール管理について、初めてpytorchに触ったということもあり、そこまで時間配分を気にせずに取り組んでしまっていました。今振り返ると、時間配分はもちろんのこと、どのようなプロセスが必要かを念頭に置いて作業していれば、誤ってデータを削除するといったこともなかったなと悔やまれます。また、スケジュール管理はコンペに限った話ではなく、プロジェクトを進めるにあたってとても重要な要素ですので、以後気をつけていきたいと思います。

また、2つ目のアンサンブルを過小評価していた点は、自身の経験不足を痛感させられました。次のコンペから活かしていきたいですね。

おわりに

非常にざっくりですが、SIGNATEの論文チャレンジに関する振り返りをこれで終えようと思います。初めてpytorch・BERTを触ったため急ピッチで臨むこととなりましたが、予想以上の結果となり満足しております。ただ、コンペの進め方などを十分に煮詰められておらず、ベストなモデルを提出できなかったことが悔やまれます。。。

Kaggleにてテーブルデータのコンペがいくつか始まっていますので、今回の経験を活かしつつ上位入賞を目指していきたいと思います。

【Pythonコード紹介】【実体験】OpenSeaでNFTを販売して実感したこと

はじめに

こちらの記事は、以下の記事に関連するPythonのコードの紹介になります。もし、本編の記事を読んでいない場合には、まずそちらをご覧ください…

はじめに

こちらの記事は、以下の記事に関連するPythonのコードの紹介になります。もし、本編の記事を読んでいない場合には、まずそちらをご覧ください。また、本編は仮想通貨とは全く関係のない内容になっております。

実際のコード

では、ざっとコードを紹介します。 Scikit-imageというライブラリが優秀ですね。これによってinput_pathに保存されている写真をモザイクアートに変換することができます。

import glob

from skimage import color
from skimage import io
from skimage import segmentation

input_path = "加工前の写真のフォルダ"
output_path = "加工後の写真の保存フォルダ"

files = glob.glob(input_path +"*")   # 加工する写真のパスを取得

for file in files:
    file_name = file[-10:-5]  #写真の名前を取得
    
    # モザイク化
    img = io.imread(file)
    label = segmentation.slic(img, compactness=30)

    # 保存
    out = color.label2rgb(label, img, kind='avg')
    io.imsave(output_path + file_name + "_re.png", out)

こうして出来上がった作品が以下の通りになります。いや〜プログラミングって便利ですね。最近は加工アプリも出ているのでわざわざプログラムを書かなくても簡単に加工ができますしね。

おわりに

以上、簡単ですがPythonでのコードを紹介しました。需要があるかは分かりませんが、今後はたまにプログラミングについても更新していきたいです。

OpenSeaで販売することも、自分で体験できてよかったと思っています。本腰を入れてNFTを売り出していくつもりはないですが、せっかくなのでモザイクアートのアカウントは残すつもりですし、気が向いたら風景画を足していこうかなと思っています。もし、CryptoMosaicを入手してみたいという方がいらっしゃいましたら差し上げます(もちろん購入いただいても大丈夫です)のでTwitterでご連絡ください。

jupyter notebookでkerasが動作しなくなった時の対処方法

症状について TensorFlowのチュートリアルとして公式サイトで紹介されている、「mnist」という手書きの数字を認識させるコードを見様見真似でjupyter notebookで動作させていました…

症状について

TensorFlowのチュートリアルとして公式サイトで紹介されている、「mnist」という手書きの数字を認識させるコードを見様見真似でjupyter notebookで動作させていました。
コードの全文は以下。

import tensorflow as tf
mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)

これを上から順に動かしていたところ、以下のモデルを用いて学習させるところでつまずきました。

model.fit(x_train, y_train, epochs=5)

実際にjupyter notebook上では、以下のエラーが表示されました。

Kernel Restarting
The kernel appears to have died. It will restart automatically.

これを読むと、kernelが何らかの原因により停止してしまったということは理解できますが、原因がなんなのか全く分かりません。

そこで、ターミナルを確認したところ、以下の通りエラーが出ていました。

OMP: Error #15: Initializing libiomp5.dylib, but found libiomp5.dylib already initialized.
OMP: Hint This means that multiple copies of the OpenMP runtime have been linked into the program. 
That is dangerous, since it can degrade performance or cause incorrect results.
The best thing to do is to ensure that only a single OpenMP runtime is linked into the process, e.g. by avoiding static linking of the OpenMP runtime in any library. 
As an unsafe, unsupported, undocumented workaround you can set the environment variable KMP_DUPLICATE_LIB_OK=TRUE to allow the program to continue to execute, but that may cause crashes or silently produce incorrect results. 
For more information, please see http://www.intel.com/software/products/support/.

解決策

OMPについての知識が全くないのですが、ターミナルのエラーに記載があるように、応急措置として、環境変数を設定することによって対処可能とあります。

実際に、jupyter notebook上で、以下のコードを読み込ませた後に、先ほどエラーが出たコードを動作させたところ、問題なく動作しました。

import os

os.environ['KMP_DUPLICATE_LIB_OK']='True'

ひとまずこれで解決しましたが、ターミナル上のエラーによると、この措置だとプログラムがクラッシュしたり、誤った結果を返す場合があるとのことです。

抜本的な解決策については、今後探していくこととしたいと思います。ひとまずこれにて。
また、正しい解決方法をご存知の方がおりましたらご連絡いただけると幸いです。

(備忘録:参考にしたサイト)
https://github.com/dmlc/xgboost/issues/1715

macOS CatalinaをインストールしてAnacondaが起動しなくなった時の対処方法

はじめに試したこと 2019年10月に、Appleから新たにmacOS Catalinaが公開されました。私は最近まで、特段不便もなかったのでアップデートしていなかったのですが、ふとXcodeを使いたくなり、ダウンロードしようとしたところ、OSが古くてダウンロードできない…

はじめに試したこと

2019年10月に、Appleから新たにmacOS Catalinaが公開されました。
私は最近まで、特段不便もなかったのでアップデートしていなかったのですが、ふとXcodeを使いたくなり、ダウンロードしようとしたところ、OSが古くてダウンロードできないことが判明したためmacOS Catalinaにアップデートすることにしました。

Catalinaへのアップデートはスムーズに終わったのですが、さてjupyter notebookを起動しようかと思ったら、起動できず、、
調べたところ、どうやらAnacondaのディレクトリの位置が更新によって変わってしまっていたことが原因のようでした。

そこで、以下のサイトを見ながら、zshで操作をしました

macOS Catalina にしたら、Anaconda 使えなくなった場合の対処法

、、、が、なぜかうまく起動できず。
zshの場合はPATHを設定しなければならないという記事も見かけていろいろと試行錯誤するも以下の通りのエラーが出てしまいました。。

zsh: command not found: conda

解決策

最終的に、Anacondaの公式が出している以下の記事にたどり着きました。

How to Restore Anaconda after Update to MacOS Catalina

この記事によると、私が試した方法は部分的な解決にしかならず、PATHを設定するのは問題があるとのことでした。
こちらの記事で紹介されていた解決方法として、以下の2つがあります。
  ・再インストール(Reinstallation)
  ・修復(Repair)

再インストール(Reinstallation)

これは実にシンプルです。
Anacondaのサイトから改めてインストールを行いました。
特段こだわりがなければこれが一番良いと思われます。

Anacondaのダウンロード(Anaconda Distribution)

修復(Repair)

こちらについては私は実施していないのでコードを紹介するのみになります。
詳しくは先ほど示したサイトを参考にしてください。

1. At a terminal, download the file and make it executable:
1. ターミナルでファイルをダウンロードし実行する

curl -L https://repo.anaconda.com/pkgs/misc/cpr-exec/cpr-0.1.1-osx-64.exe -o cpr && chmod +x cpr

2. Run the CPR tool to fix embedded paths:
2. CPRを用いてパスを修正する

./cpr rehome ~/anaconda3

3. Re-run conda init to fix your conda shell command:
3. conda initを再起動する(zshの場合はbashの代わりにzshと入力)

source ~/anaconda3/bin/activate

conda init bash

以上になります。ご参考になれば幸いです。

言語処理100本ノックをやってみた 第1章②

はじめに 言語処理の問題集として有名な、言語処理100本ノックを解いた回答をまとめてます。今回は前回の続きになります…

はじめに

言語処理の問題集として有名な、言語処理100本ノックを解いた回答をまとめてます。
今回は前回の続きになります。

第1章:準備運動

05. n-gram

与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.この関数を用い,”I am an NLPer”という文から単語bi-gram,文字bi-gramを得よ.

phrase2 = "I am an NLPer"


def n_gram(phrase, n, word=True):
    outcome_list = []
    if word == True:
        phrase_list = phrase.split()
        for i in range(len(phrase_list) - n + 1):
            outcome_list.append(phrase_list[i:i+n])
        return outcome_list
    else: #incluede or exclude space?
        phrase = phrase.replace(" ", "")
        for i in range(len(phrase) - n + 1):
            outcome_list.append(phrase[i:i+n])
        return outcome_list

    
print(n_gram(phrase2, 2, word=True))  
print(n_gram(phrase2, 2, word=False))  
>[['I', 'am'], ['am', 'an'], ['an', 'NLPer']]
>['Ia', 'am', 'ma', 'an', 'nN', 'NL', 'LP', 'Pe', 'er']

N-gramに関する問題です。
N-gramについては以下の記事を参照してください。

自然言語解析:「N-gram」について

このN-gramは英語を想定して作成しています。文字単位か単語単位かを指定して、それぞれについて、空のリストに分割された文字列を追加しています。

06. 集合

“paraparaparadise”と”paragraph”に含まれる文字bi-gramの集合を,それぞれ, XとYとして求め,XとYの和集合,積集合,差集合を求めよ.さらに,’se’というbi-gramがXおよびYに含まれるかどうかを調べよ.

x = "paraparaparadise"
y = "paragraph"

X = n_gram(x, 2, word=False)
Y = n_gram(y, 2, word=False)


def set_func(z):
    lst = set()
    for i in range(len(z)):
        lst.add(z[i])
    return lst


X = set_func(X)
Y = set_func(Y)

X_or_Y = X | Y
X_and_Y = X & Y
X_but_Y = X - Y

print (X_or_Y, X_and_Y, X_but_Y)

print("se is in X? :", "se" in X)
print("se is in Y? :", "se" in Y)
>{'pa', 'di', 'se', 'ap', 'ad', 'ar', 'is', 'ag', 'ph', 'ra', 'gr'} {'ar', 'pa', 'ap', 'ra'} {'ad', 'is', 'di', 'se'}
>se is in X? : True
>se is in Y? : False

ポイント

set( ), { }
setオブジェクト
・集合を表現するオブジェクト
・集合の演算に用いることができる

setオブジェクトの用例
add( ):オブジェクトに要素を追加
|, union( ):和集合、A∪B
&, intersection( ):積集合、A∩B
-, difference( ):差集合、A∩‾B(Bの上に棒線)

前の問題で作成したN-gramを利用しています。
あとは、それぞれの単語のbigramをsetオブジェクトにして、和集合・積集合・差集合をとっています。

07. テンプレートによる文生成

引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ.さらに,x=12, y=”気温”, z=22.4として,実行結果を確認せよ.

x1 = 12
y1 = "気温"
z1 = 22.4


def template(x, y, z):
    return "{}時の{}は{}".format(x, y, z)


print(template(x1, y1, z1))
>12時の気温は22.4

ポイント

"{ }".format( )
format( )関数
・文字列に変数を埋め込める関数

これは実にシンプルです。format( )関数を用いてます。

08. 暗号文

与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.
 ・英小文字ならば(219 – 文字コード)の文字に置換
 ・その他の文字はそのまま出力
この関数を用い,英語のメッセージを暗号化・復号化せよ.

def cipher(word, encryption=True):
    coded = ""
    decoded = ""
    alpha = "abcdefghijklmnopqrstuvwxyz"
    if encryption == True:
        for x in word:
            if x in alpha:
                coded += (chr(219 - ord(x)))
            else:
                coded += x
        return coded
    else:
        for x in word:
            if x in alpha:
                decoded += chr(219 - ord(x))
            else:
                decoded += x
        return decoded
                
    
print(cipher("abdあ"))
print(cipher("zywあ", encryption=False))
>zywあ
>abdあ

ポイント

ord( )
chr( )
ord( )関数
・入力された文字のアスキーコードをreturnする関数

chr( )関数
・入力されたアスキーコードに対応する文字をreturnする関数

暗号化する場合は、encryption=True、複合化する場合は、encryption=Falseに設定するようにしています。

09. Typoglycemia

スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し,それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ.ただし,長さが4以下の単語は並び替えないこととする.適当な英語の文(例えば”I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .”)を与え,その実行結果を確認せよ.

import random


phrase2 = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."


def shuffle_func(phrase):
    lst = phrase.split()
    shffl_lst = []
    for word in lst:
        if len(word) <=4:
            shffl_lst.append(word)
        else:
            cap_lst = []
            for i in range(1, len(word) - 1):
                cap_lst.append(word[i])
            random.shuffle(cap_lst)
            cap_shuffled = ""
            for x in cap_lst:
                cap_shuffled += x
            word2 = word[0] + cap_shuffled + word[len(word) - 1]
            shffl_lst.append(word2)
    shuffled = shffl_lst[1]
    for i in range(1, len(shffl_lst)):
        shuffled = shuffled + " " + shffl_lst[i]
    return shuffled
  
    
print(shuffle_func(phrase2))
>c'duolnt c'duolnt beleive that I colud atullcay udrnatsned what I was rdeniag : the pahnenoeml pweor of the hmaun mind .

ポイント

random
randomモジュール
・標準ライブラリに備えられているモジュール
・ランダムな数値の生成に使用する

random.shuffle( ):入力されたリストの中身の順番をランダムに入れ替えてreturnする関数
random.random( ):0以上1未満の浮動小数点数をreturnする関数

まず、与えられた単語列を単語で分割してリストに入れます。
その後、単語の長さが5以上の場合は上記のrandom.shuffle( )関数を用いて文字列を並び替えています。

以上、第1章の問題の回答でした。次回の投稿では第2章について扱おうかと思います。

自然言語解析:「N-gram」について

今回は、N-gramとは何かについて、解説したいと思います。 N-gramとは…

今回は、N-gram(エヌ-グラム)とは何かについて、解説したいと思います。
※個人的に収集した知識です。正確ではない表現や、大きな誤り等があるかもしれません。お気付きの際はご指摘いただけると幸いです。

N-gramとは

概要

文章を分割する方法。文章をN文字単位で区切る。

1文字で区切るunigram、2文字で区切るbigram、3文字で区切るtrigramなどがある。

日本語の場合、文章をそのまま文字単位で区切る方法と、形態素解析を実施した後に、単語単位で区切る方法の2種類が存在する。

恐らく例を見るのが一番分かりやすいです。

例:元の文章「今日学校に行く」
bigram(文字単位):今日, 日学, 学校, 校に, に行, 行く
bigram(単語単位):今日学校, 学校に, に行く

以上の通りやりたいことは実に簡単です。
google検索などの検索エンジンで使用されているのですが、これを知った時は、正直これって役に立つの?と思いました。
N-gramを使わずにMeCabなどを用いて形態素解析をしたら十分だと思ったからです。

もちろんN-gramにも利点があります。

例えばこれまでは存在していなかった単語(略語や造語など)を取り扱う際に、形態素解析だとその単語を認識できず、検索がうまく行えない可能性があります。

その点N-gramだと、機械的に文字を分割して検索を行えますので、そうした単語の検索でも比較的正しい検索が行えると考えられます。

コード

実際にpythonで作成したコードは以下。

def n_gram(phrase, n, word=True):
    outcome_list = []
    if word == True:
        phrase_list = phrase.split()
        for i in range(len(phrase_list) - n + 1):
            outcome_list.append(phrase_list[i:i+n])
        return outcome_list
    else: 
        phrase = phrase.replace(" ", "")
        for i in range(len(phrase) - n + 1):
            outcome_list.append(phrase[i:i+n])
        return outcome_list

こちらのコードでは、英語の文章についての文字・単語単位のN-gramとなっています。
※文字単位の場合は、スペースは除いて出力するようにしています。

N-gramに関しては多くの方が色々なコードで作成しております。
ぜひ他の方のコードもご参考にしてください。

言語処理100本ノックをやってみた 第1章①

はじめに 言語処理の問題集として有名な、言語処理100本ノックを実施していこうと思います。基本的に1章の内容を1投稿または2投稿程度でまとめていこうかと思います。 第1章…

はじめに

言語処理の問題集として有名な、言語処理100本ノックを実施していこうと思います。
基本的に1章の内容を1投稿または2投稿程度でまとめていこうかと思います。

第1章:準備運動

00. 文字列の逆順

文字列”stressed”の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.

word1 = "stressed"


def reverse_func(word):
    word_list = []
    for i in range(len(word1)):
        word_list.append(word[i])
    reverse_word = ""
    for i in range(len(word1)):
        reverse_word += word_list.pop()
    return reverse_word


print(reverse_func(word1))
>desserts

何となく関数の形で回答を作成しました。
空のリストに文字を順番に足した後に、リストの最後から順に取り出して逆順の文字列を生成しています。

01. 「パタトクカシーー」

「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ.

word2 = "パタトクカシーー"


def odd_num_word_func(word):
    odd_num_word = ""
    for i in range(0, len(word), 2):
        odd_num_word += word[i]
    return odd_num_word


print(odd_num_word_func(word2))
>パトカー

ポイント

range(start, stop, step)
start : インデックスの参照したい最初の値
stop : インデックスの参照したい最後の値+1
step : インデックスを何個おきに参照するか(デフォルトは1)

新しい空の文字列を作成して、forループを用いて文字を追加して生成しています。

02. 「パトカー」+「タクシー」=「パタトクカシーー」

「パトカー」+「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ.

word3 = "パトカー"
word4 = "タクシー"

def combine_word_func(word1, word2):
    combined_word = ""
    for i in range(len(word1)):
        combined_word = combined_word + word1[i] + word2[i]
    return combined_word


print(combine_word_func(word3, word4))
>パタトクカシーー

新しい空の文字列を作成して、forループを回して、各単語から文字を一文字ずつ読み込んで生成しています。
※文字列の長さが異なると機能しません

03. 円周率

“Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.”という文を単語に分解し,各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.

sentence1 = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."

def word_length_func(sentence):
    sentence = sentence.replace(",", "")
    sentence = sentence.replace(".", "")    
    sentence_list = sentence.split()
    cap_num_list = []
    for word in sentence_list:
        cap_num_list.append(len(word))
    return cap_num_list
    
    
print(word_length_func(sentence1))
>[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]

まず文章中の不要なカンマとピリオドを取り除いています。
その後、文章をスペースで分割してリスト化。
最後にリスト中の単語をforループで呼び出して、長さを空のリストに追加しています。

04. 元素記号

“Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.”という文を単語に分解し,1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字,それ以外の単語は先頭に2文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.

phrase1 = "Hi He Lied Because Boron Could Not Oxideze Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."

def element_func(phrase):
    phrase = phrase.replace(".", "")
    phrase_list = phrase.split()
    num = [1, 5, 6, 7, 8, 9, 15, 16, 19]
    element_dic = {}
    for i in range(len(phrase_list)):
        if i + 1 in num:
            element_dic[phrase_list[i][:1]] = i + 1
        else:
            element_dic[phrase_list[i][:2]] = i + 1
    return element_dic


print(element_func(phrase1))
>{'H': 1, 'He': 2, 'Li': 3, 'Be': 4, 'B': 5, 'C': 6, 'N': 7, 'O': 8, 'F': 9, 'Ne': 10, 'Na': 11, 'Mi': 12, 'Al': 13, 'Si': 14, 'P': 15, 'S': 16, 'Cl': 17, 'Ar': 18, 'K': 19, 'Ca': 20}

まず文章中の不要なピリオドを取り除いています。
その後、文章をスペースで分割してリスト化。
最後にリスト中の単語をforループで呼び出して、何番目の単語によって取得する文字数を変えて空のリストに追加しています。

05以降の問題は次回の投稿に掲載します。

プログラミング環境

こんにちは。自己紹介にて書き忘れていたので、ここで私のプログラミング環境について簡単に触れておこうかと思います。 パソコン MacBook Pro 開発環境 ※2021年9月3日に追記 PyCharm 無償版…

こんにちは。
自己紹介にて書き忘れていたので、ここで私のプログラミング環境について簡単に触れておこうかと思います。

パソコン

開発環境

※2021年9月3日に追記

簡潔ですが、以上になります。
開発環境でオススメなどありましたら教えていただけると助かります。