Analisis Catur dengan Informasi Terbatas

19

Dalam tantangan ini, Anda diberikan sejumlah informasi terbatas tentang permainan catur tertentu, dan Anda perlu memperkirakan siapa yang memenangkan permainan .

Anda diberi dua set data:

  1. Potongan dihitung (Potongan apa yang masih hidup)
  2. Warna papan (Warna potongan pada papan)

Lebih penting lagi, Anda tidak tahu di mana potongan-potongan itu berada . Anda perlu menentukan siapa yang menurut Anda akan menang.

Game dipilih dari semua acara yang terdaftar di PGNMentor dari 2010 hingga sekarang. Saya telah memilih 10% dari semua posisi dewan dari setiap pertandingan yang berakhir dengan kemenangan atau kekalahan. Posisi dewan akan selalu setidaknya 30 gerakan ke dalam permainan. Kasing uji dapat ditemukan di sini . (Kemenangan putih didaftar pertama, diikuti oleh kemenangan hitam)

Memasukkan

Hitungan keping akan berupa string yang terdiri dari karakter untuk setiap keping: king, queen, rook, k night, bishop, atau pawn. Huruf kecil berarti hitam, huruf besar adalah putih. Papan akan menjadi string 64 karakter (8 baris dengan 8 kolom). Bmewakili bagian hitam, Wmewakili bagian putih, dan .mewakili tempat kosong. Sampel:

W..WB......W.BB....W..B..W.WWBBB..W...B....W..BBWWW...BB.W....B.,BBKPPPPPPPQRRbbkpppppppqrr

akan mewakili dewan berikut

...B.BB.
.BBBBBBB
.B.B....
B..W....
WWWW.W..
....W.W.
...W..WW
W.....W.

dan di mana kedua warna memiliki 2 Uskup, 1 Raja, 7 Pion, 1 Ratu, 2 Benteng

Keluaran

Anda perlu mengembalikan angka floating-point antara 0 dan 1 (inklusif) untuk menentukan seberapa besar kemungkinan putih menang. Mencicipi:

0.3     (30% chance that white wins)

Keterangan lebih lanjut:

  • Setiap test case bernilai 1 poin. Skor Anda adalah 1 - (1-Output)^2jika putih menang, atau 1 - (Output)^2jika hitam menang.
  • Skor akhir Anda akan menjadi jumlah di semua kasus uji.
  • Jika saya merasa bahwa kiriman adalah hardcoding input, saya berhak mengubah kasus uji. (Jika saya mengubahnya, mereka akan memiliki hash SHA-256 893be4425529f40bb9a0a7632f7a268a087ea00b0eb68293d6c599c6c671cdee)
  • Program Anda harus menjalankan test case secara independen. Tidak ada menyimpan informasi dari satu test case ke yang berikutnya.
  • Jika Anda menggunakan pembelajaran mesin, saya sangat merekomendasikan pelatihan 80% pertama dari data, dan pengujian menggunakan 20% sisanya . (Atau persentase apa pun yang Anda gunakan). Saya menggunakan game beberapa kali dalam data, tapi saya menempatkan game yang sama secara berurutan.
  • UPDATE: Saya telah menambahkan lebih dari satu juta kasus uji untuk tujuan pengujian dan pembelajaran. Mereka dibagi menjadi bagian-bagian hitam dan putih karena batas ukuran repo github.

Semoga berhasil dan selamat bersenang - senang!

Nathan Merrill
sumber
Percakapan ini telah dipindahkan ke obrolan .
Dennis
Apakah test case baru berisi yang lama, atau apakah kedua set terpisah?
Fatalkan
Saya tidak punya ide. Saya mendapatkannya dari situs yang berbeda, jadi ada kemungkinan mereka berdua memasukkan set game yang sama.
Nathan Merrill

Jawaban:

8

Java 8 + Weka, 6413 poin, 94,5%

Jawaban ini menggunakan pendekatan pembelajaran mesin. Anda perlu mengambil perpustakaan Weka , terutama weka.jardan PackageManager.jar.

Di sini, saya menggunakan perceptron multilayer sebagai classifier; Anda dapat mengganti mlpdengan Classifierkelas Weka mana pun untuk membandingkan hasil.

Saya belum banyak mengutak-atik parameter MLP, dan cukup mengamatinya (satu lapisan tersembunyi 50 neuron, 100 zaman, laju pembelajaran 0,2, 0,1 momentum).

Saya mengirik nilai output dari MLP, jadi outputnya benar-benar 1 atau 0 seperti yang didefinisikan dalam tantangan. Dengan begitu, jumlah instance yang diklasifikasikan dengan benar seperti yang dicetak oleh Weka adalah skor kami secara langsung.

Konstruksi vektor fitur

Saya mengubah setiap instance dari string ke vektor 76 elemen, di mana:

  • 64 elemen pertama mewakili sel-sel papan, dalam urutan yang sama seperti dalam string, di mana 1bagian putih, -1adalah bagian hitam dan 0merupakan sel kosong.
  • 12 elemen terakhir mewakili masing-masing jenis lagu (6 per pemain); nilai dari elemen-elemen itu adalah jumlah keping dari tipe itu di papan ( 0menjadi "no piece of type"). Orang dapat menerapkan normalisasi untuk mereparasi nilai-nilai tersebut antara -1 dan 1 tetapi ini mungkin tidak terlalu membantu di sini.

Jumlah instance pelatihan

Jika saya menggunakan semua test case yang diberikan untuk melatih classifier saya, saya telah berhasil mendapatkan 6694 (yaitu 98,6588%) contoh yang benar diklasifikasikan . Ini jelas tidak mengherankan karena menguji model pada data yang sama dengan yang Anda gunakan untuk melatihnya terlalu mudah (karena dalam kasus itu sebenarnya bagus jika model tersebut overfits).

Menggunakan subset acak 80% dari instance sebagai data pelatihan, kami mendapatkan 6413 (yaitu 94,5173%) angka instance dengan benar yang dilaporkan dalam header (tentu saja karena subset tersebut acak Anda mungkin mendapatkan hasil yang sedikit berbeda). Saya yakin bahwa model akan bekerja dengan baik pada data baru, karena pengujian pada 20% contoh yang tersisa (yang tidak digunakan untuk pelatihan) memberikan 77,0818% klasifikasi yang benar, yang menunjukkan bahwa model tersebut menggeneralisasi dengan baik (dengan asumsi bahwa contoh yang kami berikan di sini mewakili kasus uji baru yang akan kami berikan).

Dengan menggunakan setengah contoh untuk pelatihan, dan setengah lainnya untuk pengujian, kami mendapatkan 86,7502% pada data pelatihan dan pengujian, dan 74,4988% hanya pada data uji.

Penerapan

Seperti yang saya katakan, kode ini membutuhkan weka.jardan PackageManager.jardari Weka.

Seseorang dapat mengontrol persentase data yang digunakan dalam set pelatihan TRAIN_PERCENTAGE.

Parameter MLP dapat diubah tepat di bawah TRAIN_PERCENTAGE. Seseorang dapat mencoba pengklasifikasi lain dari Weka (misalnya SMOuntuk SVM) hanya mlpdengan mengganti dengan pengklasifikasi lain.

Program ini mencetak ke set hasil, yang pertama berada di seluruh set (termasuk data yang digunakan untuk pelatihan) yang merupakan skor sebagaimana didefinisikan dalam tantangan ini, dan yang kedua hanya pada data yang tidak digunakan untuk pelatihan.

Satu input data dengan melewati jalur file yang berisi itu sebagai argumen ke program.

import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.classifiers.functions.MultilayerPerceptron;
import weka.core.Attribute;
import weka.core.DenseInstance;
import weka.core.Instance;
import weka.core.Instances;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;

public class Test {

    public static void main(String[] arg) {

        final double TRAIN_PERCENTAGE = 0.5;

        final String HIDDEN_LAYERS = "50";
        final int NB_EPOCHS = 100;
        final double LEARNING_RATE = 0.2;
        final double MOMENTUM = 0.1;

        Instances instances = parseInstances(arg[0]);
        instances.randomize(new java.util.Random(0));
        Instances trainingSet = new Instances(instances, 0, (int) Math.floor(instances.size() * TRAIN_PERCENTAGE));
        Instances testingSet = new Instances(instances, (int) Math.ceil(instances.size() * TRAIN_PERCENTAGE), (instances.size() - (int) Math.ceil(instances.size() * TRAIN_PERCENTAGE)));

        Classifier mlp = new MultilayerPerceptron();
        ((MultilayerPerceptron) mlp).setHiddenLayers(HIDDEN_LAYERS);
        ((MultilayerPerceptron) mlp).setTrainingTime(NB_EPOCHS);
        ((MultilayerPerceptron) mlp).setLearningRate(LEARNING_RATE);
        ((MultilayerPerceptron) mlp).setMomentum(MOMENTUM);


        try {
            // Training phase
            mlp.buildClassifier(trainingSet);
            // Test phase
            System.out.println("### CHALLENGE SCORE ###");
            Evaluation test = new Evaluation(trainingSet);
            test.evaluateModel(mlp, instances);
            System.out.println(test.toSummaryString());
            System.out.println();
            System.out.println("### TEST SET SCORE ###");
            Evaluation test2 = new Evaluation(trainingSet);
            test2.evaluateModel(mlp, testingSet);
            System.out.println(test2.toSummaryString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Instances parseInstances(String filePath) {
        ArrayList<Attribute> attrs = new ArrayList<>(); // Instances constructor only accepts ArrayList
        for(int i = 0 ; i < 76 ; i++) {
            attrs.add(new Attribute("a" + String.valueOf(i)));
        }
        attrs.add(new Attribute("winner", new ArrayList<String>(){{this.add("white");this.add("black");}}));
        Instances instances = new Instances("Rel", attrs, 10);
        instances.setClassIndex(76);

        try {
            BufferedReader r = new BufferedReader(new FileReader(filePath));
            String line;
            String winner = "white";
            while((line = r.readLine()) != null) {
                if(line.equals("White:")) {
                    winner = "white";
                } else if(line.equals("Black:")) {
                    winner = "black";
                } else {
                    Instance instance = new DenseInstance(77);
                    instance.setValue(attrs.get(76), winner);
                    String[] values = line.split(",");
                    for(int i = 0 ; i < values[0].length() ; i++) {
                        if(values[0].charAt(i) == 'B') {
                            instance.setValue(attrs.get(i), -1);
                        } else if(values[0].charAt(i) == 'W') {
                            instance.setValue(attrs.get(i), 1);
                        } else {
                            instance.setValue(attrs.get(i), 0);
                        }
                    }
                    // Ugly as hell
                    instance.setValue(attrs.get(64), values[1].length() - values[1].replace("k", "").length());
                    instance.setValue(attrs.get(65), values[1].length() - values[1].replace("q", "").length());
                    instance.setValue(attrs.get(66), values[1].length() - values[1].replace("r", "").length());
                    instance.setValue(attrs.get(67), values[1].length() - values[1].replace("n", "").length());
                    instance.setValue(attrs.get(68), values[1].length() - values[1].replace("b", "").length());
                    instance.setValue(attrs.get(69), values[1].length() - values[1].replace("p", "").length());
                    instance.setValue(attrs.get(70), values[1].length() - values[1].replace("K", "").length());
                    instance.setValue(attrs.get(71), values[1].length() - values[1].replace("Q", "").length());
                    instance.setValue(attrs.get(72), values[1].length() - values[1].replace("R", "").length());
                    instance.setValue(attrs.get(73), values[1].length() - values[1].replace("N", "").length());
                    instance.setValue(attrs.get(74), values[1].length() - values[1].replace("B", "").length());
                    instance.setValue(attrs.get(75), values[1].length() - values[1].replace("P", "").length());

                    instances.add(instance);
                }
            }
        } catch (Exception e) { // who cares
            e.printStackTrace();
        }
        return instances;
    }
}
Fatalisasi
sumber
Bagaimana Anda menyandikan input?
Nathan Merrill
@NathanMerrill Saya tidak yakin saya mengerti pertanyaan Anda
Fatalize
Bagaimana Anda melewati test case sebagai input ke jaringan saraf? Apakah Anda hanya melewati string mentah?
Nathan Merrill
@NathanMerrill Diedit dengan paragraf pada konstruksi vektor fitur.
Fatalkan
Bagaimana weka tahu Anda mencoba memprediksi pemenang?
user1502040
8

GNU sed + bc, 4336 5074.5 poin, 64 75%

Pembaruan: OP memberikan cara baru untuk menghitung skor prediksi untuk setiap kasus uji. Menggunakan Wolfram Alpha , saya merencanakan kedua set rumus untuk melihat perbedaan.

Cara saat ini membawa insentif yang kuat untuk menghasilkan probabilitas aktual, dan bukan hanya yang ekstrem, 0 dan 1, yang formula barunya memberikan skor maksimum yang sama seperti sebelumnya. Inilah sebabnya mengapa algoritma yang tidak berubah di bawah ini, kini memiliki tingkat prediksi yang lebih baik, bahkan tingkat yang luar biasa karena kesederhanaannya.

Namun, ada juga kekurangan yang terkait dengan formula baru, seperti yang dijelaskan dalam 'Sunting 1'.


Ini adalah estimasi sederhana berdasarkan hanya pada keuntungan / kerugian material, mengabaikan penempatan sebenarnya potongan. Saya ingin tahu bagaimana ini akan tampil. Alasan saya menggunakan sed, dan bukan bahasa yang bisa melakukan ini dalam satu baris, adalah karena itu adalah bahasa esoterik favorit saya.

/:/d                                             # delete the two headers
s:.*,::                                          # delete board positions
s:$:;Q9,R5,B3,N3,P1,K0,q-9,r-5,b-3,n-3,p-1,k-0:  # add relative piece value table
:r                                               # begin replacement loop
s:([a-Z])((.*)\1([^,]+)):\4+\2:                  # table lookup: letter-value repl.
tr                                               # repeat till last piece
s:;.*::                                          # delete value table
s:.*:echo '&0'|bc:e                              # get material difference: bc call
/^0$/c0.5                                        # print potential draw score
/-/c0                                            # print potential black win score
c1                                               # print potential white win score

Nilai satuan standar yang digunakan:

  • 9 - Ratu
  • 5 - Benteng
  • 3 - Ksatria
  • 3 - Uskup
  • 1 - Gadai
  • 0 - Raja

Saya menghitung bahan untuk kedua sisi dan mengurangi bahan hitam dari yang putih. Output untuk setiap test case didasarkan pada perbedaan itu sebagai berikut:

  • jika selisih> 0, maka output = 1 (kemungkinan menang putih)
  • jika perbedaan = 0, maka output = 0,5 (potensi penarikan).

Ini adalah satu-satunya hasil fraksional saya, maka alasan peningkatan seperti dijelaskan di atas.

  • jika perbedaan <0, maka output = 0 (kemungkinan menang hitam)

Tingkat prediksi untuk metode ini adalah 64%. Sekarang sudah 75% dengan formula baru.

Awalnya saya berharap ini akan lebih tinggi, katakanlah 70%, tetapi sebagai pemain catur saya sendiri dapat memahami hasilnya, karena saya telah kehilangan begitu banyak permainan ketika saya masih +1 / +2, dan memenangkan banyak ketika saya turun di bahan. Ini semua tentang posisi aktual. (Yah, sekarang aku mendapatkan keinginanku!)

Sunting 1: kekurangannya

Solusi sepele adalah dengan menghasilkan 0,5 untuk setiap kasus uji, karena dengan cara ini Anda mencetak setengah poin terlepas siapa yang menang. Untuk kasus uji kami, ini berarti skor total 3392,5 poin (50%).

Tetapi dengan formula baru, 0,5 (yang merupakan hasil yang akan Anda berikan jika Anda ragu-ragu siapa yang menang) dikonversi menjadi 0,75 poin. Ingat bahwa skor maksimum yang dapat Anda terima untuk kasus uji adalah 1, untuk kepercayaan 100% pada pemenang. Dengan demikian, skor total baru untuk output 0,5 konstan adalah 5088,75 poin, atau 75%! Menurut saya, insentifnya terlalu kuat untuk kasus ini.

Skor itu lebih baik, meskipun sedikit, daripada algoritma berbasis keunggulan materi saya. Alasan untuk itu adalah karena algoritma memberikan probabilitas 1 atau 0 (tidak ada insentif), diasumsikan menang atau kalah, lebih banyak kali (3831) daripada yang diberikan 0,5 (insentif), diasumsikan menarik (2954). Metode ini sederhana pada akhirnya, dan karena itu tidak memiliki persentase jawaban yang benar. Dorongan dari formula baru ke 0,5 konstan, berhasil mencapai persentase itu, secara artifisial.

Edit 2:

Adalah fakta yang diketahui, disebutkan dalam buku-buku catur, bahwa biasanya lebih baik memiliki sepasang uskup daripada sepasang ksatria. Ini terutama benar di tahap tengah hingga akhir permainan, di mana kasus uji berada, karena lebih cenderung memiliki posisi terbuka di mana kisaran uskup ditingkatkan.

Karena itu saya melakukan tes kedua, tetapi kali ini saya mengganti nilai uskup dari 3 menjadi 3,5. Nilai knight itu tetap 3. Ini adalah preferensi pribadi, jadi aku tidak menjadikannya pengajuan standarku. Total skor dalam kasus ini adalah 4411 poin (65%). Hanya peningkatan 1 poin persentase yang diamati.

Dengan formula baru, skor total adalah 4835 poin (71%). Sekarang, uskup tertimbang itu berkinerja buruk. Tapi, efeknya dijelaskan karena metode tertimbang sekarang memberi bahkan lebih banyak kali diasumsikan menang atau kalah (5089), daripada yang diasumsikan menarik (1696).

seshoumara
sumber
1
+1 untuk memberikan solusi dasar yang masuk akal. Saya juga bertanya-tanya seberapa bagus kinerja ini.
Martin Ender
@ MartinEnder Terima kasih. Gagasan saya untuk meningkatkan nilai uskup, yang disebutkan terakhir kali, hanya menghasilkan kenaikan tingkat keberhasilan 1% (lihat Pembaruan 2). Saya pikir nilai standar memang memasukkan efek itu.
seshoumara
Hei, sesuai komentar xnor, apakah Anda keberatan jika saya mengubah skor menjadi perbedaan mutlak kuadrat?
Nathan Merrill
1
Luar biasa. Juga, terima kasih telah menjawab! Saya selalu khawatir bahwa pertanyaan saya yang lebih sulit tidak akan pernah mendapat jawaban.
Nathan Merrill
@NathanMerrill Saya memperbarui jawaban saya untuk menggunakan skor baru seperti yang diminta. Maaf untuk analisis panjang, tapi saya memang sangat penasaran.
seshoumara
4

Python 3 - 84,6%, 5275 poin pada set validasi

Jika kita menipu dan menggunakan semua data, kita dapat mencapai akurasi 99,3%, dan skor 6408

Hanya MLP besar sederhana dengan dropout menggunakan Keras

import collections
import numpy as np
import random

import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers.noise import GaussianDropout
from keras.optimizers import Adam

np.random.seed(0)
random.seed(0)

def load_data():
    with open('test_cases.txt', 'r') as f:
        for line in f:
            yield line.split(',')

def parse_data(rows):
    black_pieces = "kpbkrq"
    white_pieces = black_pieces.upper()
    for i, row in enumerate(rows):
        if len(row) >= 2:
            board = row[0]
            board = np.array([1 if c == 'W' else -1 if c == 'B' else 0 for c in board], dtype=np.float32)
            pieces = row[1]
            counts = collections.Counter(pieces)
            white_counts = np.array([counts[c] for c in white_pieces], dtype=np.float32)
            black_counts = np.array([counts[c] for c in black_pieces], dtype=np.float32)
            yield (outcome, white_counts, black_counts, board)
        else:
            if 'White' in row[0]:
                outcome = 1
            else:
                outcome = 0

data = list(parse_data(load_data()))
random.shuffle(data)
data = list(zip(*data))
y = np.array(data[0])
x = list(zip(*data[1:]))
x = np.array([np.concatenate(xi) for xi in x])

i = len(y) // 10

x_test, x_train = x[:i], x[i:]
y_test, y_train = y[:i], y[i:]

model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(76,)))
model.add(GaussianDropout(0.5))
model.add(Dense(512, activation='relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(512, activation='relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='mean_squared_error', optimizer=Adam())

use_all_data = False

x_valid, y_valid = x_test, y_test

if use_all_data:
    x_train, y_train = x_test, y_test = x, y
    validation_data=None
else:
    validation_data=(x_test, y_test)

batch_size = 128

history = model.fit(x_train, y_train, batch_size=batch_size, epochs=50, verbose=1, validation_data=validation_data)

y_pred = model.predict_on_batch(x_test).flatten()
y_class = np.round(y_pred)
print("accuracy: ", np.sum(y_class == y_test) / len(y_test))

score = np.sum((y_pred - (1 - y_test)) ** 2) * (len(y) / len(y_test))
print("score: ", score)
pengguna1502040
sumber
Berapa banyak data yang Anda gunakan untuk pelatihan untuk mendapatkan angka 84,6%?
Fatalkan
Saya menggunakan split 90-10 seperti yang ditunjukkan dalam kode
user1502040
Hai, saya telah menambahkan banyak lagi test case jika Anda tertarik.
Nathan Merrill
2

Python 3 - akurasi 94,3%, 6447 poin pada set validasi 20% dari data

Menggunakan 3 jaringan saraf, regressor tetangga terdekat, hutan acak, dan peningkatan gradien. Prediksi ini dikombinasikan dengan hutan acak yang juga memiliki akses ke data.

import collections
import numpy as np
import numpy.ma as ma
import random

import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, BatchNormalization, Activation, Conv2D, Flatten
from keras.layers.noise import GaussianDropout
from keras.callbacks import EarlyStopping
from keras.optimizers import Adam
from sklearn.neighbors import KNeighborsRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
import tensorflow

tensorflow.set_random_seed(1)
np.random.seed(1)
random.seed(1)

def load_data():
    with open('test_cases.txt', 'r') as f:
        for line in f:
            yield line.split(',')

def parse_data(rows):
    black_pieces = "kqrnbp"
    white_pieces = black_pieces.upper()
    for i, row in enumerate(rows):
        if len(row) >= 2:
            board = row[0]
            board = np.array([1 if c == 'W' else -1 if c == 'B' else 0 for c in board], dtype=np.float32)
            pieces = row[1]
            counts = collections.Counter(pieces)
            white_counts = np.array([counts[c] for c in white_pieces], dtype=np.float32)
            black_counts = np.array([counts[c] for c in black_pieces], dtype=np.float32)
            yield (outcome, white_counts, black_counts, board)
        else:
            if 'White' in row[0]:
                outcome = 1
            else:
                outcome = 0

data = list(parse_data(load_data()))
random.shuffle(data)
data = list(zip(*data))
y = np.array(data[0])
x = list(zip(*data[1:]))
conv_x = []
for white_counts, black_counts, board in x:
    board = board.reshape((1, 8, 8))
    white_board = board > 0
    black_board = board < 0
    counts = [white_counts, black_counts]
    for i, c in enumerate(counts):
        n = c.shape[0]
        counts[i] = np.tile(c, 64).reshape(n, 8, 8)
    features = np.concatenate([white_board, black_board] + counts, axis=0)
    conv_x.append(features)
conv_x = np.array(conv_x)
x = np.array([np.concatenate(xi) for xi in x])
s = x.std(axis=0)
u = x.mean(axis=0)
nz = s != 0
x = x[:,nz]
u = u[nz]
s = s[nz]
x = (x - u) / s

i = 2 * len(y) // 10

x_test, x_train = x[:i], x[i:]
conv_x_test, conv_x_train = conv_x[:i], conv_x[i:]
y_test, y_train = y[:i], y[i:]

model = Sequential()

def conv(n, w=3, shape=None):
    if shape is None:
        model.add(Conv2D(n, w, padding="same"))
    else:
        model.add(Conv2D(n, w, padding="same", input_shape=shape))
    model.add(BatchNormalization())
    model.add(Activation('relu'))

conv(128, shape=conv_x[0].shape) 
conv(128)
conv(128)
conv(128)
conv(128)
conv(128)
conv(128)
conv(128)
conv(128)
conv(128)
conv(2, w=1)
model.add(Flatten())
model.add(GaussianDropout(0.5))
model.add(Dense(256))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(1))
model.add(BatchNormalization())
model.add(Activation('sigmoid'))

model.compile(loss='mse', optimizer=Adam())

model5 = model

model = Sequential()
model.add(Dense(50, input_shape=(x.shape[1],)))
model.add(Activation('sigmoid'))
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='mse', optimizer=Adam())

model0 = model

model = Sequential()
model.add(Dense(1024, input_shape=(x.shape[1],)))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(1024))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(1024))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='mse', optimizer=Adam())

model4 = model

use_all_data = False

x_valid, y_valid = x_test, y_test

if use_all_data:
    x_train, y_train = x_test, y_test = x, y
    validation_data=None
else:
    validation_data=(x_test, y_test)

def subsample(x, y, p=0.9, keep_rest=False):
    m = np.random.binomial(1, p, size=len(y)).astype(np.bool)
    r = (x[m,:], y[m])
    if not keep_rest:
        return r
    m = ~m
    return r + (x[m,:], y[m])

epochs=100

x0, y0, x_valid, y_valid = subsample(conv_x_train, y_train, keep_rest=True)
model5.fit(x0, y0, epochs=epochs, verbose=1, validation_data=(x_valid, y_valid), callbacks=[EarlyStopping(patience=1)])

x0, y0, x_valid, y_valid = subsample(x_train, y_train, keep_rest=True)
model0.fit(x0, y0, epochs=epochs, verbose=1, validation_data=(x_valid, y_valid), callbacks=[EarlyStopping(patience=1)])

x0, y0, x_valid, y_valid = subsample(x_train, y_train, keep_rest=True)
model4.fit(x0, y0, epochs=epochs, verbose=1, validation_data=(x_valid, y_valid), callbacks=[EarlyStopping(patience=1)])

model1 = RandomForestRegressor(n_estimators=400, n_jobs=-1, verbose=1)
model1.fit(*subsample(x_train, y_train))

model2 = GradientBoostingRegressor(learning_rate=0.2, n_estimators=5000, verbose=1)
model2.fit(*subsample(x_train, y_train))

model3 = KNeighborsRegressor(n_neighbors=2, weights='distance', p=1)
model3.fit(*subsample(x_train, y_train))

models = (model0, model1, model2, model3, model4, model5)

model_names = [
    "shallow neural net",
    "random forest",
    "gradient boosting",
    "k-nearest neighbors",
    "deep neural net",
    "conv-net",
    "ensemble"
]

def combine(predictions):
    clip = lambda x: np.clip(x, 0, 1)
    return clip(np.array([y.flatten() for y in predictions]).T)

def augment(x, conv_x):
    p = combine([m.predict(x) for m in models[:-1]] + [models[-1].predict(conv_x)])
    return np.concatenate((x, p), axis=1)

model = RandomForestRegressor(n_estimators=200, n_jobs=-1, verbose=1)
model.fit(augment(x_train, conv_x_train), y_train)

def accuracy(prediction):
    class_prediction = np.where(prediction > 0.5, 1, 0)
    return np.sum(class_prediction == y_test) / len(y_test)

predictions = [m.predict(x_test).flatten() for m in models[:-1]] + [models[-1].predict(conv_x_test).flatten()]+ [model.predict(augment(x_test, conv_x_test))]

for s, p in zip(model_names, predictions):
    print(s + " accuracy: ", accuracy(p))

def evaluate(prediction):
    return np.sum(1 - (prediction - y_test) ** 2) * (len(y) / len(y_test))

for s, p in zip(model_names, predictions):
    print(s + " score: ", evaluate(p))
pengguna1502040
sumber
Hai, saya telah menambahkan banyak lagi test case jika Anda tertarik.
Nathan Merrill
Woah kamu keluar pada ini.
Robert Fraser
Perhatikan jawaban java di sini bahwa "denyut" milik Anda tampaknya melaporkan% pada seluruh kumpulan data dan hanya mendapatkan 77% pada data yang tidak dilatihnya.
Robert Fraser
0

Python 3 - 4353.25 / 6785 poin - 64%

Jadi saya mengerjakan ini sebagian besar kemarin. Posting golf pertama saya, dan saya hanya menggunakan python seminggu atau lebih sekarang, jadi maafkan saya jika tidak semuanya dioptimalkan.

def GetWhiteWinPercent(a):
finalWhiteWinPercent=0
i=a.index(',')

#position
board=a[:i]
blackBoardScore=0
whiteBoardScore=0
for r in range(i):
    if board[r] == 'B': blackBoardScore += abs(7 - (r % 8))
    if board[r] == 'W': whiteBoardScore += r % 8
if   whiteBoardScore > blackBoardScore: finalWhiteWinPercent += .5
elif whiteBoardScore < blackBoardScore: finalWhiteWinPercent += .0
else: finalWhiteWinPercent+=.25

#pieces
pieces=a[i:]
s = {'q':-9,'r':-5,'n':-3,'b':-3,'p':-1,'Q':9,'R':5,'N':3,'B':3,'P':1}
pieceScore = sum([s.get(z) for z in pieces if s.get(z) != None])
if   pieceScore < 0: finalWhiteWinPercent += 0
elif pieceScore > 0: finalWhiteWinPercent += .5
else: finalWhiteWinPercent += .25

return finalWhiteWinPercent

Saya berakhir di jalan yang sama dengan jawaban seshoumara. Tetapi sejumlah besar kasus uji yang bahkan jumlah kepingnya membuat saya tidak puas.

Jadi saya mencari ciri-ciri yang menentukan siapa yang menang dalam catur (saya tidak bermain sendiri) dan memperhatikan posisi dewan, khususnya kontrol pusat, besar. Di situlah bit ini masuk

for r in range(i):
    if board[r] == 'B': blackBoardScore += abs(7 - (r % 8))
    if board[r] == 'W': whiteBoardScore += r % 8
if   whiteBoardScore > blackBoardScore: finalWhiteWinPercent += .5
elif whiteBoardScore < blackBoardScore: finalWhiteWinPercent += .0
else: finalWhiteWinPercent+=.25

Kedua bagian yang digabungkan digunakan untuk menemukan skor (0,0, 0,25, 0,50, 0,75, 1,0)

Sangat menarik bahwa posisi dewan tambahan ini tampaknya tidak meningkatkan kesempatan sama sekali untuk menebak pemenang.

Jika Anda menjatuhkan kasus uji ke beberapa file, inilah pengujiannya.

whiteWins=0
blackWins=0
totalWins=0
for line in open('testcases2.txt','r'):
    totalWins += 1
    blackWins += 1 - GetWhiteWinPercent(line)
for line in open('testcases.txt','r'):
    totalWins += 1
    whiteWins += GetWhiteWinPercent(line)

print(str(whiteWins+blackWins) +'/'+str(totalWins))

Saya tahu ini bukan tantangan golf, tetapi setiap tips atau saran dalam hal ini sangat dihargai!

Aliran data
sumber
Jawabanku? Anda maksud jawaban seshoumara? Juga, Anda tidak perlu bermain golf ini (kecuali jika Anda mau). Ini bukan tantangan kode-golf .
Nathan Merrill
Anda dapat menyimpan banyak byte hanya dengan menggunakan nama variabel satu karakter. (Meskipun tidak terlalu penting karena ini bukan kode-golf)
HyperNeutrino
Aduh! Mengedit itu sekarang. Di tempat kerja, inilah yang saya dapatkan untuk membaca sekilas!
Datastream
2
Tolong jangan golf itu. Lebih baik menjaga kode tetap terbaca saat bukan kode-golf.
mbomb007
Kontrol bagian tengah papan tidak berarti menempati bagian tengah papan, tetapi menyerang bagian tengah papan. Jika Anda ingin menambahkan beberapa kompleksitas di sekitarnya, itu dapat meningkatkan skor Anda.
Bukan berarti Charles