Inteligência Artificial, o herói do nosso tempo. Etude

Hmm. Um dos pontos que regulam a atuação dos moderadores no Habré é formulado da seguinte forma: você não deve pular artigos que tenham pouca ou nenhuma relação com temas de informática. O que imediatamente fez o autor pensar se sua postagem, que fala sobre alguns estágios da programação de seu projeto de estimação engraçado e empolgante, uma IA simples, que constrói uma rede neural baseada no envoltório de rubi FANN para jogar cruzes, está diretamente relacionada aos zeros do "tópico de TI"? A pergunta não contém coquetismo oculto, porque a descrição da lógica do código do programa em minha história está longe de ser de suma importância. "Sim, isso é uma ironia do mal!" - você diz. - Não sei.





OK. Este desenvolvimento é, de fato, uma ilustração de uma série de observações estranhas do autor, uma série de conhecidos e até amigos-amigos dos quais nos últimos anos ... o fizeram relembrar as lições de literatura de uma vez, quando ele era muito, muito escola secundária soviética. Apesar de sua convicção permanente de que sempre é possível "passar" apenas por alguma coisa, certos personagens dos clássicos russos são lembrados cada vez mais com o tempo. Ou talvez devesse ser assim?





Então, logo de cara ... após o primeiro lançamento, o programa inicia o processo de autoaprendizagem, jogando consigo mesmo várias dezenas (um minuto - dois no máximo) de milhares de jogos (o número, claro, está disponível para edição na configuração; dado o algoritmo não muito comum descrito abaixo, subjacente à lógica desta IA (experimentos desse tipo também podem fornecer material interessante para inferências). Simula o processo de aprendizagem inerente a muitas outras Inteligências Artificiais, com a única diferença de que ambos os "jogadores" igualmente não sabem jogar, fazendo jogadas absolutamente aleatórias. Mas as regras do jogo se aplicam: se o movimento aleatório não coincidir, o programa deve prosseguir e, portanto, o lado vencedor irá para o lado vencedor. Tudo é justo: sem rasuras e hacks, sem preferências ocultas,sem testes de doping falsos para você, que muitas vezes anulam os resultados dos jogos esportivos na vida real.





Em seguida, o jogo começa com o usuário: o protocolo do jogo registrado em um arquivo csv é convertido em um array, e a IA jogando com o segundo número (zeros) resolve um problema filosófico, estranhamente muito russo, tentando extrair o absurdo e o caos dos movimentos aleatórios que lhe permitirão ganhar ou pelo menos reduzir a um empate um jogo com um adversário vivo e de pensamento bastante lógico.





, ? , : , . , , (, - "") : "" , ... , , .





- , ( ), - . - ... , - , , .





. : , . , , , , , , , : (/). -, Tic Tac Toe - , - ? - , . , , , , - , , ?... , "" ; , " " , - " ", , " !".





, Artificial Intelligence. , 3x3, -, ? , , , , , , , - , ? AI, " " ; - , .





, " ". () , , - . ? , :





        if row[6].to_i - row[3].to_i == 1
            x_data.push([row[0].to_i])
            y_data.push([1]) #   , ..   ,  .
        end
      
      



? - . , .. . ?





, Tic Tac Toe AI with Neural Network ( ). , – : , – – . , , , .





, , - , , . , , , ... ?





. “"... , ? – , , : “ , , ”. , “ ” ; , “ ”. , , ; , . , , , , , , , , : , “ , ”.





. , , , . , , - , ... , - , , , .





- ( - life style). , :





  WINNING_TRIADS = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [6, 4, 2],
    [0, 4, 8]
  ].freeze
      
      



, csv- , :





  def fork?
    WINNING_TRIADS.select do |x|
      @board[x[0]] == @board[x[1]] && @board[x[2]].class != @board[x[0]].class &&
        place_x?(x[0]) ||
        @board[x[1]] == @board[x[2]] && @board[x[0]].class != @board[x[2]].class &&
          place_x?(x[1]) ||
        @board[x[0]] == @board[x[2]] && @board[x[1]].class != @board[x[2]].class &&
          place_x?(x[0])
    end
  end
      
      



, ...





  if @game.fork?.size > 1
      
      



... .





, . : , , , . , .





:





  DANGEROUS_SITUATIONS_1 = [
    [6, 4, 2],
    [0, 4, 8]
  ].freeze

  DANGEROUS_SITUATIONS_2 = [
    [0, 4, 7],
    [0, 4, 5],
    [2, 4, 3],
    [2, 4, 7],
    [3, 4, 8],
    [1, 4, 8],
    [1, 4, 6],
    [5, 4, 6]
  ].freeze
      
      



  def fork_danger_1?
    DANGEROUS_SITUATIONS_1.detect do |x|
      @board[x[0]] == @board[x[2]] &&
        @board[x[0]] != @board[x[1]]
    end
  end
  
  def fork_danger_2?
    DANGEROUS_SITUATIONS_2.detect do |x|
      @board[x[0]] == @board[x[2]] &&
        @board[x[0]] != @board[x[1]]
    end
  end

  def fork_danger_3?
    DANGEROUS_SITUATIONS_1.detect do |x|
      @board[x[0]] != @board[x[2]] &&
        @board[x[1]] == @board[x[2]]
    end
  end
      
      



, , , , , AI : 1. , 2. 3. (.. , , , ). , , . , Neural Network.





  array_of_games.each do |row|
      row.each do |e|
        next unless e == current_position

        if row[6].to_i - row[3].to_i == 2 && row[4] == 'O' && row[2].to_f != 0.2
          unacceptable_moves_array << row[0]
        # Find moves that inevitably lead to a fork:
        elsif fork_danger_1 && row[3].to_i == 3 && row[0].to_i.odd?
          unacceptable_moves_array << row[0]
        elsif (fork_danger_2 || fork_danger_3) && row[3].to_i == 3 && row[0].to_i.even?
          unacceptable_moves_array << row[0]
        end
        next if row[5].nil?

        # Find moves that may lead to a fork:
        array_of_moves_to_fork << row[0] if row[3].to_i == row[5].to_i
        # Find attacking moves:
        attack_moves_array << row[0] if row[3].to_i == row[5].to_i && row[6].to_i < 7
      end
    end
      
      



, , , AI , . ... , , , , ... , "" . , , - , , ... ? - ", , ", .





 array_of_games.each do |row|
      row.each do |e|
        next unless e == current_position

        next if arrays[0].include?(row[0])

        unless arrays[1].include?(row[0]) && !arrays[2].include?(row[0])
          if row[6].to_i - row[3].to_i == 1
            x_data.push([row[0].to_i])
            y_data.push([1])
          elsif row[6].to_i - row[3].to_i == 3
            if arrays[2].include?(row[0])
              x_data.push([row[0].to_i])
              y_data.push([0.9])
            elsif arrays[1].include?(row[0])
              x_data.push([row[0].to_i])
              y_data.push([0.3])
            end
          else
            x_data.push([row[0].to_i])
            y_data.push([row[2].to_f])
          end
        end
      end
      
      



:





    data = nn_data(board, fork_danger_1, fork_danger_2, fork_danger_3, array_of_games)
    fann_results_array = []
      train = RubyFann::TrainData.new(inputs: data[0], desired_outputs: data[1])
      model = RubyFann::Standard.new(
        num_inputs: 1,
        hidden_neurons: [4],
        num_outputs: 1
      )
      model.train_on_data(train, 5000, 500, 0.01)
      data[0].flatten.each do |i|
        fann_results_array << model.run([i])
      end
    result = data[0][fann_results_array.index(fann_results_array.max)]
      
      



: ( csv-) Neural Network .





- , - , . csv- ( , ), . , - - , , .





PS O código descrito está sempre disponível na íntegra (e não de forma fragmentada, como o formato do artigo dita) no meu github , é claro, qualquer um pode fazer um clone do git e experimentar o código, ou apenas jogar. Não sou adepto da execução do aplicativo ruby ​​no Windows, não é uma ideia muito boa, mas neste caso funcionará, experimentei. Talvez seja um pouco menos impressionante do que no console do Linux, mas a lógica funcionará.








All Articles