Hmm. L'un des points réglementant l'action des modérateurs sur Habré est formulé comme suit: il ne faut pas sauter d'articles qui sont faiblement liés à des sujets liés à l'informatique ou pas du tout. Ce qui a immédiatement amené l'auteur à se demander si son article, qui raconte certaines étapes de la programmation de son projet animalier amusant et passionnant, une simple IA, qui construit un réseau de neurones basé sur l'enveloppe rubis FANN pour jouer des croix, est directement lié aux zéros "IT-topic"? La question ne contient pas de coquetterie cachée, car la description de la logique du code du programme dans mon histoire est loin d'être d'une importance capitale. "Oui, c'est une mauvaise ironie!" - vous dites. - Je ne sais pas.
D'ACCORD. Cette évolution de facto est une illustration d'un certain nombre d'observations étranges de l'auteur, dont plusieurs connaissances et même amis-amis au cours des dernières années ... lui ont fait rappeler les leçons de littérature qu'il avait autrefois quand il était un très, très école secondaire soviétique. Malgré sa conviction permanente qu'il est toujours possible de "passer" seulement par quelque chose, certains personnages des classiques russes se souviennent de plus en plus souvent au fil du temps. Ou peut-être qu'il devrait en être ainsi?
Donc, dès le départ ... après le premier lancement, le programme commence le processus d'auto-apprentissage, jouant avec lui-même plusieurs dizaines (une minute - deux maximum) de milliers de jeux (le nombre, bien sûr, est disponible pour l'édition dans la configuration; étant donné l'algorithme pas tout à fait habituel décrit ci-dessous, sous-jacent à la logique de cette IA - des expériences de ce type peuvent également fournir un matériel intéressant pour les inférences) Il simule le processus d'apprentissage inhérent à de nombreuses autres Intelligence Artificielle, à la seule différence que les deux «joueurs» ne savent pas non plus jouer, effectuant des mouvements absolument aléatoires. Mais les règles du jeu s'appliquent: si le coup aléatoire ne correspond pas, le programme doit continuer, et en conséquence, le côté gagnant ira du côté gagnant. Tout est juste: pas d'effacements ni de hacks, pas de préférences cachées,pas de faux tests de dopage pour vous, qui annulent souvent les résultats des jeux sportifs dans la vraie vie.
: 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- ( , ), . , - - , , .
PS Le code décrit est toujours disponible dans son intégralité (et non de manière fragmentaire, comme le format de l'article l'indique) dans mon github , bien sûr, n'importe qui peut faire un clone git et expérimenter le code, ou simplement jouer. Je ne suis pas partisan de l'exécution de ruby-application sous Windows, ce n'est pas une très bonne idée, mais dans ce cas, cela fonctionnera, je l'ai essayé. Peut-être que cela s'avérera un peu moins impressionnant que dans la console Linux, mais la logique fonctionnera.