记在2019,winter is coming

那是最好的年代,也是最糟的年代。那是光明的时节,也是黑暗的时节。那是希望的春季,也是悲伤的冬日。

2019 我开始了自己的求职之旅。2个月以来,面试了10多家公司。外面整体形势很差,比自己想象的还要差。一方面各大厂hc大大减少,要求也大大提升。总体感觉这次,自己很被动。所以,以后要做更好的计划。

  1. 简历每3个月要进行一次更新。
  2. 时刻保持自己对leetcode题型的熟知程度,总之,时刻准备着....优秀是一种习惯
  3. 面试过程,一定注意编程题的细节,一定不要着急给自己挖坑,挖与不挖是智商与情商的双重考验
  4. 面试的时候,首先拿小厂积累经验,弥补不足,循序渐进,厚积薄发。记住没有没有价值的面试。涨不了技术,就涨阅历。不断的面试练习,最后巅峰时刻,去面大厂。
  5. 面试中当和面试官意见不一致时,要保持沉默,不要据理力争。同时还要注意面试官是不是给自己挖坑,不能啥都附和。总之,面试在缘分。
  6. 一定要给自己设置一个找工作的战线区间,比如一个月,比如2个月,战线千万不要啦太长。无论如何,就是一个月,我必须在我拿到的offer里面挑一个去,有压力才会有动力。
  7. 最佳的找工作时间还是3,4月,9,10月。其他时间机会相对较少。

总体面试经验分享如下,

2019.2.22

瑞途科技

公司只要是对地铁隧道中的墙壁裂缝,遗留物等检测的。有自己的嵌入式设备。

技术leader主要聊了一些工作经验。

 

2019.2.22

当当网

对方的岗位主要偏大数据方向,我主要是做cv方向,抱着试一试的态度面试。

面试主要5个环节。

1,做试卷

题型主要是选择题,问答题,编程题。

问答题

  1. PCA,LDA区别

PCA为非监督降维,LDA为有监督降维

PCA希望投影后的数据方差尽可能的大(最大可分性),因为其假设方差越多,则所包含的信息越多;而LDA则希望投影后相同类别的组内方差小,而组间方差大。LDA能合理运用标签信息,使得投影后的维度具有判别性,不同类别的数据尽可能的分开。

  1. AUC
  2. 机器学习的其他使用过的方法,评价指标

编程题

(1)给定一个输入正整数N,输出N的阶乘的值。(N<512)

要考虑大整数乘法溢出的问题。

主要思想:

初始值为1.

然后把1放入数组存着,(按位存,比如999,即f[0]=9, f[1]=9, f[2]=9)

然后数组的每一位都乘以2,(注意还有进位)

然后数组的每一位都乘以3,…

然后数组的每一位都乘以n.

 

最后从后往前,输出每一位即是结果。注意,数组后面从非0开始计算。即最高位就是第一个非0位。

#define Max 512 //最多存储3000位
int main()
{
	int n=3; //输入的数
	int temp;

	int f[Max] = { 1, 0 };  //用于存储结果的每一位数
	int i, j;
	for (i = 2; i <= n; i++)
	{
		int flag = 0;//进位标志
		for (j = 0; j < Max; j++) //对于每一个数i,把f中的每一个数字(即下标j的数字)都剩以i,注意进位
		{
			temp = f[j] * i + flag;
			f[j] = temp % 10;
			flag = temp / 10;
		}
	}
	for (j = Max - 1; j >= 0; j--)
		if (f[j]) break;
	for (i = j; i >= 0; i--)
		std::cout << f[i];
	std::cout << std::endl;

	return 0;
}

(2)给定一个input.txt,里面存着用户购买的书的编号,可以理解为一行一个字符串,大概1000w行,输出购买量前100的书的编号。

由于数据量大,需要将1000w的数据分成N份(这里为了保证相同的数据被分到同一个桶,得使用hash函数),每份取前100个,再对N份的前100进行排序,输出最终的前100项。

import hashlib

def hash_func(string_data,num_split=10):
    md5 = hashlib.md5()
    md5.update(string_data.encode('utf-8'))
    return sum(ord(x) for x in md5.hexdigest())%num_split

file=open("input.txt","r",encoding="utf-8")
lines=file.readlines()
file.close()

num_split=10
out_pre_num=100
lines_bucket=[]
for i in range(num_split):
    lines_bucket.append({})
for line in lines:
    line=line.rstrip("\n")
    hash_num=hash_func(line,num_split)
    if line in lines_bucket[hash_num].keys():
        lines_bucket[hash_num][line]+=1
    else:
        lines_bucket[hash_num][line]=1

bucket_pre_100_lists=[]
for i in range(len(lines_bucket)):
    lines_bucket_sorted_lists=sorted(lines_bucket[i].items(),key=lambda x:x[1],reverse=True)
    bucket_pre_100_lists.extend(lines_bucket_sorted_lists[:out_pre_num])


sorted_pre_100_lists=sorted(bucket_pre_100_lists,key=lambda x:x[1],reverse=True)
print(sorted_pre_100_lists[:out_pre_num])

    2.技术1面试

聊项目经验+2道编程题

  1. leetcode ,3Sum
思路,夹逼准则
S=[-1,0,1,2,-1,-4]
sum_3=0
output=[]
S=sorted(S,reverse=False)

for i in range(len(S)):
    if i>0 and S[i]==S[i-1]:
        continue
    fore_index=i+1
    back_index=len(S)-1
    target=sum_3-S[i]
    print(i)
    while fore_index<back_index:
        if S[fore_index]+S[back_index]==target:
            output.append((S[i],S[fore_index],S[back_index]))
            fore_index+=1
            back_index-=1
        elif S[fore_index]+S[back_index]<target:
            fore_index+=1
        else:
            back_index-=1

print(output)

    2.给定2个字符串,判断第一个字符串中是否按顺序的包含第二个字符串中的每个字符。

例如,字符串A=”zcfdkwuy”,字符串B=”zku”,则A字符串按顺序包含B字符串的每个元素,返回True,不包含返回False

A="zcfdkwuy"
B="zku"

index_A=0
index_B=0
while index_A<len(A) and index_B<len(B):
    if A[index_A]==B[index_B]:
        index_A+=1
        index_B+=1
    else:
        index_A+=1

output=index_B>=len(B)
print(output)

    3.技术2面试

聊项目经验+2道编程题

(1)给定一个排序后的数组A,输出该数组中任意2个数的和为给定数X的索引

和Two Sum这道题的区别就是,Two Sum输入的数组不要求是已经排序的。而这块是已经排序的,我也没闹懂出题人的意思,直接就想了二分查找(时间复杂度o(n*log(n))),其实后来一想,基于hash的思路要比这个高效(时间复杂度o(n))。

二分查找思路,

def binary_search(data_list,first,last,key):
    while first<=last:
        middle=int(first+(last-first)/2)
        if data_list[middle]==key:
            return middle
        if key<data_list[middle]:
            last=middle-1
        if data_list[middle]<key:
            first=middle+1
        print(first,last,key)
    return -1
A=[1,3,5,6,7,9]
X=8

output_list=[]
for num,i in enumerate(A):
    out_index=binary_search(A,0,len(A)-1,X-i)
    if out_index!=-1 and out_index>num:
        output_list.append((num,out_index))
print(output_list)
Hash思路,
A=[1,3,5,6,7,9]
X=8

output_list=[]
for num,i in enumerate(A):
    out_index=-1
    if X-i in A:
        out_index=A.index(X-i)
    if out_index>num:
        output_list.append((num,out_index))
print(output_list)

第二题忘了。

4,部门leader面试

5,hr面

 

上海欧拉:

new与malloc的区别:

(1)分配内存的位置,

new(自由存储区),malloc(堆)

(2)内存分配失败返回值

new(完整类型指针),malloc(void*指针)

(3)内存分配失败返回值

new(默认抛出异常),malloc(NULL)

(4)分配内存的大小

new(编译器根据类型计算得出),malloc(必须显式指定字节数)

(5)已分配内存的扩充

new(无法直观地处理),malloc(使用realloc简单完成)

(6)是否相互调用

new(可以调用malloc),malloc(不可以调用new)

(7)函数重载

new(容许),malloc(不容许)

(8)构造函数与析构函数

new(调用),malloc(不调用)

 

虚函数:

虚函数可以在子类方法中进行重载,也可以不重载而沿用父类的方法。

纯虚函数必须重载,因为声明类中没有函数的实现,virtual void func()=0;

包含纯虚函数的类为抽象类,不能声明对象,只能作为基类。

 

意锐新创:

技术面+leader面

直接聊经验,公司主要做移动二维码支付,小白盒

面试经验收获少,人生阅历有收获。

 

翔创科技:

京东人脸识别大赛第二名,主要做人工智能养猪。初创公司,直接聊技术。

 

卓视智通:

公司主要做安防,老板很年轻,初创公司,主要聊技术。

 

申哲伙伴:

面试题,

(1)1个箱子里有50个红球,50个蓝球。每次从里面取出2个。

如果是2个红色,全部放回,

如果是2个蓝色,全部取出蓝色,

如果是一个红色,一个蓝色,取出1个红色,放回一个蓝色,

求,最后剩下红色的概率。

单场懵逼,没啥思路。可以模拟10000次试验计算,但是肯定有更好的办法,只是没想到。结果应该是0.5。

取出,红,蓝

1/2(红蓝+蓝红两种情况)

取出,红,红

1/4

取出,蓝,蓝

1/4

import random

#求最后剩下红球的概率
num_temp=0
num_all=num_all_copy=10000


while num_all>0:
    num_all-=1

    red_ball_num=50#0表示
    blue_ball_num=50#1表示
    while True:
        num1=random.randint(0,1)
        num2=random.randint(0,1)

        if (num1==0 and num2==1) or (num1==1 and num2==0):
            red_ball_num-=1
        elif num1==0 and num2==0:
            pass
        elif num1==1 and num2==1:
            blue_ball_num-=2
        else:
            pass
        if blue_ball_num==0 and red_ball_num>0:
            num_temp+=1
            break
        if blue_ball_num>0 and red_ball_num==0:
            break

perception=num_temp/num_all_copy
print(perception)#0.5

(2)RPN网络可不可以做多分类任务。

(3)项目经验。

一起教育:

编程1,编辑距离,

int minDistance(const string &word1, const string &word2) {
const size_t n = word1.size();
const size_t m = word2.size();
// 长度为 n 的字符串,有 n+1 个隔板
int f[n + 1][m + 1];
for (size_t i = 0; i <= n; i++)
f[i][0] = i;
for (size_t j = 0; j <= m; j++)
f[0][j] = j;
for (size_t i = 1; i <= n; i++) {
for (size_t j = 1; j <= m; j++) {
    if (word1[i - 1] == word2[j - 1])
        f[i][j] = f[i - 1][j - 1];
    else {
        int mn = min(f[i - 1][j], f[i][j - 1]);
        f[i][j] = 1 + min(f[i - 1][j - 1], mn);
        }
    }
}
return f[n][m];
}

编程2,kmeans

#!/usr/bin/python
# coding=utf-8
import numpy as np
import random
import math
import copy
import matplotlib.pyplot as plt
dataMat=[[1.658995,4.285136],
[-3.453687,3.424321],
[4.838138,-1.151539],
[-5.379713,-3.362104],
[0.972564,2.924086],
[-3.567919,1.531611],
[0.450614,-3.302219],
[-3.487105,-1.724432],
[2.668759,1.594842],
[-3.156485,3.191137],
[3.165506,-3.999838],
[-2.786837,-3.099354],
[4.208187,2.984927],
[0.704199,-0.479481],
[-0.392370,-3.963704],
[2.831667,1.574018],
[-0.790153,3.343144],
[2.943496,-3.357075]
]
# 计算欧几里得距离
def distEclud(centroids, datai):
    dis=[]
    for i in range(len(centroids)):
        dis.append(math.sqrt((centroids[i][0] - datai[0])**2+(centroids[i][1] - datai[1])**2))
    return dis

# 构建聚簇中心,取k个(此例中为4)随机质心
def randCent(dataSet, k):
    min_x = min(dataSet[:][0])
    max_x = max(dataSet[:][0])
    min_y = min(dataSet[:][1])
    max_y = max(dataSet[:][1])

    centroids = []
    for i in range(k):
        centroids.append([random.uniform(min_x,max_x),random.uniform(min_y,max_y)])
    return centroids 
    #centroids = set()
    #while len(list(centroids))<k:
    #    centroids.add(random.randint(0,len(dataSet)))
    #return list(centroids)

# k-means 聚类算法
def kMeans(dataSet, k):
    m = len(dataSet)

    # clusterAssment第一列存放该数据所属的中心点,第二列是该数据到中心点的距离
    centroids = randCent(dataSet, k)
    pre_centroids=copy.copy(centroids)
    while True:
        clusterAssment = []   # 用于存放该样本属于哪类及质心距离

        for i in range(m):  # 把每一个数据点划分到离它最近的中心点
            distJI = distEclud(centroids, dataSet[i])
            clusterAssment.append([distJI.index(min(distJI)),min(distJI)])

        minDst=0
        for j in range(k):   # 重新计算中心点
            sum_k_x=0
            sum_k_y=0
            num_k=0
            for n in range(len(clusterAssment)):
                if clusterAssment[n][0]==j:
                    sum_k_x+=dataSet[n][0]
                    sum_k_y+=dataSet[n][1]
                    num_k+=1
            centroids[j]=[sum_k_x/(num_k+0.0001),sum_k_y/(num_k+0.0001)]
            minDst+=math.sqrt((centroids[j][0]-pre_centroids[j][0])**2+(centroids[j][1]-pre_centroids[j][1])**2)
        
        if minDst<0.5:
            break
        else:
            pre_centroids=copy.copy(centroids)

    return centroids, clusterAssment
# --------------------测试----------------------------------------------------
# 用测试数据及测试kmeans算法
myCentroids,clustAssing = kMeans(dataMat,4)
print (myCentroids)
print (clustAssing)


c_lists=['b','g','k','y']
marker_lists=['x','1','2','s']
fig = plt.figure()
axis = fig.add_subplot(111)
for i in range(len(dataMat)):
    axis.scatter([dataMat[i][0]], [dataMat[i][1]], c = c_lists[clustAssing[i][0]],marker = marker_lists[clustAssing[i][0]])
axis.scatter([myCentroids[i][0] for i in range(len(myCentroids))], [myCentroids[i][1] for i in range(len(myCentroids))], c = 'r',marker = 'o')
plt.show()

微店:

3个技术面,1个hr

程序题,

  1. 一个贝叶斯的英文题,没细看,直接说了不会。
  2. 给定2个数组,判断另外一个数组是否是由第一个数组中的元素进行打乱得到的。

例如,数组,A=[1,3,5,4,7],B=[1,5,7,4,3],则数组B中元素和数组A中元素相等,返回True。

方法1,可以将2个数组分别进行排序,然后看排序后结果是否相等。o(nlogn)时间

方法2,遍历A数组,将其中的元素进行哈希存储,然后遍历B数组,判断哈希表中的数值。o(n)时间

 

智力题,

  1. 一个固定大小的桌子,有无数的固定大小的硬币。A,B两人一人每次放一枚,不容许重叠的放。直到不能再放为止,轮到谁不能再放,就算谁输,假设A先放,A怎么样保证自己一定赢。

放中心位置。因为桌子是关于中心对称的,只有中心位置只有1个。只要占了中心位置。这样不管B怎么放,A都可以放在B的放的位置的对称位置。

  1. 逻辑回归,假设有100个特征向量,将其中的一个特征复制100次,生成200个维度的特征向量,问这样训练和原来的100维的训练会有区别吗?

不会有区别,假设复制的那个向量的分数为p,这样最记得假设,复制后每个向量的分数为p/101,和原来的向量还是一样的。

58同城:

聊项目经验

 

小鹏汽车:

聊项目经验

问了一些构造函数的多态。

Lstm手写公式,

Svm推导

Face++:

(1)NMS

import numpy as np  
  
def nms(dets, thresh):
    #dets[x1,y1,x2,y2,p] 
    dets=sorted(dets,key=lambda x:x[4],reverse=True)   
    delete_lists=[]
for n,xy in enumerate(dets): 
    if dets [n][4]=0:
        continue
    for num,xxyy in enumerate(dets[n+1:]): 
        if dets [n+1+num][4]=0:
            continue

            xx1 = np.maximum(xy[0], xxyy[0])  
            yy1 = np.maximum(xy[1], xxyy[1])  
            xx2 = np.minimum(xy[2], xxyy[2])  
            yy2 = np.minimum(xy[3], xxyy[3])  
  
            w = np.maximum(0.0, xx2 - xx1 + 1)  
            h = np.maximum(0.0, yy2 - yy1 + 1)  
            inter = w * h
            union=  (xy[2]-xy[0])*(xy[3]-xy[1])+(xxyy[2]-xxyy[0])*(xxyy[3]-xxyy[1])
            ovr = inter / (union - inter+0.00001)  
 
            if ovr >= thresh:
                dets [n+1+num][4]=0
                delete_lists.append(n+1+num)
    dets=np.delete(dets,delete_lists,axis=0)
    return dets

(2)单链表反转

struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};

ListNode* ReverseList(ListNode* pHead) {
        ListNode *root=pHead; 
        ListNode *pre=NULL;  
        ListNode *next=NULL;
        if(pHead==NULL) return NULL; 
    while(root->next){  
        next=root->next;   
        root->next=pre;      
        pre=root;       
        root=next;     
    }    
        root->next=pre; 
        return root; 
}

美图:

3个技术面,1个hr面,

(1)线性回归和逻辑回归区别。

线性回归用来预测,逻辑回归用来分类。

线性回归是拟合函数,逻辑回归是预测函数

线性回归的参数计算方法是最小二乘法,逻辑回归的参数计算方法是梯度下降

 

(2)偏差和方差区别

偏差: 描述模型输出结果的期望与样本真实结果的差距。 
方差: 描述模型对于给定值的输出稳定性。 

泛化性能=偏差+方差+noise

[高方差] (过拟合)解决思路:

采集更多的样本数据,减少特征数量,去除非主要的特征,增加正则化参数 λ

[高偏差] (欠拟合)解决思路:

引入更多的相关特征,采用多项式特征,减小正则化参数 λ

(3)类似百度的相似图片查找

KNN,KD Tree,矩阵运算加速等。

(4)分类和回归的区别。

分类是离散的,定性的,回归是连续的,定量的

编程题,

两个list转化为一个dict,

list1 = ['key1','key2','key3']
list2 = ['1','2','3']
dict(zip(list1,list2))

支付宝:

神经网络训练,很多时候彩色图训练和灰度图训练效果差不多,比如人脸识别中,那么颜色到底是不是一种特征?

当时被问到这个,自己也是左右纠结,传统算法中,颜色确实是一个特征,比如itti。人脸识别训练确实是灰度图和彩图没啥区别,有些ocr中甚至灰度图效果更好。

于是自己pytorch路了个简单的例子验证。

 

造图片程序:

import  cv2
import numpy as np
import random

image_shape=56
shape_type=["triangle","rectange","circle"]
color_shape=[(0,0,255),(0,255,0),(255,0,0)]
color_shape_name=["red","green","blue"]
image_class_num=20
dataset_folder="data/"

for cn,color_type in enumerate(color_shape):
    for ic_num in range(image_class_num):
        image=np.ones((image_shape,image_shape,3), np.uint8)*255
        shape=shape_type[random.randint(0,2)]


        
        if (shape=="triangle"):
            pts = np.array([[random.randint(5,image_shape),random.randint(5,image_shape)],[random.randint(5,image_shape),random.randint(5,image_shape)],[random.randint(5,image_shape),random.randint(5,image_shape)]], np.int32)
            pts = pts.reshape((-1,1,2))
            image = cv2.polylines(image,[pts],True,color_type,1)
            image=cv2.fillPoly(image, [pts], color_type);
        elif (shape=="rectange"):
            x1=random.randint(1,image_shape-10)
            y1=random.randint(1,image_shape-10)
            x2=x1+random.randint(5,image_shape-x1)
            y2=y1+random.randint(5,image_shape-y1)
            image=cv2.rectangle(image,(x1,y1),(x2,y2),color_type,-1)
        elif (shape=="circle"):
            center_x=random.randint(5,image_shape-5)
            center_y=random.randint(5,image_shape-5)
            radius=random.randint(5,min(min(center_x,center_y),min(image_shape-center_x,image_shape-center_y)))
            image=cv2.circle(image,(center_x,center_y), radius, color_type, -1)
        else:
            pass
        cv2.imwrite(dataset_folder+color_shape_name[cn]+"_"+shape+"_"+str(ic_num)+".jpg",image)

图片大小56*56,形状分为三角形,圆形,四边形,颜色分为红,绿,蓝。每一个颜色都包含这三种形状。也就是说颜色是唯一的分类特征。

训练和测试程序:

#dataset.py
import os
from PIL import Image
import cv2
import torch
from torch.utils import data
from torchvision import transforms
from torchvision.transforms import functional as F
import numbers
import numpy as np
import random

class ImageData(data.Dataset):
    def __init__(self,train_root):
        self.image_root = train_root
        self.image_list = os.listdir(self.image_root)
        self.image_num=len(self.image_list)
        self.label_dict={"red":0,"green":1,"blue":2}

    def __getitem__(self, item):
        im_name = self.image_root+self.image_list[item % self.image_num]
        image = load_image(im_name)
        image = cv_random_flip(image)
        label = self.label_dict[self.image_list[item % self.image_num].split("_")[0]]

        #彩图注释该行
        image= np.expand_dims(np.sum(image,axis=0)/3,axis=0)



        sample = {'image': image, 'label': label}
        return sample

    def __len__(self):
        return self.image_num




def get_loader(mode='train'):
    if mode == 'train':
        shuffle = True
        dataset = ImageData("./data/train/")
        data_loader = data.DataLoader(dataset=dataset, batch_size=100, shuffle=shuffle, num_workers=2)
    else:
        
        shuffle = False
        dataset = ImageData("./data/test/")
        data_loader = data.DataLoader(dataset=dataset, batch_size=100, shuffle=shuffle, num_workers=2)
    return data_loader

def load_image(path):
    if not os.path.exists(path):
        print('File {} not exists'.format(path))
    im = cv2.imread(path,1)
    in_ = np.array(im, dtype=np.float32)
    in_ -= np.array((104.00699, 116.66877, 122.67892))
    in_ = in_.transpose((2,0,1))
    return in_



def cv_random_flip(img):
    flip_flag = random.randint(0, 1)
    if flip_flag == 1:
        img = img[:,:,::-1].copy()
    return img
#train_test.py
import os
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from dataset import get_loader
print(torch.__version__)

os.environ["CUDA_VISIBLE_DEVICES"] = '0'

EPOCHS=50 # 总共训练批次
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 让torch判断是否使用GPU,建议使用GPU环境,因为会快很多




class ConvNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv0=nn.Conv2d(1,20,5) # 10, 24x24#彩图修改输入为3
        self.conv1=nn.Conv2d(20,20,5) 
        self.conv2=nn.Conv2d(20,40,3) 
        self.fc1 = nn.Linear(1960,100)
        self.fc2 = nn.Linear(100,3)
    def forward(self,x):
        in_size = x.size(0)
        out = self.conv0(x)
        out = F.max_pool2d(out, 2, 2) 


        out = self.conv1(out) 
        out = F.relu(out)
        out = self.conv1(out)
        out = F.relu(out)
        out = F.max_pool2d(out, 2, 2) 
        out = self.conv2(out)
        out = F.relu(out)
        out = out.view(in_size,-1)
        out = self.fc1(out)
        out = F.relu(out)
        out = self.fc2(out)
        
        out = F.log_softmax(out,dim=1)
        return out




model = ConvNet().to(DEVICE)
optimizer = optim.Adam(model.parameters(),lr = 0.0001)
criterion = nn.CrossEntropyLoss()

def train(model, device, train_loader, optimizer, epoch):
    model.train()
    for batch_idx, data_target in enumerate(train_loader):
        data, target = Variable(data_target['image']).to(device), Variable(data_target['label']).to(device)
        optimizer.zero_grad()
        output = model(data)
        loss = F.nll_loss(output, target)
        #loss = criterion(output, target)
        loss.backward()
        optimizer.step()
        if(batch_idx+1)%10 == 0: 
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.item()))






def test(model, device, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data_target in test_loader:
            data, target = data_target['image'].to(device), data_target['label'].to(device)
            output = model(data)
            test_loss += F.nll_loss(output, target, reduction='sum').item() # 将一批的损失相加
            pred = output.max(1, keepdim=True)[1] # 找到概率最大的下标
            correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader.dataset)
    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))






for epoch in range(1, EPOCHS + 1):
    train(model, DEVICE, get_loader(mode='train'), optimizer, epoch)
    test(model, DEVICE, get_loader(mode='test'))

灰度图训练结果:

彩图训练结果:

最终结论,

灰度图的准确性略高于平均准确性33%,彩图准确性基本100%。。可见颜色也是一种神经网络可以学习的特征。所以可以根据实际应用场景,增加或者去掉颜色特征。

 

 

高德

1面电话聊项目经验

2面现场面,项目经验为主,一些基本框架

3面现场面,主要编程,

编程1,IOU,需要定义结构体

编程2,二叉树翻转,求深度

int maxDepth(TreeNode *root) {
    if (root == nullptr) return 0;
        return max(maxDepth(root->left), maxDepth(root->right)) + 1;
}
void exchange(TreeNode *root) {
    if (root == nullptr) return;
    TreeNode *temp=root->right;
root->right=root->left;
root->left=temp;
exchange(root->left);
exchange(root->right);

}

编程3,2sum,o(n)的怎么处理,o(n*log(n))怎么处理?

Hashmap,二分查找,左右夹逼。

 

京东:

1面,2面,聊项目经验,以及一些遇到的问题怎么处理

3面,leader聊一些工作情况

4面,hr

 

作业帮:

1面,2面聊项目经验。3面,hr小姐姐面。

笔试题,

检测恶意访问的服务IP。假设一个服务访问,可以得到IP,访问时间,假设连续的10秒内,同一个IP的访问超过10次,就算该IP为恶意访问的IP。假设没有大量的并发情况。

思路,定义一个queue,每次来了访问服务,就加入该queue。定义一个hashmap,里面存储所有的IP。如果超过10秒,就将该hash对应的访问次数值清零。否则就加1。如果超过10次就证明是恶意访问。


#include <iostream>
#include <queue>
#include <utility>
#include <string>
#include <unordered_map>
using namespace std;


struct MALICE{
	float time;
	int count;
	MALICE(float t, int c) :time(t), count(c){};
};

int main()
{
	float time_gap = 10.0;
	int count_gap = 10;
	unordered_map<string, queue<MALICE>> umap;

	//初始化
	int a = 0, b = 0, c = 0, d = 0;
	int max_num = 4;
	while (true)
	{
		queue<MALICE> malice;
		malice.push(MALICE(0.0, 0));
		string temp = to_string(a) + "." + to_string(b) + "." + to_string(c) + "." + to_string(d);
		umap.insert(make_pair(temp, malice));
		d += 1;
		if (d > max_num)
		{
			d = 0;
			c += 1;
			if (c > max_num)
			{
				c = 0;
				b += 1;
				if (b > max_num)
				{
					b = 0;
					a += 1;
				}
				if (a > max_num)
					break;
			}
		}

	}

	//新来的访问
	umap["0.0.0.0"].back().count = 10;
	float time = 5;
	string ip = "0.0.0.0";
	while (time - umap[ip].front().time >= time_gap)
	{
		umap[ip].pop();
	}
	if (umap[ip].size() == 0)
	{
		umap[ip].push(MALICE(time, 0));
	}
	else
	{
		if (time - umap[ip].front().time < time_gap)
		{

			umap[ip].push(MALICE(time, umap[ip].back().count + 1));
			if (umap[ip].back().count > count_gap)
			{
				umap[ip].back().count = 0;
				cout << "malice ip:" << ip << endl;
			}
		}
		

	}
	
	return 1;
}

 

好未来:

1面,主要还是聊项目经验。实际遇到的问题。

笔试,快排的思想讲解,不需要写代码。

 

其他题型:

题目1:

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

 

示例 1:

输入: coins = [1, 2, 5], amount = 11

输出: 3

解释: 11 = 5 + 5 + 1

示例 2:

 

输入: coins = [2], amount = 3

输出: -1

说明:

你可以认为每种硬币的数量是无限的。

int coinMinWays(vector<int>& coins, int amount) {
	vector<int> dp(amount+1, amount+1);
	dp[0] = 0;

	for (int i = 1; i <= amount; ++i) {
		for (int j = 0; j < coins.size(); ++j) {
			if (coins[j] <= i) {
				dp[i] = min(dp[i], dp[i - coins[j]] + 1);
			}
		}
	}

	return (dp[amount] > amount) ? -1 : dp[amount];

题目2:

有1,2,5,10等不同零钱各若干,问如果要组合成N元,有多少种不同的组合方式?假设有m种零钱,具体面值存在arr中,要找的钱为n。

例如:arr=[1, 2, 5, 10], n=5, 则有4种组合方式,分别为:

1,1,1,1,1

1,1,1,2

1,2,2

5

提示:不需要给出具体的组合,只需要找出组合的数量

int countWays(vector<int>&coins, int amount) {
	vector<int> dp(amount+1 , 0);
	dp[0] = 1;
	for (int i = 0; i < coins.size(); ++i){
		for (int j = coins[i]; j <= amount; ++j){
			dp[j] = (dp[j] + dp[j - coins[i]]);
		}
	}
	return dp[amount];
}

int main() {
	vector<int> coins;
	coins.push_back(1);
	coins.push_back(2);
	coins.push_back(5);
	coins.push_back(10);

	int amount = 5;
	cout << coinMinWays(coins, amount) << endl;
	cout<<countWays(coins, amount) << endl;
}

题目3,

取1000w正整数的前100个输出。

思路,堆排序,

bool compare(int a, int b)
{
	return a > b;
}
int main()
{
	int MAX_NUM = 10;
	int pre_num = 5;
	int input;
	vector<int> small_top_heap;
	int index = 0;
	while (cin >> input)
	{
		small_top_heap.push_back(input);
		index += 1;
		if (index == pre_num)
		{
			make_heap(small_top_heap.begin(), small_top_heap.end(), compare);
		}

		if (index > pre_num)
		{
			push_heap(small_top_heap.begin(), small_top_heap.end(), compare);
			pop_heap(small_top_heap.begin(), small_top_heap.end(), compare);
			small_top_heap.pop_back();
		}
			
		if (index >= MAX_NUM)
			break;

	}
	sort_heap(small_top_heap.begin(), small_top_heap.end(), compare);
	for (int i = 0; i < small_top_heap.size(); i++)
		cout << small_top_heap[i] << " ";
	cout << endl;

	return 0;
}

 

Tensorflow学习笔记——Summary用法

tf.summary.scalar用来显示标量信息

tf.summary.histogram一般用来显示训练过程中变量的分布情况

tf.summary.distribution分布图,一般用于显示weights分布

tf.summary.text将文本类型的数据转换为tensor写入summary中

tf.summary.image输出图像

tf.summary.audio展示训练过程中记录的音频 

tf.summary.merge_all

tf.summary.FileWriter指定一个文件用来保存图

 

 

最后,分享一下本人的leetcode笔记。

想想来北京3年了,从最开始的不被认可,被钓鱼,到现在,感觉收货也蛮多的,至少到现在还是得到好多公司的认可。有时候收了别人的offer最后又拒绝了别人,心里也挺难过的。最后感谢一下,曾经认可自己的公司和人。

其他建议:

(1)明确目前阶段的自己最需要的是什么。是镀金,是money,是带团队经验,是提升自己能力,是安稳......,在没有一个offer满足所有优点的时候,选择自己最需要的那个。

(2)寒冬中的跳槽,无非是从一个坑到另一个坑。很多时候,从脉脉上得到的消息,你会感觉所有你面上的公司都有负面新闻。这时候就根据自己的面试感受做选择了。做到,既来之,则安之。

(3)还有一个感触就是,在AI算法这方面,每年都有好多新的东西更新,知识保值性太差了。新人永远比老人有优势。想想当年这个时候的自己,和现在的应届生比,差距确实很大。或许这就是知识进步太快了。就好比,从SVM提出,到第一个程序实现,中间经历了好长时间,那个年代就没有牛人吗?但是,现在面试应届生,随便都可以将SVM说个很不错。牛顿穷其一生发现了3个定律,现在的学生,也许不需要一学期就都学会了。爱迪生,特斯拉,瓦特......泡沫终将退去,也许在算法和工程的抉择中,工程才是最终的胜利者。

 

后记:

鲁迅说过,人只要又钱,烦恼就会减掉90%以上,情商和智商也会提高,更不会乱发火。钱从哪里来,鲁迅没说,但是,褚老说了,

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值