什么是logtis??
在深度學習的上下文中,logits 就是一個向量,下一步通常被投給 softmax/sigmoid 的向量。。
softmax的輸出是分類任務的概率,其輸入是logits層。 logits層通常產生-infinity到+ infinity的值,而softmax層將其轉換為0到1的值。
舉個例子:
如果一個二分類模型的輸出層是一個單節點,沒有激活函數,輸出值是2.5。則2.5就是這個樣本被預測為正類的logits。
如果一個多分類模型的輸出層是5個節點,沒有激活函數,輸出值是[1.2, 3.1, -0.5, 4.8, 2.3]。則這個向量表示該樣本屬于5個類別的logits。
logits可以取任意實數值,正值表示趨向于分類到該類,負值表示趨向于不分類到該類。與之對應,probability經過softmax/sigmoid歸一化到0-1之間,表示屬于該類的概率。
logtis在交叉熵損失中的示例:
logtis可以看作神經網絡輸出的未經過歸一化(softmax/sigmoid)的概率,所以將其結果用于分類任務計算loss時,如求cross_entropy的loss函數會設置from_logits參數。
因此,當from_logtis=False(默認情況)時,可以理解為輸入的y_pre不是來自logtis,那么它就是已經經過softmax或者sigmoid歸一化后的結果了;當from_logtis=True時,則可以理解為輸入的y_pre是logits,那么需要對它進行softmax或者sigmoid處理再計算cross entropy。
如下面的兩種方式計算得到的loss都是一樣的:
import torch
import torch.nn as nn
import torch.nn.functional as Ffrom_logits = True ?# 標記logtis or sigmoid
y_pre = torch.FloatTensor([[5, 5], [2, 8]]) ?# logtis值:神經網絡的輸出,未概率歸一化
y_true = torch.FloatTensor([[1, 0], [0, 1]]) ?# 真實的二分類標簽if from_logits == True:# BCEWithLogitsLoss可以直接對logtis值進行二分類的損失計算criterion = nn.BCEWithLogitsLoss()loss = criterion(y_pre, y_true)
else:# BCELoss需要對logtis值進行概率歸一化,然后再進行二分類的損失計算criterion = nn.BCELoss()y_pre = F.sigmoid(y_pre)loss = criterion(y_pre, y_true)
print(loss)
傅里葉變換
連續與離散
一般人們口中所說的傅里葉變換都是指連續傅里葉變換,針對的是連續時域信號。維基百科上是這么描述連續信號的:
連續信號或稱連續時間信號是指定義在實數域的信號,自變量(一般是時間)的取值連續。若信號的幅值和自變量均連續,則稱為模擬信號。根據實數的性質,時間參數的連續性意味著信號的值在時間的任意點均有定義。
簡單來說,對于一個sin函數的連續信號,其波形長這樣:
對于計算設備的信號處理,因為采樣設備的采樣率是有限的。因此得到的采樣信號都是離散的,所以就有了針對離散信號的離散傅里葉變換。維基百科是這么描述離散信號:
離散信號是在連續信號上采樣得到的信號。與連續信號的自變量是連續的不同,離散信號是一個串行,即其自變量是“離散”的。這個串行的每一個值都可以被看作是連續信號的一個采樣。由于離散信號只是采樣的串行,并不能從中獲得采樣率,因此采樣率必須另外存儲。以時間為自變量的離散信號為離散時間信號。
離散信號并不等同于數字信號。數字信號不僅是離散的,而且是經過量化的。即,不僅其自變量是離散的,其值也是離散的。因此離散信號的精度可以是無限的,而數字信號的精度是有限的。而有著無限精度,亦即在值上連續的離散信號又叫抽樣信號。所以離散信號包括了數字信號和抽樣信號。
信號的篩選
簡單概括公式所表達的實際意義后,我們再來看為什么要這么做。廢話少說直接按照傅里葉變換公式所描述的做法,將信號與各已頻率信號乘法后積分,寫一段簡單的matlab程序。最終結果如下圖:
從圖上可以很清楚直觀的看出,當未知信號與基信號頻率相同時,他們乘積的積分達到了最大。而這個積分最終的圖像是不是就很像信號經過傅里葉變換后的頻域圖像呢!利用了乘法負負得正的特性,當基信號與未知信號頻率完全相同的時候,其時域上乘積全為正數。因此,此時的積分達到最大值。通過此類操作即可得到未知信號的頻率。
說人話,就是用各種頻率的基信號與未知信號做對比,看看哪個頻率的基信號與未知信號最像!!!,而這個對比的方法,用數學來描述就是先相乘后積分,這樣描述的話,是不是聽起來就沒那么復雜了。
初始相位的問題
上文所討論的對未知信號頻率的篩選,全部都是建立在未知信號相位為0的情況下。但是實際使用過程中,信號的相位與頻率都是未知的,若只使用上文(4)所描述的方式肯定是不行的,如下圖:
可以看到若未知信號的初始相位為90°,若還使用公式4,得出的結果與實際就有誤了。
此時再回頭看看傅里葉變換的公式,不難發現,傅里葉變換使用的是復數信號。e ? j ω t = c o s ( ω t ) ? j s i n ( ω t ) e^{-j\omega t} = cos(\omega t)-jsin(\omega t)e?
?jωt
?=cos(ωt)?jsin(ωt)。也就是說傅里葉變換對未知信號使用復數信號相乘后求積分。而不是只對單個正弦信號做比較。
不難看出,傅里葉變換的結果是復數信號,其結果實部的值就是表示未知信號與cos信號的相關度,虛部值表示未知信號與sin信號的相關度。由此可以看出,傅里葉變換的結果還包含了未知信號的相位信息。
為了分析其頻率信息,我們可以對結果做取模開方處理
快速傅里葉變換(FFT)
快速傅里葉算法本質上是對離散傅里葉變化的改進,本質上是利用矩陣乘法時不同基信號在奇數或偶數點的與被采樣信號的乘積相同來減少計算,嚴格的數學推斷可以參考這篇快速理解FFT算法(完整無廢話)
MATLAB 仿真代碼
% 設置時間范圍
t = 0:0.01:2*pi;
freq1 = 5;
freq2 = 0;% 創建GIF文件
filename = 'sin_wave_animation.gif';
fps = 120;% 初始化乘積結果的和
sum_of_product = zeros(1, length(t));
sum_of_product_sin = zeros(1, length(t));
sum_of_product_cos = zeros(1, length(t));for i = 1:length(t)% 生成兩個不同頻率的正弦波y1 = cos(freq1 * t);y2 = sin((freq2+i/10) * t);y3 = cos((freq2+i/10) * t);% 計算兩個正弦波的乘積y_product_sin = y1 .* y2;y_product_cos = y1 .* y3;% 計算乘積結果的和sum_of_product_sin(i+1) = sum(y_product_sin);sum_of_product_cos(i+1) = sum(y_product_cos);sum_of_product = sqrt(power(sum_of_product_sin, 2) + power(sum_of_product_cos, 2));arr = 0:0.1:10;subplot(3, 1, 1);plot(arr(1:i), sum_of_product_sin(1:i), 'g'); % 只繪制當前時間點之前的數據xlabel('x');ylabel('y');xlim([0, 10]);ylim([-500, 500]);title('Re');arr = 0:0.1:10;subplot(3, 1, 2);plot(arr(1:i), sum_of_product_cos(1:i), 'g'); % 只繪制當前時間點之前的數據xlabel('x');ylabel('y');xlim([0, 10]);ylim([-500, 500]);title('Im');arr = 0:0.1:10;subplot(3, 1, 3);plot(arr(1:i), sum_of_product(1:i), 'g'); % 只繪制當前時間點之前的數據xlabel('x');ylabel('y');xlim([0, 10]);ylim([-500, 500]);title('sqrt(power(Re, 2) + power(Im, 2));');% 保存當前圖像為GIFframe = getframe(gcf);im = frame2im(frame);[imind, cm] = rgb2ind(im, 256);if i == 1imwrite(imind, cm, filename, 'gif', 'Loopcount', inf, 'DelayTime', 1/fps);elseimwrite(imind, cm, filename, 'gif', 'WriteMode', 'append', 'DelayTime', 1/fps);endif i == 100break;endend