सीमित जानकारी के साथ शतरंज विश्लेषण


19

इस चुनौती में, आपको शतरंज के किसी विशेष खेल के बारे में सीमित मात्रा में जानकारी दी जाती है, और आपको यह अनुमान लगाने की आवश्यकता है कि गेम किसने जीता है

आपको डेटा के दो सेट दिए गए हैं:

  1. टुकड़ा मायने रखता है (क्या टुकड़े अभी भी जीवित हैं)
  2. बोर्ड रंग (बोर्ड पर टुकड़ों का रंग)

इससे भी महत्वपूर्ण बात, आप नहीं जानते कि टुकड़े कहाँ स्थित हैं । आपको यह निर्धारित करने की आवश्यकता है कि आपको कौन लगता है कि जीत होगी।

खेलों को 2010 से अब तक PGNMentor पर सूचीबद्ध सभी घटनाओं में से चुना गया है । मैंने प्रत्येक गेम से बोर्ड के सभी 10% पदों को चुना है जो एक जीत या हार में समाप्त होता है। बोर्ड की स्थिति हमेशा खेल में कम से कम 30 चालों की होगी। परीक्षण के मामले यहां देखे जा सकते हैं । (श्वेत जीत पहले सूचीबद्ध होती है, उसके बाद काली जीत होती है)

इनपुट

टुकड़ा गणना प्रत्येक टुकड़े के लिए एक चरित्र से युक्त एक स्ट्रिंग होगी: kआईएनजी, queen, rook, k night, bishop, या pawn। लोअरकेस का अर्थ है काला, अपरकेस सफेद है। बोर्ड 64 अक्षरों (8 स्तंभों द्वारा 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% का उपयोग करके परीक्षण करता हूं । (या जो भी प्रतिशत आप उपयोग करते हैं)। मैं डेटा में कई बार गेम का उपयोग करता हूं, लेकिन मैं एक ही गेम को क्रमिक रूप से एक साथ रखता हूं।
  • अद्यतन: मैंने परीक्षण और सीखने के प्रयोजनों के लिए एक लाख से अधिक परीक्षण मामलों को जोड़ा है। गिथब रेपो आकार सीमा के कारण वे काले और सफेद भागों में विभाजित हैं।

गुड लक और मजा करें!


इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
डेनिस

क्या नए परीक्षण मामलों में पुराने शामिल हैं, या दो सेट असहमति हैं?
घातक

मुझे पता नहीं है। मैंने उन्हें विभिन्न साइटों से प्राप्त किया, इसलिए यह संभव है कि वे दोनों एक ही खेल के सेट में शामिल थे।
नाथन मेरिल

जवाबों:


8

जावा 8 + वीका, 6413 अंक, 94.5%

यह उत्तर मशीन सीखने के दृष्टिकोण का उपयोग करता है। आपको Weka पुस्तकालय को पुनः प्राप्त करने की आवश्यकता है , विशेष रूप से weka.jarऔर PackageManager.jar

यहाँ, मैं एक बहुस्तरीय अवधारणात्मक को क्लासिफायरियर के रूप में उपयोग करता हूं; आप परिणामों की तुलना करने के लिए वीका के mlpकिसी भी Classifierवर्ग के साथ बदल सकते हैं ।

मैंने MLP के मापदंडों के साथ ज्यादा छेड़छाड़ नहीं की है, और बस उन्हें नेत्रगोलक (50 न्यूरॉन्स की एक छिपी हुई परत, 100 युग, 0.2 सीखने की दर, 0.1 गति)।

मैं एमएलपी के आउटपुट मूल्य को सीमा में रखता हूं, इसलिए चुनौती में परिभाषित के अनुसार आउटपुट वास्तव में 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

एमएलपी के मापदंडों को बस नीचे बदला जा सकता है TRAIN_PERCENTAGE। एक Weka के अन्य सहपाठियों (जैसे SMOSVMs के लिए) की कोशिश कर सकते हैं बस mlpएक और वर्गीकारक के साथ बदलकर ।

यह कार्यक्रम परिणामों के सेटों को प्रिंट करता है, पहला सेट पूरे प्रशिक्षण पर (प्रशिक्षण के लिए उपयोग किए जाने वाले डेटा सहित) जो कि इस चुनौती में परिभाषित स्कोर है, और दूसरा केवल उन डेटा पर है जो प्रशिक्षण के लिए उपयोग नहीं किया गया था।

एक डेटा को प्रोग्राम के लिए एक तर्क के रूप में युक्त फ़ाइल के पथ को पास करके इनपुट करता है।

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

आप इनपुट को कैसे एन्कोड करते हैं?
नाथन मेरिल

@NathanMerrill मुझे यकीन नहीं है कि मैं आपके प्रश्न को समझ सकता हूं
घातक

आप तंत्रिका नेटवर्क के इनपुट के रूप में परीक्षण के मामले को कैसे पारित कर रहे हैं? क्या आप अभी कच्चे तार में गुजर रहे हैं?
नाथन मेरिल

@NathanMerrill सुविधा वेक्टर निर्माण पर एक पैराग्राफ के साथ संपादित।
घातक

वीका कैसे जानता है कि आप विजेता की भविष्यवाणी करने की कोशिश कर रहे हैं?
user1502040

8

GNU sed + bc, 4336 5074.5 अंक, 64 75%

अद्यतन: ओपी ने एक व्यक्तिगत परीक्षण मामले के लिए भविष्यवाणी के स्कोर की गणना करने का एक नया तरीका दिया। वोल्फ्राम अल्फा का उपयोग करते हुए , मैंने मतभेदों को देखने के लिए सूत्र के दोनों सेटों को प्लॉट किया।

वर्तमान तरीका वास्तविक संभावनाओं को आउटपुट करने के लिए एक मजबूत प्रोत्साहन लाता है, और न केवल चरम, 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, तो आउटपुट = 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 (कोई प्रोत्साहन) की संभावना देता है, मान लिया गया जीत या नुकसान, अधिक बार (3831) की तुलना में यह 0.5 (प्रोत्साहन), ग्रहणित ड्रॉ (2954) देता है। विधि अंत में सरल है, और इस तरह इसके पास सही उत्तरों का उच्च प्रतिशत नहीं है। नए सूत्र से निरंतर 0.5 तक की वृद्धि, कृत्रिम रूप से उस प्रतिशत तक पहुंचने का प्रबंधन करती है।

2 संपादित करें:

यह एक ज्ञात तथ्य है, जिसका उल्लेख शतरंज की किताबों में किया गया है, कि आमतौर पर एक नाइट जोड़ी की तुलना में बिशप जोड़ी रखना बेहतर होता है। यह खेल के अंतिम चरण के अंत में विशेष रूप से सच है, जहां परीक्षण के मामले हैं, क्योंकि यह एक खुली स्थिति होने की संभावना है जहां एक बिशप की सीमा बढ़ जाती है।

इसलिए मैंने दूसरा परीक्षण किया, लेकिन इस बार मैंने बिशप के मूल्य को 3 से 3.5 तक बदल दिया। शूरवीर का मूल्य 3 बना रहा। यह एक व्यक्तिगत प्राथमिकता है, इसलिए मैंने इसे अपना डिफ़ॉल्ट प्रस्तुत नहीं किया। इस मामले में कुल स्कोर 4411 अंक (65%) था। केवल 1 प्रतिशत अंक की वृद्धि देखी गई।

नए फॉर्मूले के साथ, कुल स्कोर 4835 अंक (71%) है। अब भारित बिशप अंडरपरफॉर्मर। लेकिन, प्रभाव की व्याख्या की जाती है क्योंकि भारित पद्धति अब ग्रहण किए गए ड्रॉ (1696) की तुलना में कई गुना अधिक जीत या हानि (5089) देती है।


1
एक उचित आधार रेखा समाधान प्रदान करने के लिए +1। मैं भी सोच रहा था कि यह कितना अच्छा प्रदर्शन करेगा।
मार्टिन एंडर

@MartinEnder धन्यवाद। बिशप के मूल्य को बढ़ाने का मेरा विचार, पिछली बार उल्लेख किया गया था, केवल 1% सफलता दर में वृद्धि (अपडेट 2 देखें)। मुझे लगता है कि मानक मूल्यों ने उस प्रभाव को शामिल किया।
शीशमारा

अरे, एक्सनोर की टिप्पणी के अनुसार, क्या आप बुरा मानेंगे अगर मैं स्कोरिंग को पूर्ण अंतर में बदल दूं?
नाथन मेरिल

1
बहुत बढ़िया। इसके अलावा, उत्तर देने के लिए धन्यवाद! मुझे हमेशा चिंता है कि मेरे कठिन सवालों का जवाब कभी नहीं मिलेगा।
नाथन मेरिल

@NathanMerrill मैंने पूछा के रूप में नए स्कोरिंग का उपयोग करने के लिए अपना जवाब अपडेट किया। लंबे विश्लेषण के लिए खेद है, लेकिन मैं वास्तव में उत्सुक था।
शेषमारा

4

पायथन 3 - 84.6%, एक सत्यापन सेट पर 5275 अंक

यदि हम सभी डेटा को धोखा देते हैं और उपयोग करते हैं, तो हम 99.3% की सटीकता, और 6408 का स्कोर प्राप्त कर सकते हैं

केरस का उपयोग करते हुए ड्रॉपआउट के साथ एक साधारण बड़े एमएलपी

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% आंकड़ा प्राप्त करने के लिए आप प्रशिक्षण के लिए कितना डेटा उपयोग करते हैं?
घातक

मैंने एक 90-10 विभाजन का उपयोग किया जैसा कि कोड में दिखाया गया है
user1502040

अरे, अगर आप रुचि रखते हैं, तो मैंने एक टन और परीक्षण मामले जोड़े हैं।
नाथन मेरिल

2

पायथन 3 - 94.3% सटीकता, 20% डेटा के सत्यापन सेट पर 6447 अंक

3 तंत्रिका नेटवर्क का उपयोग करता है, एक निकटतम पड़ोसी regressor, एक यादृच्छिक जंगल, और ढाल बूस्टिंग। इन भविष्यवाणियों को एक यादृच्छिक जंगल के साथ जोड़ा जाता है जिसमें डेटा तक पहुंच भी होती है।

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

अरे, अगर आप रुचि रखते हैं, तो मैंने एक टन और परीक्षण मामले जोड़े हैं।
नाथन मेरिल

वाह आप इस पर बाहर चले गए।
रॉबर्ट फ्रेजर

यहाँ जावा उत्तर पर ध्यान दें कि "बीट" आपका संपूर्ण डेटा सेट पर% रिपोर्ट करने के लिए प्रकट होता है और केवल उस डेटा पर 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

मैं उसी रास्ते से समाप्त हुआ, जब तक शशमौरा का उत्तर शुरू नहीं हो जाता। लेकिन बड़ी संख्या में परीक्षण के मामले जो टुकड़ों की गिनती भी थे, मुझे असंतुष्ट छोड़ गए।

इसलिए मैंने उन लक्षणों को जाना, जो तय करते हैं कि शतरंज में कौन जीत रहा है (मैं खुद खेल नहीं खेलता) और बोर्ड की स्थिति, विशेष रूप से केंद्र नियंत्रण पर ध्यान दिया, जो बड़ा है। यहीं पर यह बिट आता है।

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 का जवाब मतलब है? इसके अलावा, आपको इसकी आवश्यकता नहीं है (जब तक आप नहीं चाहते)। यह एक कोड-गोल्फ चुनौती नहीं है।
नाथन मेरिल

आप केवल एक-वर्ण चर नामों का उपयोग करके कई बाइट्स बचा सकते हैं। (हालांकि यह वास्तव में कोई फर्क नहीं पड़ता क्योंकि यह कोड-गोल्फ नहीं है)
हाइपरन्यूट्रीनो

ओह! अब इसका संपादन किया जा रहा है। काम पर, यह मुझे स्कीमिंग के लिए मिलता है!
डेटास्ट्रीम

2
कृपया इसे गोल्फ न करें। कोड-गोल्फ नहीं होने पर कोड को पठनीय रखना बेहतर है।
mbomb007

बोर्ड के मध्य पर नियंत्रण का मतलब बोर्ड के मध्य पर कब्जा करना नहीं है, बल्कि बोर्ड के मध्य पर हमला करना है। यदि आप उसके आसपास कुछ जटिलता जोड़ना चाहते हैं, तो यह आपके स्कोर में सुधार कर सकता है।
नहीं कि
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.