How many files(0-15)

競馬の予想システムで一儲を企むおっさんのヨコシマな横顔

機械学習で競馬予想 其の012 ~リファクタリング~

僕は、pythonの素人で、行き当たりばったりなコーディングをしているため、ソースが冗長で汚くなってきたので、このタイミングでリファクタリングしようと思います。機械学習で競馬予想という本筋から逸れてしまいますが、(筆者の)今後のためにも仕方ありません。pythonに詳しい方であれば本エントリは無視した方が良いでしょう。基本的には冗長な部分の排除とよりpythonらしいと思われる記述にしていきます。

手始めに、プロパティ的なものをハードコーディングしていたのでプロパティファイルへ外だし。
pythonではConfigParserを使うと良いらしいので以下のように実装。

  • ConfigParser.SafeConfigParserでプロパティファイル読込用にインスタンスを生成
  • readでプロパティファイルの読み込み


プロパティファイルの内容を取得するには、getを使う。
これだけ。

import ConfigParser

# 環境設定ファイル読込処理
envFile = ConfigParser.SafeConfigParser()
envFile.read(r'config.ini')

horse_data_file_path = envFile.get('horse_data', 'file_path')


プロパティファイルにはカテゴリというのを設定できる。具体的な記述は以下のとおり。

[horse_data]
file_path=.\horse


次に、元々、genfromtxtで馬のデータを取得したものに対して、dataShapingという関数で、不要データを削除や、データの形式を整形部分をgenfromtxtの呼び出し部分に記述。
実装は以下のような感じ。convertersで単にファイルから取得した値を返却するだけだったのを元々dataShaping関数で実装していた整形モジュール呼び出しと連動させただけ。

# 馬データの読み込み
def loadHorseData(filename):
    horsedata = sp.genfromtxt(os.path.join(horse_data_file_path, filename), delimiter="\t", 
        dtype=[ ('日付','S10'),         # 0:日付
                ('開催地','i3'),       # 1:開催地
                ('レース','i2'),         # 2:レース 
                ('レース名','U50'),       # 3:レース名  
                ('距離','i4'),          # 4:距離  
                ('天候','i3'),         # 5:天候  
                ('馬番','i2'),          # 6:馬番 
                ('人気','i3'),          # 7:人気 
                ('着順','U10'),         # 8:着順 
                ('タイム','f5'),        # 9:タイム 
                ('差/事故', 'i4'),     # 10:差/事故  
                ('上3F','i4'),         # 11:上3F 
                ('通過順','U10'),      # 12:通過順
                ('体重','i4'),         # 13:体重
                ('騎手','U20'),        # 14:騎手
                ('負担重量','i4'),     # 15:負担重量
                ('調教師','U20'),      # 16:調教師
                ('獲得賞金(円)','U10')  # 17:獲得賞金
                ],                  
        converters={ 
            0 : lambda s: convertDate(s.decode('utf8')), # 開催日
            1 : lambda s: createLocationDict(s.decode('utf8')),    # 開催地
            3 : lambda s: s.decode('utf8'),    # レース名
            5 : lambda s: createWeatherDict(s.decode('utf8')),    # 天候
            9 : lambda s: convertTime(s.decode('utf8')), # タイム
            14 : lambda s: s.decode('utf8'),    # 騎手
            16: lambda s: s.decode('utf8'),    # 調教師
        })

    return np.array(horsedata.tolist(), dtype = object)


それぞれのデータ整形に使っている処理は以下のとおり。以前は、大井競馬場のデータだけを使っていたけど、今回はすべての開催地のデータを使うようについでに修正。

def addZero(data):
    if len(data) == 2:
        return data
    else:
        return "0" + str(data)

def convertDate(date):
    aryYmd = date.split("/")
    year = addZero(aryYmd[0])
    month = addZero(aryYmd[1])
    day = addZero(aryYmd[2])
    return str(year) + str(month) + str(day)

def convertTime(time):
    if len(time.split(":")) == 2:
        return np.float32(time.split(":")[0])*60+np.float32(time.split(":")[1])
    else:
        return np.float32(time)
  
def createWeatherDict(weather):
    global weatherDict
    global weatherIndex
    
    if weatherDict.has_key(weather) == False:
        weatherIndex += 1
        weatherDict[weather] = weatherIndex
    
    return weatherIndex

def createLocationDict(location):
    global locationDict
    global locationIndex
    
    if locationDict.has_key(location) == False:
        locationIndex += 1
        locationDict[location] = locationIndex
    return locationDict[location]


そうすると、結果が微妙に変わった。この辺の評価は後日にするとして次回もリファクタリングを進めます。

8R 1200m 実績
馬番 タイム(秒) タイム(秒) タイム(秒)
1 80.4909487166 74.2050783599 75.1
2 74.955080275 74.5661372198 76.6
3 73.6787991346 74.1367306308 74.1
4 76.1923007581 72.3405306744 75.0
5 77.984841449 81.7183619077 77.2
6 74.878874984 73.5652206548 76.2
7 76.8652917749 80.5876352042 78.0
8 76.739123412 73.8367610183 75.0
9 74.2465295977 75.2493784691 75.1
10 81.3600303209 81.3099440104 76.4
11 75.9533880198 76.1685987163 76.6
12 74.1004315609 73.9210259265 74.5
13 75.9515585476 76.2881028763 78.7
9R 1600m 実績
馬番 タイム(秒) タイム(秒) タイム(秒)
1 104.009553751 105.449829127 106.3
2 105.285454948 104.446635423 105.1
3 104.170221199 103.544665086 104.8
4 103.561907896 102.832908331 104.8
5 105.803250689 106.681494384 107.0
6 104.753017942 104.852490486 105.5
7 103.855474193 104.096728343 104.1
8 103.621835287 101.063900125 104.9
9 105.521398972 105.44998775 106.9
10 105.96640969 106.27426342 106.2
11 102.40205078 102.557512398 106.3
12 104.211524406 104.923401093 105.8
13 104.522090684 103.621225058 107.0
14 106.726775191 103.160208763 104.3
10R 1200m 実績
馬番 タイム(秒) タイム(秒) タイム(秒)
1 73.9448633203 74.053751696 74.7
2 74.4725932805 74.791709691 75.6
3 76.4310043125 74.9716748455 75.5
4 77.8331423393 91.0018906849 78.3
5 80.8977378491 79.8907980544 75.4
6 69.0830010014 68.6452500517 75.1
7 76.5005151764 75.2536390704 75.8
8 74.3322163529 74.4513043382 74.7
9 74.6606315693 53.7728385949 76.4
10 75.0673609574 74.9747204476 75.1
11 73.237177527 73.2287457443 76.5
12 82.8226314627 85.7890644837 75.7
13 73.5605822215 75.1488630555 74.5
11R 1600m 実績
馬番 タイム(秒) タイム(秒) タイム(秒)
1 101.298091317 101.639022812 102.3
2 101.843065646 104.904044778 103.2
3 103.375501518 102.832548994 102.6
4 106.789608436 104.198294174 101.0
5 101.40716234 100.890777032 105.3
6 101.866305864 101.794480623 103.2
7 100.723857238 103.042734984 102.3
8 102.829131723 102.415056316 103.9
9 102.544875956 101.758714813 106.6
12R 1800m 実績
馬番 タイム(秒) タイム(秒) タイム(秒)
1 114.444510794 117.24558277 117.1
2 118.470400983 119.808649496 118.5
3 117.646829198 115.77679082 116.3
4 115.078354065 114.421506359 117.1
5 116.195286215 91.7595650662 117.7
6 116.622796412 115.25449028 118.5
7 118.748983122 119.789764968 118.4
8 121.098679561 107.532586121 121.1
9 117.614868291 120.763363564 120.0
10 115.438044791 109.776689962 117.7
11 114.906238595 115.068710391 116.5
12 116.709747135 111.356021988 117.6
13 116.006504665 116.470179101 116.7