Я пытаюсь разработать нейронную сеть для умножения и деления двух чисел, используя этот метод. Часть умножения проходит хорошо, а деление - нет - каждый раз, когда программа запускается, для каждой пары входных данных на выходе получается небольшое, почти фиксированное значение (фиксируемое при каждом запуске программы). С помощью ответа на предыдущий вопрос, который я задал (я бы рекомендовал не возвращаться и не читать все это, чтобы избежать путаницы), я добился некоторого прогресса, но все еще сталкивался с проблемами и решил, что так будет лучше. задать новый вопрос. Код моей нейронной сети:
import tensorflow as tf
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras import regularizers
num_train = 1000
X_train = np.random.rand(num_train, 2)
y_train_add = X_train[:, 0] + X_train[:, 1]
model_add = Sequential(
[
Dense(10),
Dense(1)
]
)
batch_size = 32
epochs = 100
model_add.compile(loss = 'mse', optimizer='adam')
model_add.fit(X_train, y_train_add, batch_size=batch_size, epochs=epochs, verbose = 1)
a = np.random.random((2000000,1))*100-50
b = np.random.random((100000,1))*10
x_train = np.append(a, b)
#This is because previously there had been severe inaccuracies near 0, which led to problems during division, so I increased the training data near zero
y_train = np.square(x_train)
model_sqr = Sequential(
[
Dense(8, activation = 'elu', kernel_regularizer = regularizers.l2(0.001), input_shape = (1,)),
Dense(8, activation = 'elu', kernel_regularizer = regularizers.l2(0.001)),
Dense(1)
]
)
batch_size = 32
epochs = 100
model_sqr.compile(loss = 'mse', optimizer='adam')
model_sqr.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose = 1)
x = "n"
while True:
print("enter first num:")
x = input()
if x == "end":
break
print("Enter operation:")
op= input()
print("enter second num:")
y = input()
X = int(x)
Y = int(y)
Ydiv = np.reciprocal(Y)
if op == "*":
predicted_product = model_sqr.predict(model_add.predict(np.array([[X, Y]]))) - model_sqr.predict(np.array([X])) - model_sqr.predict(np.array([Y]))
print(predicted_product/2)
elif op = = "/":
predicted_quot = model_sqr.predict(model_add.predict(np.array([[X, Ydiv]]))) - model_sqr.predict(np.array([X])) - model_sqr.predict(np.array([Ydiv]))
print(predicted_quot/2)
Например, при сохранении весов и запуске программы для каждой используемой пары чисел получается примерно -0,123 каждый раз, когда я ее запускаю.
Пытаясь понять, почему это происходит, я запустил, например, 25/5, изменив программу так, чтобы она отображала (25+(1/5))^2, 25^2 и (1/5)^2. слишком. Я получил значения 623,7364, 623,73645 и 0,24594116.
Чтобы понять, почему были получены эти значения и как их исправить, я вместе построил квадратную функцию (оранжевый) и свою модель нейронной сети для квадрата (синий):
Увеличение близко к 25;
Увеличение близко к 0;
Проблема в том, что промежуточные значения, которые я вижу, были предсказаны на основе графиков, это не те, которые я распечатал. Используя курсор, я мог видеть, например, что 25^2 было предсказано примерно как 624, (25+(1/5))^2 было предсказано примерно 634 и (1/5)^2 было предсказано как быть 0,42. Используя эти значения, вы получите приемлемый ответ, но значения, которые я распечатал, другие.
(1): Почему эти значения различны?
(2): Как я могу заставить модель делать приемлемые прогнозы, которые, по-видимому, дает график?
@BenetOriol: Увеличенную версию какого из них вам нужна?
Я не вижу причины, по которой ваш сюжет должен показывать результаты, отличные от вашего сценария. Вы уверены, что используете одинаковый вес модели для обеих моделей? Я имею в виду, сохраняете ли вы свою модель после подгонки, а затем загружаете модель перед построением этой кривой?
@BenetOriol: Да, я использую один и тот же сохраненный файл .keras как для программы печати, так и для сценария. Сценарий, который я запускаю для отображения значений, на самом деле представляет собой отдельную программу, а не приведенную выше; он состоит только из импорта файла .keras, а затем цикла while в приведенном выше коде.
это модель, которую обучают имитировать эти математические операции, верно? Я бы не ожидал, что результат будет абсолютно правильным (отклонение на несколько процентов вполне прилично). Вероятно, вы могли бы повысить точность, тренируясь дольше везде, как вы делали это при почти нулевой точности. Также существует ограничение точности, зависящее от количества параметров модели, поэтому вы также можете попробовать увеличить размер и количество слоев в модели.
Попробуйте обучить модель на разном количестве выборок (1000, 10000, 50000 и т. д.) и проверьте, улучшается ли точность при увеличении количества выборок. Если повышение точности стабилизируется, вы можете добавить больше слоев и повторить попытку.
@IanChu: Количество обучающих примеров уже составило 2 100 000, поэтому я оставил его прежним и обучил их на модифицированной модели из пяти слоев: 16 нейронов в первых четырех и один в последнем. Теперь я получаю довольно точный набор значений из графика: 634,90, 624,85 и 0,1. Они должны дать значение, близкое к 5, но я все равно получаю разные значения для каждого из них, когда запускаю окончательный сценарий, и проблема небольшого фиксированного числа сохраняется. Что мне следует сделать, чтобы это исправить?
@harry, ты проверил мой ответ об использовании просто (Y * 1.0) в обратной функции?
Я думаю, проблема в том, что когда вы выполняете обратное целочисленному значению Y, оно возвращает 0, поэтому вы всегда вычисляете произведение X на ноль.
Y = int(y)
Ydiv = np.reciprocal(Y) # Ydiv is zero because the reciprocal of a positive integer is zero
Я думаю, это основная причина, по которой ваша программа всегда возвращает один и тот же результат.
Чтобы преодолеть эту ситуацию, вы можете, например:
X = int(x)
Y = int(y)
Ydiv = np.reciprocal(Y * 1.0)
print("Ydiv")
print(Ydiv)
print(np.array([X]))
print(np.array([Ydiv]))
if op == "*":
add_predict = model_add.predict(np.array([[X, Y]]))
add = float(add_predict[0][0]);
msqr = model_sqr.predict(np.array([add]));
xsqr = model_sqr.predict(np.array([X]));
ysqr = model_sqr.predict(np.array([Y]));
predicted_product = msqr - xsqr - ysqr
result = predicted_product[0][0] / 2.0
print(f'result of {X} * {Y}: {result}')
elif op = = "/":
add_predict = model_add.predict(np.array([[X, Ydiv]]))
print("x + 1/y = ")
print(add_predict)
add = float(add_predict[0][0]);
msqr = model_sqr.predict(np.array([add]));
xsqr = model_sqr.predict(np.array([X]));
ysqr = model_sqr.predict(np.array([Ydiv]));
#predicted_quot = model_sqr.predict(model_add.predict(np.array([[X, Ydiv]]))) - model_sqr.predict(np.array([X])) - model_sqr.predict(np.array([Ydiv]))
predicted_quot = msqr - xsqr - ysqr
print("result:")
print(predicted_quot/2)
print("---------")
print("x + 1/y = ")
print(add_predict)
print(Ydiv)
print("---------")
print("(x + 1/y)^2 = ")
print(msqr)
print("---------")
print("(x)^2 = ")
print(xsqr)
print("---------")
print("(y)^2 = ")
print(ysqr)
print("---------")
Я выполнил вашу программу на 1000 циклов для деления x/y, дав результаты от 0 до 50, и ошибка между ожидаемым и прогнозируемым результатом кажется хорошей, просто есть смещение 0,5 для компенсации и некоторое расхождение для близких значений. до нуля
Что мне следует использовать вместо этого? Как я упоминал в предыдущем вопросе, Ydiv=1/Y выдает ValueError. np.power() делает то же самое. '
Я попробовал привести Y к типу float(y) и попробовал описанное выше, чтобы получить те же результаты.
Вы можете использовать, например. (см. исходный ответ для лучшего форматирования) Y = int(y) Ydiv = np.reciprocal(Y * 1.0) ... elif op = = "/": add_predict = model_add.predict(np.array([[X, Ydiv) ]])) add = float(add_predict[0][0]); msqr = model_sqr.predict(np.array([add])); xsqr = model_sqr.predict(np.array([X])); ysqr = model_sqr.predict(np.array([Ydiv])); предсказанный_quot = msqr - xsqr - ysqr
Я добавил график результатов модели: его можно улучшить, но результаты кажутся нормальными.
Я добавил в модуль добавления два вектора по 10 000 элементов: один с диапазоном 0 .. 1 и один с диапазоном 0 .. 50, 30 эпох. Аналогичным образом я добавил в модуль умножения два вектора по 40 000 элементов с тем же диапазоном, что и у модели добавления. Как вы сказали, повышение разрешения чисел от 0 до 1 должно повысить точность конечного результата. Наконец, я протестировал нашу модель, удалив приведение к int для x и y и используя пары x,y, чтобы деление x/y не превышало мой максимальный тренировочный диапазон 50, т. е. деление 25/0,1 = 250 выходит за пределы допустимого диапазона и не учитывается.
Он по-прежнему выдает «ValueError: Исключение, возникшее при вызове Sequential.call(). Невозможно принять длину фигуры с неизвестным рангом». из-за строки «model_sqr.predict(np.array([Ydiv]))». Есть ли способ это исправить?
Привет, у меня возникла такая же ошибка при использовании вашего кода; он исчез после того, как я передал в квадратную модель переменную "add", взятую из model_add, как вы можете видеть в моем коде выше.
Теперь он выдает ошибку всякий раз, когда я пытаюсь разделить после умножения (или наоборот) при каждом запуске программы. Каждый раз во время работы, когда я меняю операцию, которую использовал ранее, возникает ошибка. Я просто не понимаю ни ошибки, ни того, как вам удалось ее исправить, и почему она сохраняется таким странным образом; ты можешь это объяснить?
Извините, я еще не пробовал часть умножения; Я посмотрю и сообщу тебе
Привет, я попробовал умножение, и оно выдало ошибку, о которой вы сообщили; Я изменил код в исходном ответе аналогично тому, что было сделано для частного, на моей платформе он работает без ошибок (по-видимому, с плохой точностью для исследования)
Извините, не обращайте внимания на точность в моем предыдущем комментарии: в моем коде была ошибка копирования/вставки, я исправил ее, и модель, похоже, работает нормально.
Спасибо. Не могли бы вы объяснить, почему именно это исправление работает? Я не понимаю, почему настройка кода суммы все исправляет.
Привет, похоже, это связано с размерами векторов: извините, но я не могу сейчас разобраться, как вы и сказали, я подправил код, чтобы он работал.
Все в порядке, спасибо, просто ответь, когда будет время.
Можешь поделиться сюжетом крупным планом? те, которыми вы поделились, слишком уменьшены, чтобы с такой точностью определить их значение.