1. 判斷滿二叉樹
所有節點的度要麼為0,要麼為2,且所有的葉子節點都在最後一層。
#include <iostream>
using namespace std;
class TreeNode {
public:
int val;
TreeNode* left;
TreeNode* right;
//建立的時候輸入引數x,會把x給val,nullptr給left和right
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {};
TreeNode(int x, TreeNode* l, TreeNode* r) : val(x), left(l), right(r) {};
};
bool isfull(TreeNode* cur) {
if (cur == nullptr) return true;
if (cur->left == nullptr && cur->right != nullptr || cur->left != nullptr && cur->right == nullptr) return false;
if (cur->left != nullptr) {
isfull(cur->left);
isfull(cur->right);
}
else {
return true;
}
}
int main() {
int x = 1;
TreeNode* left = new TreeNode(1);
TreeNode* right = new TreeNode(1);
TreeNode* root = new TreeNode(1, left, nullptr);
cout << isfull(root) << endl;
}
重點在於建立一個TreeNode類,並且寫出建構函式,呼叫建構函式建立節點。
2. 給定一個數,求該數的平方根,不用內建函式
二分法求解。遞迴。
float n;
float e = 0.001;
float findsquare(float left, float right) {
float mid = (left + right) / 2;
if (mid * mid - n >= 0 && mid * mid - n < e || mid * mid - n <= 0 && mid * mid - n >= -e) {
return mid;
}
else {
if (mid * mid > n) {
findsquare(left, mid);
}
else {
findsquare(mid, right);
}
}
}
int main() {
cin >> n;
cout<< findsquare(0, n)<<endl;
}
3. GAN model 內容
影像生成模型。影像生成模型比較瞭解的兩種是GAN和diffusion。
GAN的基本流程:生成器可以用任何輸出二維圖片的網路,例如DNN或者CNN。
Discriminator一般輸入為圖片,輸出為real或者fake。
每一輪,將reference輸入到discriminator裡判別為real,Generator輸出的輸入到discriminator裡判別為假。
Generator的損失函式和Discriminator的損失函式都是二元交叉熵,也就是評估真實資料的機率,Generator的目標是最大化二元交叉熵,也就是讓假結果都為正,而Discriminator是最小化二元交叉熵,讓假結果都為假。
4. Diffusion model 內容
首先是數學知識:
條件機率公式
基於馬爾科夫假設:當前機率僅與上一刻機率有關,與其他時刻無關。可以把條件機率其他項約掉。
高斯分佈的KL散度公式:
引數重整化:整理出z作為網路輸入,其他兩個作為網路引數,可求梯度的。
多元VAE目標函式,都是根據x推理出z,用z預測x。多元VAE的z有多個。
Diffusion Model 主要是兩個過程,先從目標分佈中擴散,得到噪聲分佈,是熵增的過程;
然後是從噪聲分佈中預測出目標分佈。訓練過程就是訓練好這個x,這樣就能在隨機生成(例如高斯分佈 )的噪聲中獲得想要的目標分佈。
擴散過程是p,逆擴散過程是q。漂移量是兩者之間的差。
5. 二叉樹的建立,插入和刪除
這裡應該是搜尋二叉樹,左節點小於自己,右節點大於自己。
刪除先不寫了不會
#include<iostream>
using namespace std;
class TreeNode {
public:
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) :val(x), left(nullptr), right(nullptr) {};
TreeNode(int x, TreeNode* l, TreeNode* r) : val(x), left(l), right(r) {};
};
TreeNode* insert(TreeNode* cur, int x) {
if (cur == nullptr) {
return new TreeNode(x);
}
if (x < cur->val) {
cur->left = insert(cur->left, x);
}
else if (x > cur->val) {
cur->right = insert(cur->right, x);
}
return cur;
}
//有點複雜,先不寫了
TreeNode* deleteNode(TreeNode* cur, int val) {
if (cur == nullptr) {
return cur;
}
}
int main() {
int x = 1;
TreeNode* root = new TreeNode(x);
insert(root, 2);
}
6. Linux相關命令:
top 檢視程序資訊
df -h 檢視硬碟使用情況
ps aux 檢視所有程序
kill -9 pid 殺死編號為pid的程序
chmod 修改許可權
grep 從檔名中找到包含某個字串的資料
wc -l 統計行數
cut 分割一行內容
echo $PATH | cut -d ':' -f 3,5:輸出PATH用:分割後第3、5列資料
find -name 查詢檔案
vim 瀏覽
head -3 顯示前三行內容
docker:
docker ps -a 檢視容器
docker attach 恢復容器
docker exec 掛起容器
docker run 跑容器
vim :n 到第n行 dd 刪除當前行 :q!直接退出 :wq儲存退出 gg=G格式化
ssh 登入伺服器 scp -r傳檔案
7. 快速排序
#include <bits/stdc++.h>
using namespace std;
const int N = 100001;
void quicksort(int * arr, int l, int r){
if(l >= r) return;
int i = l-1, j = r+1;
int mid = (l+r) / 2;
int x = arr[mid];
while(i<j){
do i++; while(arr[i] < x) ;
do j--; while(arr[j] > x) ;
if(i<j) swap(arr[i],arr[j]);
}
quicksort(arr, l,j);
quicksort(arr, j+1, r);
}
int main(){
int n;
cin>>n;
int arr[N];
for(int i =0;i<n;i++){
cin>>arr[i];
}
quicksort(arr,0,n-1);
for(int i =0;i<n;i++){
cout<<arr[i]<<" ";
}cout<<endl;
}
總是會忘記的點:先do後while,i和j初始化為l-1和r+1,因為進入dowhile迴圈後會自增or自減。
quicksort(arr, l,j); 這裡不能用i代替j,因為i是一定大於x的,j是小於等於x的。要保證左邊的段是小於等於x,右邊的段是大於等於x。
8. xgboost和deepfm的效能。
(1)xgboost的結構:由多個迴歸決策樹的模型構成。每一步都加入一個新的樹。(前向分佈演算法,用貪心的策略)逐步最佳化基學習器。
最佳化第t棵樹時,前面t-1顆樹的引數是確定的。每輪的目標函式是n個樣本的最小損失+正則項
正則項是前t顆樹的複雜度。它由葉子結點的個數和每個節點值w的平方和決定,正則項是為了防止過擬合的。葉子節點越多,越容易過擬合。節點值大,就會導致這棵樹佔比比較多,也容易過擬合。
在機器學習中,一般透過梯度下降法最佳化引數。但是樹模型是階躍的,不連續的函式求不了梯度。所以xgboost是對每個葉節點求loss。 每個葉結點的loss可以用梯度來算,分別用了一階導數和二階導數也就是Hessian矩陣來找最優的分割點。
(2)xgboost如何用在推薦系統上?
將使用者的上下文資訊作為特徵輸入到xgboost中,預測使用者的點選機率。所以xgboost是做迴歸的,放入到裡面後
因為是迴歸任務,所以每輪迭代是選擇葉節點的分裂點,然後根據分裂點得到一個值,這個值就是點選機率。多個數就是加權求平均。樹的節點個數這些都是超引數。
(3)xgboost如何並行的?
並行時,在最優分裂點時用並行運算加快效率。它對特徵進行分塊,平行計算每個特徵的增益,透過增益找到最佳分割點。再同步結果,選擇最大的特徵進行分割。
xgboost相對於梯度提升樹(GBDT)有啥提升?
引入了二階導數(Hessian),這在最佳化過程中比傳統GBDT(只使用一階導數資訊)更為準確。
(4)Deepfm演算法:
deep factorization machines 因子分解機。它對低階特徵做特徵互動,另外一個DNN神經網路,做高階特徵互動。一般輸出是兩者的加權和。
因子分解機(FM)是什麼?
FM是SVM的擴充,更適合用於處理稀疏特徵。主要考慮到多維特徵之間的交叉關係(就像SVM的核函式,用內積,但是卻是用因子分解引數化的方式,而SVM中用的是稠密引數化的方式,這使得FM相比SVM的引數少了很多,更加容易計算)。其中引數的訓練使用的矩陣分解的方法。
例如對於電影評分中的資料,用onehot向量建模,一個特徵是非常稀疏的,非常長。因子分解機就是一種改進的二階多項式模型,考慮到兩個向量之間的相似性,例如喜歡這個型別電影的對另一個型別電影的喜歡。(推薦系統之FM(因子分解機)模型原理以及程式碼實踐 - 簡書)
本質上是用deepfm給召回階段的候選集合排序。所以做的僅僅只是排序,不是召回。Loss用的是adam。
(5)為什麼在大規模資料集上使用deepfm?
在處理使用者行為資料和隱式反饋資料時,DeepFM透過其深度部分能夠捕捉到複雜的非線性關係,表現較好。在大規模推薦系統中,如廣告推薦、商品推薦等,DeepFM具有優勢。
適合大規模資料和自動特徵學習的場景,尤其在處理高維稀疏特徵時表現出色。但需要大量資料和計算資源才能充分發揮其優勢。
9. 判斷連結串列裡是否有環
可以用雜湊法或者快慢指標法。快慢指標要注意:判斷fast的next。不然會出界,並且初始化兩個指標不能相同,不然當只有一個資料時返回就不對了。
bool hasCycle(ListNode *head) {
if (head == nullptr) return false;
ListNode* slow = head;
ListNode* fast = head->next;
while(slow != fast){
if(fast == nullptr || fast->next == nullptr) return false;
slow = slow->next;
fast = fast->next->next;
}
return true;
}
雜湊表法:注意插入是insert
bool hasCycle(ListNode *head) {
unordered_set<ListNode*> sets;
ListNode * cur = head;
while(cur!=nullptr){
if(sets.count(cur)) return true;
sets.insert(cur);
cur = cur->next;
}
return false;
}
10. HDFS相關基礎知識
對hadoop瞭解的不多,主要是使用了一些hadoop的命令進行資料讀取。
HDFS是hadoop distribution file system。HDFS的檔案分佈在伺服器叢集上,提供副本和容錯率保證。
適用於儲存特別大的檔案,採用流式資料進行訪問。但不適合毫秒級別的訪問,是有點延時的。
我是使用了一些命令列的命令,例如:
hadoop fs -copyFromLocal // copy file
hadoop fs mkdir
hadoop fs -ls