제한된 정보로 체스 분석


19

이 도전에서는 특정 체스 게임에 대한 정보가 제한되어 있으며 누가 이겼는지 예측해야합니다 .

두 가지 데이터 세트가 제공됩니다.

  1. 조각 수 (여전히 살아있는 조각)
  2. 보드 색상 (보드의 조각 색상)

더 중요한 것은, 당신은 하지 않습니다 조각의 위치 알고있다 . 누가 이길 것이라고 생각할지 결정해야합니다.

게임은 2010 년부터 현재까지 PGNMentor에 나열된 모든 이벤트에서 선택됩니다 . 승리 또는 패배로 끝나는 각 게임에서 모든 보드 위치의 10 %를 선택했습니다. 보드 위치는 항상 게임에서 30 회 이상 움직입니다. 테스트 사례는 여기 에서 찾을 수 있습니다 . (흰색 승리가 먼저 나열되고 검은 승리가 나열 됨)

입력

조각 수는 각 조각에 대한 문자 ( king, queen, rook, kight n, bishop 또는 awn) 로 구성된 문자열 p입니다. 소문자는 검은 색, 대문자는 흰색을 의미합니다. 보드는 64 자 (8 행 x 8 열)의 문자열입니다. B검은 색 조각을 W나타내고 흰색 조각을 .나타내며 빈 자리를 나타냅니다. 견본:

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

다음 보드를 나타냅니다

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

두 색상 모두 주교 2 명, 왕 1 명, 폰 7 명, 여왕 1 명, 루크 2 명

산출

흰색이 이길 가능성을 확인하려면 0에서 1 (포함) 사이의 부동 소수점 숫자를 반환해야합니다. 견본:

0.3     (30% chance that white wins)

자세한 내용은:

  • 각 테스트 케이스는 1 포인트의 가치가 있습니다. 1 - (1-Output)^2흰색이이기거나 1 - (Output)^2검은 색이 이기면 점수가됩니다 .
  • 최종 점수는 모든 테스트 사례의 합계입니다.
  • 제출물이 입력을 하드 코딩한다고 생각되면 테스트 사례를 변경할 권리가 있습니다. (내가 변경하면 SHA-256 해시가 있습니다 893be4425529f40bb9a0a7632f7a268a087ea00b0eb68293d6c599c6c671cdee)
  • 프로그램은 테스트 케이스를 독립적으로 실행해야합니다. 한 테스트 사례에서 다음 테스트 사례로 정보를 저장하지 않습니다.
  • 기계 학습을 사용하는 경우 데이터의 처음 80 %에 대한 교육과 나머지 20 %를 사용한 테스트를 강력히 권장 합니다. (또는 당신이 사용하는 비율). 데이터에서 게임을 여러 번 사용하지만 동일한 게임을 순차적으로 결합합니다.
  • 업데이트 : 테스트 및 학습 목적으로 백만 개가 넘는 테스트 사례 를 추가했습니다 . github repo 크기 제한으로 인해 흑백 부분으로 나뉩니다.

행운을 빌고 재미있게 보내!


이 대화는 채팅 으로 이동 되었습니다 .
Dennis

새로운 테스트 케이스에 이전 테스트 케이스가 포함되어 있습니까, 아니면 두 세트가 분리되어 있습니까?
Fatalize

나도 몰라 다른 사이트에서 가져 왔으므로 둘 다 동일한 게임 세트를 포함했을 가능성이 있습니다.
Nathan Merrill

답변:


8

Java 8 + Weka, 6413 포인트, 94.5 %

이 답변은 기계 학습 접근법을 사용합니다. 당신은 검색해야 웨카의 특히, 라이브러리를 weka.jar하고 PackageManager.jar.

여기에서는 분류 자로 다층 퍼셉트론을 사용합니다. mlp모든 ClassifierWeka 클래스로 대체 하여 결과를 비교할 수 있습니다.

나는 MLP의 매개 변수를 많이 고민하지 않았고 단순히 그것들을 눈으로 보았습니다 (50 뉴런의 숨겨진 레이어 하나, 100 시대, 0.2 학습 속도, 0.1 운동량).

MLP의 출력 값을 임계 값으로 지정하므로 출력은 실제로 챌린지에 정의 된대로 1 또는 0입니다. 이런 식으로 Weka가 인쇄 한 올바르게 분류 된 인스턴스 수는 바로 우리의 점수입니다.

특징 벡터 구성

각 인스턴스를 문자열에서 76 요소로 구성된 벡터로 바꿉니다.

  • 첫 번째 64 개 요소는 문자열과 같은 순서로 보드의 셀을 나타냅니다. 여기서 1흰색 조각 -1은 검은 색 조각이며 0빈 셀입니다.
  • 마지막 12 개 요소는 각 유형의 조각 (플레이어 당 6 개)을 나타냅니다. 해당 요소의 값은 보드에서 해당 유형의 조각 수입니다 ( 0"해당 유형의 조각 없음"). 정규화를 적용하여 -1과 1 사이의 값을 다시 맞출 수는 있지만 여기서는 그다지 도움이되지 않습니다.

교육 인스턴스 수

분류자를 훈련시키기 위해 제공된 모든 테스트 사례를 사용하는 경우 올바르게 분류 된 6694 개 (즉, 98.6588 %)를 얻었습니다 . 훈련에 사용한 것과 동일한 데이터로 모델을 테스트하는 것이 너무 쉬운 방법이기 때문에 이는 놀라운 일이 아닙니다 (이 경우 실제로 모델이 과적 합하는 것이 좋기 때문에).

교육 데이터로 인스턴스의 80 %의 임의의 하위 집합을 사용 하여 헤더에보고 된 6413 (예 : 94.5173 %)의 올바르게 분류 된 인스턴스 그림 을 얻습니다 (물론 하위 집합이 무작위이므로 약간 다른 결과를 얻을 수 있음). (훈련에 사용되지 않은) 인스턴스의 나머지 20 %에 대한 테스트가 77.0818 %의 정확한 분류를 제공하기 때문에 모델이 새 데이터에서 제대로 작동 할 것이라고 확신합니다 . 여기에 제시된 사례는 새로운 테스트 사례를 나타냅니다.

반 교육에 대한 인스턴스 및 테스트를위한 나머지 절반을 사용하여, 우리는 얻을 86.7502 %를 교육 및 테스트 데이터, 모두 74.4988 % 만 테스트 데이터에.

이행

내가 말했듯이 코드가 필요 weka.jar하고 PackageManager.jar웨카에서.

로 훈련 세트에 사용 된 데이터의 백분율을 제어 할 수 있습니다 TRAIN_PERCENTAGE.

MLP의 매개 변수는 바로 아래에서 변경할 수 있습니다 TRAIN_PERCENTAGE. 다른 분류기로 SMO대체 mlp하여 Weka의 다른 분류기 (예 : SVM)를 사용해 볼 수 있습니다 .

이 프로그램은 결과 세트로 인쇄합니다. 첫 번째 결과는이 과제에 정의 된 점수 인 전체 세트 (훈련에 사용 된 데이터 포함)에 있고 두 번째 결과는 훈련에 사용되지 않은 데이터에만 있습니다.

데이터를 포함하는 파일의 경로를 프로그램에 인수로 전달하여 데이터를 입력합니다.

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;
    }
}

입력을 어떻게 인코딩합니까?
Nathan Merrill

@NathanMerrill 나는 당신의 질문을 이해하지 못합니다
Fatalize

테스트 케이스를 신경망에 입력으로 어떻게 전달합니까? 당신은 원시 문자열을 전달하고 있습니까?
Nathan Merrill

@NathanMerrill 특징 벡터 구성에 대한 단락으로 편집했습니다.
Fatalize

weka는 당신이 승자를 예측하려고한다는 것을 어떻게 알 수 있습니까?
user1502040

8

GNU는 나오지 + BC, 4336 5074.5 포인트를, 64 75 %

업데이트 : OP는 개별 테스트 사례에 대한 예측 점수를 계산하는 새로운 방법을 제공했습니다. Wolfram Alpha를 사용 하여 차이점을 확인하기 위해 두 공식 세트를 플로팅했습니다.

현재 방식은 극단적 인 0과 1만이 아니라 실제 확률을 산출하는 데 큰 동기를 부여합니다. 새로운 공식은 이전과 동일한 최대 점수를줍니다. 이것이 아래의 변경되지 않은 알고리즘이 더 나은 예측 속도를 갖는 이유입니다.

그러나 '편집 1'에 설명 된대로 새로운 공식과 관련된 단점도 있습니다.


이것은 조각의 실제 배치를 무시하고 재료의 장점 / 단점에 기초한 간단한 추정입니다. 이것이 어떻게 수행되는지 궁금했습니다. 내가 한 줄에 이것을 할 수있는 언어가 아닌 sed를 사용하는 이유는 그것이 내가 가장 좋아하는 밀교 언어이기 때문입니다.

/:/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

사용 된 표준 부품 값 :

  • 9-퀸
  • 5-루크
  • 3-기사
  • 3-주교
  • 1-폰
  • 0-왕

양면의 재료를 계산하고 흰색의 재료에서 검은 재료를 뺍니다. 각 테스트 케이스의 출력은 다음과 같은 차이를 기반으로합니다.

  • 차이가 0보다 크면 출력 = 1 (잠재적 흰색 승리)
  • 차이가 0이면 출력 = 0.5 (잠재적 추첨)입니다.

이것은 나의 유일한 분수 출력이므로 위에서 설명한 개선의 이유입니다.

  • 차이가 0보다 작 으면 출력 = 0 (잠재적 검은 승리)

이 방법의 예측률은 64 %였다. 이제 새로운 공식으로 75 %입니다.

처음에는 70 %가 더 높을 것으로 예상했지만, 체스 플레이어로서 내가 +1 / +2 일 때 많은 게임을 잃어 버렸기 때문에 결과를 이해할 수있었습니다. 재료. 그것은 실제 위치에 관한 것입니다. (음, 이제 내 소원을 얻었습니다!)

편집 1 : 단점

사소한 해결책은 각 테스트 사례에 대해 0.5를 출력하는 것입니다.이 방법으로 누가 이겼는지에 관계없이 반점을 얻었 기 때문입니다. 테스트 사례에서 이는 총 점수 3392.5 점 (50 %)을 의미했습니다.

그러나 새로운 공식을 사용하면 0.5 (누가 이길 지 결정하면 출력)는 0.75 포인트로 변환됩니다. 테스트 사례에 대해받을 수있는 최대 점수는 1이며 우승자에 대한 100 % 신뢰도입니다. 따라서 상수 0.5 출력에 대한 새로운 총점은 5088.75 점 또는 75 %입니다! 제 생각에는이 경우 인센티브가 너무 강합니다.

그 점수는 내 머티리얼 우위 기반 알고리즘보다 미미하지만 더 좋습니다. 그 이유는 알고리즘이 1 또는 0 (인센티브 없음), 승 또는 상정 가정, 0.5 (인센티브), 무승부 (2954)보다 많은 시간 (3831)을 제공하기 때문입니다. 이 방법은 결국 단순하며 정답 비율이 높지 않습니다. 새로운 공식에서 상수 0.5 로의 증가는 인위적으로 그 비율에 도달합니다.

편집 2 :

체스 서적에서 언급 한 바와 같이 일반적으로 기사 쌍보다 주교 쌍을 갖는 것이 좋습니다. 이것은 감독의 범위가 증가하는 개방 된 위치를 가질 가능성이 높기 때문에 테스트 사례가있는 게임의 중간에서 마지막 단계에서 특히 그렇습니다.

그러므로 두 번째 시험을했지만 이번에는 감독의 가치를 3에서 3.5로 바꿨습니다. 기사의 가치는 3으로 유지되었습니다. 이것은 개인적인 취향이므로 기본 제출물로 만들지 않았습니다. 이 경우의 총점은 4411 점 (65 %)입니다. 1 % 포인트 증가 만이 관찰되었습니다.

새로운 공식의 경우 총점은 4835 점 (71 %)입니다. 이제 가중 감독은 성과가 떨어집니다. 그러나 가중치 적용 방법은 가정 된 추첨 (1696)보다 더 많은 시간을 가정 된 승리 또는 손실 (5089)을 제공하기 때문에 효과가 설명됩니다.


1
합리적인 기준 솔루션을 제공하기위한 +1 또한 이것이 얼마나 잘 수행되는지 궁금했습니다.
Martin Ender

@MartinEnder 감사합니다. 마지막으로 언급 한 주교의 가치를 높이 겠다는 생각은 성공률이 1 %에 불과했습니다 (업데이트 2 참조). 나는 표준 값이 결국 그 효과를 포함했다고 생각합니다.
seshoumara

xnor의 의견에 따라 점수를 절대 제곱으로 변경해도 괜찮습니까?
Nathan Merrill

1
대박. 또한 답변 주셔서 감사합니다! 나는 어려운 질문이 답을 얻지 못할 것을 항상 걱정합니다.
Nathan Merrill

@NathanMerrill 요청에 따라 새 점수를 사용하도록 답변을 업데이트했습니다. 긴 분석에 대해 죄송하지만 실제로 정말 궁금했습니다.
seshoumara

4

Python 3-84.6 %, 유효성 검사 세트에서 5275 점

모든 데이터를 부정하고 사용하는 경우 99.3 %의 정확도와 6408의 점수를 달성 할 수 있습니다

Keras를 사용한 드롭 아웃이있는 단순한 대형 MLP

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)

84.6 % 수치를 얻기 위해 훈련에 사용하는 데이터의 양은 얼마입니까?
Fatalize

코드에 표시된대로 90-10 분할을 사용했습니다
user1502040

이봐, 내가 추가 한 t 당신이 관심이 있다면 더 테스트 케이스를.
Nathan Merrill

2

Python 3-94.3 % 정확도, 데이터의 20 % 유효성 검사 세트에서 6447 포인트

3 개의 신경망, 가장 가까운 이웃 회귀 분석기, 임의의 숲 및 그래디언트 부스팅을 사용합니다. 이러한 예측은 데이터에 액세스 할 수있는 임의 포리스트와 결합됩니다.

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))

이봐, 내가 추가 한 t 당신이 관심이 있다면 더 테스트 케이스를.
Nathan Merrill

와 당신이 이것에 나갔다.
Robert Fraser

여기에있는 자바 대답은 전체 데이터 세트에서 %를보고하고 훈련하지 않은 데이터에서만 77 %를 얻는다는 점에 유의하십시오.
로버트 프레이저

0

파이썬 3-4353.25 / 6785 포인트-64 %

그래서 나는 주로 어제 일했습니다. 내 첫 번째 골프 후, 나는 일주일 정도만 파이썬을 사용하고 있었으므로 모든 것이 최적화되지 않았다면 용서하십시오.

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

나는 seshoumara의 대답과 같은 길을 따라 끝났다. 그러나 많은 수의 테스트 사례조차도 나를 불만족스럽게 만들었습니다.

그래서 나는 체스에서 누가 이기고 있는지 (내가 게임을하지 않습니다)를 지시하는 특성을 봤으며 보드 위치, 특히 중앙 제어가 큰 것을 알았습니다. 이 비트가 나오는 곳입니다.

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

이 절반을 합하여 점수를 구합니다 (0.0, 0.25, 0.50, 0.75, 1.0).

이 보드 포지션이 승자를 추측 할 확률이 높아지지 않는다는 점이 매우 흥미 롭습니다.

테스트 케이스를 일부 파일에 놓으면 테스트가 있습니다.

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))

나는 이것이 골프 도전이 아니라는 것을 알고 있지만, 그 점에 관한 조언이나 조언은 높이 평가됩니다!


내 대답은? seshoumara의 답변을 의미합니까? 또한 골프를 할 필요가 없습니다 (원하지 않는 한). 이것은 코드 골프 도전 이 아닙니다 .
Nathan Merrill

한 문자 변수 이름 만 사용하여 많은 바이트를 저장할 수 있습니다. (코드 골프가 아니기 때문에 실제로 중요하지는 않지만)
HyperNeutrino

웁스! 지금 편집 중입니다. 직장에서 이것이 스키밍을 위해 얻는 것입니다!
데이터 스트림

2
골프하지 마십시오. 코드 골프가 아닐 때 코드를 읽을 수있게 유지하는 것이 좋습니다.
mbomb007

보드 중앙을 제어한다는 것은 보드 중앙을 차지하는 것이 아니라 보드 중앙을 공격한다는 의미입니다. 그 주위에 약간의 복잡성을 더하고 싶다면 점수를 향상시킬 수 있습니다.
찰스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.