在宅リーマン勉強日誌

忘れがちな毎日のメモ。

【9日目】KaggleでPythonの勉強してみた【独学】

KaggleでPythonの勉強をしています。

7日目あたりからそろそろ終わりたいと思いつつずるずる引きずった上に、また1日さぼりました…。 進捗は93%となっています。 8日目はTutorialの途中までだったので、進めます。

勉強内容

Lesson : Working with External Libraries(Tutorial)

TutorialはCourseの和訳(概略)、Tutorialは試行とどう考えていたかを記しています。

Lesson : Working with External Libraries(Tutorial)

Operator overloading

Pythonのルールは厳密であるように見えますが、実際には非常に手のかからないアプローチをとっています。 新しい型を定義するとき、追加の機能をどうするかや、オブジェクトのタイプが何と同じ意味をもつのかを選ぶことができます。

リストの設計者は、リストに値を足すことを禁止しました。 しかし、numpy配列の設計者は配列の各要素に数字を足せるようにしました。

ここではPython演算子とは少し違った動きを持つnumpy配列を紹介します。

例えば、numpy のarrayに数字を入れると、array+10で各要素に10ずつ数字を足していけます。array<3で各要素のTrue/Falseを返してくれます。

numpyのnfarrayは多次元型のデータに特化している型なので、独自のインデックスロジックを持っており、タプルでインデックスを作成して各次元でインデックスを指定することができます。

When does 1 + 1 not equal 2?

1足す1が2にならないときは?こんな変なことが起こりうるのです。 テンソルフローというものを聞いたことがあるかもしれませんが、これはPythonの有名な深層学習のライブラリです。 これは演算子オーバーロードを多用しています。

ライブラリが時折演算子オーバーロードを不透明に、謎な方法で使っていることを知っておくことは重要です。 Python演算子がどのように整数型、文字型、リストに対して働くかを知っておくだけでは、他のライブラリでどのように動くかすぐ理解できるとは限りません。

Curious how it all works?

オブジェクトのhelp()dir()を呼び出したときに、全ての名前の前後にアンダーラインが2つずつついていることを疑問に思ったことはありませんか?

これは演算子オーバーロードに直接関係していることを示します。 Pythonプログラマ演算子のふるまいを定義したいとき、2つのアンダーラインを付けて特別な名前として実装します。 一般的には、2つのアンダーラインがついているフォーマットはPythonにおいて特別な意味を持っています。

もし興味があれば、Pythonの公式文書を確認してみてください。 そこでは、たくさんのアンダースコアがついたメソッドが解説されています。

Lesson : Working with External Libraries(Exercise)

今回のチュートリアルは少しヘビーでした。 Pythonに関しては本当に初心者で臨んでいるので、「よくわからないな?」で放置していた部分に深く入り込んでいった印象ですね。

Q1:関数を完成せよ。(スロットマシンの収支グラフ)

リストとタプルのExerciseで作成したスロットマシンのestimate_average_slot_payout関数によると、Learn Python Casinoは長期的に遊んばれても利益が出ているように仕組まれていることに気づきました。

手持ち金$200から始めて500回スロットを引き、各試行毎に収支をリストに記録しました。 彼は、収支のグラフをmatplotlibライブラリで描画しました。

見ての通り、調子は悪そうです。 彼は絵文字付きでツイートをしようとしましたが、このグラフのままではフォロワーはそれを見て混乱することでしょう。 以下の様に変更させましょう。 * タイトルに"Results of 500 slot machine pulls"と追加しましょう。 * Y軸を0から始めるようにしましょう。 * Y軸に"Balance"というラベルを追加しましょう。

dir(graph)で役に立つメソッド、.set_title(), .set_ylim(), と .set_ylabel()が出てきます。 これらのメソッドを使って、関数を完成させましょう。 ライブラリを呼び出して、図を作成する、というものです。 どちらのメソッドも、えいやで書けば、それらしきものが出てくるので、トライ&エラーで書けました。

ボーナスとして出されている、問題は少し難しかったので、回答例をちょっと見ていきます。

ボーナス問題

Y軸を数字だけでなく、金額であることがわかるように、「$○○」としましょう。 ここでは、 y軸の目盛りを取得する(get_yticks)→目盛りの表記を書き換える(for文で先頭に$を入れる)→y軸の目盛りを設定する(set_yticklabels)

water2litter.net

www.pynote.info

Q2:関数を完成せよ。超難問・

ルイージマリオカートサーキットで勝つために最もよいアイテムの決定を分析しようとしています。彼は下記の通りのディクショナリリストを持っています。 itemはレースの時に疲労とパワーアップできるもので、finishはゴールの順位です。 ここは超難問ということであっさり諦めました。 いつか、コードを見に来ようかな。

Q3:関数を完成せよ。難問

ブラックジャックを代表する新しい手法を考え出そうと思っています。 この型を使って、比較演算子(><=など)をオーバーロードして、ある一手が相手を負かすことができるかどうかを調べることができると、かっこいいですよね。

さて、これらのすべてのことはしませんが(クラスを定義するのは、レッスンのスコープから外れるので)、これから定義する関数はもし独自のBlackjackHandクラスを作成するとしたら同じようなことを実施します。

docstringに従って関数を完成させてください。 ざっくり言ってしまえば、ブラックジャックの点数を計算する関数です。 入力値は文字列ですね。 試行錯誤しながら完成させました。

書き方はスマートではないのですが、割と考え方としては正答例と近いかな。returnがださいなー

def score_calc(l_s):
    #純粋にスコアのみを返す関数
    ace_count = 0
    s_ls = 0
    for i in range(len(l_s)):
        temp = l_s[i]
        if not temp.isdecimal():
            #英字の時
            if (temp == 'A') and (ace_count == 0):
                l_s[i] = 11
                ace_count+=1
            elif (temp == 'A') and (ace_count > 0):
                l_s[i] = 1
            else:
                l_s[i] = 10
        else:
            l_s[i] = int(l_s[i])
        
    if sum(l_s)>21 and (ace_count > 0):
        s_ls = sum(l_s)-10
    else:
        s_ls = sum(l_s)
    return s_ls


def blackjack_hand_greater_than(hand_1, hand_2):
    """
    Return True if hand_1 beats hand_2, and False otherwise.
    
    In order for hand_1 to beat hand_2 the following must be true:
    - The total of hand_1 must not exceed 21
    - The total of hand_1 must exceed the total of hand_2 OR hand_2's total must exceed 21
    
    Hands are represented as a list of cards. Each card is represented by a string.
    
    When adding up a hand's total, cards with numbers count for that many points. Face
    cards ('J', 'Q', and 'K') are worth 10 points. 'A' can count for 1 or 11.
    
    When determining a hand's total, you should try to count aces in the way that 
    maximizes the hand's total without going over 21. e.g. the total of ['A', 'A', '9'] is 21,
    the total of ['A', 'A', '9', '3'] is 14.
    
    Examples:
    >>> blackjack_hand_greater_than(['K'], ['3', '4'])
    True
    >>> blackjack_hand_greater_than(['K'], ['10'])
    False
    >>> blackjack_hand_greater_than(['K', 'K', '2'], ['3'])
    False
    """
    sc1 = score_calc(hand_1)
    sc2 = score_calc(hand_2)    
    return (sc2>21 and sc1<sc2 and sc1<22) or (max(sc1, sc2)<=21 and sc1>sc2)
The end

これでPythonのコースは終了です。

コースに関する質問:Learn Forum

さらにPythonのスキルを得るのに良いコース

  1. Machine learning with scikit-learn

  2. Pandas for data manipulation

  3. Deep learning with TensorFlow

新出単語

what the heck:一体何? rig:装備する rigged:不正に仕組まれた