搜广推校招面经四

字节

  • 一、手撕DIN
python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
class DIN(nn.Module):
    def __init__(self, num_users, num_items, embedding_dim, history_size):
        super(DIN, self).__init__()
        
        self.user_embedding = nn.Embedding(num_users, embedding_dim)
        self.item_embedding = nn.Embedding(num_items, embedding_dim)
        self.history_embedding = nn.Embedding(num_items, embedding_dim)
        
        self.attention_layer = nn.Linear(embedding_dim * 2, 1)
        self.fc_layer = nn.Sequential(
            nn.Linear(embedding_dim * 2, 128),
            nn.ReLU(),
            nn.Linear(128, 1)
        )
    def forward(self, user_id, item_id, history_ids):
        user_emb = self.user_embedding(user_id)
        item_emb = self.item_embedding(item_id)
        history_emb = self.history_embedding(history_ids)
        
        # 计算兴趣提取:使用注意力机制加权历史行为嵌入
        # 计算历史行为与目标物品的相似度 (比如使用点积)
        combined_emb = torch.cat((history_emb, item_emb_expanded), dim=-1)  # 拼接历史行为和物品嵌入
        # 计算注意力权重
        attention_weights = F.softmax(self.attention_layer(combined_emb), dim=1)
        weighted_history_emb = torch.sum(attention_weights * history_emb, dim=1)

        fusion_emb = torch.cat((item_emb, weighted_history_emb), dim=-1)
        output = self.fc_layer(fusion_emb)
        return output
model = DIN(num_users, num_items, embedding_dim, history_size)
  • 二、手撕NCE loss
    NCE Loss 是一种用于训练概率模型的损失函数,最初在学习词向量(Word2Vec)时提出。NCE Loss 的核心思想是通过将目标分布与噪声分布进行对比,来简化模型的训练过程,从而避免了传统的 softmax 计算中昂贵的归一化步骤。NCE Loss 适用于训练大规模语言模型和推荐系统等。

    NCE 通过将原始任务转换为二分类任务:对于每个真实的样本,判断它是来自目标分布还是来自噪声分布(负样本)。这样,我们不再需要计算所有词汇的总和,而是只需要根据噪声词和正样本来训练模型。具体来说,NCE 会为每个正样本 w w w和上下文词 c c c生成一组负样本 w 1 , . . . . . w k w_1,.....w_k w1,.....wk (噪声词),然后训练模型区分正样本和负样本。
python 复制代码
import torch
import torch.nn.functional as F
def nce_loss(pos_score, neg_scores, num_neg_samples):
    """
    计算NCE损失
    :param pos_score: 正样本的得分(来自目标分布)
    :param neg_scores: 负样本的得分(来自噪声分布)
    :param num_neg_samples: 负样本数量
    :return: NCE损失
    """
  
    # 正样本的损失,sigmoid对正样本得分
    pos_loss = F.logsigmoid(pos_score)
    
    # 负样本的损失,sigmoid对负样本得分,取负
    neg_loss = F.logsigmoid(-neg_scores).sum(dim=-1)
    
    # 计算总损失
    total_loss = -(pos_loss + neg_loss) / num_neg_samples
    return total_loss.mean()  # 返回平均损失
 
# 假设 pos_score 是正样本得分,neg_scores 是负样本得分(来自噪声分布)
pos_score = torch.randn(batch_size, 1)  # 正样本得分
neg_scores = torch.randn(batch_size, num_neg_samples)  # 负样本得分
num_neg_samples = 5  # 负样本数量
# 计算NCE损失
loss = nce_loss(pos_score, neg_scores, num_neg_samples)
  • 三、手撕AUC
预测为1 预测为0
真实label=1 (正类) True Positive (TP) False Negative (FN)
真实label=0 (负类) False Positive (FP) True Negative (TN)

精确率(Precision) : Precision = T P T P + F P \text{Precision} = \frac{TP}{TP + FP} Precision=TP+FPTP
召回率(Recall) : Recall = T P T P + F N \text{Recall} = \frac{TP}{TP + FN} Recall=TP+FNTP
F1分数(F1-Score) : F1-Score = 2 × Precision × Recall Precision + Recall \text{F1-Score} = 2 \times \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}} F1-Score=2×Precision+RecallPrecision×Recall
真正率(TPR)/ 召回率 : T P R = T P T P + F N TPR = \frac{TP}{TP + FN} TPR=TP+FNTP
假正率(FPR) : T P R = F P F P + T N TPR = \frac{FP}{FP + TN} TPR=FP+TNFP

通过绘制不同阈值下TPR 和 FPR 就可以得到ROC曲线,AUC就等于ROC曲线和X轴之间的面积。但实际上AUC有一个更为常用的定义:随机从正样本和负样本中各选一个,分类器对于该正样本打分大于该负样本打分的概率。基于计算AUC的代码可以写为

python 复制代码
def cal_auc_1(label, pred):
    numerator = 0    # 分子
    denominator = 0  # 分母
    for i in range(len(label) - 1):
        for j in range(i, len(label)):
            if label[i] != label[j]:
                denominator += 1
                # 统计所有正负样本对中,模型把相对位置排序正确的数量
                r = (label[i] - label[j]) * (pred[i] - pred[j])
                if r > 0:
                    numerator += 1
                elif r == 0:
                    numerator += 0.5
    return numerator / denominator
  • 四、算法题:力扣53题 最大子数组和
    这道题可以直接双循环暴力求解,考试想不起还是可以用用的
python 复制代码
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        ans = nums[0]
        for i in range(len(nums)):
            for j in range(i, len(nums)):
                ans = max(ans, sum(nums[i:j+1]))
        return ans
        
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        size = len(nums)
        if size == 0:
            return 0
        dp = [0 for _ in range(size)]

        dp[0] = nums[0]
        for i in range(1, size):
            if dp[i - 1] >= 0:
                dp[i] = dp[i - 1] + nums[i]
            else:
                dp[i] = nums[i]
        return max(dp)   
相关推荐
weixin_4597539422 分钟前
golang如何实现Trace上下文传播_golang Trace上下文传播实现思路
jvm·数据库·python
weixin_4440129332 分钟前
PHP 中逻辑或(--)运算符的正确使用与条件逻辑重构指南
jvm·数据库·python
iAm_Ike7 小时前
Go 中自定义类型与基础类型间的显式类型转换详解
jvm·数据库·python
iuvtsrt7 小时前
Golang怎么实现方法集与接口的匹配_Golang如何理解值类型和指针类型实现接口的区别【详解】
jvm·数据库·python
旦莫7 小时前
AI驱动的纯视觉自动化测试:知识库里应该积累什么知识内容
人工智能·python·测试开发·pytest·ai测试
知识领航员8 小时前
蘑兔AI音乐深度实测:功能拆解、实测表现与适用场景
java·c语言·c++·人工智能·python·算法·github
如何原谅奋力过但无声10 小时前
【灵神高频面试题合集06-08】反转链表、快慢指针(环形链表/重排链表)、前后指针(删除链表/链表去重)
数据结构·python·算法·leetcode·链表
deephub10 小时前
2026 RAG 选型指南:Vector、Graph、Vectorless 该怎么挑
人工智能·python·大语言模型·rag
爱喝雪碧的可乐10 小时前
2026 腾讯广告算法大赛优秀方案启示:行为条件化多模态自回归生成推荐摘要
算法·数据挖掘·回归·推荐系统·推荐算法
狐狐生风12 小时前
使用 UV 创建并运行 Python 项目(完整步骤)
python·uv