機械学習に挑戦する③ scikit-learn
R5.2月からPythonの勉強をしているプログラミング初心者です。
勉強した内容を備忘メモ程度にアウトプットしていきます。
参考書籍はこちら。
(さすがに全てまるまる写してしまうとまずいので部分的に抽出していきます。)
前回、前々回と「scikit-learn」に入っているデータを見ていきました。今回は、scikit-learnを使って自分で書いた数字を読み込ませて正しく判断してくれるかやってみようと思います。
(仕事の繁忙期と転職活動とWBCの応援でなかなかブログ更新できませんでした…。今回、かなり長くなったので何日かに分けてブログを書いています。)
画像ファイルから数字を予測するプログラム
それでは「画像ファイルから数字を予測するプログラム」を作っていきます。
早速プログラムを書いていきましょう。
import sklearn.datasets
import sklearn.svm
import PIL.Image
import numpy
#画像ファイルを数値リストに変換する
def imageToData(filename):
# 画像を8x8のグレースケールに変換
grayImage = PIL.Image.open(filename).convert("L")
grayImage = grayImage.resize((8,8),PIL.image.Resampling.LANCZOS)
# 数値リストに変換
numImage = numpy.asarray(grayImage, dtype = float)
numImage = 16 - numpy.floor(17 * numImage / 256)
numImage = numImage.flatten()
return numImage
#数字を予測する
def predictDigits(data):
#学習用データを読み込む
digits = sklearn.datasets.load_digits()
#機械学習する
clf = sklearn.svm.SVC(gamma = 0.001)
clf.fit(digits.data, digits.target)
#予測結果を表示する
n = clf.predict([data])
print("予測",n)
# 画像ファイルを数値リストに変換する
data = imageToData("2.png")
# 数字を予測する
predictDigits(data)
このプログラムファイルと同じフォルダにペイントで作った画像データを入れます。
今回書いたのはこれ。
これで準備は完了しました。
早速プログラムを実行してみます。
予測が2と出ました。合ってますね!
これだけだとたまたまかもしれないのでもう一つ読み込ませてみましょう。
次読み込ませるのはこれ。
ちゃんと合ってます!
これは頭いいですねぇ。
では長いですが、一行一行どのようなプログラムになっているか見ていきましょう。
正直わからんところ多くて大変です。
一行ごとの解説
それでは一行ごとの解説を見ていきましょう。
import sklearn.datasets
import sklearn.svm
import PIL.Image
import numpy
まずはライブラリをインポートしています。
sklearn.datasetsは以前もありましたね。sklearnに入っているデータを呼び出しています。
sklearn.svmはsklearnに入っているSVM(サポートベクターマシン)だそうです。
※SVM(サポートベクターマシン)とは、データを分類して境界線を引くためのアルゴリズムです。「教師あり学習」と呼ばれる手法を用い、正解データを「教師からの助言」として学習し、学習結果をもとに境界線を定めた「分類器」を作成します。
その分類器を活用して、新しいデータ(未知のデータ)を入力した時に、そのデータがどちらに分類されるかどうかを区別することができるようになります。
要は手書きの数字を識別してくれるライブラリのようですね。
PIL.Imageも前回出てきましたね。画像を扱うライブラリです。
import numpy(ナンパイ)は今回初めてですね、書籍には具体的にどんなライブラリか載っていないのですが、Wikipediaを調べてみると「数値計算を効率的に行うための拡張モジュールである。効率的な数値計算を行うための型付きの多次元配列(例えばベクトルや行列などを表現できる)のサポートをPythonに加えるとともに、それらを操作するための大規模な高水準の数学関数ライブラリ」となっています。
何を言っているのかよくわからない…。おそらく使い道が沢山あるんでしょうね。
今回はnumpyのasarryというメソッドで画像を数値化するのに用いています。
#画像ファイルを数値リストに変換する
def imageToData(filename):
# 画像を8x8のグレースケールに変換
grayImage = PIL.Image.open(filename).convert("L")
grayImage = grayImage.resize((8,8),PIL.image.Resampling.LANCZOS)
# 数値リストに変換
numImage = numpy.asarray(grayImage, dtype = float)
numImage = 16 - numpy.floor(17 * numImage / 256)
numImage = numImage.flatten()
return numImage
「#画像ファイルを数値リストに変換する」これはプログラム上に残せるメモみたいなものですね。最初に「#」をつけることでコンピュータがその行を無視するので処理には影響しません。
「def imageToData(filename):」は以下の処理をimageToDataという関数にするということを定義していますね。
「grayImage = PIL.Image.open(filename).convert("L")
grayImage = grayImage.resize((8,8),PIL.image.Resampling.LANCZOS)」
はメモの通り、読み込んだ画像を8x8のグレースケールに変換しています。1行目の「 PIL.Image.open(filename)」で画像を開いて「convert("L")」で8bit グレースケールに変換しています。“L”の他にも”RGB(8bit x 3)”や”I(32bit 整数)”など種類が沢山あるようですね。
そして「grayImage = grayImage.resize((8,8),」画像のサイズを8x8にして「PIL.image.Resampling.LANCZOS)」でリサンプル(補完)します。画像を拡大した時に画像の画素と画素の間の輝度値を調整します。今回は「LANCZOS」にしていますが「NEAREST」や「HAMMING」など色々あるようです。
「 # 数値リストに変換
numImage = numpy.asarray(grayImage, dtype = float)
numImage = 16 - numpy.floor(17 * numImage / 256)
numImage = numImage.flatten()」
これは「numpy」を使って先ほど読み込んで8x8にした画像を数値リストに変換しています。1行目がそうですね。一行目の()内について書籍にも説明がないので正しいかどうかわからないのですが、「dtype = float」とありますがこれは数値化して上がってきたデータのデータ型を浮動小数点型にしているということでしょうかね?
そして1行目のままだと255~0までの濃淡データができてしまうので「16 - numpy.floor(17 * numImage / 256)」で0~16までの数値リストに変換させているんですね。
3行目がちょっとわからない。flattenという関数を用いているのですがどうやらこれはデータを1次元に平坦化させる関数のようです。これをしないと読み込めないようです。試しにこの1行を抜くとエラーが出ました。
グーグルでflattenについて調べたところ、例えばリストで[0,1,2,3],[4,5,6]という別々に分かれているデータを[0,1,2,3,4,5,6]のように一つにまとめる時に使うようです。
8x8に数値化したものがそれぞれデータとして分かれているのでそれを平坦化させるといった処理でしょうか?間違っていたらすみません。
「return numImage」は戻り値でしたね。今回の場合は読み込み→8bitグレイスケールに変換→数値リストに変換したデータを返しています。
#数字を予測する
def predictDigits(data):
#学習用データを読み込む
digits = sklearn.datasets.load_digits()
#機械学習する
clf = sklearn.svm.SVC(gamma = 0.001)
clf.fit(digits.data, digits.target)
#予測結果を表示する
n = clf.predict([data])
print("予測",n)
「def predictDigits(data):」で以下の処理をpredictDigits(data)という関数にするということを定義していますね。(data)は読み込む画像データのことです。後で出てくるので気にしなくて大丈夫です。
「digits = sklearn.datasets.load_digits()」は前回もやりましたね。ライブラリの中に入っているデータを読み込んでいます。
「clf = sklearn.svm.SVC(gamma = 0.001)
clf.fit(digits.data, digits.target)」でclfという変数にSVM(サポートベクターマシン)の境界線を代入しています。この行については調べても高難度なことが書いてあったため、あまり理解できませんでした…。数値を大きくすると複雑なデータも分類できるようですがやりすぎると過学習の問題が出てくるようです。
「 n = clf.predict([data])」で予測します。「predict」は「予測する」という意味です。そのままですね。
「print("予測",n)」は結果の表示ですね。なんかprint関数が出るとプログラムの終わりって感じがして安心します。
# 画像ファイルを数値リストに変換する
data = imageToData("2.png")
# 数字を予測する
predictDigits(data)
そして最後の2行。(コメント行除く。)
「data = imageToData("2.png")」でdataという変数に画像ファイルを読み込みんで先ほど作った「imageToData()」関数を実行する命令を代入します。今回は「2.png」と名前をつけたファイルを読み込みます。
「predictDigits(data)」は先ほど作った「predictDigits()」関数を実行します。
まとめ
難しい上に長くなってしまい、ブログ更新が滞ってしまいました。今後も長くなりそうです。とりあえず今回でPython1年生の内容は終了ですね。この後もアプリ形式にして画像を読み込むなどあるのですがブログでは書きません。すごくわかりやすい本だったので是非購入して読んでみてください。
次回からPython2年生の内容を書いていきたいと思います。複数あるのですが今やっているのは「デスクトップアプリ開発のしくみ」です・
WBCも終わるし、転職も決まりそうなのでもう少し更新頻度上がるかな~。
機械学習に挑戦する② scikit-learn
R5.2月からPythonの勉強をしているプログラミング初心者です。
勉強した内容を備忘メモ程度にアウトプットしていきます。
参考書籍はこちら。
(さすがに全てまるまる写してしまうとまずいので部分的に抽出していきます。)
前回はライブラリscikit-learnに入っている1番目の数値化されたデータとそのデータに紐づけられている答えを見ていきました。
今回はその数字のデータを画像化してみましょう。
数値化されたデータを画像化する
前回は数値化されたデータを出力しましたが今回はそのデータを画像化してみましょう。「matplotlib(マットプロットリブ)」というライブラリを使用します。
では前回数値で表示したデータを画像として表示させるプログラムを入力していきましょう。
import sklearn.datasets
import matplotlib.pyplot as plt
digits = sklearn.datasets.load_digits()
plt.imshow(digits.images[0], cmap="Greys")
plt.show()
プログラムを実行すると、
画像が表示されました。
これはどう見ても「0」ですね。
モザイク画像みたいになっていますが8×8のデータを画像化したのでこのようになっています。人工知能はこのようなモザイク画像を見て数字を学習していきます。
一行ごとの解説
では一行ごとどのような命令が行われているか見ていきましょう。
「import sklearn.datasets」
「import matplotlib.pyplot as plt」
この二つはライブラリをインポートしていますね。前回も使った「scikit-learn」と今回数値データを画像化するための「matplotlib」ですね。
「digits = sklearn.datasets.load_digits()」
これは前回も出てきました。「scikit-learn」の中に入っているデータを読み込む命令を変数digitsに代入しています。
「plt.imshow(digits.images[0], cmap="Greys")」
「matplotlib(ライブラリ)」の「imshow」というメソッドを使います。すみません、調べたら関数ではなくメソッドというらしいです。関数とメソッドは使い方や呼び出し方が明確に違いがあるそうです。色々読んでていてもなんとなくしかわかりませんでしたが…。「imshow」はデータを画像で表示してくれる命令です。()の中に画像化したいデータを指定します。今回はscikit-learnの1番目[0]のデータを指定し、cmapでGreysの色を指定しています。ほかの色も選べるみたいですね。
「plt.show()」
これは画像化したものを表示させる命令ですね。
一言メモ
画像の色を「cmap」のところで変えられるので試しに春らしく「spring」という色で表示させてみました。
それがこちら。
これは見づらい。笑
目がチカチカしますね。
まとめ
今回は前回数値データ化したものを画像化させてみました。前回も書きましたがこのようなデータがscikit-learnには1797個入っているそうです。全部表示させたらすごいことになりそうですね。今回はデータを一つだけ表示させましたがfor文を使えばデータの個数を指定して何個も表示できるようです。このブログでは割愛しますが、気になる方は是非書籍を読んでみてください。
次回はいよいよ自分で書いた数字を人工知能に読み込ませて正しい答えが返ってくるか試してみます!
機械学習に挑戦する① scikit-learn
R5.2月からPythonの勉強をしているプログラミング初心者です。
勉強した内容を備忘メモ程度にアウトプットしていきます。
参考書籍はこちら。
(さすがに全てまるまる写してしまうとまずいので部分的に抽出していきます。)
機械学習に挑戦する
機械学習とは人間が知識を教えるのではなく、コンピュータにたくさんのデータを与えてコンピュータ自身が学習する方法です。
学習方法は主に3種類あります。
1つ目は「教師あり学習」です。これは「問題と答えのペア」を大量に与えて特徴を学習させる方法です。答えのことを「教師データ」と呼ぶので教師あり学習と言います。新しいデータを与えた時、その特徴からそれが何なのか答えることができます。文字認識や音声認識、翻訳などで使われています。
2つ目は「教師なし学習」です。これは答えのない大量のデータを調べるので答えを見つけるための学習ではありません。大量のデータから似たデータをまとめて特徴を抽出したり、グループ分け(クラスタリング)したりする時に使う方法です。
3つ目は「強化学習」です。これは色々試行錯誤させて、良い結果が出た時に「報酬」を与えて強化していく学習方法です。よりよい方法を見つけるための方法で、ロボットの制御や将棋や囲碁などで使われています。例えば将棋のAIなどは何億回も対局してより良い手を学習していくので人間よりも強くなったりするわけですね。
ではライブラリを使って機械学習に挑戦してみましょう。
(ライブラリのインストール方法は割愛します。)
一言メモ
なんかPythonの真骨頂みたいな分野来ましたね。AIを通じて好きなエピソードは藤井総太竜王(当時七段)の指した手を「AIで4億手読ませた段階では5番手にも挙がらなかったのに、6億手読ませると、突如最善手として現れる手だった」というエピソード。しかもAIが6億手かかった手を藤井竜王は23分の考慮時間で指したとか。今後AIは人間を超えていくのは確実だと思いますが、藤井総太竜王のこのエピソードは天才棋士として箔がつく素晴らしいエピソードだと思いました。
学習データを読み込んで表示する
これから作る「手書きの数字を認識するアプリ」は特徴を見て「それが何なのか」を答えるものなので「教師あり学習」で作ります。
大量の「数字の画像」と「それが何の数字か」のペアを与えて、「数字の特徴」を学習させるのです。
学習させるには大量のデータが必要なのですが、今回使用する「scikit-learn(sklearn)」(サイキットラーン)にはすでに学習用のデータがあるのでこれを使います。この中には「手書きの数字画像(data、images)」と「それが何の数字か(target)」がペアで沢山入っています。
まずは、sklearnにどんなデータが用意されているのか確認してみましょう。データを読み込んで、そのデータを表示します。「データの個数」と「1つ目の画像データ」と「1つ目の数字が何なのか」を表示します。
import sklearn.datasets
digits = sklearn.datasets.load_digits()
print("データの個数",len(digits.images))
print("画像データ",digits.images[0])
print("何の数字か=",digits.target[0])
これで出力すると
数字がいっぱい出てきましたね~。
データの個数を見るとsklearnには数字の画像データが1797個入っているようです。
画像データを見ると8x8で数値が並んでいます。これは濃淡を数値で表しています。0が一番明るい白で16が一番黒です。こう見るとうっすら輪っかになっているよう感じがします。
「何の数字か」を見ると0です。このデータは数字の「0」を表しているのです。
一行ごとの解説
参考書籍にも解説がないので正直あまり自信がないのですが解説していきます。
「import sklearn.datasets」これはライブラリのインポートですね。ほぼ毎回出てきますね。
「digits = sklearn.datasets.load_digits()」sklearnの中に入っている学習用データを読み込む命令を変数「digits」に代入しています。
「print("データの個数",len(digits.images))」ここで初めて出てきたlen()関数。これはPythonに標準で備わっている関数のようで、リストの中の個数を数えてくれたりかなり便利な関数のようです。今回の場合はsklearnに組み込まれている学習用データの個数を数えてくれています。便利!
「print("画像データ",digits.images[0])」これは画像データの1番目([0])のデータを開く命令ですね。この命令だと数値が8x8で並ぶことになりますね。
「print("何の数字か=",digits.target[0])」これは画像データの1番目([0])のデータの答えを見る命令ですね。
なんとなくそんな感じかなぁという解説にもなっていない解説…。笑
何か間違いがあればご指摘ください。
まとめ
今回は機械学習ができるライブラリを使ってまずはライブラリのデータの中身を見ていきました。内容がかなりボリューミーなので次回に続いていきます。次回は自分で書いた数字をAIがきちんと数字として判断してくれるか試してみたいと思います!
画像ファイルを読み込むアプリを作る
R5.2月からPythonの勉強をしているプログラミング初心者です。
勉強した内容を備忘メモ程度にアウトプットしていきます。
参考書籍はこちら。
(さすがに全てまるまる写してしまうとまずいので部分的に抽出していきます。)
画像表示アプリを作ってみよう
今回は外部ライブラリを使って画像を読み込むアプリを作ってみましょう。
(ライブラリのインストール方法は割愛します。)
このアプリは
ウインドウを表示する「tkinter(前回も使いましたね)」、
ファイルダイアログを使う「tkinter.filedialog」、
画像を扱う「PIL.Image」、
画像をtkinterで作った画面上に表示させるための「PIL.ImageTk」、
の4つのモジュールを使います。
早速プログラムを入力してみましょう。
import tkinter as tk
import tkinter.filedialog as fd
import PIL.Image
import PIL.ImageTk
def dispPhoto(path):
newImage = PIL.Image.open(path).resize*1
imageData = PIL.ImageTk.PhotoImage(newImage)
imageLabel.configure(image = imageData)
imageLabel.Image = imageData
def openFile():
fpath = fd.askopenfilename()
if fpath:
dispPhoto(fpath)
root = tk.Tk()
root.geometry("400x350")
btn = tk.Button(text="ファイルを開く",command = openFile)
imageLabel = tk.Label()
btn.pack()
imageLabel.pack()
tk.mainloop()
出力するとこんな感じのウインドウが表示されます。
「ファイルを開く」ボタンを押すとダイアログが表示され、
画像を選択すると、(今回は僕の大好きなBUMP OF CHICKENのギターボーカル藤原基央さんのめちゃくちゃかっこいい写真を選択します。)
ちょっと大きさが変わりましたが表示されました!やっぱかっこいいぜ藤君!!
1~4行目の解説
では一行ずつ細かく見てみましょう。見たことない関数ばかりで頭がおかしくなりそうですが、一行ずつ細かく見ていけば大丈夫です。ちゃんと理解できます。いや、嘘つきました、すみません。正直理解できていないところもあります。
import tkinter as tk
import tkinter.filedialog as fd
import PIL.Image
import PIL.ImageTk
最初の1~4行目までは大丈夫ですよね。まずはライブラリをインポートします。
「as ~」の部分はこれからプログラムを書く時にそのままの名前だと入力面倒なので略して呼びますよ~という事でしたね。
6行目~10行目の解説
def dispPhoto(path):
newImage = PIL.Image.open(path).resize*2
imageData = PIL.ImageTk.PhotoImage(newImage)
imageLabel.configure(image = imageData)
imageLabel.Image = imageData
ここがすごく難しかったです。「def」という事は何か新しく関数を作っていることがわかります。
「def dispPhoto(path)」これからdispPhoto(path)という関数を定義しますという命令ですね。
「newImage = PIL.Image.open(path).resize*3 」画像データを読み込ませ、サイズを300x300に変更する命令をします。
「 imageData = PIL.ImageTk.PhotoImage(newImage)」先ほど読み込んだ画像データ(newImage)を表示させる命令をします。
「imageLabel.configure(image = imageData)」そしてその読み込んで表示させる画像データをラベルに貼り付けます。
「imageLabel.Image = imageData」ここがわからなかった。参考書籍にも記載がなく、グーグル検索でなんのためにこの1行があるか調べたのですが見つかったのが「GC(ガーベッジコレクション)による変数データ削除を動かさないようにするために、imageLabel.image というパラメーターに画像データを結びつけておく。」ということでした。自分にはまだ意味が解らない…。その解説した人も「今はまだ詳しくわからなくいいので今後どこかのタイミングで勉強してください」とのことでした。
ということで、ここで作った「dispPhoto(path)」という関数は画像データを読み込んでリサイズして表示させる命令ですね。
12行目~15行目の解説
def openFile():
fpath = fd.askopenfilename()
if fpath:
dispPhoto(fpath)
「def openFile():」はわかりますね。openFile()という関数を定義しています。
「fpath = fd.askopenfilename()」ファイルダイアログを開いて選択したファイル名を取得します。
「if fpath」if文は以前やりましたね。この場合はもしファイル名があったら~です。
「 dispPhoto(fpath)」さきほど6~10行目で定義したこと(画像を読み込み、リサイズし表示する)を実行してくださいという文ですね。
17~24行目の解説
root = tk.Tk()
root.geometry("400x350")
btn = tk.Button(text="ファイルを開く",command = openFile)
imageLabel = tk.Label()
btn.pack()
imageLabel.pack()
tk.mainloop()
ここら辺からは以前もやったのですいすいいけそうですね。
root = tk.Tk()
root.geometry("400x350")
この2つはウィンドウを作成してウィンドウの大きさを決める命令ですね。
ウィンドウの上にボタンやラベルと配置していきます。
「btn = tk.Button(text="ファイルを開く",command = openFile)」ボタンに「ファイルを開く」というテキストをつけて、ボタンを押すと先ほど作ったopenFile関数が発動するようになっています。
「imageLabel = tk.Label()」画面表示用のラベルを作ります。
「btn.pack()」ウィンドウにボタンを配置します。
「imageLabel.pack()」ウィンドウにラベルを配置します。
「tk.mainloop()」作ったウインドウを表示します。
まぁ、ここら辺は正直ウィニングラン的な感じがします。
まとめ
さて、今回はこんな感じです。ライブラリの関数で出来ることが多くてなかなか難しかったですね…。ちょっとずつ覚えていきましょう。ライブラリの関数で何ができるかを知っておくことってめちゃくちゃ重要な感じがしますね。参考書籍ではこの後にアプリの改造などもあるのですがブログでは触れないことにします。
操作できるアプリを作る GUIツールキット
R5.2月からPythonの勉強をしているプログラミング初心者です。
勉強した内容を備忘メモ程度にアウトプットしていきます。
参考書籍はこちら。
(さすがに全てまるまる写してしまうとまずいので部分的に抽出していきます。)
今回はGUIツールキットを使って操作できるアプリを作ってみましょう。
Pythonでは操作できる画面を作る時は標準ライブラリの「tkinter(ティーキンター・ティーケーインター)」を使います。
「tkinter」とはGUIツールキットの一種で、GUIツールキットとは「ウィンドウの上にボタンやラベルを並べて操作できる画面を作ることができるライブラリ」です。
ちなみにGUIとは「グラフィカルユーザーインターフェース」の略です。
こんにちはアプリを作ってみよう。
まずは、「ラベルとボタンを表示するだけのアプリ」を作ってみましょう。
(今回から一行一行をしっかり理解するために画像ではなく入力でコードを書いていきます。)
import tkinter as tk・・・・・・tkinterをインポートしてtkと略して使う
root = tk.Tk() ・・・・・・・・画面を作る
root.geometry("200x100")・・・画面の大きさを決める(xは半角英字の小文字エックス)
lbl = tk.Label(text="LABEL")・・・ラベルを作る
btn = tk.Button(text="PUSH")・・ボタンを作る
lbl.pack()・・・・・・・・・・・画面にラベルを配置する
btn.pack()・・・・・・・・・・・画面にボタンを配置する
tk.mainloop()・・・・・・・・・作ったウィンドウを表示する
以上のプログラムを実行すると下のウインドウが作成されます。
一気に見慣れない命令が続出して「うっ」となってしまいますが、そんなに難しいことはしていないので一行ずつ命令の意味を見ていきましょう。
一行ごとの解説
import tkinter as tk・・・・・・tkinterをインポートしてtkと略して使う
まずはtkinterをインポートして、tkinterと毎回入力するのは面倒なので今後はtkと呼ぶという命令をします。
root = tk.Tk() ・・・・・・・・画面を作る
次に「root」という変数に「tk.Tk()」という命令を代入します。これは以前「モジュール名.関数名」でやったものと同じですね。tkinter(tk)というモジュール(ライブラリ)のTk()という関数を使うという命令です。
Tk()関数を使用することでメインウィンドウを作成することがでます。
root.geometry("200x100")・・・画面の大きさを決める(xは半角英字の小文字エックス)
geometry()はウィンドウの大きさを決める命令です。rootで作成したウインドウの大きさを決めているんですね。数字は横×高さになっています。
lbl = tk.Label(text="LABEL")・・・ラベルを作る
lblという変数にLabel()を代入します。 これはラベルの部品を作成する命令です。ラベルとは文字列や画像のことです。今回は文字列「LABEL」という部品を作っています。
btn = tk.Button(text="PUSH")・・ボタンを作る
btnという変数にButton()を代入します。これはボタンの部品を作成する命令です。今回はボタンの上に「PUSH」という文字を表示させます。
lbl.pack()・・・・・・・・・・・画面にラベルを配置する
btn.pack()・・・・・・・・・・・画面にボタンを配置する
これは上で作ったラベルとボタンをウィンドウに配置する命令(pack())です。上から順に先ほど作った部品を配置していきます。
tk.mainloop()・・・・・・・・・作ったウィンドウを表示する
最後にmainloop()という命令で作成したウインドウと表示させます。
それでこのようなアプリが作られるわけですね。
ただ、このままではボタンを押しても何も起こらないので命令を追加してみましょう。
ボタンで動くようにする
ボタンをクリックしたらラベルに「こんにちは」と表示されるアプリに改造します。
「こんにちはと表示される関数」を追加して、ボタンがクリックされたらその関数を呼び出すように修正します。
import tkinter as tk
def displabel():
lbl.configure(text="こんにちは")
root = tk.Tk()
root.geometry("200x100")
lbl = tk.Label(text="LABEL")
btn = tk.Button(text="PUSH",command = displabel)
lbl.pack()
btn.pack()
tk.mainloop()
赤字部分が追加した部分です。
def displabel():
lbl.configure(text="こんにちは")
これはdisplabelという関数を新たに作る命令です。defは以前やりましたね。
「configure」とは修正するという意味です。lblの文字列を「こんにちは」に修正するという命令ですね。
btn = tk.Button(text="PUSH",command = displabel)
「command = displabel」のcommand部分は「ボタンが押されたら」という意味になります。「ボタンが押されたらdisplabel(lblの文字列LABEL→こんにちはに修正)を実行してください。」という命令になりますね。
ボタンを押すと
LABEL→こんにちはに変わるようになりました。
ランダムのアプリを作ってみた
これを少し応用して前回出てきたrandomモジュールを使って僕が友人や先輩たちと15年近く前に大ハマりしたゲーム「モンスターハンター」の武器おみくじアプリを作ってみました。
import tkinter as tk
import random
def displabel():
kuji =["大剣","片手剣","双剣","太刀","ハンマー","狩猟笛","ランス","ガンランス","スラッシュアックス","チャージアックス","操虫昆","弓","ライトボウガン","ヘビィボウガン"]
lbl.configure(text=random.choice(kuji))
root = tk.Tk()
root.geometry("200x100")
lbla = tk.Label(text="武器ルーレット")
lbl =tk.Label(text="武器を表示")
btn = tk.Button(text="PUSH",command = displabel)
lbla.pack()
lbl.pack()
btn.pack()
tk.mainloop()
アプリを起動すると
この画面が表示されます。
これでボタンを押すと、
武器が表示されます。
もう一度押すと、
武器の表示が変わりました。
当時、モンスターハンターポータブル2ndGをやっていたんですがどんなモンスターでも楽に勝てるようになってきて少しマンネリ化してきた時、紙で作ったくじで当たった武器を使って狩りに行くという遊び方を始めたんですがこれが本当面白かったんですよね。みんな慣れない武器に悪戦苦闘しながらやるのが面白かったです。
それを今回アプリ化してみました。そのうちモンスターやクエストもランダムで選べるようなアプリに改造したい…。
あと見た目ももっとちゃんとしたものにしたいですねぇ。
まとめ
今回はアプリを作ってみました。アプリを作ると一気にプログラミングをしている感があって面白いです。初めて自分でアプリを作ってみましたが愛着があって可愛く感じますね。もっと勉強して今回作ったアプリをパワーアップさせていきたいです。
他の人が作ったプログラムを利用する import
R5.2月からPythonの勉強をしているプログラミング初心者です。
勉強した内容を備忘メモ程度にアウトプットしていきます。
参考書籍はこちら。
(さすがに全てまるまる写してしまうとまずいので部分的に抽出していきます。)
他の人が作ったプログラムを利用する
前回は「def」を使って関数を自分で作りましたが、実は他にも複雑なプログラムをシンプルにする工夫があります。それが「import」です。
「import」を使うと別のファイルに書いた関数などのプログラムを読み込んで利用することができます。importで読み込むプログラムファイルのことを「モジュール」と呼びます。
書式:インポートする方法
import モジュール名
書式:importしたモジュールの関数を実行する方法
モジュール名.関数名
モジュールを作ってみよう
前回、消費税(10%)を計算してくれるプログラムを作ったので、今回はそれを2つのファイルに分けて作ってみましょう。
1つ目のファイルには「モジュール」を作り、2つ目のファイルには「そのモジュールを読み込んで動かすプログラム」を作ります。
モジュールを作ります
このファイルは関数部分だけを書いて「モジュール」にします。書き終わったら「tax.py」というファイル名で保存します。
この時、モジュールの保存場所に注意が必要です。今回作った「モジュールのファイル」とこれから作る「モジュールを読み込むファイル」がそれぞれ別のフォルダに入ってしまうとimportする時に見つからずエラーになってしまいます。今回のように単純なプログラムであれば同じフォルダ内に一緒に入れておけばわかりやすいでしょう。
もっとプログラムの規模が大きくなってきたらフォルダに分けて入れて管理する必要も出てきます。そうなると、importで呼び出す時や関数名で呼び出す時もフォルダ名をつけて指定する必要があります。
モジュールを読み込んで動かすプログラムを作ります
先ほどのモジュール名(ファイル名の.pyより前の部分)を指定してimportで読み込みます。関数を呼び出す時は「モジュール名.関数」で指定します。
なので今回はtaxというモジュールの中のpostTaxPrice関数なので「tax.postTaxPrice」と指定します。
無事計算できましたね。
一言メモ
これ初めて知った時に感動した記憶があります。「こうやってimportで呼び出せるなら大勢で色々作れるじゃん!」と。チーム力が試されそうですね。
用意されたモジュールをimportする
Pythonにはあらかじめ「標準モジュール」がたくさん用意されています。例えば数値計算を行う「math」「random」、日付や時刻を使う「datetime」「time」「calendar」、データファイルに使う「csv」や「json」、ユーザーインターフェースが作れる「tkinter」など色々あります。
前回、「3.戻り値だけある関数」ということでおみくじの結果をランダムに表示するプログラムを作りました。
その際は「Import random」で呼び出し、その中の「random.choice」を使いました。これはリストの中からランダムに1つ選びだす命令なのです。
モジュール名を省略する(その1):as
「import モジュール名」を使って読み込むと「モジュール名.関数名」と指定して使いますが、プログラムの中で何度もその関数を実行するような場合、長いモジュール名だと読みにくくなってしまいます。
そういう時は「import モジュール名 as 省略名」とすることでモジュール名を省略名で書くことができるようになります。今後、よく出てくるので覚えておきましょう。
モジュール名を省略する(その2):from
「import モジュール名」を使って読み込むと「モジュール名.関数名」と指定して使いますが、関数名の前のモジュール名を書かずに済ませる方法があります。
それが「from モジュール名 import *」です。
上記のプログラムに当てはめると「 from random import *」と読み込むと「random.choice」ではなく、「choice」だけで使えています。
まとめ
今回はモジュールを学んでいきました。実は参考書籍の最初のほうにこの「import」がよく使われています。ここにきてようやく「importってそういう意味だったのか!」と気付くのです。「ただのプログラミング体験で文法の意味はこれから学んでいくよ~」というスタンスの内容だったのでブログでは省いていますが。
ずっと法律(税法)の勉強ばかりしてきたのでプログラミングの勉強はとても新鮮で楽しいです。平日でもほぼ休ます毎日3~4時間勉強しちゃってます。寝不足に気を付けなければ…。
関数を自分で作る def
R5.2月からPythonの勉強をしているプログラミング初心者です。
勉強した内容を備忘メモ程度にアウトプットしていきます。
参考書籍はこちら。
(さすがに全てまるまる写してしまうとまずいので部分的に抽出していきます。)
関数で命令をまとめる
「ある仕事を行う命令のまとまり」をブロックに書いてまとめたものが「関数」です。これまで出てきたprint()やint()などもPythonに最初から用意されている関数です。
関数は用意されているものだけではなく、自分で作ることができます。
今回は関数を自分で作る方法を学んでいきます。
書式:関数の作り方
def 関数名():
関数で行う処理
関数は「関数名」を自由に決めて「def 関数名():」と指定し、「その関数で行う処理」を指示して作ります。「関数名」は「この関数は何をするものなのか」をわかりやすく表現した名前をつけましょう。
「関数で行う処理」は、まとまった処理なのでif文やfor文と同じように「ブロック」で作ります。インデントで一段下げて作ります。
作った関数を使う時は「関数名()」で呼び出して実行します。名前で呼び出したら「関数で行った処理」をまとめて行ってくれるのです。
試しに関数を作ってみましょう。
最初の2行でsayhelloという関数を作成し、下の3行は関数を呼び出しています。
print(”こんにちは”)と定義されている関数を3行呼び出したので「こんにちは」と3行出力されていますね。
一言メモ
defはかなり使い勝手良さそうな感じがします。ちなみになぜ「def」かというと「define」の略みたいですね。意味は「(~を)定義する」だそうです。そのままですね。
引数(ひきすう)を使って関数にデータを渡す
上記の関数は「関数名で呼べば”こんにちは”と表示するだけ」の「決まりきった仕事をする関数」でした。
しかし、仕事にはいろいろあります。データを渡して処理を調整したり、計算した結果を返してもらったりするような仕事もあります。
関数に引き渡すデータのことを「引数(ひきすう)」または「パラメータ」といい、関数が処理したあと結果として戻ってくる値のことを「戻り値(もどりち)」といいます。
書式:関数の作り方(引数と戻り値がある場合)
def 関数名(引数1,引数2,…):
関数で行う処理
return 戻り値
関数には
- 引数も戻り値もない関数
- 引数だけある関数
- 戻り値だけある関数
- 引数も戻り値もある関数
などの種類があります。
一言メモ
これだけ読むとなんだかよくわからないですよね。でも実際やってみると言っていることはそんなに難しくないです。
消費税(10%)を計算してくれるプログラムを書こう
それでは商品の本体価格(引数)を渡すと消費税計算を行い、消費税込みの金額(戻り値)がわかる関数を作ってみましょう。これは「4.引数も戻り値もある関数」に該当します。
1行目で「postTaxPrice」という関数を作り、引数を(Price)とします。
2行目で「ans」という変数に「Price(引数)x1.1」の計算を代入します。
3行目で戻り値を2行目で代入した「ans」とします。
1~3行目まで関数postTaxPriceと定義します。
1行空けて
5~7行目からは1~3行目で定義したpostTaxPrice関数と()に引数を入力していきます。
引数からそれぞれ消費税10%込の金額が出力されました。
一言メモ
なんだか難しく見えますが1行1行見ていくとそんなに難しいことはしていないですよね。
引数か戻り値だけの関数の使い道
上記は「4.引数も戻り値もある関数」でしたが、「2.引数だけある関数」や「3.戻り値だけある関数」はどのように使うのか学んでいきましょう。
「2.引数だけある関数」は「値を渡して処理を調整したい時」に使います。
例えば「ユーザー名付きでこんにちはと表示する」ような場合は「2.引数だけある関数」を使います。
ユーザー名が引数になっています。これはよくありそうな形ですね。
「3.戻り値だけある関数」は「処理に変化があるので知りたい時」に使えます。例えば、実行して初めて処理がわかる「おみくじ」などがその例です。
「import random」や「random.choice」については次回学んでいきます。
今回は引数がなく、リスト(大吉、中吉、小吉、凶)の中からランダムに戻り値があるプログラムという認識があれば大丈夫かと思います。
ランダムに結果が出てきますね。2回実行しましたが結果は中吉と小吉でした。
一言メモ
「3.戻り値だけある関数」は自分が作りたいものに関わっているのでしっかり覚えたいと思います。自分の中で使うことがはっきりしているとちゃんと覚えられますね。笑
まとめ
今回は関数を自分で作る方法を学んでいきました。引数と戻り値については慣れるまでは頭がゴチャゴチャしてしまいますね。
実はこのブログに書いている頃は参考書籍3周目なのですが、引数と戻り値については1周目ではちゃんと理解できませんでした。2周目できちんと理解して3周目で忘れないようにするといった流れでやっています。わからなくても一度最後まで読んでからまた読むと新たな発見があったりして面白いです。