1 # coding: utf-8
2
3 """张量的基本运算"""
4
5 # In[9]:
6
7 A = tf.constant([[1., 2.], [3., 4.]])
8 B = tf.constant([[5., 6.], [7., 8.]])
9
10 # output:
11
12 (<tf.Tensor: id=31, shape=(2, 2), dtype=float32, numpy=
13 array([[1., 2.],
14 [3., 4.]], dtype=float32)>,
15 <tf.Tensor: id=32, shape=(2, 2), dtype=float32, numpy=
16 array([[5., 6.],
17 [7., 8.]], dtype=float32)>)
18
19
20 # In[11]:
21
22 C = tf.add(A, B)
23
24 # output:
25
26 <tf.Tensor: id=33, shape=(2, 2), dtype=float32, numpy=
27 array([[ 6., 8.],
28 [10., 12.]], dtype=float32)>
29
30 # In[13]:
31
32 D = tf.matmul(A,B)
33
34 # output:
35
36 <tf.Tensor: id=34, shape=(2, 2), dtype=float32, numpy=
37 array([[19., 22.],
38 [43., 50.]], dtype=float32)>
39
40
41 """ 自动求导机制 """
42
43 # In[8]:
44
45 import tensorflow as tf
46
47 x = tf.Variable(initial_value=3.) #用变量的好处是默认打开梯度追踪
48 with tf.GradientTape() as tape: # 在 tf.GradientTape() 的上下文内,所有计算步骤都会被记录以用于求导。————记录器
49 y = tf.square(x)
50 y_grad = tape.gradient(y, x) # 计算y关于x的导数——求导方法
51 print([y, y_grad])
52
53 # output:
54 [<tf.Tensor: id=26, shape=(), dtype=float32, numpy=9.0>, <tf.Tensor: id=30, shape=(), dtype=float32, numpy=6.0>]
55
56
57 # In[6]:
58
59 import tensorflow as tf
60 X = tf.constant([[1.,2.],[3.,4.]])
61 y = tf.constant([[1.],[2.]])
62 w = tf.Variable(initial_value = [[1.],[2.]]) #变量的初始化器:initial_value
63 b = tf.Variable(initial_value = 1.)
64 with tf.GradientTape() as tape:
65 L = tf.reduce_sum(tf.square(tf.matmul(X,w) + b - y))
66 #tf.reduce_sum可以通过设置axis来对不同维度求和;tf.reduce_sum(X,0) = = [4,6] ;tf.reduce_sum(X,1) = = [3,7];tf.reduce_sum(X) = = 10
67 #tf.square对tensor里的每一个元素平方,但是不改变tensor的shape
68 w_grad,b_grad = tape.gradient(L,[w,b])
69 print([L.numpy(),w_grad.numpy(),b_grad.numpy()])#tensor.numpy()取tensor的值,忽略类型信息
70 print([L,w_grad,b_grad])
71
72
73 """线性回归示例"""
74
75 X,y
76
77 # ### 梯度下降法
78 # #### 首先构建损失函数
79 # #### 其次求参数梯度,更新参数
80 # #### 迭代下一轮
81
82 # L = sum_{i=1}^n(ax_i + b - y_i)^2
83
84
85 # In[45]:
86
87 import numpy as np
88
89 X_raw = np.array([2013, 2014, 2015, 2016, 2017], dtype=np.float32)
90 y_raw = np.array([12000, 14000, 15000, 16500, 17500], dtype=np.float32)
91
92 X = (X_raw - X_raw.min()) / (X_raw.max() - X_raw.min()) #归一化
93 y = (y_raw - y_raw.min()) / (y_raw.max() - y_raw.min())
94
95
96
97
98 """ 一、NumPy 下的线性回归 """
99
100 # In[14]:
101
102 a,b = 0, 0
103 num_epoch = 10000
104 lr = 1e-3
105 for e in range(num_epoch):
106 y_pred = a*X + b
107 grad_a,grad_b = (y_pred - y).dot(X),(y_pred - y).sum()
108 a,b = a - lr*grad_a, b-lr*grad_b
109 print(a,b)
110
111 # output:
112 0.9763702027872221 0.057564988311377796
113
114 # #### 再深再复杂的模型就很痛苦了
115
116 """ 二、TensorFlow 下的线性回归"""
117
118 # ### 默认开启Eager Execution(动态图)模式
119
120 # In[47]:
121
122 X= tf.constant(X) #tensor化
123 y = tf.constant(y)
124
125 a = tf.Variable(initial_value = 0.) #参数初始化
126 b = tf.Variable(initial_value = 0.)
127
128 variables = [a,b]
129
130 num_epoch = 10000
131 optimizer = tf.keras.optimizers.SGD(learning_rate = 1e-3) #声明优化器
132 for e in range(num_epoch):
133 with tf.GradientTape() as tape: #对正向传播和损失函数,开启梯度记录器
134 y_pred = a*X+b
135 loss = 0.5*tf.reduce_sum(tf.square(y_pred - y))
136 grads = tape.gradient(loss,variables) #计算梯度
137 optimizer.apply_gradients(grads_and_vars = zip(grads,varibales))
138 #更新参数关键字:grads_and_vars: 需要传入一个python列表,[(grad_a, a), (grad_b, b)] 。
139 #因此用python内置函数zip(g,v) 将参数和梯度打包拼装成需要的参数形式
140 #梯度归0
141 print(a,b)
142
143 # output:
144 <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=0.0> <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=0.0>
145
146
147
148 """ python内置函数zip"""
149
150 # In[42]:
151 a = [1, 3, 5]
152 b = [2, 4, 6]
153 zip(a,b)
154
155 # output:
156 [(1,2),(3,4),(5,6) ]
157
158 """
159 整个流程总结:
160 """
161 构建模型 tf.keras.Model 和tf.keras.layers
162 模型损失:tf.keras.losses
163 模型优化器:tf.keras.optimizer
164 模型评估:tf.keras.metrics
165 """
166
167 import tensorflow as tf
168 import numpy as np
169 class MyModel(tf.keras.Model):
170 def __init__(self):
171 super().__init__() # Python 2 下使用 super(MyModel, self).__init__()
172 # 此处添加初始化代码(包含 call 方法中会用到的层),例如
173 # layer1 = tf.keras.layers.BuiltInLayer(...)
174 # layer2 = MyCustomLayer(...)
175
176 def call(self, input): #实现的是模型的调用 y_pred = Model(X)的过程
177 #此处添加模型调用的代码(处理输入并返回输出),例如
178 x = layer1(input)
179 output = layer2(x)
180 return output
181
182 # 还可以添加自定义的方法
183 """
184 layers对变量和计算流程进行封装(如全连接层dense,卷积层,池化层),Model对各种layers进行组织链接,并封装成一个整体,Model描述的是由输入到输出的运算过程。
185 模型定义通过继承父类tf.keras.Model实现,还要重写init() (构造函数,初始化)和 call(input) (模型调用,重写)两个方法,同时也可以根据需要增加自定义的方法。
186 构造函数初始化模型所需的所有层,call()方法描述了输入如何由输入数据得通过layers得到输出
187 """
188
189 """
190 kernel_initializer 、 bias_initializer :权重矩阵 kernel 和偏置向量 bias 两个变量的初始化器。默认为 tf.glorot_uniform_initializer 1 。设置为 tf.zeros_initializer 表示将两个变量均初始化为全 0
191 """
192
193
194
195 #模型继承:
196 class Linear(tf.keras.Model):
197
198 #模型实例化
199 model = Linear() #相当于Linear.call()
200
201 """
202 模型为何非要继承并重写父类tf.keras.Model实现?? 因为父类实现了很多包括其他的属性,如在实例化模型后,可以用model.variable直接获得模型所有变量等,因此要继承。
203
204 #相当于Linear.call() 私有属性 父类tf.keras.Model其实定义了call()方法来,为何不直接重写call()来调用Linear() y_pred = Linear(X).而是又实现一个call()方法暴露出来来重写呢? 这是因为后期 Keras 在模型调用的前后还需要有一些自己的内部操作,所以暴露出一个专门用于重载的 call() 方法,然后我们去重写
205 """