三、分类问题

本文记录了对minist数据集进行分类的学习过程,包括手写和框架实现,同时分享了作者在找算法实习岗位时的面试经历,涉及基础深度学习知识和技术面试的体验。

三、分类问题

内容参考来自https://github.com/dragen1860/Deep-Learning-with-TensorFlow-book开源书籍《TensorFlow2深度学习》,这只是我做的简单的学习笔记,方便以后复习。

1.加载minist数据集

import os
import tensorflow as tf # 导入 TF 库
from tensorflow import keras # 导入 TF 子库 keras
from tensorflow.keras import layers, optimizers, datasets # 导入 TF 子库等
(x, y), (x_val, y_val) = datasets.mnist.load_data() # 加载 MNIST 数据集
x = 2*tf.convert_to_tensor(x, dtype=tf.float32)/255.-1 # 转换为浮点张量,并缩放到-1~1
y = tf.convert_to_tensor(y, dtype=tf.int32) # 转换为整形张量
y = tf.one_hot(y, depth=10) # one-hot 编码
print(x.shape, y.shape)
train_dataset = tf.data.Dataset.from_tensor_slices((x, y)) # 构建数据集对象
train_dataset = train_dataset.batch(512) # 批量训练

2. minist数据集分类,手写实现

import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import matplotlib
from matplotlib import pyplot as plt

# Default parameters for plots
matplotlib.rcParams['font.size'] = 20
matplotlib.rcParams['figure.titlesize'] = 20
matplotlib.rcParams['figure.figsize'] = [9, 7]
matplotlib.rcParams['font.family'] = ['STKaiTi']
matplotlib.rcParams['axes.unicode_minus'] = False

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import datasets

# x: [60k, 28, 28],
# y: [60k]
(x, y), _ = datasets.mnist.load_data()
# x: [0~255] => [0~1.]
x = tf.convert_to_tensor(x, dtype=tf.float32) / 255.
y = tf.convert_to_tensor(y, dtype=tf.int32)

print(x.shape, y.shape, x.dtype, y.dtype)
print(tf.reduce_min(x), tf.reduce_max(x))
print(tf.reduce_min(y), tf.reduce_max(y))

train_db = tf.data.Dataset.from_tensor_slices((x, y)).batch(128)
train_iter = iter(train_db)
sample = next(train_iter)
print('batch:', sample[0].shape, sample[1].shape)

# [b, 784] => [b, 256] => [b, 128] => [b, 10]
# [dim_in, dim_out], [dim_out]
w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))
b1 = tf.Variable(tf.zeros([256]))
w2 = tf.Variable(tf.random.truncated_normal([256, 128], stddev=0.1))
b2 = tf.Variable(tf.zeros([128]))
w3 = tf.Variable(tf.random.truncated_normal([128, 10], stddev=0.1))
b3 = tf.Variable(tf.zeros([10]))

lr = 1e-3

losses = []

for epoch in range(20):  # iterate db for 20
    for step, (x, y) in enumerate(train_db):  # for every batch
        # x:[128, 28, 28]
        # y: [128]

        # [b, 28, 28] => [b, 28*28]
        x = tf.reshape(x, [-1, 28 * 28])

        with tf.GradientTape() as tape:  # tf.Variable
            # x: [b, 28*28]
            # h1 = x@w1 + b1
            # [b, 784]@[784, 256] + [256] => [b, 256] + [256] => [b, 256] + [b, 256]
            h1 = x @ w1 + tf.broadcast_to(b1, [x.shape[0], 256])
            h1 = tf.nn.relu(h1)
            # [b, 256] => [b, 128]
            h2 = h1 @ w2 + b2
            h2 = tf.nn.relu(h2)
            # [b, 128] => [b, 10]
            out = h2 @ w3 + b3

            # compute loss
            # out: [b, 10]
            # y: [b] => [b, 10]
            y_onehot = tf.one_hot(y, depth=10)

            # mse = mean(sum(y-out)^2)
            # [b, 10]
            loss = tf.square(y_onehot - out)
            # mean: scalar
            loss = tf.reduce_mean(loss)

        # compute gradients
        grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])
        # print(grads)
        # w1 = w1 - lr * w1_grad
        w1.assign_sub(lr * grads[0])
        b1.assign_sub(lr * grads[1])
        w2.assign_sub(lr * grads[2])
        b2.assign_sub(lr * grads[3])
        w3.assign_sub(lr * grads[4])
        b3.assign_sub(lr * grads[5])

        if step % 100 == 0:
            print(epoch, step, 'loss:', float(loss))

    losses.append(float(loss))

plt.figure()
plt.plot(losses, color='C0', marker='s', label='loss')
plt.xlabel('Epoch')
plt.legend()
plt.ylabel('MSE')
# plt.savefig('forward.svg')
plt.show()

在这里插入图片描述

3. minist数据集分类,框架实现

import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import matplotlib
from matplotlib import pyplot as plt

# Default parameters for plots
matplotlib.rcParams['font.size'] = 20
matplotlib.rcParams['figure.titlesize'] = 20
matplotlib.rcParams['figure.figsize'] = [9, 7]
matplotlib.rcParams['font.family'] = ['STKaiTi']
matplotlib.rcParams['axes.unicode_minus'] = False
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, optimizers, datasets

(x, y), (x_val, y_val) = datasets.mnist.load_data()
x = tf.convert_to_tensor(x, dtype=tf.float32) / 255.
y = tf.convert_to_tensor(y, dtype=tf.int32)
y = tf.one_hot(y, depth=10)
print(x.shape, y.shape)
train_dataset = tf.data.Dataset.from_tensor_slices((x, y))
train_dataset = train_dataset.batch(200)

val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val)).batch(200)

model = keras.Sequential([
    layers.Dense(512, activation='relu'),
    layers.Dense(256, activation='relu'),
    layers.Dense(10)])

optimizer = optimizers.SGD(learning_rate=0.001)

losses = []
accs = []


def train_epoch(epoch):
    # Step4.loop
    for step, (x, y) in enumerate(train_dataset):

        with tf.GradientTape() as tape:
            # [b, 28, 28] => [b, 784]
            x = tf.reshape(x, (-1, 28 * 28))
            # Step1. compute output
            # [b, 784] => [b, 10]
            out = model(x)
            # Step2. compute loss
            loss = tf.reduce_sum(tf.square(out - y)) / x.shape[0]

        # Step3. optimize and update w1, w2, w3, b1, b2, b3
        grads = tape.gradient(loss, model.trainable_variables)
        # w' = w - lr * grad
        optimizer.apply_gradients(zip(grads, model.trainable_variables))

        if step % 100 == 0:
            print(epoch, step, 'loss:', loss.numpy())
    losses.append(loss)

    acc = 0
    for step, (x, y) in enumerate(val_dataset):
        # [b, 28, 28] => [b, 784]
        x = tf.reshape(x, (-1, 28 * 28))
        # [b, 784] => [b, 10]
        out = model(x)
        y_ = np.argmax(out, axis=1)
        right_eatch = np.sum(np.array(y_) == y)
        acc = right_eatch / x.shape[0]
        tf.reduce_mean(acc)
    accs.append(acc)


def train():
    for epoch in range(15):
        train_epoch(epoch)

    plt.figure()
    plt.plot(losses, color='r', marker='s', label='loss')
    plt.plot(accs, color='b', marker='s', label='acc')
    plt.xlabel('Epoch')
    plt.legend()
    plt.ylabel('MSE')
    # plt.savefig('forward.svg')
    plt.show()


if __name__ == '__main__':
    train()

在这里插入图片描述

这两节内容有点少,我看书上的内容也不多,总结起来能看的就更少了,不过等到从卷积神经网络开始,可以写的东西应该就非常多了。

4. 题外话和闲聊

题外话:说说我这几天都在干啥,从上周开始我就打算在拉钩上投投算法的实习岗试试,看看能不能找到比较好的实习岗,如果能找到我就去实习了,想着不用返校也挺爽的,哈哈。但是想法很丰满,现实很骨感。目前大概投了三十多家公司(招算法实习岗的本来就不多),收到面试邀请的公司就三家,我下面分别来聊一聊这三次面试。

​ 第一家公司是15人左右的小公司,8月13号在腾讯会议上面试的,面试我的人应该是一个技术人员,说公司在清华傍边,是一个清华的老板开的公司,现在有个项目主要做三维重建(虽然在学校学过,但是老师讲的很浅,我啥也不会),问了我一些基础的深度学习的知识,还有在研一期间学过的课程,还问我会linux不?(这个当然会了,虽然本科不是科班出身,但是学校开过这门课程,当然只是略懂皮毛,即简单的操作,而且以前也认证看完了马哥的linux基础篇)说要在linux上搭建神经网络,要求会基本的linux的操作,总之技术方面问的很简单。之后还说了实习的待遇,北京实习一天200,如果按照一个月大概能上22天班的,一个月就4k左右,我想在北京租房、吃饭、加交通费,可能得倒贴钱,所以就不想去了,第二天我就回绝了,hr问我不想去的原因,我就直接说工资太低了,在北京生活困难,她问我的期望实习薪资是多少,我回答了每个月6k,算下来一天270,hr问了他们领导说太高了,让我找找其它的公司,不过会把岗位给我留到下周一(8月23),我其实还挺感谢这家公司的,有公司愿意收留我这个菜鸟,还感觉挺不错的。

​ 第二家公司是在拉钩招聘的软件上面试的(我第一次知道在拉钩上还能面试,原谅我的无知),这次的面试就比较正规了,感觉比第一家在流程上要严肃很多,直接是一个技术面试我的,开始先让我自我介绍,问了一些机器学习和深度学习的基础知识,我老实的回答了我所知道的,我说好多都是我从视频和书上学到的知识,只了解皮毛,人家就笑了,感觉面试官很和蔼。面试结束之后给了我三道python的编程测试题,让我写完发给他,三道题就第二道题有关用python表示链表,并且做反转操作,我感觉有点麻烦,其它的两道题都很简单。总之给他发完消息之后就没有结果了,估计是凉了。。哈哈,终究我还是太菜了。

​ 第三家公司是北京的***(考虑再三,不说公司名了),hr给我说公司比较大,是上市的国企,我面试的还是机器学习和深度学习的开发岗。面试的时候是有两个人,一个是技术,一个非技术(具体我也不知道他是啥,只问了我能实习多长时间,啥时候能到,就是一些生活的事,应该不是hr,因为hr另有其人)。具体说说有关技术面吧,这次的技术面有点尴尬,好多我都不知道怎么回答(可能还是我太菜了),他问了我深度学习项目开发的流程是什么?什么是分类,什么是回归?反向传播中梯度下降算法有哪些(我回答了我最常见到的SGD和Adam,其他我真的忘了)?因为我的简历上有j两年的java开发经历,所有还问了我接触到的java框架,我直接说我不会spring cloud的一套,没咋接触过,不过真有需要往里面套东西的话,我应该还是可以的,之后他又问了我java中的Map,让我说一下具体说一下Map,这个我有点蒙,以前一直在用,你让我说一下,我还真不会(好吧,我还是很菜)。早上面试完,下午hr给我说我面试通过了,我还有点窃喜,晚上和毕业不久的同一个实验室的学长聊了一会,说了我的这次面试,说我有可能来北京了,哈哈,学长还是一如既往的很好,如有需要让我把东西先寄到他那边,等开始实习的时候再去取(开心)。晚上我详细的搜了一下这家公司,结果和我想的有很大的反转(好多说是外包公司,加班多,没有加班费…尴尬),有太多人吐槽这家公司了,顿时心里没底了,有点迷茫了,最后去不去这家公司我现在还真没底,明天再打听打听,再做决定(有两个北京好朋友劝我别急,再找找)。哈哈,如果你之后还能看到我写的有关深度学习的笔记没断的话,那就证明我没有去(尴尬)。

结束语:匆匆的研一生活已经离我而去了,因为疫情的原因,开学又推迟了,我现在还待在家里,每天看看深度学习的知识,做做笔记也挺好,争取打好扎实的基础,以后能有机会去大厂实习(这个不强求,随缘,尽力就好)。关于我写笔记的原因是,我首先想做一些笔记方便以后自己复习和使用,接着就是和大家一起分享我学到的知识。前人栽树,后人乘凉,我之前遇到的好多不会的,解决不了的问题也是通过别人的经验贴解决的,所有我希望我写的东西除了助我巩固知识之外,还能帮到大家,这是我目前的想法。我没有啥好的项目可以在github上开源,和大家一起分享,希望以后有机会能做到这点。愿我们共同成长!(笑脸)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coder_jyz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值