20221114

0

改进的点

  1. 增加input,为input增加循环
  2. load_data增加归一化,与之对应输出时需要将归一化还原

存疑的点

  1. 分类阈值是否和常识一样为0.5/如果改成不是奇偶数判断(例如是否被3整除)阈值是否是0.5

  2. BATCH_SIZE:即一次训练所抓取的数据样本数量,更改之后有什么影响,built_model里面的参数的依据

  3. 现行代码accuracy很低,且predicted值在x值较大时全部为1,是代码 / model问题(多次model.predict除了y之外都相同)

  4. 神经网络的建立(完全无了解)

原代码

built_model

def built_model():
    model = Sequential()
    model.add(Dense(units=256,
                    input_dim=2,
                    activation='relu'))
    # input_length就是输入数据的长度,Input_dim就是数据的维度
    # https://www.jianshu.com/p/807936809af4
    # https://blog.csdn.net/weixin_46322028/article/details/110873992 dense参数参考
    # activation=None, #激活函数.但是默认 liner
    # https://long97.blog.csdn.net/article/details/107749268 激活函数的类型
    model.add(Dropout(0.5))
    # https://blog.csdn.net/yangwohenmai1/article/details/123346240 关于dropout
    model.add(Dense(units=128,
                    activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(units=1,
                    activation='sigmoid'))
    model.compile(loss='binary_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy'])
    model.summary()
    # https://blog.csdn.net/weixin_48207979/article/details/110855623 关于summary()
    return model
# https://blog.csdn.net/weixin_42499236/article/details/84624195

train_model

def train_model(batch_size=32, verbose=0, validation_split=0.2, model=None):
    # BATCH_SIZE:即一次训练所抓取的数据样本数量;
    # BATCH_SIZE的大小影响训练速度和模型优化。同时按照以上代码可知,其大小同样影响每一epoch训练模型次数。
    # verbose是日志显示,有三个参数可选择,分别为0,1和2。
    # 当verbose=0时,简单说就是不输出日志信息 ,进度条、loss、acc这些都不输出。
    # 当verbose=1时,带进度条的输出日志信息
    # 当verbose=2时,为每个epoch输出一行记录,和1的区别就是没有进度条
    # validation_split 的意思是将 data_dir 目录的所有图片的 百分之多少划分为验证集 。 这里设置为 0.2 表示,20% 为验证集,80% 为训练集

    data, labels = load_data()
    train_x, train_y = data[: int(len(data) * 0.7), 0: 2], labels[: int(len(labels) * 0.7)]
    # print(train_x,train_y)
    test_x, test_y = data[int(len(data) * 0.7): len(data), 0: 2], labels[int(len(labels) * 0.7): len(labels)]
    # print('=============')
    # print(test_x,test_y)
    if model is None:
        model = built_model()
        history = model.fit(train_x, train_y,
                            batch_size=batch_size,
                            epochs=10,                        # epoch:整数,训练终止时的epoch值,训练将在达到该epoch值时停止,当没有设置initial_epoch时,它就是训练的总轮数,否则训练的总轮数为epochs - inital_epoch

                            verbose=verbose,
                            validation_split=validation_split)# 用来指定训练集的一定比例数据作为验证集
        # print ("刻画损失函数的变化趋势")

        # plt.figure('f1')
        # plt.plot(history.history['loss'], label='train')
        # plt.plot(history.history['val_loss'], label='valid')
        # plt.legend()
        # plt.show()
        print ("模型构建成功,开始预测数据")

        score = model.evaluate(test_x, test_y,
                               batch_size=batch_size)

batch_size参数调整试验

https://www.zhihu.com/question/457626871

尝试16和64发现最终accuracy并不是设置batch=32时最高,而在使用SGD的情况下,GPU对2的整数次幂的batchsize表现更好,所以更换batch_size为其他2的整数幂进行尝试

batch_size=16epoch=20,summary:376/376 [==============================] - 2s 5ms/step - loss: 0.1809 - accuracy: 0.9008

batch_size=32,epoch=20,summary:188/188 [==============================] - 1s 4ms/step - loss: 0.2348 - accuracy: 0.8970

batch_size=64,94/94 [==============================] - 0s 4ms/step - loss: 0.2730 - accuracy: 0.9022

batch_size=128,47/47 [==============================] - 0s 4ms/step - loss: 0.3888 - accuracy: 0.7012

batch_size=8,751/751 [==============================] - 3s 4ms/step - loss: 0.0366 - accuracy: 1.0000

可以看到在2的整数幂情况下,幂越大模型运算速度越快,而只是因为好奇尝试跑的batch_size=8跑出了这串代码第一次1.0的accuracy
以下是使用batch_size=8模型所做的尝试

234
2022-11-15 18:29:02.997431: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:114] Plugin optimizer for device_type GPU is enabled.
234 4 0.99903727
偶数
235
235 5 0.07666259
奇数
2356
2356 6 0.9681723
偶数
53467
53467 7 0.024803855
奇数
1231245
1231245 5 1.0896908e-07
奇数
12312344
12312344 4 5.098695e-25
奇数
1231244
1231244 4 0.00010418004
奇数
123124
123124 4 0.99661297
偶数

依旧无法幸免大数的predict最终向0靠近

可以感知到,小batchsize导致代码运行过慢,过大batchsize会导致accuracy降低而可能收敛到一些不好的局部最优点

增加的output部分

while(1):
            x = int(input())
            if x == 0:
                print('finish')
                break
            else:
                y = np.array([x, x % 10])
                test_x[0] = y
                # 单独输出model.predict(y,batch_size=batch_size,verbose=0)会报错 unsolved
                predicted = model.predict(test_x,
                                          batch_size=batch_size,
                                          verbose=0)
                print(test_x[0], predicted[0][0])
                if (predicted[0][0] > 0.5):
                    print("偶数")
                else:
                    print("奇数")

增加的归一化 和 归一化还原部分

# load_data
seclar = pp.MinMaxScaler(feature_range=(0, 1))
    data = seclar.fit_transform(data)
    np.random.shuffle(data)
    data = np.array(data)
# model 
y = np.array([(x-1)/20000, (x % 10)/(10-1)])

现状:

  1. 1-100000(10num)accuracy尚可,100000后mod0-4基本正确其余错误,再变大数字会逐渐变成1/0(在前面改变batch_size时进一步尝试,界限并不严格是10num
  2. epoch为偶数时 最后大数predict为1,但是epoch为奇数时大数predict结果为0
  3. 更换模10(特征)到模3/模5 accuracy很低
  4. 更换模2到模3 accuracy很低,个人认为是阈值(threshold)划分问题

神经网络

另一个例子

https://blog.csdn.net/N2O_666/article/details/114299612

Requires

from numpy import array,exp,random,dot

创建数据

然后创建一个矩阵X,将小A、小B、小C三个人前五次的数据放到矩阵中去;创建一个装置矩阵y,将小D前五次的数据放到矩阵中去。注意矩阵X是3x5的,所以这里需要将1x5的矩阵y转置一下成5x1的矩阵,才能进行矩阵运算。

X = array([[0,1,0],[1,1,0],[1,0,1],[0,0,1],[0,1,1]])
y = array([[1,1,0,0,1]]).T

初始假设

下面利用随机数做一个假设,假设小D去不去爬山与小A、小B、小C三人去不去爬山的相关关系的数值(权重)为weights。

random.seed(1)
weights = 2 * random.random((3,1))-1

神经元计算

接下来进入循环,使用假设的weights算出output(output数值越接近“0”,代表小D去不去爬山的可能性越大,output数值越接近“1”,代表小D去爬山的可能性越大),前五次小D的数据y - 利用假设关系得到的output数值=得到误差 error,通过循环不断调整假设关系weights,减小误差,最终得到误差最小的一组关系系数weights。

for it in range(100000):
    output = 1/(1+exp(-dot(X,weights)))
    error = y - output
    delta = error * output *(1-output)
    weights += dot(X.T,delta)

使用纯numpy进行奇偶数预测(依旧增加模数特征) (todo)

伪代码大致为

X = data
y = label
# get the weight
for it in range(100000):
    output = 1/(1+exp(-dot(X,weights)))
    error = y - output
    delta = error * output *(1-output)
    weights += dot(X.T,delta)
num = input()
print("误差为:\n",error)
print("相关系数为:\n",weights)
climbing_probability = 1/(1+exp(-dot([[num,num%10]],weights)))
print("小D会去爬山的概率为(数字为奇数/偶数的概率是):\n",climbing_probability)

原神经网络解读(todo, Chap 5)

关于阈值(threshold)Chap 2.3.3

https://blog.csdn.net/weixin_39781323/article/details/110262035

https://blog.csdn.net/qq_38432089/article/details/120699953

  • TP: True Positives, 表示实际为正例且被分类器判定为正例的样本数
  • FP: False Positives, 表示实际为负例且被分类器判定为正例的样本数
  • FN: False Negatives, 表示实际为正例但被分类器判定为负例的样本数
  • TN: True Negatives, 表示实际为负例且被分类器判定为负例的样本数

ROC曲线

在分类任务中,测试部分通常是获得一个概率表示当前样本属于正例的概率, 我们往往会采取一个阈值,大于该阈值的为正例, 小于该阈值的为负例。 如果我们减小这个阈值, 那么会有更多的样本被识别为正类,这会提高正类的识别率,但同时会降低负类的识别率。

为了形象的描述上述的这种变化, 引入ROC曲线来评价一个分类器的好坏。 ROC 曲线主要关注两个指标:
其中, FPR 代表将负例错分为正例的概率, TPR 表示能将正例分对的概率, 如果我们增大阈值, 则 TPR 会增加,而对应的FPR也会增大, 而绘制ROC曲线能够帮助我们找到二者的均衡点。

image

AUC:Area under Curve

AUC 为ROC 曲线下的面积, 这个面积的数值介于0到1之间, 能够直观的评价出分类器的好坏, AUC的值越大, 分类器效果越好。

  • AUC = 1: 完美分类器, 采用该模型,不管设定什么阈值都能得出完美预测(绝大多数时候不存在)
  • 0.5 < AUC < 1: 优于随机猜测,分类器好好设定阈值的话,有预测价值
  • AUC = 0.5: 跟随机猜测一样,模型没有预测价值
  • AUC < 0.5 :比随机猜测还差,但是如果反着预测,就优于随机猜测。
posted @ 2022-11-15 14:23  noobwei  阅读(103)  评论(0编辑  收藏  举报