今日小结——20190409(LeetCode日常+knn)

前段时间太浪了,现在就用日志的方式约束自己每天的学习任务,希望有个好的结果~

一、cs231n课程作业部分

cs231n视觉与深度学习课程是很适合补基础的课程,当然也有一定的难度,因为双系统Linux坏了,就打算在windows下配置cs231n的作业环境。

1.使用Anaconda

 Anaconda本质上就是一个环境管理器,可以用这一个终端配置电脑的python各种环境,也可以下载各种包,使用了一段时间,我觉得必须要安装的几个包就是pip(下载工具)、jupyter notebook(代码编辑工具)、要使用的python版本以及自建的虚拟环境(包含要使用的所有头文件,例如numpy,script,etc.)。

安装可以在Anaconda Prompt中采用pip install xxx的形式,也可以采用conda安装方式,输入你安装的名称后缀--version可以查看版本和安装信息,总得来说,anaconda对于python开发是非常方便的,集成度高,包的下载也比较省时间(部分包下载巨慢QAQ)

对于新人有一点可能比较重要的就是jupyter的使用,首先我们要将她升级到最新版,然后!很关键的一点就是,不要直接输入jupyter notebook开打开网页,这样在你用notebook去upload其他.ipynb文件后,会出现MoudlenotFounderror,原因就是你的jupyter notebook打开路径不在你的.ipynb文件路径中,找不到所import的文件和函数,对于这个问题,我花了很久的时间在debug上,殊不知原来是路径问题(真蠢!),不过程序这种东西就是这样,bug千奇百怪,找的时候觉得很困难找不到,找到了又觉得也没啥很简单,这就需要大量的debug经验惹。。。打开对应路径的方法是在Anaconda Prompt终端输入:

jupyter notebook URL(e.g.:D:\study\cs231n\CS231n-2017-master\assignment1)

之后就会自动打开jupyter,点开.ipynb文件即可开始作业!

2.knn作业代码分享

根据课程内容,我开始了作业的编写……

首先是...\cs231n\classifiers\k_nearest_neighbor.py

作业中把要求写的地方都空出来了并做了要求,第一部分是要每个测试数据和每个训练数据分别计算(两层循环),并且不可以使用loop。

L2 distance:dists[i,j] = np.sqrt(np.sum((X[i,:]-self.X_train[j,:])**2))

第二部分是每个测试数据和训练数据分别整体进行计算(一层循环)

dists[i,:] = np.sqrt(np.sum((X[i,:] - self.X_train)**2, axis = 1)),注意axis一定要赋值为1,因为是在一维求距离,X[i,:]维度由于广播的原因会变为num_train*D,因此和X_train[i:]运算后dists[i,:]维度为1*num_train。

第三部分是计算所有的测试点和训练点,无循环

   X_squared = np.sum(X**2,axis=1)
   Y_squared = np.sum(self.X_train**2,axis=1)
   XY = np.dot(X, self.X_train.T)
   dists = np.sqrt(X_squared[:,np.newaxis] + Y_squared -2*XY)

第四部分是predict


      test_row = dists[i,:]
      sorted_row = np.argsort(test_row)
      closest_y = self.y_train[sorted_row[0:k]]

np.argsort() 可以对dists[] 进行排序选出test_row个最近的训练样本的下标

 closest_y即为找到的最近的k个样本

然后需要在这k个样本中找到最接近的一个,返回到y_pred[]数组

 y_pred[i] = np.argmax(np.bincount(closest_y))

 第五部分是对代码的测试,根据课程内容在jupyter上完成,报了一些错误,已解决。

 knn部分已完成,由于需要把测试集每一张图片和训练集进行L1 L2比对,时间上实属浪费,所以只需要了解原理,不需要深究,明天研究softmax!

 

 二、LeetCode刷题部分

 1.第九题:回文数

要求:输入数字,正序倒序一样即为true,否则false

此题较为简单,首先拿到题要分析输入源,输入数字可以是正数和负数还有0,众所周知,个位数正数一定是回文数,那么我们吧0-9这十个数归为一类,负数一定不是回文数,也为一类,那我们要考虑的就是11-无穷,当然不能越int的范围。

此题最简单的方法就是用基本的求余数整除法,但是需要把每一位放入数组,静态数组的方法效率较低,所以可以采用动态数组的方法,也就是我们常用的vector向量,自带push_back函数,方便放入数组(此处就不如python的列表舒服惹。。。),然后头尾进行比较即可判断,当然效率最高的方法还是用链表加指针变量哦。下面贴出代码:

class Solution {
public:
    bool isPalindrome(int x) {
        if(x<0)
        {
            return false;
        }
        if(x>-1&&x<10)
        {
            return true;
        }
        vector<int> v;
        while(x>0)
        {
            int num =x%10;
            x/=10;
            v.push_back(num);
        }
        int pre=0,last=v.size()-1;
        while(pre<=last)
        {
            if(v[pre]!=v[last])
                return false;
            pre++;
            last--;
        }
        return true;
    }
};

 2.第七题:整数反转

此题要求将32位有符号整数进行反转,因为有符号且要考虑到0反转在首位取消的问题,就采用逢十进位的方法,首先保证输入数字不能是越界数,卡一下范围,然后有一个小问题,可能被忽略的比较多,我们平时接触的都是正数整除,而负数整除会有怎样的结果呢?没chuo,都是向零取整,怎么理解呢,比如9/-4 = 1,9/(-4) = -1,5%-3 = 2  ,-5%-3 = -2 ;换句话缩,就是不用考虑那么多,直接当成正数去整除和取余就好啦,结果一样的,该带的负号一个不少,代码如下:

class Solution {
public:
    int reverse(int x) {
        if(x>2147483647||x<-2147483648)
        {
            return 0;
        }
        char num[15]={};
        int low_num;
        int temp=x;
        long result=0;
        int i=0;
        while(temp!=0)
        {
            low_num=temp%10;
            temp=temp/10;
            num[i]=low_num;
            result=result*10+num[i++];
            if(result>2147483647||result<-2147483648)
            {
                 return 0;
             }
        }
        return result;
    }
};

 3.第六题:Z字变换

此题要求是。。。懒得打字了,贴图吧

 相信这个题读完第一遍就会问,如果是四行五行是啥样呢?

那你就把这个题理解为N变换,一堆NNNNNN连在一起。。。。神奇哦

言归正传,这个题我看完他的怕排布规律之后发现是个周期性的排列,那么我们就可以利用他的周期性来解题,例如三阶的,第一行字母在原字符串排序分别是1 5 9 13,第二行排序是2 4 6 8 10 12……,所以规律很明显,再扩充到四阶,规律就更明显了,利用周期性解题是关键,这个题就变成了找规律问题!

int Time=(numRows-2)+numRows;这个Time即为周期,不同人对周期的算法不同,这里只是个人的计算方式。。。

class Solution {
public:
    string convert(string s, int numRows) {
        if(numRows==1)
        {
            return s;
        }
        int Time=(numRows-2)+numRows;
        string a="";
        for(int i=0;i<numRows;i++)
        {
            int count=0;
            while(1)
            {
                if(count*Time+i<s.length())
                {
                    a+=s[count*Time+i];
                }
                else
                {
                    break;
                }
                if(i==0||i==Time/2)
                {
                    count++;
                    continue;
                }
                if(count*Time+Time-i<s.length())
                {
                    a+=s[count*Time+Time-i];
                }
                else
                {
                    break;
                }
                count++;
            }
        }
       return a; 
    }
};

 因为涉及到字符串,第一个想法就是遍历,那么遍历就离不开while,所以后面的代码都是卸载whlie中~

上面的代码是定义了一个string类型空字符串,然后进行第一行字符的统计,根据string的用法,我们可以直接在空字符串中添加筛选出来的字符

我们可以看到,不管有多少行,每一行字符的下标规律只有两种,count*Time+i即为第一行字符和最后一行下标的通用公式,每找对一个,则会进入下面的if语句进行count++,这里我用到了continue,是为了不继续进行下面的中间行下标规律语句,而是直接再进行while循环继续找第一行的字符

如果找完了第一行所有元素,那么就会在最开始break,跳出while循环,i++,然后直接进行中间行的字符提取,中间行字符的下标规律为count*Time+Time-i,找完了这一行之后进行count++,进行下一行的筛选。

 

明天计划:刷2-3个LeetCode题目,cs231n学习softmax

希望能坚持,加油~

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值