Ответ 1
- Правило перцептрона всегда работает, если данные линейно разделяются
- Гарантируется, что правило Перцептрона будет сходиться для линейно разделяемых данных
- Перцептрон лучше всего работает, когда функция активации является гиперболическим касанием или жестким ограничением
- Если вы используете линейную активацию, весы взорвутся
- вам нужно использовать регуляризацию на весах, чтобы веса не становились слишком большими
- Правило обновления веса:
new_weight = old_weight + (target - logits) * input
- В приведенном выше правиле обновления веса
error = (target - logits)
- Указанное правило обновления веса называется дельта-правилом
- В правиле дельта вы также можете использовать скорость обучения:
new_weight = old_weight + learning_rate * (target - logits) * input
- Вы используете правило обновления веса:
new_weight = old_weight + (logits) * input
- Обновление веса, которое вы используете, не будет работать хорошо.
- Использовать правило дельта
- В вашем правиле обновления веса вы не используете цель, и, следовательно, это неконтролируемое правило hebb
- Пожалуйста, обратитесь к этой ссылке github: https://github.com/jayshah19949596/Neural-Network-Demo/tree/master/Single%20Neuron%20Perceptron%20Learning
- Эта ссылка точно делает то, что вы хотите с помощью gui
Обновлено: см. Код ниже.... Я тренировался на 100 epoochs
- Веса могут идти в бесконечность, если использовать функцию линейной активации
- Чтобы избежать переноса веса в бесконечность, применяйте регуляризацию или ограничивайте свои веса до определенного числа
- В приведенном ниже коде я ограничил значение весов и не применял регуляризацию
==============================================
import numpy as np
import matplotlib.pyplot as plt
def plot_line(x_val, y_val, points):
fig = plt.figure()
plt.scatter(points[0:2, 0], points[0:2, 1], figure=fig, marker="v")
plt.scatter(points[2:, 0], points[2:, 1], figure=fig, marker="o")
plt.plot(x_val, y_val, "--", figure=fig)
plt.show()
def activation(net_value, activation_function):
if activation_function == 'Sigmoid':
# =============================
# Calculate Sigmoid Activation
# =============================
activation = 1.0 / (1 + np.exp(-net_value))
elif activation_function == "Linear":
# =============================
# Calculate Linear Activation
# =============================
activation = net_value
elif activation_function == "Symmetrical Hard limit":
# =============================================
# Calculate Symmetrical Hard limit Activation
# =============================================
if net_value.size > 1:
activation = net_value
activation[activation >= 0] = 1.0
activation[activation < 0] = -1.0
# =============================================
# If net value is single number
# =============================================
elif net_value.size == 1:
if net_value < 0:
activation = -1.0
else:
activation = 1.0
elif activation_function == "Hyperbolic Tangent":
# =============================================
# Calculate Hyperbolic Tangent Activation
# =============================================
activation = ((np.exp(net_value)) - (np.exp(-net_value))) / ((np.exp(net_value)) + (np.exp(-net_value)))
return activation
# ==============================
# Initializing weights
# ==============================
input_weight_1 = 0.0
input_weight_2 = 0.0
bias = 0.0
weights = np.array([input_weight_1, input_weight_2])
# ==============================
# Choosing random data points
# ==============================
data_points = np.random.randint(-10, 10, size=(4, 2))
targets = np.array([1.0, 1.0, -1.0, -1.0])
outer_loop = False
error_array = np.array([5.0, 5.0, 5.0, 5.0])
# ==========================
# Training starts from here
# ==========================
for i in range(0, 100):
for j in range(0, 4):
# =======================
# Getting the input point
# =======================
point = data_points[j, :]
# =======================
# Calculating net value
# =======================
net_value = np.sum(weights * point) + bias # [1x2] * [2x1]
# =======================
# Calculating error
# =======================
error = targets[j] - activation(net_value, "Symmetrical Hard limit")
error_array[j] = error
# ============================================
# Keeping the error in range from -700 to 700
# this is to avoid nan or overflow error
# ============================================
if error > 1000 or error < -700:
error /= 10000
# ==========================
# Updating Weights and bias
# ==========================
weights += error * point
bias += error * 1.0 # While updating bias input is always 1
###########################################################
# If you want to use unsupervised hebb rule then use the below update rule
# weights += targets[j] * point
# bias += targets[j] * 1.0 # While updating bias input is always 1
###########################################################
if (error_array == np.array([0.0, 0.0, 0.0, 0.0])).all():
outer_loop = True
break
x_values = np.linspace(-10, 10, 256)
if weights[0] == 0:
weights[0] = 0.1
if weights[1] == 0:
weights[1] = 0.1
# ========================================================
# Getting the y values to plot a linear decision boundary
# ========================================================
y_values = ((- weights[0] * x_values) - bias) / weights[1] # Equation of a line
input_weight_1 = weights[0]
input_weight_2 = weights[1]
if outer_loop:
break
input_weight_1 = weights[0]
input_weight_2 = weights[1]
print(weights)
plot_line(x_values, y_values, data_points)
==============================================
Выход:
================================================== ====
Использование кода с моим кодом
import numpy as np
import matplotlib.pyplot as plt
def plot_line(x_val, y_val, targets, points):
fig = plt.figure()
for i in range(points.shape[0]):
if targets[i] == 1.0:
plt.scatter(points[i, 0], points[i, 1], figure=fig, marker="v", c="red")
else:
plt.scatter(points[i, 0], points[i, 1], figure=fig, marker="o", c="black")
plt.plot(x_val, y_val, "--", figure=fig)
plt.show()
def activation(net_value, activation_function):
if activation_function == 'Sigmoid':
# =============================
# Calculate Sigmoid Activation
# =============================
activation = 1.0 / (1 + np.exp(-net_value))
elif activation_function == "Linear":
# =============================
# Calculate Linear Activation
# =============================
activation = net_value
elif activation_function == "Symmetrical Hard limit":
# =============================================
# Calculate Symmetrical Hard limit Activation
# =============================================
if net_value.size > 1:
activation = net_value
activation[activation >= 0] = 1.0
activation[activation < 0] = -1.0
# =============================================
# If net value is single number
# =============================================
elif net_value.size == 1:
if net_value < 0:
activation = -1.0
else:
activation = 1.0
elif activation_function == "Hyperbolic Tangent":
# =============================================
# Calculate Hyperbolic Tangent Activation
# =============================================
activation = ((np.exp(net_value)) - (np.exp(-net_value))) / ((np.exp(net_value)) + (np.exp(-net_value)))
return activation
a = 1
b = 1
def target(x):
if x[1] > a*x[0]+b:
return 1
else:
return -1
def gen_y(X_sim):
return np.array([target(x) for x in X_sim])
def train(data_points, targets, weights):
outer_loop = False
error_array = np.zeros_like(targets) + 0.5
bias = 0
# ==========================
# Training starts from here
# ==========================
for i in range(0, 1000):
for j in range(0, data_points.shape[0]):
# =======================
# Getting the input point
# =======================
point = data_points[j, :]
# =======================
# Calculating net value
# =======================
net_value = np.sum(weights * point) + bias # [1x2] * [2x1]
# =======================
# Calculating error
# =======================
error = targets[j] - activation(net_value, "Symmetrical Hard limit")
error_array[j] = error
# ============================================
# Keeping the error in range from -700 to 700
# this is to avoid nan or overflow error
# ============================================
if error > 1000 or error < -700:
error /= 10000
# ==========================
# Updating Weights and bias
# ==========================
weights += error * point
bias += error * 1.0 # While updating bias input is always 1
###########################################################
# If you want to use unsupervised hebb rule then use the below update rule
# weights += targets[j] * point
# bias += targets[j] * 1.0 # While updating bias input is always 1
###########################################################
# if error_array.all() == np.zeros_like(error_array).all():
# outer_loop = True
# break
x_values = np.linspace(-10, 10, 256)
if weights[0] == 0:
weights[0] = 0.1
if weights[1] == 0:
weights[1] = 0.1
# ========================================================
# Getting the y values to plot a linear decision boundary
# ========================================================
y_values = ((- weights[0] * x_values) - bias) / weights[1] # Equation of a line
if outer_loop:
break
plot_line(x_values, y_values, targets, data_points)
def pcp(X, y):
w = np.zeros(2)
Z = np.hstack((X, np.array([y]).T))
X = Z[0:, 0:2]
Y = Z[0:, 2]
train(X, Y, w)
# while ~all(z[2]*np.dot(w, z[:2]) > 0 for z in Z): # some training sample is miss-classified
# i = np.where(y*np.dot(w, x) < 0 for x in X)[0][0] # update the weight based on misclassified sample
# print(i)
# w = w + y[i]*X[i]
return w
if __name__ == '__main__':
X = np.random.multivariate_normal([1, 1], np.diag([1, 1]), 20)
y = gen_y(X)
w = pcp(X, y)
print(w)