Paper Read Records

本文介绍了一种基于历史点击信息预测用户查询是否具有广告点击意图的方法。通过两种模型——基于查询词内容匹配的点击预测模型及基于朴素贝叶斯分类的预测模型,实现了对新查询的广告点击意图预测,从而提高广告投放的效率。

本文用来记录读研期间论文阅读情况,并对每一篇文章给出我自己的理解,必要时做出点评.... 主要是记录我的"reading paper career",将来能够回忆起"那些年哥读过的论文..."

第1篇:题目:《搜索引擎用户查询的广告点击意图分析》

     作者:靳岩钦,张敏,刘奕群,马少平 ;  单位: 清华大学智能技术与系统国家重点实验室

本文主要讲述了基于用户查询点击日志的历史点击信息,来对一个新的查询 预测用户是否广告点击意图。以此来提高广告投放的有效性和精度。对于一个新的查询,经过模型判断此次查询如果没有广告点击意图,那么就较少投放广告投放数量或者不投广告(文中是假设不投);如果此次查询判断有广告点击意图,则返回搜索结果时, 进行广告投送。这样就减少了广告投送的盲目性(每一个查询都投送广告),减少了投放引擎的代价。

首先:用户给予历史数据,统计出广告CTR(广告点击次数/总的点击量) 和 每一天引发广告点击的查询比例;

其次:作者提出了两种方法对搜索引擎用户查询的广告点击意图进行分析和预测,分别是 基于查询词内容匹配的点击预测模型 和 基于贝叶斯分类的预测模型。

基于查询词内容匹配的点击预测模型:考虑怎样判断一个词项是否具有引发广告点击的可能性?文中做法是将日志中所有的查询分为两类:引发过广告点击的查询 和 未引发过广告点击的查询。对所有查询中的词项,根据他们在两类查询中的频度进行排名,如果前者的排名高于(数值上小于)在后者的排名,则具有一定的广告点击意图. 以上判断了单个词项是否具有广告点击意图----------------> 映射到 完整查询的广告意图. 最后,给定任意用户的查询Q,进行中文分词,得到一个词项集合s,并定义一个映射g,即 s = segment(Q) = {t1, t2, ..., tn} g(Q) = g(t1, t2, ..., tn);  如果g(Q)大于某一阈值,则判定查询Q具有引发广告点击的倾向,反之,则没有。

基于朴素贝叶斯分类的预测模型:所有查询被分为两类,不含有广告点击意图的查询C1和有广告点击意图的查询C2。

先验概率p(Ci):分别统计在所有查询中具有和不具有广告点击意图的查询的比例; 每一个词项的条件概率p(t|Ci): 可以通过统计词项t出现在C1和C2类查询中的频度估计. 

根据贝叶斯公式可以得到:p(Ci|q) 

假设查询中的各个词项独立:s = segment(Q) = {t1, t2, ..., tn}; 

p1 = p(C1|s) = p(C1)*∏p(t|C1),   p2 = p(C2|s) = p(C2)*∏p(t|C2)

如果p1>p2,则Q属于C1, 不含有广告点击意图,这是减少投放数量 or 甚至不投放广告;如果p1<p2, Q属于C2,Q更肯呢过含有广告点击意图,应投放相关广告.

总结: 本文是基于历史点击信息,判断一个新的查询是否具有广告点击意图。如果有,则投放相关的广告(CTR和点击价值), 如果没有,则少投或不投广告;本文只是预测给定查询是否具有广告点击意图(二分类问题), 并没有采用用户信息为特征,并结合用户历史查询or浏览行为进行判断用户是否有点击意图(特征单一),忽略了查询的用户(假设所有user都一样). 优点:通过预测一次查询是否具有点击意图,来决定是否投放广告,这样减少了投放广告的盲目性,提高了投放精度和有效性。(注意这不是广告的精准定向,信息量不足); 缺点:①没有给出明确的CTR,真正的投放引擎还是需要算CTR的;② 只是较少了广告投放引擎的代价,其实对于投放引擎来讲无关紧要....

使用latex完成下面代码的设计文档: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <time.h> #include <stdint.h> /* 计算校验和 */ uint32_t checksum(const char *data, size_t len) { uint32_t sum = 0; for (size_t i = 0; i < len; i++) { sum += (unsigned char)data[i]; } return sum; } int main() { int pipe_a2b[2]; /* A->B的管道 */ int pipe_b2a[2]; /* B->A的管道 */ time_t start_time = time(NULL); /* 创建管道 */ if (pipe(pipe_a2b) == -1 || pipe(pipe_b2a) == -1) { perror("pipe"); exit(EXIT_FAILURE); } pid_t pid = fork(); /* 创建子进程 */ if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (pid == 0) /* 子进程 B */ { close(pipe_a2b[1]); /* 关闭A->B的写端 */ close(pipe_b2a[0]); /* 关闭B->A的读端 */ /* 记录通信信息 */ struct { time_t time; size_t size; uint32_t recv_checksum; uint32_t calc_checksum; int result; } records[2]; for (int i = 0; i < 2; i++) { /* 读取头部(8字节:4字节长度 + 4字节校验和) */ uint32_t data_len, recv_checksum; read(pipe_a2b[0], &data_len, sizeof(uint32_t)); read(pipe_a2b[0], &recv_checksum, sizeof(uint32_t)); /* 读取具体数据 */ char *data = malloc(data_len); read(pipe_a2b[0], data, data_len); /* 计算校验和 */ uint32_t calc_checksum = checksum(data, data_len); int check_result = (calc_checksum == recv_checksum) ? 0 : 1; /* 记录信息 */ records[i].time = time(NULL); records[i].size = data_len; records[i].recv_checksum = recv_checksum; records[i].calc_checksum = calc_checksum; records[i].result = check_result; /* 打印接收信息 */ int elapsed = (int)(records[i].time - start_time); printf("[第%d秒] B: 我从A接收了%u字节数据,%s\n", elapsed, data_len, check_result ? "校验错误" : "校验正确"); /* 发送确认(5字节:4字节长度 + 1字节结果) */ write(pipe_b2a[1], &data_len, sizeof(uint32_t)); write(pipe_b2a[1], &check_result, sizeof(char)); free(data); } /* 打印B的统计信息 */ printf("\nB进程统计结果:\n"); size_t total_received = 0; for (int i = 0; i < 2; i++) { char time_buf[20]; strftime(time_buf, sizeof(time_buf), "%H:%M:%S", localtime(&records[i].time)); printf("时间: %s, 大小: %zu字节, 接收校验和: %u, 计算校验和: %u, 结果: %s\n", time_buf, records[i].size, records[i].recv_checksum, records[i].calc_checksum, records[i].result ? "失败" : "成功"); total_received += records[i].size; } printf("总接收大小: %zu字节\n", total_received); close(pipe_a2b[0]); close(pipe_b2a[1]); exit(0); } else /* 父进程 A */ { close(pipe_a2b[0]); /* 关闭A->B的读端 */ close(pipe_b2a[1]); /* 关闭B->A的写端 */ /* 准备数据(第一次100字节,第二次200字节)*/ size_t sizes[2] = {100, 200}; char *data1 = malloc(sizes[0]); char *data2 = malloc(sizes[1]); memset(data1, 'A', sizes[0]); memset(data2, 'B', sizes[1]); /* 记录通信信息 */ struct { time_t time; size_t size; uint32_t sent_checksum; int ack_result; } records[2]; for (int i = 0; i < 2; i++) { sleep(3); /* 等待3秒(n=1) */ /* 发送数据 */ uint32_t data_len = (uint32_t)sizes[i]; char *data = (i == 0) ? data1 : data2; uint32_t sum = checksum(data, sizes[i]); /* 发送头部(8字节) */ write(pipe_a2b[1], &data_len, sizeof(uint32_t)); write(pipe_a2b[1], &sum, sizeof(uint32_t)); if( i==1 ) { data[sizes[i]-1] = 'X'; /* 故意制造错误 */ } /* 发送数据 */ write(pipe_a2b[1], data, sizes[i]); /* 记录发送信息 */ records[i].time = time(NULL); records[i].size = sizes[i]; records[i].sent_checksum = sum; /* 打印发送信息 */ int elapsed = (int)(records[i].time - start_time); printf("[第%d秒] A: 我发送了%u字节数据给B\n", elapsed, data_len); /* 接收确认(5字节) */ uint32_t ack_len; char ack_result; read(pipe_b2a[0], &ack_len, sizeof(uint32_t)); read(pipe_b2a[0], &ack_result, sizeof(char)); /* 记录确认结果 */ records[i].ack_result = ack_result; printf("[第%d秒] A: B告诉我收到了%u字节数据,%s\n", elapsed, ack_len, ack_result ? "但校验失败" : "校验正确"); } /* 打印A的统计信息 */ printf("\nA进程统计结果:\n"); size_t total_sent = 0; for (int i = 0; i < 2; i++) { char time_buf[20]; strftime(time_buf, sizeof(time_buf), "%H:%M:%S", localtime(&records[i].time)); printf("时间: %s, 大小: %zu字节, 发送校验和: %u, 结果: %s\n", time_buf, records[i].size, records[i].sent_checksum, records[i].ack_result ? "失败" : "成功"); total_sent += records[i].size; } printf("总发送大小: %zu字节\n", total_sent); free(data1); free(data2); close(pipe_a2b[1]); close(pipe_b2a[0]); wait(NULL); /* 等待子进程结束 */ } return 0; }
最新发布
08-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值