一緒に書く習慣を身につけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して18日目です。クリックしてイベントの詳細をご覧ください。
序文
ロジスティック回帰は何ができますか?
始める前に、ロジスティック回帰で何ができるかを明確にしましょう。まず、これは最急降下法を使用して修正します。プロセス全体、ロジスティック回帰のプロセスは、小さなニューラルネットワークに似ています。このようなものは、主に二項分類の問題に使用されます。
関連する理論については、以下を参照してください。ロジスティック回帰モデルの詳細(ロジスティック回帰)ここでは、理論的な調査はあまり行いません。
判断基準
ここでの言葉は主に実際の戦闘に基づいています。ニューラルネットワークのワークフローを示すために、超単純なロジスティック回帰ドームを手でプレイする方法。このインスピレーションは今でもこの兄貴から来ています:BoyC(Old Scroll King:私は他の誰かの冷酷な老人を虐殺するよりも倦怠感で死にたいです!!!)
1つ目は損失関数です。このように長い。
ここで、y ^は予測値、yは実際の値です。これは2つのクラスの問題であるため、0ラベルの損失をフィッティングして計算する場合、損失値は1に近いほど良いです。1ラベルをフィッティングする場合は、0に近いほど良いので、全体的な損失が大きくなります。値が大きいほど、0.5に近いほど良いです。これは主に彼らの理論から導き出されたものであり、私がここで直接述べた結論です。
次に、予測機能があります。
今日のブログ投稿では、単純な二項分類を行っています。10セットのデータがあります。最後の効果を見てみましょう。
もちろん、ここでは、私の損失計算はまだ少し問題があります。一般的にこのように、後で最適化を検討できます。
この場合の転送機能は、より適切にはネットワーク機能と呼ばれ、このようになります。
def Net(X):
X = X.T * W
X = np.sum(X) +B
X = sigmod(X)
if(X>=1):
X = X-0.0001
elif(X<=0):
X = X + 0.0001
return X
复制代码
ここで+-0.0001の理由は、ここでのsigmod処理の後、特定の値が1または0に非常に近い場合、1または0と見なされるためですが、これは許可されていません。特別にしか扱えません。そうすると、ネットワーク構造全体は次のようになります。だから、なぜそのネット関数がこのようになっているのかがわかります。
データセット
ドームでは、データセットは次のようになります。
X_train = np.linspace(1,20,20).reshape((10,2))
classes = ["小猫","小狗"]
Labels = {"小猫":0,"小狗":1}
Y_train = np.array([Labels["小猫"],Labels["小狗"]])
复制代码
トレーニング戦略
之后咱们来说说咱们的这个训练策略。 首先,咱们的这个数据是一行一行输入进去的,前5组属于0标签,后5组属于1标签。之后,为了模拟这个神经网络的batch_size 所以,我这里还干脆在每一轮训练的时候,每进去5组,5组计算完了之后,我再去进行梯度下降,更新权重,每一次计算,我先把所有的梯度加起来,然后后面求平均值然后去更新。(我们现在模拟的是非常简答的网络结构,对于复杂的,我们就需要单独记录梯度然后去更新,这样如果每进去一组我就更新梯度的话是会浪费很多时间的)
梯度更新
这里的话通过求导,我们最后可以发现这个 W1 的 梯度会等于 (当前预测值-实际值)* 当前对于的X1 然后,这里的话,我们既然使用了矩阵,那么我这里更新的时候,直接使用矩阵更新。
同样的,这个B 的话,就是直接 等于 (当前预测值-实际值) 由于我们 是 5 轮 更新一次嘛,所以都要先求个总和然后取平均值。
编码
前面都说的差不多了,那么我们就可以直接进行编码了。 这里由于使用的是梯度下降法,所以的话,我们这里的学习率就是Lr取0.00025 为什么取那么小,因为这个范围0-1本来就很小,参数变化很敏感,梯度下降嘛,容易出现那么几种情况,要么步子太大了过去了,要么就步子太小在局部出不来了,所以那个Lr其实是不太好设置的,在我们实际使用Pytroch的时候,其实我们使用的优化器的那个Lr是动态更新的。但是咱们这里模拟就不搞那么多花里胡哨的了。而且这个我们这里是100轮训练,那个Lr还是我自己调出来的,实际上做的时候,那个参数是作为超参数自适应的。
import numpy as np
import math
X_train = np.linspace(1,20,20).reshape((10,2))
classes = ["小猫","小狗"]
Labels = {"小猫":0,"小狗":1}
Y_train = np.array([Labels["小猫"],Labels["小狗"]])
W = np.random.randint(0,1,(2,1))
#划分,2个特征决定0,1,一共十组,这十组前五组为0,后五组为1
#对1类的拟合,是越接近0越好,对于0类的拟合是越接近1越好,
# 对于损失函数,也就是说,总体的损失函数是越接近0.5越好
B = 0
m = 5
def sigmod(X):
return 1/(1+np.exp(-X))
def com_grad(X,Y_,Y_T):
#返回的是一个
# w1
# { } 的向量
# w2
W_ = (X.T)*(Y_ - Y_T)
#计算梯度
return W_
def Net(X):
X = X.T * W
X = np.sum(X) +B
X = sigmod(X)
if(X>=1):
X = X-0.0001
elif(X<=0):
X = X + 0.0001
return X
def loss(pred,Y_t):
loss_ = -Y_t * math.log(pred) - (1-Y_t)*math.log(1-pred)
return loss_
ecpho = 100
Lr = 0.000025
for e in range(ecpho):
Y_T = None
B_run = 0
Pred_total = 0
W_Z = np.zeros((2,1)) # m个运算之后的总的W
Loss_Total = 0
loss_y1_y2 = 0 #这个是针对那个不同的Y的损失
for i in range(len(X_train)):
X_ = X_train[i]
pred = Net(X_)
if((i+1)<=5):
Y_T = Y_train[0]
else:
Y_T = Y_train[1]
loss_now = loss(pred,Y_T)
Loss_Total+=loss_now
loss_y1_y2+= loss_now
w_c = com_grad(X_,pred,Y_T)
w_c = w_c.reshape(2,1)
W_Z+=w_c
B_run+=(pred-Y_T)
Pred_total +=pred
if((i+1)%m==0):
W_Z = W_Z /m
B = B_run/m
W = W - W_Z*Lr
print("第{}次训练对--{}--标签拟合的平均损失为{}".format(e + 1,Y_T,loss_y1_y2 / m))
#我们是每m次更新一次,所以更新完之后都要重新刷新
B_run = 0
loss_y1_y2 = 0
W_Z = np.zeros([2, 1]) # m个运算之后的总的W
print("第{}次训练的平均损失为{}".format(e+1,Loss_Total/10))
# 预测部分,在我们的那个数据里面,前面5个是标签1,后面是0,分别对应不同的类别
inx = 1
for i in X_train:
P = Net(i)
if(P<0.5):
print("第{}组预测为:{}".format(inx,classes[0]))
else:
print("第{}组预测为:{}".format(inx, classes[1]))
inx+=1
复制代码
看大上面后面的写法,有没有发现和我先前写的那个HuClassfiy分类器有那么点类似。 最后效果是这样的
你改一下学习率,例如Lr=0.001
これはランダムです。もちろん、これも多くの要因によって決定されます。場合によっては、一部のパラメーターの相関が非常に悪く、適合が難しいため、この影響は避けられません。この場合でも、2つの機能を持つカテゴリを決定します。たとえば、データセットの番号1と2は、子猫に対応する0カテゴリであると共同で決定します。もちろん、上記のドームにはまだ多くの欠点があります。