日子竟然晃晃悠悠已经来到了 2020 年。好久没有更新这个版块了。断断续续的终于看完了《Deep Learning with Python》。
稍微总结下吧。
定义问题:有什么可用的数据?要预测什么?需不需要收集更多信息或手动标记数据集?
确定可靠衡量目标成功的方法:对于简单的问题,可以是预测的准确性,而对于大多数问题来说,就需要复杂的特定指标数据(metric)来衡量。
准备用于评估模型的验证过程:你需要准备一个训练集、一个验证集和一个测试集。验证集和测试集的数据不能泄露到训练集中去。
向量化数据:对数据进行向量化和预处理以便其能被神经网络所使用。
开发第一个模型来证明机器学习模型能比基于常识的基准方法表现更好。
通过调整超参数并添加正则化来逐步优化模型架构:通过对验证集的表现来调整参数(不能使用测试集和训练集)。在添加正则化或缩小模型之前,先保证你的模型已经过拟合了。
注意在调整参数过程中的验证集的过拟合:你的参数可能会针对这个验证集被过于专门化(overspecialized),这也是需要一个独立的测试集的原因。
一个简单的输入模式与适当的网络架构之间的映射的概述:
密集连接网络由多个 Dense Layer 组成,用于处理向量化数据(vector data)。主要用于分类数据,以及大多数网络模型的最后的分类或回归阶段。
二元分类(binary classification):在最底层使用 Dense Layer,使用单个单元,sigmoid 激活函数(activation)和 binary_crossentropy 损失函数(loss)
from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(32, activation='relu', input_shape=(num_input_features,)))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy')
单标签分类(single-label categorical classification):在最底层使用 Dense Layer,单元数为分类类别数,softmax 激活函数(activation)和 categorical_crossentropy (one-hot encoded) sparse_categorical_crossentropy (integers) 损失函数(loss)
model = models.Sequential()
model.add(layers.Dense(32, activation='relu', input_shape=(num_input_features,)))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_classes, activation='softmax'))
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
多标签分类(multilabel categorical classification):在最底层使用 Dense Layer,单元数为分类类别数,sigmoid 激活函数(activation)和 binary_crossentropy (k-hot encoded) 损失函数(loss)
model = models.Sequential()
model.add(layers.Dense(32, activation='relu', input_shape=(num_input_features,)))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_classes, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy')
回归(regression):在最底层使用 Dense Layer,单元数为预测值的数量,没有激活函数(activation)和 mean_squared_error (MSE) 或 mean_absolute_error (MAE) 损失函数(loss)
model = models.Sequential()
model.add(layers.Dense(32, activation='relu', input_shape=(num_input_features,)))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_values))
model.compile(optimizer='rmsprop', loss='mse')
卷积神经网络可以处理不同维度的数据:1D (sequences), 2D (images), 3D (volumes)。可以使用 Conv1D 来处理序列(特别是文本),Conv2D 来处理图像,Conv3D 来处理声音。目前,传统的卷积方法将会被 Depthwise separable convolution (SeparableConv2D) 替代。
model = models.Sequential()
model.add(layers.SeparableConv2D(32, 3, activation='relu',
input_shape=(height, width, channels)))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.GlobalAveragePooling2D())
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_classes, activation='softmax'))
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
递归神经网络(RNN)的工作方式是一次处理一个时间步长的输入序列,并在整个过程中保持状态。在 Keras 中有三种 RNN 层:SimpleRNN, GRU, LSTM。GRU 和 LSTM 用的最多。LSTM 最为强大但比较耗时,GRU则是一个较为简单和快速的替代方法。
一层 RNN 处理二元分类向量化序列:
model = models.Sequential()
model.add(layers.LSTM(32, input_shape=(num_timesteps, num_features)))
model.add(layers.Dense(num_classes, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy')
多层 RNN 处理二元分类向量化序列:
model = models.Sequential()
model.add(layers.LSTM(32, return_sequences=True,
input_shape=(num_timesteps, num_features)))
model.add(layers.LSTM(32, return_sequences=True))
model.add(layers.LSTM(32))
model.add(layers.Dense(num_classes, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy')
arXiv - an open-access preprint server for physics, mathematics, and computer science research papers
Kaggle - machine-learning competitions
Given a non-empty array of digits representing a non-negative integer, plus one to the integer.
The digits are stored such that the most significant digit is at the head of the list, and each element in the array contain a single digit.
You may assume the integer does not contain any leading zero, except the number 0 itself.
Example 1:
Input: [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.
Example 1:
Input: [4,3,2,1]
Output: [4,3,2,2]
Explanation: The array represents the integer 4321.
func plusOne(digits []int) []int {
count := len(digits)
carry := true
for i := count - 1; i >= 0; i-- {
if carry {
if digits[i] == 9 {
digits[i] = 0
} else {
digits[i]++
carry = false
}
}
}
if carry && digits[0] == 0 {
digits = append([]int{1}, digits...)
}
return digits
}
最近尝试了下转换到 gin 框架,但遇到了一系列问题。这个方案暂时无法实施了。
问题是 gin 不支持递归导入 html template。貌似已经有 PR 在新增一个 LoadHTMLFilesRecursively 方法来支持了。#1296
另外有个问题是,不支持导入相同名字(但在不同目录下)的 html template (#321)。Workaround 是在 template 文件中定义 {{define NAME}},例如 {{ define "post/index.tmpl" }} 。但这也不是特别方便。
淘宝店终究还是关门了。2013年1月6日开业至今,正好是整整7年。接下来还是要整理整理,看看有什么新的业务点。