当前位置: 首页 > 编程日记 > 正文

深度学习与计算机视觉系列(9)_串一串神经网络之动手实现小例子

深度学习与计算机视觉系列(9)_串一串神经网络之动手实现小例子

作者:寒小阳 
时间:2016年1月。 
出处:http://blog.csdn.net/han_xiaoyang/article/details/50521072 
声明:版权所有,转载请联系作者并注明出处

1.引言

前面8小节,算从神经网络的结构、简单原理、数据准备与处理、神经元选择、损失函数选择等方面把神经网络过了一遍。这个部分我们打算把知识点串一串,动手实现一个简单的2维平面神经网络分类器,去分割平面上的不同类别样本点。为了循序渐进,我们打算先实现一个简单的线性分类器,然后再拓展到非线性的2层神经网络。我们可以看到简单的浅层神经网络,在这个例子上就能够有分割程度远高于线性分类器的效果。

2.样本数据的产生

为了凸显一下神经网络强大的空间分割能力,我们打算产生出一部分对于线性分类器不那么容易分割的样本点,比如说我们生成一份螺旋状分布的样本点,如下:

N = 100 # 每个类中的样本点
D = 2 # 维度
K = 3 # 类别个数 X = np.zeros((N*K,D)) # 样本input y = np.zeros(N*K, dtype='uint8') # 类别标签 for j in xrange(K): ix = range(N*j,N*(j+1)) r = np.linspace(0.0,1,N) # radius t = np.linspace(j*4,(j+1)*4,N) + np.random.randn(N)*0.2 # theta X[ix] = np.c_[r*np.sin(t), r*np.cos(t)] y[ix] = j # 可视化一下我们的样本点 plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.Spectral)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

得到如下的样本分布:


螺旋样本点集

紫色,红色和黄色分布代表不同的3种类别。

一般来说,拿到数据都要做预处理,包括之前提到的去均值和方差归一化。不过我们构造的数据幅度已经在-1到1之间了,所以这里不用做这个操作。

3.使用Softmax线性分类器

3.1 初始化参数

我们先在训练集上用softmax线性分类器试试。如我们在之前的章节提到的,我们这里用的softmax分类器,使用的是一个线性的得分函数/score function,使用的损失函数是交叉熵损失/cross-entropy loss。包含的参数包括得分函数里面用到的权重矩阵W和偏移量b,我们先随机初始化这些参数。

#随机初始化参数
import numpy as np
#D=2表示维度,K=3表示类别数
W = 0.01 * np.random.randn(D,K) b = np.zeros((1,K))

  • 1
  • 2
  • 3
  • 4
  • 5

  • 1
  • 2
  • 3
  • 4
  • 5

3.2 计算得分

线性的得分函数,将原始的数据映射到得分域非常简单,只是一个直接的矩阵乘法。

#使用得分函数计算得分
scores = np.dot(X, W) + b

  • 1
  • 2

  • 1
  • 2

在我们给的这个例子中,我们有2个2维点集,所以做完乘法过后,矩阵得分scores其实是一个[300*3]的矩阵,每一行都给出对应3各类别(紫,红,黄)的得分。

3.3 计算损失

然后我们就要开始使用我们的损失函数计算损失了,我们之前也提到过,损失函数计算出来的结果代表着预测结果和真实结果之间的吻合度,我们的目标是最小化这个结果。直观一点理解,我们希望对每个样本而言,对应正确类别的得分高于其他类别的得分,如果满足这个条件,那么损失函数计算的结果是一个比较低的值,如果判定的类别不是正确类别,则结果值会很高。我们之前提到了,softmax分类器里面,使用的损失函数是交叉熵损失。一起回忆一下,假设f是得分向量,那么我们的交叉熵损失是用如下的形式定义的:

Li=log⎛⎝efyijefj⎞⎠

直观地理解一下上述形式,就是Softmax分类器把类别得分向量f中每个值都看成对应三个类别的log似然概率。因此我们在求每个类别对应概率的时候,使用指数函数还原它,然后归一化。从上面形式里面大家也可以看得出来,得到的值总是在0到1之间的,因此从某种程度上说我们可以把它理解成概率。如果判定类别是错误类别,那么上述公式的结果就会趋于无穷,也就是说损失相当相当大,相反,如果判定类别正确,那么损失就接近log(1)=0。这和我们直观理解上要最小化损失是完全吻合的。

当然,当然,别忘了,完整的损失函数定义,一定会加上正则化项,也就是说,完整的损失L应该有如下的形式:

L=1NiLidata loss+12λklW2k,lregularization loss

好,我们实现以下,根据上面计算得到的得分scores,我们计算以下各个类别上的概率:

# 用指数函数还原
exp_scores = np.exp(scores)
# 归一化
probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)

  • 1
  • 2
  • 3
  • 4

  • 1
  • 2
  • 3
  • 4

在我们的例子中,我们最后得到了一个[300*3]的概率矩阵prob,其中每一行都包含属于3个类别的概率。然后我们就可以计算完整的互熵损失了:

#计算log概率和互熵损失
corect_logprobs = -np.log(probs[range(num_examples),y])
data_loss = np.sum(corect_logprobs)/num_examples
#加上正则化项
reg_loss = 0.5*reg*np.sum(W*W)
loss = data_loss + reg_loss

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

正则化强度λ在上述代码中是reg,最开始的时候我们可能会得到loss=1.1,是通过np.log(1.0/3)得到的(假定初始的时候属于3个类别的概率一样),我们现在想最小化损失loss

3.4 计算梯度与梯度回传

我们能够用损失函数评估预测值与真实值之间的差距,下一步要做的事情自然是最小化这个值。我们用传统的梯度下降来解决这个问题。多解释一句,梯度下降的过程是:我们先选取一组随机参数作为初始值,然后计算损失函数在这组参数上的梯度(负梯度的方向表明了损失函数减小的方向),接着我们朝着负梯度的方向迭代和更新参数,不断重复这个过程直至损失函数最小化。为了清楚一点说明这个问题,我们引入一个中间变量p,它是归一化后的概率向量,如下:

pk=efkjefjLi=log(pyi)

我们现在希望知道朝着哪个方向调整权重能够减小损失,也就是说,我们需要计算梯度Li/fk。损失Lip计算而来,再退一步,依赖于f。于是我们又要做高数题,使用链式求导法则了,不过梯度的结果倒是非常简单:

Lifk=pk1(yi=k)

解释一下,公式的最后一个部分表示yi=k的时候,取值为1。整个公式其实非常的优雅和简单。假设我们计算的概率p=[0.2, 0.3, 0.5],而中间的类别才是真实的结果类别。根据梯度求解公式,我们得到梯度df=[0.2,0.7,0.5]。我们想想梯度的含义,其实这个结果是可解释性非常高的:大家都知道,梯度是最快上升方向,我们减掉它乘以步长才会让损失函数值减小。第1项和第3项(其实就是不正确的类别项)梯度为正,表明增加它们只会让最后的损失/loss增大,而我们的目标是减小loss;中间的梯度项-0.7其实再告诉我们,增加这一项,能减小损失Li,达到我们最终的目的。

我们依旧记probs为所有样本属于各个类别的概率,记dscores为得分上的梯度,我们可以有以下的代码:

dscores = probs
dscores[range(num_examples),y] -= 1
dscores /= num_examples

  • 1
  • 2
  • 3

  • 1
  • 2
  • 3

我们计算的得分scores = np.dot(X, W)+b,因为上面已经算好了scores的梯度dscores,我们现在可以回传梯度计算W和b了:

dW = np.dot(X.T, dscores)
db = np.sum(dscores, axis=0, keepdims=True)
#得记着正则化梯度哈
dW += reg*W

  • 1
  • 2
  • 3
  • 4

  • 1
  • 2
  • 3
  • 4

我们通过矩阵的乘法得到梯度部分,权重W的部分加上了正则化项的梯度。因为我们在设定正则化项的时候用了系数0.5(因为ddw(12λw2)=λw),因此直接用reg*W就可以表示出正则化的梯度部分。

3.5 参数迭代与更新

在得到所需的所有部分之后,我们就可以进行参数更新了:

#参数迭代更新
W += -step_size * dW
b += -step_size * db

  • 1
  • 2
  • 3

  • 1
  • 2
  • 3

3.6 大杂合:训练SoftMax分类器

#代码部分组一起,训练线性分类器#随机初始化参数
W = 0.01 * np.random.randn(D,K)
b = np.zeros((1,K))#需要自己敲定的步长和正则化系数 step_size = 1e-0 reg = 1e-3 #正则化系数 #梯度下降迭代循环 num_examples = X.shape[0] for i in xrange(200): # 计算类别得分, 结果矩阵为[N x K] scores = np.dot(X, W) + b # 计算类别概率 exp_scores = np.exp(scores) probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True) # [N x K] # 计算损失loss(包括互熵损失和正则化部分) corect_logprobs = -np.log(probs[range(num_examples),y]) data_loss = np.sum(corect_logprobs)/num_examples reg_loss = 0.5*reg*np.sum(W*W) loss = data_loss + reg_loss if i % 10 == 0: print "iteration %d: loss %f" % (i, loss) # 计算得分上的梯度 dscores = probs dscores[range(num_examples),y] -= 1 dscores /= num_examples # 计算和回传梯度 dW = np.dot(X.T, dscores) db = np.sum(dscores, axis=0, keepdims=True) dW += reg*W # 正则化梯度 #参数更新 W += -step_size * dW b += -step_size * db

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

得到结果:

iteration 0: loss 1.096956
iteration 10: loss 0.917265
iteration 20: loss 0.851503 iteration 30: loss 0.822336 iteration 40: loss 0.807586 iteration 50: loss 0.799448 iteration 60: loss 0.794681 iteration 70: loss 0.791764 iteration 80: loss 0.789920 iteration 90: loss 0.788726 iteration 100: loss 0.787938 iteration 110: loss 0.787409 iteration 120: loss 0.787049 iteration 130: loss 0.786803 iteration 140: loss 0.786633 iteration 150: loss 0.786514 iteration 160: loss 0.786431 iteration 170: loss 0.786373 iteration 180: loss 0.786331 iteration 190: loss 0.786302

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

190次循环之后,结果大致收敛了。我们评估一下准确度:

#评估准确度
scores = np.dot(X, W) + b
predicted_class = np.argmax(scores, axis=1)
print 'training accuracy: %.2f' % (np.mean(predicted_class == y))

  • 1
  • 2
  • 3
  • 4

  • 1
  • 2
  • 3
  • 4

输出结果为49%。不太好,对吧?实际上也是可理解的,你想想,一份螺旋形的数据,你偏执地要用一个线性分类器去分割,不管怎么调整这个线性分类器,都非常非常困难。我们可视化一下数据看看决策边界(decision boundaries):


线性分类器与决策边界

4.使用神经网络分类

从刚才的例子里可以看出,一个线性分类器,在现在的数据集上效果并不好。我们知道神经网络可以做非线性的分割,那我们就试试神经网络,看看会不会有更好的效果。对于这样一个简单问题,我们用单隐藏层的神经网络就可以了,这样一个神经网络我们需要2层的权重和偏移量:

# 初始化参数
h = 100 # 隐层大小(神经元个数)
W = 0.01 * np.random.randn(D,h)
b = np.zeros((1,h)) W2 = 0.01 * np.random.randn(h,K) b2 = np.zeros((1,K))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

然后前向计算的过程也稍有一些变化:

#2层神经网络的前向计算
hidden_layer = np.maximum(0, np.dot(X, W) + b) # 用的 ReLU单元
scores = np.dot(hidden_layer, W2) + b2

  • 1
  • 2
  • 3

  • 1
  • 2
  • 3

注意到这里,和之前线性分类器中的得分计算相比,多了一行代码计算,我们首先计算第一层神经网络结果,然后作为第二层的输入,计算最后的结果。哦,对了,代码里大家也看的出来,我们这里使用的是ReLU神经单元。

其他的东西都没太大变化。我们依旧按照之前的方式去计算loss,然后计算梯度dscores。不过反向回传梯度的过程形式上也有一些小小的变化。我们看下面的代码,可能觉得和Softmax分类器里面看到的基本一样,但注意到我们用hidden_layer替换掉了之前的X:

# 梯度回传与反向传播
# 对W2和b2的第一次计算
dW2 = np.dot(hidden_layer.T, dscores)
db2 = np.sum(dscores, axis=0, keepdims=True)

  • 1
  • 2
  • 3
  • 4

  • 1
  • 2
  • 3
  • 4

恩,并没有完事啊,因为hidden_layer本身是一个包含其他参数和数据的函数,我们得计算一下它的梯度:

dhidden = np.dot(dscores, W2.T)

  • 1

  • 1

现在我们有隐层输出的梯度了,下一步我们要反向传播到ReLU神经元了。不过这个计算非常简单,因为r=max(0,x),同时我们又有drdx=1(x>0)。用链式法则串起来后,我们可以看到,回传的梯度大于0的时候,经过ReLU之后,保持原样;如果小于0,那本次回传就到此结束了。因此,我们这一部分非常简单:

#梯度回传经过ReLU
dhidden[hidden_layer <= 0] = 0

  • 1
  • 2

  • 1
  • 2

终于,翻山越岭,回到第一层,拿到总的权重和偏移量的梯度:

dW = np.dot(X.T, dhidden)
db = np.sum(dhidden, axis=0, keepdims=True)

  • 1
  • 2

  • 1
  • 2

来,来,来。组一组,我们把整个神经网络的过程串起来:

# 随机初始化参数
h = 100 # 隐层大小
W = 0.01 * np.random.randn(D,h)
b = np.zeros((1,h)) W2 = 0.01 * np.random.randn(h,K) b2 = np.zeros((1,K)) # 手动敲定的几个参数 step_size = 1e-0 reg = 1e-3 # 正则化参数 # 梯度迭代与循环 num_examples = X.shape[0] for i in xrange(10000): hidden_layer = np.maximum(0, np.dot(X, W) + b) #使用的ReLU神经元 scores = np.dot(hidden_layer, W2) + b2 # 计算类别概率 exp_scores = np.exp(scores) probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True) # [N x K] # 计算互熵损失与正则化项 corect_logprobs = -np.log(probs[range(num_examples),y]) data_loss = np.sum(corect_logprobs)/num_examples reg_loss = 0.5*reg*np.sum(W*W) + 0.5*reg*np.sum(W2*W2) loss = data_loss + reg_loss if i % 1000 == 0: print "iteration %d: loss %f" % (i, loss) # 计算梯度 dscores = probs dscores[range(num_examples),y] -= 1 dscores /= num_examples # 梯度回传 dW2 = np.dot(hidden_layer.T, dscores) db2 = np.sum(dscores, axis=0, keepdims=True) dhidden = np.dot(dscores, W2.T) dhidden[hidden_layer <= 0] = 0 # 拿到最后W,b上的梯度 dW = np.dot(X.T, dhidden) db = np.sum(dhidden, axis=0, keepdims=True) # 加上正则化梯度部分 dW2 += reg * W2 dW += reg * W # 参数迭代与更新 W += -step_size * dW b += -step_size * db W2 += -step_size * dW2 b2 += -step_size * db2

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

输出结果:

iteration 0: loss 1.098744
iteration 1000: loss 0.294946
iteration 2000: loss 0.259301 iteration 3000: loss 0.248310 iteration 4000: loss 0.246170 iteration 5000: loss 0.245649 iteration 6000: loss 0.245491 iteration 7000: loss 0.245400 iteration 8000: loss 0.245335 iteration 9000: loss 0.245292

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

现在的训练准确度为:

#计算分类准确度
hidden_layer = np.maximum(0, np.dot(X, W) + b)
scores = np.dot(hidden_layer, W2) + b2
predicted_class = np.argmax(scores, axis=1)
print 'training accuracy: %.2f' % (np.mean(predicted_class == y))

  • 1
  • 2
  • 3
  • 4
  • 5

  • 1
  • 2
  • 3
  • 4
  • 5

你猜怎么着,准确度为98%,我们可视化一下数据和现在的决策边界:


神经网络决策边界

看起来效果比之前好多了,这充分地印证了我们在手把手入门神经网络系列(1)_从初等数学的角度初探神经网络中提到的,神经网络对于空间强大的分割能力,对于非线性的不规则图形,能有很强的划分区域和区分类别能力。

参考资料与原文

cs231n 神经网络小例子

相关文章:

虚拟主机上用Asp.net实现Urlrewrite

在网上看到&#xff0c;很多朋友在asp.net中做urlrewrite&#xff0c;用的是HttpHandle&#xff0b;Server.Transfer的方法。其实这种方法是错误的。第一&#xff0c;HttpHandle是实现不了urlrewrite的&#xff1b;第二Server.Transfer是标准的重定向&#xff0c;根本不是urlre…

String spilt时转义特殊字符【转】

在使用String.split方法分隔字符串时&#xff0c;分隔符如果用到一些特殊字符&#xff0c;可能会得不到我们预期的结果。 我们经常使用public String[] split(String regex)方法来拆分一个有分隔符的字符串&#xff0c;但是由于参数regex是一个 regular-expression的匹配模式而…

融合AI与大数据技术,腾讯教育发布智能作业灯

3月2日&#xff0c;腾讯教育新品发布会在深圳举行&#xff0c;发布会上&#xff0c;腾讯教育联合暗物智能正式对外发布了AILA智能作业灯&#xff0c;并与华东师范大学出版社、宏途教育、众诚智学教育、江西软云科技等教育行业合作伙伴签订战略合作协议&#xff0c;共同打造智慧…

【踩坑记录】记一次MySQL主从复制延迟的坑

最近开发中遇到的一个MySQL主从延迟的坑&#xff0c;记录并总结&#xff0c;避免再次犯同样的错误。 情景 一个活动信息需要审批&#xff0c;审批之后才能生效。因为之后活动要编辑&#xff0c;编辑后也可能触发审批&#xff0c;审批中展示的是编辑前的活动内容&#xff0c;考虑…

ASP.NET 应用中大文件上传研究

在项目中经常要用到了大文件上传&#xff0c;要上传的文件有100多m&#xff0c;于是研究现在国内使用的大文件上传的组件发现用的比较多的有两个控件AspnetUpload 2.0和Lion.Web.UpLoadModule&#xff0c;两个控件的方法是&#xff1a;利用隐含的HttpWorkerRequest&#xff0c;…

哪家互联网公司涨薪最厉害?居然不是阿里腾讯

最近脉脉职言区有一条讨论火了&#xff1a;哪家互联网公司涨薪最厉害&#xff1f;按照拼多多员工的说法&#xff0c;应届毕业生可以拿比腾讯阿里高30%的薪资&#xff0c;而有工作经验的员工普遍薪资水平也高出业内30%~50%以上。而且在去年由于疫情众多企业降薪、甚至裁员的状况…

如何修改 远程桌面的 默认端口号 3389

修改注册表的以下位置的键值&#xff1a; [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp]"PortNumber"dword:00000d3d

Yolov11-detect训练自己的数据集

至此,整个YOLOv11的训练预测阶段完成,与YOLOv8差不多。欢迎各位批评指正。

联通和阿里云合作 建互联网云化卡号管理系统

1月17日晚间消息&#xff0c;继去年11月中国联通与阿里巴巴签订战略合作框架协议之后&#xff0c;今天下午阿里云宣布将于中国联通建卡号管理系统“cBSS2.0集中号卡系统”。据了解&#xff0c;这将是电信行业第一个核心业务系统云化改造的重点工程&#xff0c;也是云计算技术在…

如何最大限度提高.NET的性能

优化 .NET的性能 1&#xff09;避免使用ArrayList。 因为任何对象添加到ArrayList都要封箱为System.Object类型&#xff0c;从ArrayList取出数据时&#xff0c;要拆箱回实际的类型。建议使用自定义的集合类型代替ArrayList。.net 2.0提供了一个新的类型&#xff0c;叫泛型…

别找了,Thonny 才是 Python 小白的最理想的 IDE

来源 | Python编程时光作者 | 写代码的明哥头图 | 下载于视觉中国当你在搜索引擎&#xff08;如百度&#xff09;或者各种问答社区&#xff08;如知乎&#xff09;搜索『学习Python 最好的 IDE/编辑器是哪个&#xff1f;』的时候&#xff0c;我想答案肯定是&#xff1a;PyCharm…

图书抄袭何时休,技术人的版权在哪里?

今天&#xff0c;一个很偶然的机会&#xff0c;看到了一本北京邮电大学出版社出版的技术图书《Linux服务器架设、性能调优、集群管理教程——实训与项目案例》&#xff0c;感觉有种似曾相识的感觉&#xff0c;于是打开目录大概了解了下&#xff0c;一个我不想看到的现象发生了&…

让MySql支持表情符号(MySQL中4字节utf8字符保存方法)

UTF-8编码有可能是两个、三个、四个字节。Emoji表情是4个字节&#xff0c;而MySQL的utf8编码最多3个字节&#xff0c;所以数据插不进去。解决方案&#xff1a;将编码从utf8转换成utf8mb4。 1. 修改my.ini [mysqld] character-set-serverutf8mb4 2. 在Connector/J的连接参数中&a…

短信编码类无错版PDUdecoding.cs

////程 序 员&#xff1a;武志文(蚕蛹)/// sillnet163.net///文 件&#xff1a;PDUdecoding.cs///概 要&#xff1a;针对国内短信编码&#xff08;USC2&#xff09;///组成结构&#xff1a;包含四个函数&#xff1a;/// smsDecodedCenterNumber(string…

你还有学了三年建模的朋友吗?他有救了

【 编者按】“我朋友学了 3 年建模”系列&#xff0c;一直以浮夸的操作占据于各大视频网站搞笑榜。此前&#xff0c;来自布拉格捷克理工大学、 Google 研究院、和华盛顿大学以及苏黎世联邦理工学院的研究者们发布了 Monster Mash 项目的论文和动效视频。用户绘制二维图像&#…

iOS培训objective-c——实例化对象

蓝鸥iOS培训推荐&#xff1a;好像好长时间没和大家分享了&#xff0c;那么今天主要和大家说说OC内容创建实例化对象&#xff0c;基本让也就分为几大类&#xff1a;1.ClassName*myNewClassName;//指针2.myNewClassName[ClassNamealloc];//通过alloc这个命令申请一个空间来存放我…

#423 Div2 D

#423 Div2 D 题意 构造一个 n 个节点的树&#xff0c;恰好有 k 个叶子节点 (叶子节点的定义是只与树上的某一个节点存在连边)&#xff0c;要求任意两个叶子节点的距离的最大值最小&#xff0c;距离为两个节点间边的数量&#xff0c;输出距离的最大值&#xff0c;以及 n - 1 条边…

CDMA模块上网设置的过程

CDMA模块上网设置的过程一&#xff09; AT指令设置部分&#xff08;1&#xff09; ATCSQ 检查信号 若返回10—31&#xff0c;99之间的信号数字则继续&#xff0c;如果信号是99&#xff0c;99&#xff0c;则应该考虑不停的键入A/命令&#xff0c;不停的让模块去搜寻网络。&…

RedHat 年度报告:只索取不贡献的开源消费“大户”不受待见

编译 | 清儿爸编辑 | 夕颜头图 | 下载于视觉中国据 Red Hat 公司委托发布的一份新报告称&#xff0c;新冠疫情可能在云计算基础设施和企业开源软件方面留下不可磨灭的印记。Red Hat 是 IBM 于 2018 年以 340 亿美元收购的企业开源软件产品供应商。第三次年度《企业开源现状》&a…

做产品的一些思考

从我当前的职业经历来看&#xff0c;做过两种类别的产品&#xff1a;一种是客户定义好了需求由我们去实现&#xff0c;我姑且称其为做项目&#xff1b;一种是自己去探索用户需求然后在不断的摸索中引导用户&#xff0c;实现价值&#xff0c;这是我笔下真正的产品。做项目目标明…

查看JDK的历史版本

1.打开如下链接http://www.oracle.com/technetwork/java/javase/downloads/index.html2.查找如下内容,点击进行3.选择你需要的版本,点击进入4.找到相应的版本下载即可转载于:https://blog.51cto.com/suyanzhu/1947530

终于有人解救Python人了!

从事Python开发的这些年中&#xff0c;我见过很多相关的入门教程和书籍&#xff0c;他们大都这样讲 &#xff1a;先介绍 Python 的基本语法规则、list、dict、tuple 等数据结构&#xff0c;然后再介绍字符串处理和正则表达式&#xff0c;介绍文件等IO操作.... 就这样一点一点往…

WISMO模块GPRS上网设置的过程

WISMO模块GPRS上网设置的过程一&#xff09; AT指令设置部分&#xff08;1&#xff09; ATCGCLASS“B”置为“B”模式。&#xff08;2&#xff09; ATCGDCONT1&#xff0c;“IP”&#xff0c;“CMNET”设置APN。&#xff08;3&#xff09; ATCSQ 检查信号 若返回10—31&#x…

【虚拟化实战】VM设计之一vCPU

作者&#xff1a;范军 &#xff08;Frank Fan&#xff09; 新浪微博&#xff1a;frankfan7虚拟机需要多少个vCPU呢&#xff1f;是不是个数越多性能越好呢&#xff1f;这方面存在着很多误区。给VM配置CPU资源的时候&#xff0c;要精打细算才能最大可能的利用已有资源&#xff0c…

新手小白 python之路 Day1 (三级菜单功能实现)

直接上需求: 实现一个多级菜单 三级菜单的实现 可以依次选择进入各个子菜单 也可以返回上级菜单 所需知识 列表 字典 需求也比较简单&#xff0c;但实际上做起来还是遇到许多的问题&#xff0c;我这边主要用到的知识点大概就是 字典 等 大致的思路 我…

简要AT命令介绍

FUNCTIONSAT COMMANDSDETAILS厂家认证ATCGMI获得厂家的标识模式认证ATCGMM查询支持频段修订认证ATCGMR查询软件版本生产序号ATCGSN查询IMEI NO.TE设置ATCSCS选择支持网络查询IMSIATCIMI查询国际移动电话支持认证卡的认证ATCCID查询SIM卡的序列号功能列表ATGCAP查询可供使用的功…

CentOS 5.6下创建KVM虚拟机

【51CTO专家投稿】RedHat 的下一代旗舰产品RedHat Enterprise Linux 6只包含 KVM&#xff0c;这一点 RedHat 官方已经在很久以前、在不同场合都确认过。KVM 发展很快&#xff0c;稳定性有了很大提高&#xff0c;随着 RHEL 6 的正式到来&#xff0c;KVM 应用到生产环境的日子应该…

手把手教你如何制作可视化大屏!

在我们生活和工作中&#xff0c;经常会看到可视化大屏&#xff0c;主要用于展示一些汇总信息&#xff0c;那如何制作一个酷炫的可视化大屏呢&#xff1f;今天带大家看个github上的案例。项目地址&#xff1a;https://github.com/yyhsong/iDataV/tree/master/case09效果如下&…

ES5和ES6数组遍历方法详解

ES5和ES6数组遍历方法详解 在ES5中常用的10种数组遍历方法: 1、原始的for循环语句2、Array.prototype.forEach数组对象内置方法3、Array.prototype.map数组对象内置方法4、Array.prototype.filter数组对象内置方法5、Array.prototype.reduce数组对象内置方法6、Array.prototype…

短信猫GSM Modem

短信猫是用来收发短信的设备&#xff0c;和手机一样 插入SIM卡&#xff0c;通过&#xff08;USB或串口&#xff09;数据线/PCI插槽接到电脑上 在电脑上通过相关软件就可以实现短信收发的功能相关软件也就是收发短信的短信应用软件 可以自己开发&#xff0c;也可以要求短信猫设备…