Я строю связи с функциональными нейронами, но встречаю несоответствие типов, которое не понимаю. Проблема возникает в рекурсии, поэтому это непросто. Функции applyInputs и output ведут себя аналогично, но первая не работает, а вторая работает. Я подозреваю, что это трюк Python...
import copy
import itertools
import math
import numpy as np
import pydot
import pytest
import random
import sympy
import textdistance
import time
import typing
for p in parameters:
barycenter.append(p[len(p) // 2])
initialCells.append(barycenter)
"""
count = 1
for p in parameters:
count *= len(p)
while (len(initialCells) < percentage * count):
point = []
for p in parameters:
point.append(random.choice(p))
initialCells.append(point)
"""
visitedCells = []
cells = []
for c in initialCells:
directions = []
for i in range(0, len(c)):
direction = []
for v in c:
if (isinstance(v, np.ndarray)):
x = copy.deepcopy(v)
x.fill(0)
else:
x = type(v)()
direction.append(x)
j = index(parameters, c)
direction = parameters[j - 1] - c
directions.append(direction)
direction = copy.deepcopy(direction)
direction = parameters[(j + 1) % len(parameters)] - c
directions.append(direction)
try:
value = function(c)
cost = heuristic(value, target)
cells.append((cost, c, directions))
except:
pass
cells = sorted(cells, key = lambda x: x[0])
if (len(cells) == 0):
return None
bestCost = cells[0][0]
bestParams = cells[0][1]
while (len(cells)):
cell = cells[0]
del cells[0]
if (index(visitedCells, cell) != -1):
continue
visitedCells.append(cell)
if (len(visitedCells) > limit):
break
for direction in cell[2]:
c = copy.deepcopy(cell[1])
for i in range(0, len(c)):
c[i] += direction[i]
d = []
for i in range(0, len(c)):
direction = []
for v in c:
if (isinstance(v, np.ndarray)):
x = copy.deepcopy(v)
x.fill(0)
else:
x = type(v)()
def toTuple(x) -> tuple:
if (isinstance(x, dict)):
return tuple(map(tuple, x.items()))
if (isinstance(x, np.ndarray) or isinstance(x, list) or isinstance(x, set)):
l = []
for v in x:
l.append(normalizedOutput(v))
return tuple(l)
return tuple(x)
def normalizedOutput(output):
if (isinstance(output, list) or isinstance(output, np.ndarray) or isinstance(output, set) or isinstance(output, dict)):
return toTuple(output)
return output
class Neuron:
def __init__(self, name, function, inputTypes: tuple[type], outputType: type):
self.name = name
self.function = function
self.inputTypes = inputTypes
self.outputType = outputType
def dot(self, index: int = 0):
s = ""
startIndex = copy.deepcopy(index)
for i in range(0, len(self.inputTypes)):
s += "n" + str(index) + ' [label="' + str(self.inputTypes[i]).replace("", "") + '", shape=circle, style=fill];\n'
s += "n" + str(index) + " -> n" + str(startIndex + len(self.inputTypes)) + ";\n"
index += 1
s += "n" + str(index) + ' [label="' + self.name + '", shape=circle, style=fill];\n'
index += 1
s += "n" + str(index) + ' [label="' + str(self.outputType).replace("", "") + '", shape=circle, style=fill];\n'
s += "n" + str(startIndex + len(self.inputTypes)) + " -> n" + str(index) + ";\n"
index += 1
return s, index
def __eq__(self, other):
if (isinstance(other, Neuron)):
return self.name == other.name and self.function == other.function and self.inputTypes == other.inputTypes and self.outputType == other.outputType
for i in range(0, len(self.inputs)):
if (isinstance(self.inputs[i], Connection)):
self.inputs[i] = copy.copy(self.inputs[i])
def __eq__(self, other):
if (isinstance(other, Connection)):
return self.neuron == other.neuron and self.inputs == other.inputs
return False
def __hash__(self):
return hash(self.neuron) + int(np.sum([hash(x) for x in self.inputs]))
def applyInputs(self, inputs: list):
index = 0
for i in range(0, len(self.inputs)):
input_ = self.inputs[i]
if (isinstance(input_, Connection)):
size = len(input_.inputTypes())
input_.applyInputs(inputs[index:index + size])
index += size
else:
if (index < len(inputs)):
if (isinstance(inputs[index], Connection)):
assert(inputs[index].neuron.outputType == self.neuron.inputTypes[i])
elif (isinstance(inputs[index], Neuron)):
assert(inputs[index].outputType == self.neuron.inputTypes[i])
elif (isinstance(inputs[index], type)):
assert(inputs[index] == self.neuron.inputTypes[i])
else:
assert(type(inputs[index]) == self.neuron.inputTypes[i])
if (isinstance(inputs[index], Connection)):
self.inputs[i] = copy.copy(inputs[index])
else:
self.inputs[i] = inputs[index]
index += 1
def output(self, inputs: list = None):
args = []
index = 0
for i in range(0, len(self.inputs)):
input_ = self.inputs[i]
if (isinstance(input_, Connection)):
if (inputs == None):
args.append(input_.output())
else:
size = len(input_.inputTypes())
args.append(input_.output(inputs[index:index + size]))
index += size
else:
if (inputs != None):
if (index < len(inputs)):
args.append(inputs[index])
index += 1
elif (isinstance(input_, Neuron)):
args.append(input_.function())
else:
args.append(input_)
return self.neuron.function(*args)
def inputTypes(self) -> list:
types = []
for input_ in self.inputs:
if (isinstance(input_, Connection)):
types.extend(input_.inputTypes())
elif (isinstance(input_, Neuron)):
types.extend(input_.inputTypes)
elif (isinstance(input_, typing.GenericAlias)):
types.append(input_)
elif (isinstance(input_, type)):
types.append(input_)
else:
types.append(type(input_))
return types
def cost(self) -> int:
cost = 0
for i in self.inputs:
cost += 1
if (type(i) is Connection):
cost += i.cost()
return cost
def toStr(self) -> str:
args = []
for i in self.inputs:
if (type(i) is Connection):
args.append(i.toStr())
elif (type(i) is Neuron):
args.append(i.name)
else:
args.append(str(i))
s = self.neuron.name
if (len(self.neuron.inputTypes)):
s += "(" + ", ".join(args) + ")"
return s
class Brain:
def __init__(self, neurons: list[Neuron]):
self.neurons = neurons
def directLearn(self, targets: list = [], targetTypes: list = None, level: int = 3):
if (targetTypes == None):
targetTypes = []
for t in targets:
targetTypes.append(type(t))
assert(len(targets) == len(targetTypes))
parameters = dict()
types = dict()
for neuron in self.neurons:
if (len(neuron.inputTypes) == 0):
d = parameters.get(neuron.outputType, dict())
value = neuron.function()
types[neuron.outputType] = neuron.outputType
value = normalizedOutput(value)
l = d.get(value, [])
l.append(neuron)
d[value] = l
parameters[neuron.outputType] = d
learnedConnections = [None] * len(targets)
connectionMapping = {}
connections = set()
for neuron in self.neurons:
if (len(neuron.inputTypes)):
connections.add(Connection(neuron, neuron.inputTypes))
for ll in range(0, level):
mapping = copy.deepcopy(connectionMapping)
for connection in connections:
l = mapping.get(connection.neuron.outputType, set())
args = connection.neuron.inputTypes
args = [[x] for x in args]
for j in range(0, len(connection.neuron.inputTypes)):
args[j].extend(connectionMapping.get(connection.neuron.inputTypes[j], []))
if (len(args)):
product = itertools.product(*args)
for p in product:
c = copy.deepcopy(connection)
c.applyInputs(p)
l.add(c)
if (len(l)):
if (connection.neuron.outputType in targetTypes):
newL = set()
for c in l:
args = []
connectionInputTypes = c.inputTypes()
for t in connectionInputTypes:
l = list(parameters[t].keys())
for i in range(0, len(l)):
if (types[t] == np.ndarray):
l[i] = np.asarray(l[i])
else:
l[i] = types[t](l[i])
args.append(l)
tt = [x == connection.neuron.outputType for x in targetTypes]
evalConnections = []
for j in range(0, len(tt)):
if (tt[j]):
params = fit(targets[j], c.output, args)
if (params == None):
continue
inputs = []
for k in range(0, len(connectionInputTypes)):
inputs.append(parameters[connectionInputTypes[k]][normalizedOutput(params[k])][0])
Я строю связи с функциональными нейронами, но встречаю несоответствие типов, которое не понимаю. Проблема возникает в рекурсии, поэтому это непросто. Функции applyInputs и output ведут себя аналогично, но первая не работает, а вторая работает. Я подозреваю, что это трюк Python... import copy import itertools import math import numpy as np import pydot import pytest import random import sympy import textdistance import time import typing
def toTuple(x) -> tuple: if (isinstance(x, dict)): return tuple(map(tuple, x.items()))
if (isinstance(x, np.ndarray) or isinstance(x, list) or isinstance(x, set)): l = []
for v in x: l.append(normalizedOutput(v))
return tuple(l)
return tuple(x)
def normalizedOutput(output): if (isinstance(output, list) or isinstance(output, np.ndarray) or isinstance(output, set) or isinstance(output, dict)): return toTuple(output)
return output
class Neuron: def __init__(self, name, function, inputTypes: tuple[type], outputType: type): self.name = name self.function = function self.inputTypes = inputTypes self.outputType = outputType
def dot(self, index: int = 0): s = "" startIndex = copy.deepcopy(index)
for i in range(0, len(self.inputTypes)): s += "n" + str(index) + ' [label="' + str(self.inputTypes[i]).replace("", "") + '", shape=circle, style=fill];\n' s += "n" + str(index) + " -> n" + str(startIndex + len(self.inputTypes)) + ";\n" index += 1
s += "n" + str(index) + ' [label="' + self.name + '", shape=circle, style=fill];\n' index += 1
s += "n" + str(index) + ' [label="' + str(self.outputType).replace("", "") + '", shape=circle, style=fill];\n' s += "n" + str(startIndex + len(self.inputTypes)) + " -> n" + str(index) + ";\n" index += 1
return s, index
def __eq__(self, other): if (isinstance(other, Neuron)): return self.name == other.name and self.function == other.function and self.inputTypes == other.inputTypes and self.outputType == other.outputType
for i in range(0, len(self.inputs)): if (isinstance(self.inputs[i], Connection)): self.inputs[i] = copy.copy(self.inputs[i])
def __eq__(self, other): if (isinstance(other, Connection)): return self.neuron == other.neuron and self.inputs == other.inputs
return False
def __hash__(self): return hash(self.neuron) + int(np.sum([hash(x) for x in self.inputs]))
def applyInputs(self, inputs: list): index = 0
for i in range(0, len(self.inputs)): input_ = self.inputs[i]
if (isinstance(input_, Connection)): size = len(input_.inputTypes()) input_.applyInputs(inputs[index:index + size]) index += size else: if (index < len(inputs)): if (isinstance(inputs[index], Connection)): assert(inputs[index].neuron.outputType == self.neuron.inputTypes[i]) elif (isinstance(inputs[index], Neuron)): assert(inputs[index].outputType == self.neuron.inputTypes[i]) elif (isinstance(inputs[index], type)): assert(inputs[index] == self.neuron.inputTypes[i]) else: assert(type(inputs[index]) == self.neuron.inputTypes[i])
if (isinstance(inputs[index], Connection)): self.inputs[i] = copy.copy(inputs[index]) else: self.inputs[i] = inputs[index]
index += 1
def output(self, inputs: list = None): args = [] index = 0
for i in range(0, len(self.inputs)): input_ = self.inputs[i]
if (isinstance(input_, Connection)): if (inputs == None): args.append(input_.output()) else: size = len(input_.inputTypes()) args.append(input_.output(inputs[index:index + size])) index += size else: if (inputs != None): if (index < len(inputs)): args.append(inputs[index]) index += 1 elif (isinstance(input_, Neuron)): args.append(input_.function()) else: args.append(input_)
return self.neuron.function(*args)
def inputTypes(self) -> list: types = []
for input_ in self.inputs: if (isinstance(input_, Connection)): types.extend(input_.inputTypes()) elif (isinstance(input_, Neuron)): types.extend(input_.inputTypes) elif (isinstance(input_, typing.GenericAlias)): types.append(input_) elif (isinstance(input_, type)): types.append(input_) else: types.append(type(input_))
return types
def cost(self) -> int: cost = 0
for i in self.inputs: cost += 1
if (type(i) is Connection): cost += i.cost()
return cost
def toStr(self) -> str: args = []
for i in self.inputs: if (type(i) is Connection): args.append(i.toStr()) elif (type(i) is Neuron): args.append(i.name) else: args.append(str(i))
s = self.neuron.name
if (len(self.neuron.inputTypes)): s += "(" + ", ".join(args) + ")"
return s
class Brain: def __init__(self, neurons: list[Neuron]): self.neurons = neurons
def directLearn(self, targets: list = [], targetTypes: list = None, level: int = 3): if (targetTypes == None): targetTypes = []
for t in targets: targetTypes.append(type(t))
assert(len(targets) == len(targetTypes))
parameters = dict() types = dict()
for neuron in self.neurons: if (len(neuron.inputTypes) == 0): d = parameters.get(neuron.outputType, dict()) value = neuron.function() types[neuron.outputType] = neuron.outputType value = normalizedOutput(value) l = d.get(value, []) l.append(neuron) d[value] = l parameters[neuron.outputType] = d
learnedConnections = [None] * len(targets)
connectionMapping = {}
connections = set()
for neuron in self.neurons: if (len(neuron.inputTypes)): connections.add(Connection(neuron, neuron.inputTypes))
for ll in range(0, level): mapping = copy.deepcopy(connectionMapping)
for connection in connections: l = mapping.get(connection.neuron.outputType, set())
args = connection.neuron.inputTypes args = [[x] for x in args]
for j in range(0, len(connection.neuron.inputTypes)): args[j].extend(connectionMapping.get(connection.neuron.inputTypes[j], []))
if (len(args)): product = itertools.product(*args)
for p in product: c = copy.deepcopy(connection) c.applyInputs(p) l.add(c)
if (len(l)): if (connection.neuron.outputType in targetTypes): newL = set()
for c in l: args = []
connectionInputTypes = c.inputTypes()
for t in connectionInputTypes: l = list(parameters[t].keys())
for i in range(0, len(l)): if (types[t] == np.ndarray): l[i] = np.asarray(l[i]) else: l[i] = types[t](l[i])
args.append(l)
tt = [x == connection.neuron.outputType for x in targetTypes]
evalConnections = []
for j in range(0, len(tt)): if (tt[j]): params = fit(targets[j], c.output, args)
if (params == None): continue
inputs = []
for k in range(0, len(connectionInputTypes)): inputs.append(parameters[connectionInputTypes[k]][normalizedOutput(params[k])][0])