所使用的的数据连接:https://www.ituring.com.cn/book/download/d16bf588-375b-4176-b319-ec3c3a2d99a1
原书网址
读入EXCEL文件的DATA工作簿中的学习数据
将读入的数据分解成为 12*64 维数组,每一行代表一个待识别的数字(0或者 1)
将正解转换为tuple形式并保存在value列表中。其中(0,1)代表1, (1,0)代表0
这一步比较复杂,要反复尝试。
import pandas, numpy
file = r'D:\ChromeCoreDownloads\【Excel示例文件】深度学习的数学\3-5 NN(求解器).xlsx'
data = pandas.read_excel(file, sheet_name='Data', engine='openpyxl')
df = pandas.DataFrame(data)
# 通过切片,去除部分没有意义的行和列
df1 = df.iloc[2:8, 10:]
file的文件路径要更改为相应的文件路径。
value = []
for i in range(0, 256, 4):
target_area = df1.iloc[:, i:i+4]
if int(target_area.iloc[5, 3]) == 0:
value.append((1, 0))
elif int(target_area.iloc[5, 3]) == 1:
value.append((0, 1))
else:
print('error', df1.iloc[0, 0])
target_area = target_area.iloc[1:-1, 0:3]
# 将4行3列的学习数据转化为1行
target_area = numpy.array(target_area).flatten()
target_area = pandas.DataFrame(target_area).transpose()
if i == 0:
data_new = target_area
else:
# 将学习数据打包为一个Dataframe
data_new.loc[len(data_new)] = target_area.iloc[0, :]
print(data_new)
print(value)
结果如下图:
0 1 2 3 4 5 6 7 8 9 10 11
0 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0 1.0 1.0 1.0
1 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0 1.0 1.0 1.0
2 1.0 1.0 0.0 1.0 0.0 1.0 1.0 0.0 1.0 1.0 1.0 1.0
3 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0 1.0 1.0 0.0
4 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0 0.0 1.0 1.0
.. ... ... ... ... ... ... ... ... ... ... ... ...
59 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 1.0 1.0 0.0
60 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0
61 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0
62 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 1.0 0.0
63 0.0 1.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0
[64 rows x 12 columns]
[(1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (1, 0), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1)]
Process finished with exit code 0
以下是三层网络及梯度的计算过程。梯度的计算要按照公式一个一个计算。没有什么捷径。
def add_gradient(l):
# 将各个图片的平方误差的偏导数相加得到梯度
total = l[0]
for i in range(1, len(l)):
total += l[i]
return total
def neural_example(data_new, i):
global b21, b22, b23, w21, w22, w23, w31, w32, b31, b32
# 通过改变seed来获得不同的代价函数C的值
# 获取隐藏层的初始值, (w21, w22, w23)对应隐藏层的权重,b21, b22, b23对应隐藏层的偏置。
numpy.random.seed(i)
data_new = numpy.array(data_new)
w21 = numpy.random.randn(3, 12)[0]
w22 = numpy.random.randn(3, 12)[1]
w23 = numpy.random.randn(3, 12)[2]
b21, b22, b23 = numpy.random.randn(3)
# 获取输出层初始化参数值(权重和偏置)
w31 = numpy.random.randn(2, 3)[0]
w32 = numpy.random.randn(2, 3)[1]
b31, b32 = numpy.random.randn(2)
# 学习率初始化为 -1
step = -1
for x in range(50):
# 计算隐藏层的各个神经元输入z及输出a。
z21 = data_new.dot(w21) + b21
a21 = 1/(numpy.exp(-1*z21)+1)
z22 = data_new.dot(w22) + b22
a22 = 1/(numpy.exp(-1*z22)+1)
z23 = data_new.dot(w23) + b23
a23 = 1/(numpy.exp(-1*z23)+1)
# 计算输出层的输入z及输出a
z31 = numpy.array([a21, a22, a23]).transpose().dot(numpy.array(w31)) + b31
z32 = numpy.array([a21, a22, a23]).transpose().dot(numpy.array(w32)) + b32
a31 = 1/(numpy.exp(-1*z31)+1)
a32 = 1/(numpy.exp(-1*z32)+1)
# 计算代价函数值c
c = 0
for j in range(64):
c += 1/2 * ((a31[j]-value[j][0])**2 + (a32[j]-value[j][1])**2)
# 梯度下降法调整参数值
# 先计算神经单元误差
value_1 = []
value_2 = []
for v in value:
value_1.append(v[0])
value_2.append(v[1])
value_1 = numpy.array(value_1)
value_2 = numpy.array(value_2)
# 输出层的神经单元误差 sigma = (a - value) * a * (1 - a) 为 2*64矩阵
sigma31 = (a31 - value_1) * a31 * (1 - a31)
sigma32 = (a32 - value_2) * a32 * (1 - a32)
sigma3 = numpy.array((sigma31, sigma32)).transpose()
# 隐藏层的神经单元误差 sigma 为3x84矩阵 dfs为输出a对输入的导数
sigma21 = sigma3.dot(numpy.array((w31, w32))[:, 0]) * (a21*(1-a21))
sigma22 = sigma3.dot(numpy.array((w31, w32))[:, 1]) * (a22*(1-a22))
sigma23 = sigma3.dot(numpy.array((w31, w32))[:, 2]) * (a23*(1-a23))
# print(numpy.array((w31, w32))[:, 0])
# 计算梯度
# 输出层
s_b31 = sigma31
s_b31 = add_gradient(s_b31) * step
s_b32 = sigma32
s_b32 = add_gradient(s_b32) * step
s_w31 = numpy.array((sigma31 * a21, sigma31 * a22, sigma31 * a23)).transpose()
s_w31 = add_gradient(s_w31) * step
s_w32 = numpy.array((sigma32 * a21, sigma32 * a22, sigma32 * a23)).transpose()
s_w32 = add_gradient(s_w32)
# 隐藏层
s_b21, s_b22, s_b23 = sigma21, sigma22, sigma23
s_b21 = add_gradient(s_b21) * step
s_b22 = add_gradient(s_b22) * step
s_b23 = add_gradient(s_b23) * step
s_w21 = (data_new.transpose() * sigma21).transpose()
s_w21 = add_gradient(s_w21) * step
s_w22 = (data_new.transpose() * sigma22).transpose()
s_w22 = add_gradient(s_w22) * step
s_w23 = (data_new.transpose() * sigma23).transpose()
s_w23 = add_gradient(s_w23) * step
# print(s_w23)
# 根据梯度调整参数值
b21 += s_b21
b22 += s_b22
b23 += s_b23
w21 += s_w21
w22 += s_w22
w23 += s_w23
b31 += s_b31
b32 += s_b32
w31 += s_w31
w32 += s_w32
if c < 1:
print(c, x)
step = -0.05
if c < 0.5:
break
return c
用书中的数据进行测试,能够准确的预测。
def check(data_new):
# 计算结果
# 计算隐藏层的z及输出a
data_new = numpy.array(data_new)
z21 = data_new.dot(w21) + b21
a21 = 1 / (numpy.exp(-1 * z21)+1)
z22 = data_new.dot(w22) + b22
a22 = 1 / (numpy.exp(-1 * z22)+1)
z23 = data_new.dot(w23) + b23
a23 = 1 / (numpy.exp(-1 * z23)+1)
# 计算输出层的z及输出a
z31 = numpy.array([a21, a22, a23]).transpose().dot(numpy.array(w31)) + b31
z32 = numpy.array([a21, a22, a23]).transpose().dot(numpy.array(w32)) + b32
a31 = 1 / (numpy.exp(-1 * z31)+1)
a32 = 1 / (numpy.exp(-1 * z32)+1)
if a31 > a32:
print('结果为', 0)
elif a31 < a32:
print('结果为', 1)
print(a31, a32)
# 用书中的例子测试结果
# data_test = numpy.array((0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0))
# data_test = (0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1)
data_test = (0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0)
c = neural_example(data_new, 0)
print(c)
check(data_test)
计算结果如下:
0.7812709960623921 22
0.34322063461320146 23
0.34322063461320146
结果为 1
0.07197658369715122 0.999977452430708
Process finished with exit code 0
期间还参考了很多博主的文件,一并感谢。
以上只是我的粗陋见解,特别是求最优化参数的方法,应该还有很大的改进空间,希望路过的多多指教。