文章目录

  • 1 Dense Layer
  • 2 对比原始的add layer方法和继承方法的不同
    • 2.1 global config
    • 2.1 用add实现
    • 2.2 用继承实现
  • 3 有权重的对比
    • 3.1 用自带add_weight方法自定义权重
    • 3.2 用add实现
    • 3.3 用继承实现
  • 4 用自定义矩阵为权重矩阵
    • 4.1 初始化权重和偏移项矩阵
    • 4.2 用add实现
    • 4.3 用继承实现
  • 5 用numpy实现
    • 5.1 初始化权重和偏移项矩阵
    • 5.2 add实现,有激活函数
    • 5.3 tf 实现
    • 5.4 numpy实现

1 Dense Layer

目的:构建Dense层,对比两种方法实现的区别

2 对比原始的add layer方法和继承方法的不同

2.1 global config

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Input, LSTM, Dense
import numpy as npnp.random.seed(1)rows = 10000    # 样本数
columns = 100  # 特征数train_x1 = np.random.random(size=(int(rows/2), columns))
train_y1 = np.random.choice([0], size=(int(rows/2), 1))
train_x2 = np.random.random(size=(int(rows/2), columns))+1
train_y2 = np.random.choice([1], size=(int(rows/2), 1))train_x = np.vstack((train_x1, train_x2))
train_y = np.vstack((train_y1, train_y2))units = 5    # 自定义cell个数

2.1 用add实现

tf.random.set_seed(1)        # 固定随机值model1 = keras.Sequential()
model1.add(Input(shape=(columns,)))
model1.add(Dense(units=units))model1.compile(optimizer="adam", loss="mse", metrics=["accuracy"])model1.fit(train_x, train_y, epochs=10)
model1.predict(train_x)[-1][-1]l1 = model1.layers[0]
w1, b1 = l1.get_weights()

api中的参数分几部分

  1. initializer 初始项,初始化参数
  2. regularizer 正则项,选择不同正则模式L1L2
  3. constraint 约束项,非负约束或者最大模约束

2.2 用继承实现

tf.random.set_seed(1)        # 固定随机值class MyDenseLayer(keras.layers.Layer):def __init__(self, num_outputs):super(MyDenseLayer, self).__init__()self.num_outputs = num_outputsdef build(self, input_shape):self.kernel = self.add_weight(name="kernel", shape=[int(input_shape[-1]), self.num_outputs])self.bias = self.add_weight(name="bias", shape=[self.num_outputs, ], initializer=keras.initializers.zeros)self.build = Truedef call(self, input):return tf.matmul(input, self.kernel) + self.biasmodel2 = keras.Sequential()
model2.add(Input(shape=(columns,)))
model2.add(MyDenseLayer(units))     model2.compile(loss="mse", optimizer="adam", metrics=['accuracy'])model2.fit(train_x, train_y, epochs=10)
model2.predict(train_x)[-1][-1]l2 = model2.layers[0]
w2, b2 = l2.get_weights()

3 有权重的对比

3.1 用自带add_weight方法自定义权重

自定义初始的权重和偏移项。为什么要定义这两个方法?为了用add_weight方法初始权重和偏移项

def w_init(shape, dtype=tf.float32):return tf.random.normal(shape=shape, dtype=dtype)def b_init(shape, dtype=tf.float32):return tf.zeros(shape=shape, dtype=dtype)

3.2 用add实现

tf.random.set_seed(1)        # 固定随机值model3 = keras.Sequential()
model3.add(Input(shape=(columns,)))
model3.add(Dense(units=units, kernel_initializer=w_init, bias_initializer=b_init))   # 需要固定weightsmodel3.compile(optimizer="adam", loss="mse", metrics=["accuracy"])model3.fit(train_x, train_y, epochs=10)
model3.predict(train_x)[-1][-1]l3 = model3.layers[0]
w3, b3 = l3.get_weights()

3.3 用继承实现

tf.random.set_seed(1)        # 固定随机值class MyDenseLayer(keras.layers.Layer):def __init__(self, num_outputs):super(MyDenseLayer, self).__init__()self.num_outputs = num_outputsdef build(self, input_shape):self.kernel = self.add_weight(initializer=w_init, shape=(input_shape[-1], self.num_outputs), dtype=tf.float32)    # 自定义权重self.bias = self.add_weight(initializer=b_init, shape=(self.num_outputs,), dtype=tf.float32)     # 自定义偏移项def call(self, input):return tf.matmul(input, self.kernel) + self.biasmodel4 = keras.Sequential()
model4.add(Input(shape=(columns,)))
model4.add(MyDenseLayer(units))     model4.compile(loss="mse", optimizer="adam", metrics=['accuracy'])model4.fit(train_x, train_y, epochs=10)
model4.predict(train_x)[-1][-1]l4 = model4.layers[0]
w4, b4 = l4.get_weights()

4 用自定义矩阵为权重矩阵

4.1 初始化权重和偏移项矩阵

tf.random.set_seed(1)
w = tf.random.normal(shape=(columns, units), dtype=tf.float32)
b = tf.zeros(shape=(units,), dtype=tf.float32)def w_init(shape, dtype=tf.float32):return wdef b_init(shape, dtype=tf.float32):return b

4.2 用add实现

tf.random.set_seed(1)        # 固定随机值model5 = keras.Sequential()
model5.add(Input(shape=(columns,)))
model5.add(Dense(units=units, kernel_initializer=w_init, bias_initializer=b_init))       model5.compile(loss="mse", optimizer="adam", metrics=['accuracy'])model5.fit(train_x, train_y, epochs=10)
model5.predict(train_x)[-1][-1]

4.3 用继承实现

不用Layer.add_weight方法,自己实现一个权重矩阵,然后用权重矩阵作为初始化,进行训练

tf.random.set_seed(1)        # 固定随机值class MyDenseLayer(keras.layers.Layer):def __init__(self, num_outputs):super(MyDenseLayer, self).__init__()self.num_outputs = num_outputsdef build(self, input_shape):self.kernel = tf.Variable(w, trainable=True)self.bias = tf.Variable(b, trainable=True)def call(self, input):return tf.matmul(input, self.kernel) + self.biasmodel6 = keras.Sequential()
model6.add(Input(shape=(columns,)))
model6.add(MyDenseLayer(units))     model6.compile(loss="mse", optimizer="adam", metrics=['accuracy'])model6.fit(train_x, train_y, epochs=10)
model6.predict(train_x)[-1][-1]

5 用numpy实现

5.1 初始化权重和偏移项矩阵

tf.random.set_seed(1)train_x = np.ones(shape=(rows, columns), dtype="float32")  # 这里一定要dtype一致,否则numpy与keras计算结果会有差异,我这里统一使用float32
train_y = np.vstack([np.ones(shape=(int(rows/2), 1), dtype="float32"), np.zeros(shape=(int(rows/2),1), dtype="float32")])w = tf.random.normal(shape=(columns, 1), dtype=tf.float32)
b = tf.zeros(shape=(1,), dtype=tf.float32)def w_init(shape, dtype=tf.float32):return tf.convert_to_tensor(w, dtype=tf.float32)def b_init(shape, dtype=tf.float32):return tf.convert_to_tensor(b, dtype=tf.float32)

5.2 add实现,有激活函数

tf.random.set_seed(1)        # 固定随机值model7 = keras.Sequential()
model7.add(Input(shape=(columns,)))
model7.add(Dense(units=1, kernel_initializer=w_init, bias_initializer=b_init, activation="sigmoid"))h1 = model7.predict(train_x)model7.compile(loss="mse", optimizer=tf.keras.optimizers.SGD(learning_rate=learning_rate), metrics=['accuracy'])model7.fit(train_x, train_y, epochs=1, batch_size=rows)    #这里要注意batch_size要用BatchGD,因为numpy实现时没有用batch,用的是全量数据更新w1, b1 = model7.layers[0].weights

5.3 tf 实现

tf.random.set_seed(1)        # 固定随机值x = tf.Variable(train_x, dtype=tf.float32)
w2 = w
b2 = b
with tf.GradientTape(persistent=True) as tape:tape.watch([w2, b2])y_pred = 1/(1+tf.math.exp(-1*tf.matmul(x, w2)+b2))loss = tf.math.reduce_mean(tf.math.square(tf.subtract(y_pred, train_y)))dw2 = tape.gradient(target=loss, sources=w2)
db2 = tape.gradient(target=loss, sources=b2)w2 = w2 - dw2*learning_rate
b2 = b2 - db2*learning_rate

5.4 numpy实现

import numpy as npclass MyModel:def __init__(self, w, b, learning_rate):self.w = wself.b = bself.learning_rate = learning_ratedef fit(self, train_x, train_y, epochs, batch_size):self.x = train_xself.y = train_yfor epoch in range(epochs):print(f"epoch {epoch}")self.forward()  # 正向传播self.get_loss()self.backward()def forward(self):self.h3 = self.sigmoid(np.dot(self.x, self.w) + self.b)def backward(self):learning_rate = 0.01dw3 = np.dot(self.x.T, 2*(self.h3 - self.y)*self.h3*(1-self.h3)/train_x.shape[0])  # loss对w的求导db3 = np.dot(np.ones(shape=(1, rows)), 2*(self.h3 - self.y)*self.h3*(1-self.h3)/train_x.shape[0])  # loss对b的求导self.w -= dw3 * learning_rateself.b -= db3 * learning_ratedef sigmoid(self, x):return 1 / (1 + np.exp(-x))def get_loss(self):loss = np.sum((np.square(self.h3-self.y)), axis=0)/rowsprint(f"loss {loss}")def predict(self):passmodel8 = MyModel(w, b, learning_rate)
model8.fit(train_x, train_y, epochs=1, batch_size=rows)w3 = model8.w
b3 = model8.b

tf dense layer两种创建方式的对比和numpy实现相关推荐

  1. TF、keras两种padding方式:vaild和same

    TF.keras两种padding方式:vaild和same TF.keras两种padding方式:vaild和same:https://oldpan.me/archives/tf-keras-pa ...

  2. 【无标题】单例模式的两种创建方式:饿汉式和懒汉式

    这里写自定义目录标题 单例模式的两种创建方式:饿汉式和懒汉式 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题,有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂 ...

  3. Java多线程两种实现方式的对比

    Java多线程两种实现方式的对比 一种,直接继承Thread类 一种,实现Thread类的Runnable接口 两种方式的区别 比如,售票厅有四个窗口,可以发售某日某次列出的100张车票,此时,100 ...

  4. java中字符串的创建_【转载】 Java中String类型的两种创建方式

    本文转载自 https://www.cnblogs.com/fguozhu/articles/2661055.html Java中String是一个特殊的包装类数据有两种创建形式: String s ...

  5. eclipse让实现类也添加上接口的注释_多线程:面试常问的两种创建方式,数据共享实现和正确停止线程...

    多线程 进程与线程的区别: 进程:程序的执行过程,持有资源(内存)(共享内存和文件)和线程.比如,电脑上的eclipse.QQ.微信等运行中的软件就是一个进程 线程应用:1.eclipse编辑代码时, ...

  6. java多线程总结一:线程的两种创建方式及优劣比较

    1.通过实现Runnable接口线程创建 (1).定义一个类实现Runnable接口,重写接口中的run()方法.在run()方法中加入具体的任务代码或处理逻辑. (2).创建Runnable接口实现 ...

  7. android编程fragment,详解Android中Fragment的两种创建方式

    onCreate():在创建fragment时系统会调用此方法.在实现代码中,你可以初始化想要在fragment中保持的那些必要组件,当fragment处于暂停或者停止状态之后可重新启用它们. onC ...

  8. java多线程总结一:线程的两种创建方式及比较

    1.线程的概念:线程(thread)是指一个任务从头至尾的执行流,线程提供一个运行任务的机制,对于java而言,一个程序中可以并发的执行多个线程,这些线程可以在多处理器系统上同时运行.当程序作为一个应 ...

  9. Spark对Kafka两种连接方式的对比——Receiver和Direct

    在知乎 Flink 取代 Spark Streaming 的实战之路中,提到 因此下面对两种方式进行详细说明一下. Receiver方式 Receiver:接收器模式是使用Kafka高级Consume ...

最新文章

  1. [爬虫学习笔记]C# 使用 ScrapySharp 并行下载天涯图片
  2. 012_日期内建函数
  3. 菜鸟教程python位运算符_NumPy 位运算
  4. wdcp mysql密码_wdcp默认的mysql密码是多少?
  5. 我的Android进阶之旅------Android利用Sensor(传感器)实现水平仪功能的小例
  6. 工作174:数组转换为对象项目案例
  7. web前端网站推荐(后续继续补充)
  8. kepware mysql_Kepware EX6与MySQL数据库通讯(上篇)
  9. GB35114---基于openssl加密库进行开发(二)
  10. 风控建模十:传统建模方法存在的问题探讨及改进方法探索
  11. 结节性硬化症会一直病变吗?结节性硬化最晚多大发病?
  12. win7+Ubuntu双系统安装
  13. 机器学习定义及基本术语(根据周志华的《机器学习》概括)
  14. 【转载】完全版线段树 by notonlysuccess大牛
  15. 华为计算机平台芯片,华为连发两款AI芯片,计算力远超谷歌及英伟达
  16. 极验滑块验证码破解最新版
  17. 嵌入式Linux设备驱动程序开发指南3(构建Microchip SAMA5D2嵌入式 Linux系统)——读书笔记
  18. 杰理之杰理音箱方案选型【篇】
  19. 如何让谷歌浏览器支持小字体?
  20. 基于Python的机器学习之预测鲍鱼年龄数据集

热门文章

  1. C/C++基础知识点(四)
  2. 记录 McAfee WebAdvisor 产生大量日志文件,卸载时一直转圈圈,成功卸载方式
  3. 计算机网络之数据链路层思维导图总结
  4. Linux 之五 最新 2021 一图看尽 Linux 发行版
  5. Linux C: 内嵌汇编语法
  6. C#语法:委托与方法
  7. python123第三章作业答案_swift playground类似的游戏
  8. 数据结构与算法 / 排序算法 / 堆排序
  9. 数据结构与算法 / 堆结构
  10. signal.h 中的宏定义 SIG_DFL 及 SIG_IGN