机器学习基本流程
采集数据
数据处理【预处理】
选择 模型【线性、非线性】、算法【随机梯度下降法、smo...】、策略【极大似然估计法(交叉熵)、最小二乘法、svm...】
模型训练 <------I
模型评估 I
调参---------------I
预测
验证集与测试集
验证集的作用在于模拟测试集,而测试集的最大特点就是「未知」,即在训练过程中是见不到的。正因为验证集和测试集在训练过程中都是未知的,你才可以说,「如果你的超参数适用于验证集,那么它们也大概会适用于测试集」。如果你不分开验证集和测试集,那么你调出的超参数就是适用于训练集的,但因为训练集和测试集不具有「未知」这个共同点,所以训练集上的好性能不一定能泛化到测试集上去,这就叫「过拟合」。
激活函数的作用
多感知器分类器没有激活函数不管它怎么组合,最多就是线性方程的组合,最后得到的分类器本质还是一个线性方程,该处理不了的非线性问题,它还是处理不了。
通过这个激活函数映射之后,输出很明显就是一个非线性函数。能不能解决非线性分类问题不清楚,但是至少说明有可能啊,不加入激活函数神经网络压根就不可能解决这个问题。
给定一个链表的 头节点 head
,请判断其是否为回文链表。
如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。
===========================================================
- 先快慢指针找到中间节点;
- 原地反转后半部分链表;
- 依次比较前半部分链表与反转后的后半部分链表;
- ================================================================
bool isPalindrome(struct ListNode* head)
{
struct ListNode* phead = head;
struct ListNode* fast = head;
struct ListNode* slow = head;
while (fast != NULL && fast->next != NULL)//快慢指针找中点
{
fast = fast->next->next;
slow = slow->next;
}
struct ListNode* p1 = NULL;
struct ListNode* p2 = slow;
struct ListNode* p3 = slow->next;
while (p2 != NULL)
{
p2->next = p1;
p1 = p2;
p2 = p3;
if (p3 != NULL)
{
p3 = p3->next;
}
}
while (p1 != NULL)//比较
{
if (p1->val == phead->val)
{
p1 = p1->next;
phead = phead->next;
}
else
{
return false;
}
}
return true;
}
给定单链表的头节点 head
,请反转链表,并返回反转后的链表的头节点。
=================================================================
递进至最后一个结点,使最后一个结点为反转链表的头结点,然后在归出的过程中是后面的结点指向前面的结点,前面的结点指向空,最终实现链表反转。
=================================================================
struct ListNode* reverseList(struct ListNode* head){
if (head == NULL || head->next == NULL) {
return head;
}
struct ListNode *next = head->next;
struct ListNode *node = reverseList(next);
next->next = head;
head->next = NULL;
return node;
}