Inteligencia artificial, el héroe de nuestro tiempo. Ejercicio musical

Mmm. Uno de los puntos que regula las acciones de los moderadores en Habré está formulado de la siguiente manera: no debes saltarte artículos que estén débilmente relacionados con temas relacionados con TI o que no se salten en absoluto. Lo que hizo pensar inmediatamente al autor sobre si su publicación, que habla sobre algunas etapas de la programación de su divertido y emocionante proyecto mascota, una IA simple, que construye una red neuronal basada en la envoltura de rubíes de FANN para jugar cruces, está directamente relacionada a los ceros del "tema de TI"? La pregunta no contiene coquetería oculta, porque la descripción de la lógica del código del programa en mi historia está lejos de ser de suma importancia. "¡Sí, esto es una ironía maligna!" - tu dices. - No lo sé.





está bien. Este desarrollo de facto es una ilustración de una serie de extrañas observaciones del autor, una serie de conocidos e incluso amigos-amigos de los cuales en los últimos años ... le hicieron recordar las lecciones de literatura que una vez tuvo cuando era un muy, muy escuela secundaria soviética. A pesar de su convicción permanente de que siempre es posible "pasar" solo por algo, ciertos personajes de los clásicos rusos se recuerdan cada vez con más frecuencia con el tiempo. ¿O tal vez debería ser así?





Entonces, desde el principio ... después del primer lanzamiento, el programa comienza el proceso de autoaprendizaje, jugando consigo mismo varias decenas (un minuto, dos como máximo) de miles de juegos (el número, por supuesto, está disponible para editar en la configuración; dado el algoritmo no muy habitual que se describe a continuación, que subyace a la lógica de esta IA (los experimentos de este tipo también pueden proporcionar material interesante para inferencias). Simula el proceso de aprendizaje inherente a muchas otras Inteligencias Artificiales, con la única diferencia de que ambos "jugadores" por igual no saben jugar, realizando movimientos absolutamente aleatorios. Pero se aplican las reglas del juego: si el movimiento aleatorio no coincide, el programa debe continuar y, en consecuencia, el lado ganador pasará al lado ganador. Todo es justo: sin borrados ni cortes, sin preferencias ocultas,no hay pruebas de dopaje falsas para usted, que a menudo anulan los resultados de los juegos deportivos en la vida real.





: csv- , AI, () , - , , .





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





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





. : , . , , , , , , , : (/). -, 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- ( , ), . , - - , , .





PD: El código descrito siempre está disponible en su totalidad (y no fragmentariamente, como dicta el formato del artículo) en mi github , por supuesto, cualquiera puede hacer un clon de git y experimentar con el código, o simplemente jugar. No soy partidario de ejecutar ruby-application en Windows, esta no es una muy buena idea, pero en este caso funcionará, lo probé. Quizás resulte un poco menos impresionante que en la consola de Linux, pero la lógica funcionará.








All Articles