1. 使用tensorflow训练一个三分类问题。
分类是一个双曲线分成的三部分。蓝色部分对应的是x<=-(y^2+1)^(1/2),其向量为[1,0,0],黄色部分对应的是x>=(y^2+1)^(1/2),其向量为[0,0,1],其余部分为x^2<y^2+1,对应向量为[0,1,0]
# coding: utf-8
import tensorflow as tf
from tensorflow.keras import layers
import math
print(tf.__version__)
print(tf.keras.__version__)
if __name__ == '__main__':
model = tf.keras.Sequential()
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(3, activation='softmax'))
model.compile(optimizer=tf.keras.optimizers.Adam(0.001),
loss=tf.keras.losses.categorical_crossentropy,
metrics=[tf.keras.metrics.categorical_accuracy])
train_x = [[x, y] for x in range(-10, 10) for y in range(-10, 10)]
train_y = map(lambda v: [1, 0, 0] if v[0] <= -math.sqrt(v[1] * v[1] + 1) else (
[0, 0, 1] if v[0] >= math.sqrt(v[1] * v[1] + 1) else [0, 1, 0]), train_x)
print train_x
print train_y
model.fit(train_x, train_y, batch_size=1, epochs=200,
validation_data=([[0, 0], [10, 0]], [[0, 1, 0], [0, 0, 1]]))
result = model.predict([[0, 0], [1000, 100]], batch_size=1)
print '################'
print(result)
2. 回归问题
f(x,y)=x*y
通过这两个模型的构建参数,足以见得我对模型构建一窍不通。
# coding: utf-8
import tensorflow as tf
from tensorflow.keras import layers
print(tf.__version__)
print(tf.keras.__version__)
if __name__ == '__main__':
model = tf.keras.models.load_model('./regression')
result = model.predict([[0.4, 0], [10, 10]], batch_size=1)
print '################'
print(result)
# exit(0)
model = tf.keras.Sequential()
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(1))
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
loss=tf.keras.losses.mse,
metrics=['mae', 'mse'])
train_x = [[1.0 * x, 1.0 * y] for x in range(-10, 10) for y in range(-10, 10)]
train_y = [[e[0] * e[1]] for e in train_x]
print train_x
print train_y
model.fit(train_x, train_y, batch_size=1, epochs=200,
validation_data=([[0, 0], [10, 0]], [[0], [0]]))
result = model.predict([[0, 0], [1000, 100]], batch_size=1)
model.save('./regression')
print '################'
print(result)
---------------------------------------------------
损失函数:
经过一天的折腾,终于明白了tensorflow.keras.losses.BinaryCrossEntropy和tensorflow.keras.losses.CategoricalCrossentropy的区别,也明白了为什么是这样的。
对于:
y_true=[[0,2,1],[1,0,0]]
y_pred=[[0.1, 0.7, 0.7], [0.2, 0, 0]]
如果是BinaryCrossEntropy,对于每一项都会根据0/1计算交叉熵,对于第一个样本,会计算三个交叉熵,即
bce1=1/N*Σ ( yi*ln pi + (1-yi)*ln(1-pi) ) = -0.00952922 # yi,pi分别是y_true和y_pred中对应的项
bce2=1/N*Σ ( yi*ln pi + (1-yi)*ln(1-pi) ) = 0.5364791
#可以使用tf.keras.losses.binary_crossentropy(y_true, y_pred),这个方法会计算每个样本的交叉熵,而不是最后的汇总结果
如果是CategoricalCrossentropy,每个样本会计算一个交叉熵,计算之前会先对y_pred进行正规化,具体的方法不是采用softmax函数,而是直接根据比例重新划分,在上例中,正规化后的结果为
y_pred=[[1/15, 7/15, 7/15], [1, 0, 0]]
然后在正规化的结果上计算交叉熵
cce1= Σ ( yi*ln pi) = 2.2864201 # yi,pi分别是y_true和y_pred中对应的项
cce2= Σ ( yi*ln pi) = 1.1920929e-07
#可以使用tf.keras.losses.categorical_crossentropy(y_true, y_pred),这个方法会计算每个样本的交叉熵,而不是最后的汇总结果
这两种计算方式的不同是可以理解的。对于二分类问题,输出的每个点代表一个类,回答的问题是是否属于这个类,一个输入,可以同属于多个类,因此,应该认为每个分类是独立的。但是对于多分类问题,一般认为,一个输出判断的是属于哪一个类的问题,因此y_pred预测的是哪一个类。因此对于一个y_true=[0,1,1],说明的是这个分类不属于第一类,但是属于第二、三类。但是对于一个多分类问题,这个输出一般认为是无意义的,一个多分类问题的向量中只应该有一个值为1,对应的属于的类。