
オープンソースのPython用機械学習ライブラリPyTorch開発チームは、最新版となる「PyTorch 1.8」を3月4日(現地時間)にリリースした。
Python用機械学習ライブラリ「PyTorch 1.8」がリリース、科学計算用フロントエンドAPIの追加など変更多数:CodeZine(コードジン)
⇧ ますます「機械学習」のライブラリが充実していく世の中に我々は生きているということですかね、どうもボクです。
そんなこんなで、Pythonについてです。
レッツトライ~。
Pythonは動的型付け言語である!
Wikipedia様の御宣託を見分することにより、我の曇り切ったPythonへの知見が解消されんことを、恐み恐み(かしこみかしこみ)乞祷(こいのみ)奉(たてまつ)らむ、ということで、
Pythonは動的に型付けされていて、ガベージコレクションされている。構造化(特に手続き型)、オブジェクト指向、関数型プログラミングを含む複数のプログラミングパラダイムをサポートしている。Pythonは、その包括的な標準ライブラリのため、しばしば「バッテリーを含む」言語と表現される。
⇧ みんな大好きPythonは、「動的型付け言語」ですと。
「動的型付け言語」、確かに、コーディングした内容を逐次実行できるから便利なんですが、「型」を定義しなくてもコーディングできてしまうために、コーディングの意図ってのが見え辛いってことがあるあるかと。
ただ、Pythonもコーディングにおける「型」についての問題意識は持っていたのかは分かりませんが、
typing --- 型ヒントのサポート
バージョン 3.5 で追加.
このモジュールは PEP 484, PEP 526, PEP 544, PEP 586, PEP 589, PEP 591 によって規定された型ヒントへのランタイムサポートを提供します。 最も基本的なサポートとして Any、 Union、 Tuple、 Callable、 TypeVar および Generic 型を含みます。 完全な仕様は PEP 484 を参照してください。 型ヒントの簡単な導入は PEP 483 を参照してください。
⇧ Python 3.5 から「type hinting」のサポートが導入されてますと。
まぁ、コーディングに使用してるエディターなんかの個々人の環境にお任せということで、Pythonランタイム自体は、コーディング時に「型」を意識してようがしてまいが、どうでも良いよってスタンスみたいですね...
Oh, my gosh...
なので、意識高い系?であれば、「静的型付け言語」みたいに、「型」を意識したコーディングを行おうと思えば行えるみたいですかね。
結局のところ、型を意識しないと駄目やん?
で、本題。
「型」を意識していないと、駄目な例が「len()」関数、というか、何か値に対して処理する関数すべてにおいて言えると思うので、結局のところ、すべてにおいて「型」を意識する必要は少なからず出てくるとは思われますが...
で、「len()」関数のドキュメントを確認してみると、
len(s)
オブジェクトの長さ (要素の数) を返します。引数はシーケンス (文字列、バイト列、タプル、リスト、range 等) かコレクション (辞書、集合、凍結集合等) です。
⇧ ってな感じで、「『オブジェクト』の『長さ(要素の数)』を返します。」ってあるんだけど、引数として受け付けることのできる「型」は、
- シーケンス
- 文字列
- バイト列
- タプル
- リスト
- range
- コレクション
- 辞書
- 集合
- 凍結集合
等、である必要がありますと。(「等」ってのが曖昧な感じになってるので、ハッキリさせてくれんかね、と思ってしまう私は心の狭い人間なのだろうか...)
まぁ、この時点で、ドキュメントがイケてないと思えて仕方ないんだけど、無償でドキュメントを作ってくださっている方々への感謝を忘れてはいけませんよ!
そもそもとして、Pythonってどんな「型」あるんだっけ?
コレクションクラスには、ミュータブルなものがあります。コレクションのメンバをインプレースに足し、引き、または並べ替えて、特定の要素を返さないメソッドは、コレクション自身ではなく None を返します。
⇧ ってな感じで、「型」の全量が無茶苦茶に把握し辛いんですと、っていうか、ドキュメントの全てをなめるように読み込まないといけないんか...
いや、すみません、失言でした、ドキュメント読むの楽しいな~。
Pythonの組み込み関数の内が1つ、「len()」関数で見事に躓く
ズバリ、「len()」関数という、超初歩的な関数で躓いたことを反省いたします...
で、今回、「janome」っていう「自然言語処理」で「形態素解析」する際に使用するライブラリを使ってたのですが(事前に、Python仮想環境内でpipを使い「janome」をインストールしておく必要があります)、
import janome
def get_target(target_list):
target = []
# Tokenizerオブジェクトのインスタンスを生成
t = Tokenizer(wakati=False)
for target in target_list:
# tokenize関数を用いてtargetを形態素解析
target_row = t.tokenize(target)
if len(target_row) > 0:
# 形態素結果のtarget_now[0]を取得
target.append(target_row[0].surface)
return target
ってな感じでコーディングしたところ、
TypeError: object of type 'generator' has no len()
⇧ ってなエラーが出たんだけど、
コーディングの内容を、
import janome
def get_target(target_list):
target = []
# Tokenizerオブジェクトのインスタンスを生成
t = Tokenizer(wakati=False)
for target in target_list:
# tokenize関数を用いてtargetを形態素解析
target_row = [i.surface for i in t.tokenize(target)]
if len(target_row) > 0:
# 形態素結果のtarget_now[0]を取得
target.append(target_row[0])
return target
⇧ ってな感じにしたところ、無事にエラーが解消されましたと。
エラーの原因は、Pythonの「len()」関数が「generator」型を扱うことができない、ってことらしいですね。
そもそもジェネレータには2つの意味がある(!)
ジェネレータは文脈によって意味が異なり、
の2つの意味がある(参考)
それぞれの意味は、
⇧ ってことらしいので、むっちゃ紛らわしいやん...
まぁ、結局のところ、Pythonは「動的型付け言語」であるからして「型」とかあまり意識されないでコーディングできてしまうことがあるあるだとは思うのですが、「型」を意識してないと躓きやすいってことですかね...
Pythonはいろんなライブラリが手軽に使えるというのは利点かもしれませんが、「型」は気にするようにしときたいですかね...
何て言うか「機械学習」に関係ない、一般的なPythonのコーディングについても詰まるところが多くて疲れる...
「型」を意識的にコーディングしてくれる文化が根付いてくれれば助かるんですけどね...
今回はこのへんで。