人工智能基礎(chǔ)-算法工程師為什么要懂線(xiàn)性代數(shù)?

2021-02-16    分類(lèi): 網(wǎng)站建設(shè)

線(xiàn)性代數(shù)是什么?

在大學(xué)數(shù)學(xué)學(xué)科中,線(xiàn)性代數(shù)是最為抽象的一門(mén)課,從初等數(shù)學(xué)到線(xiàn)性代數(shù)的思維跨度比微積分和概率統(tǒng)計(jì)要大得多。很多人學(xué)過(guò)以后一直停留在知其然不知其所以然的階段,若干年之后接觸圖形編程或機(jī)器學(xué)習(xí)等領(lǐng)域才發(fā)現(xiàn)線(xiàn)性代數(shù)的應(yīng)用無(wú)處不在,但又苦于不能很好地理解和掌握。的確,多數(shù)人很容易理解初等數(shù)學(xué)的各種概念,函數(shù)、方程、數(shù)列一切都那么的自然,但是一進(jìn)入線(xiàn)性代數(shù)的世界就好像來(lái)到了另一個(gè)陌生的世界,在各種奇怪的符號(hào)和運(yùn)算里迷失了。



我在初接觸線(xiàn)性代數(shù)的時(shí)候簡(jiǎn)直感覺(jué)這是一門(mén)天外飛仙的學(xué)科,一個(gè)疑問(wèn)在我腦子里浮現(xiàn)出來(lái):

線(xiàn)性代數(shù)到底是一種客觀(guān)的自然規(guī)律還是人為的設(shè)計(jì)?

如果看到這個(gè)問(wèn)題,你的反應(yīng)是“這還用問(wèn),數(shù)學(xué)當(dāng)然是客觀(guān)的自然規(guī)律了”,我一點(diǎn)兒都不覺(jué)得奇怪,我自己也曾這樣認(rèn)為。從中學(xué)的初等數(shù)學(xué)和初等物理一路走來(lái),很少人去懷疑一門(mén)數(shù)學(xué)學(xué)科是不是自然規(guī)律,當(dāng)我學(xué)習(xí)微積分、概率統(tǒng)計(jì)時(shí)也從來(lái)沒(méi)有懷疑過(guò),唯獨(dú)線(xiàn)性代數(shù)讓我產(chǎn)生了懷疑,因?yàn)樗母鞣N符號(hào)和運(yùn)算規(guī)則太抽象太奇怪,完全對(duì)應(yīng)不到生活經(jīng)驗(yàn)。所以,我還真要感謝線(xiàn)性代數(shù),它引發(fā)了我去思考一門(mén)數(shù)學(xué)學(xué)科的本質(zhì)。其實(shí),不止是學(xué)生,包括很多數(shù)學(xué)老師都不清楚線(xiàn)性代數(shù)到底是什么、有什么用,不僅國(guó)內(nèi)如此,在國(guó)外也是這樣,國(guó)內(nèi)的孟巖寫(xiě)過(guò)《理解矩陣》,國(guó)外的Sheldon Axler教授寫(xiě)過(guò)《線(xiàn)性代數(shù)應(yīng)該這樣學(xué)》,但都還沒(méi)有從根本上講清楚線(xiàn)性代數(shù)的來(lái)龍去脈。對(duì)于我自己來(lái)講,讀大學(xué)的時(shí)候沒(méi)有學(xué)懂線(xiàn)性代數(shù),反而是后來(lái)從編程的角度理解了它。很多人說(shuō)數(shù)學(xué)好可以幫助編程,我恰好反過(guò)來(lái)了,對(duì)程序的理解幫助了我理解數(shù)學(xué)。

本文的目標(biāo)讀者是程序員,下面我就帶各位做一次程序員在線(xiàn)性代數(shù)世界的深度歷險(xiǎn)!既然是程序員,在進(jìn)入線(xiàn)性代數(shù)的領(lǐng)域之前,我們不妨先從考察一番程序世界,請(qǐng)思考這樣一個(gè)問(wèn)題:

計(jì)算機(jī)里面有匯編、C/C++、Java、Python等通用語(yǔ)言,還有Makefile、CSS、SQL等DSL,這些語(yǔ)言是一種客觀(guān)的自然規(guī)律還是人為的設(shè)計(jì)呢?

為什么要問(wèn)這樣一個(gè)看起來(lái)很蠢的問(wèn)題呢?因?yàn)樗拇鸢革@而易見(jiàn),大家對(duì)天天使用的程序語(yǔ)言的認(rèn)識(shí)一定勝過(guò)抽象的線(xiàn)性代數(shù),很顯然程序語(yǔ)言雖然包含了內(nèi)在的邏輯,但它們本質(zhì)上都是人為的設(shè)計(jì)。所有程序語(yǔ)言的共同性在于:建立了一套模型,定義了一套語(yǔ)法,并將每種語(yǔ)法映射到特定的語(yǔ)義。程序員和語(yǔ)言實(shí)現(xiàn)者之間遵守語(yǔ)言契約:程序員保證代碼符合語(yǔ)言的語(yǔ)法,編譯器/解釋器保證代碼執(zhí)行的結(jié)果符合語(yǔ)法相應(yīng)的語(yǔ)義。比如,C++規(guī)定用new A()語(yǔ)法在堆上構(gòu)造對(duì)象A,你這樣寫(xiě)了C++就必須保證相應(yīng)的執(zhí)行效果,在堆上分配內(nèi)存并調(diào)用A的構(gòu)造函數(shù),否則就是編譯器違背語(yǔ)言契約。

從應(yīng)用的角度,我們能不能把線(xiàn)性代數(shù)視為一門(mén)程序語(yǔ)言呢?答案是肯定的,我們可以用語(yǔ)言契約作為標(biāo)準(zhǔn)來(lái)試試。假設(shè)你有一個(gè)圖像,你想把它旋轉(zhuǎn)60度,再沿x軸方向拉伸2倍;線(xiàn)性代數(shù)告訴你,“行!你按我的語(yǔ)法構(gòu)造一個(gè)矩陣,再按矩陣乘法規(guī)則去乘你的圖像,我保證結(jié)果就是你想要的”。實(shí)際上,線(xiàn)性代數(shù)和SQL這樣的DSL非常相似,下面來(lái)作一些類(lèi)比:

  • 模型和語(yǔ)義:SQL是在低級(jí)語(yǔ)言之上建立了關(guān)系模型,核心語(yǔ)義是關(guān)系和關(guān)系運(yùn)算;線(xiàn)性代數(shù)在初等數(shù)學(xué)之上建立了向量模型,核心語(yǔ)義是向量和線(xiàn)性變換
  • 語(yǔ)法:SQL為每種語(yǔ)義定義了相應(yīng)的語(yǔ)法,如select, where, join等;線(xiàn)性代數(shù)也定義了向量、矩陣、矩陣乘法等語(yǔ)義概念相應(yīng)的語(yǔ)法
  • 編譯/解釋?zhuān)篠QL可以被編譯/解釋為C語(yǔ)言;線(xiàn)性代數(shù)相關(guān)概念和運(yùn)算規(guī)則可以由初等數(shù)學(xué)知識(shí)來(lái)解釋
  • 實(shí)現(xiàn):我們可以在MySQL、Oracle等關(guān)系數(shù)據(jù)庫(kù)上進(jìn)行SQL編程;我們也可以在MATLAB、Mathematica等數(shù)學(xué)軟件上進(jìn)行線(xiàn)性代數(shù)編程

所以,從應(yīng)用的角度看,線(xiàn)性代數(shù)是一種人為設(shè)計(jì)的領(lǐng)域特定語(yǔ)言(DSL),它建立了一套模型并通過(guò)符號(hào)系統(tǒng)完成語(yǔ)法和語(yǔ)義的映射。實(shí)際上,向量、矩陣、運(yùn)算規(guī)則的語(yǔ)法和語(yǔ)義都是人為的設(shè)計(jì),這和一門(mén)語(yǔ)言中的各種概念性質(zhì)相同,它是一種創(chuàng)造,但是前提是必須滿(mǎn)足語(yǔ)言契約。

為什么要有線(xiàn)性代數(shù)?

可能有人對(duì)把線(xiàn)性代數(shù)當(dāng)成一門(mén)DSL不放心,我給你一個(gè)矩陣,你就把我的圖形旋轉(zhuǎn)了60度沿x軸拉伸了2倍,我總感覺(jué)不踏實(shí)啊,我都不知道你“底層”是怎么做!其實(shí),這就像有的程序員用高級(jí)語(yǔ)言不踏實(shí),覺(jué)得底層才是程序的本質(zhì),老是想知道這句話(huà)編譯成匯編是什么樣?那個(gè)操作又分配了多少內(nèi)存?別人在Shell里直接敲一個(gè)wget命令就能取下一個(gè)網(wǎng)頁(yè),他非要用C語(yǔ)言花幾十分鐘來(lái)寫(xiě)一堆代碼才踏實(shí)。其實(shí),所謂底層和上層只是一種習(xí)慣性的說(shuō)法,并不是誰(shuí)比誰(shuí)更本質(zhì)。程序的編譯和解釋本質(zhì)上是不同模型間的語(yǔ)義映射,通常情況下是高級(jí)語(yǔ)言映射為低級(jí)語(yǔ)言,但是完全也可以把方向反過(guò)來(lái)。Fabrice Bellard用JavaScript寫(xiě)了一個(gè)虛擬機(jī),把Linux跑在JavaScript虛擬機(jī)上,這就是把機(jī)器模型往JavaScript模型上映射。

建立新模型肯定依賴(lài)于現(xiàn)有的模型,但這是建模的手段而不是目的,任何一種新模型的目的都為了更簡(jiǎn)單地分析和解決某一類(lèi)問(wèn)題。線(xiàn)性代數(shù)在建立的時(shí)候,它的各種概念和運(yùn)算規(guī)則依賴(lài)于初等數(shù)學(xué)的知識(shí),但是一旦建立起來(lái)這層抽象模型之后,我們就應(yīng)該習(xí)慣于直接利用高層次的抽象模型去分析和解決問(wèn)題。說(shuō)到線(xiàn)性代數(shù)是為了比初等數(shù)學(xué)更容易地分析和解決問(wèn)題,下面我們通過(guò)一個(gè)例子來(lái)實(shí)際感受一下它的好處:

給定三角形的頂點(diǎn)(x1, y1), (x2, y2), (x3, y3),求三角形的面積。

初等數(shù)學(xué)中三角形面積最著名的計(jì)算公式是area = 1/2 * base * height ,當(dāng)三角形有一條邊恰好在坐標(biāo)軸上時(shí)我們就很容易算出它的面積。但是,假如同樣一個(gè)三角形我們把坐標(biāo)軸旋轉(zhuǎn)一下,讓它的邊不在坐標(biāo)軸上,怎么辦?我們還能得到它的底和高嗎?答案肯定是可以的,但是就明顯復(fù)雜了,而且還要分很多種情況去分別討論。

相反,如果我們用線(xiàn)性代數(shù)知識(shí)來(lái)解決這個(gè)問(wèn)題就非常輕松。在線(xiàn)性代數(shù)中兩個(gè)向量a,b的叉積(Cross Product)是一個(gè)向量,其方向與a,b垂直,其大小等于a,b構(gòu)成的平行四邊形的面積:



我們可以把三角形的邊視為向量,所以三角形的面積等于兩個(gè)邊向量的叉積向量的長(zhǎng)度除以二:

area = 1/2 * length(cross_product((x2 - x1, y2 - y1), (x3 - x1, y3 - y1)))

注:length表示取向量長(zhǎng)度,cross_product表示兩個(gè)向量的叉積。

這樣一個(gè)在初等數(shù)學(xué)里面有點(diǎn)兒小難的問(wèn)題在線(xiàn)性代數(shù)中瞬間搞定!可能有人會(huì)說(shuō),你直接基于叉積來(lái)做,當(dāng)然簡(jiǎn)單了,但是叉積本身不是也挺復(fù)雜的嗎?你把它展開(kāi)試試看呢?是的,模型的作用就是把一部分復(fù)雜性隱藏到模型中,使得模型的使用者可以更加簡(jiǎn)單地解決問(wèn)題。曾經(jīng)有人質(zhì)疑C++太復(fù)雜,C++之父Bjarne Stroustrup這樣回答:

Complexity will go somewhere: if not the language then the application code.

在特定環(huán)境下,問(wèn)題的復(fù)雜性是由其本質(zhì)決定的,C++把一部分的復(fù)雜性納入了語(yǔ)言和標(biāo)準(zhǔn)庫(kù),目的是使得應(yīng)用程序更為簡(jiǎn)單。當(dāng)然,并非所有場(chǎng)合C++都使得問(wèn)題更加簡(jiǎn)單,但是從原理上講,C++的復(fù)雜性是有道理的。除了C++,Java、SQL、CSS等各種語(yǔ)言和框架莫不如是,想象一下,如果不使用數(shù)據(jù)庫(kù),動(dòng)不動(dòng)就自己去做數(shù)據(jù)存儲(chǔ)和管理是多么復(fù)雜啊!這樣我們就不難理解為什么線(xiàn)性代數(shù)要定義叉積這樣奇怪的運(yùn)算了,它和C++把很多常用的算法和容器納入STL是同一道理。同樣的,甚至你還可以在線(xiàn)性代數(shù)中定義自己想要的運(yùn)算拿來(lái)復(fù)用。所以,數(shù)學(xué)一點(diǎn)兒不死板,它和程序一樣是活活潑潑的,你理解了它的來(lái)龍去脈就能駕馭自如。說(shuō)到這里,我們就順便回答一個(gè)很常見(jiàn)的疑惑:

線(xiàn)性代數(shù)的點(diǎn)積、叉積還有矩陣運(yùn)算都很奇怪,為什么要定義這些運(yùn)算呢?它們的定義又為什么是這個(gè)樣子呢?

其實(shí),和程序復(fù)用一樣,線(xiàn)性代數(shù)定義點(diǎn)積、叉積和矩陣運(yùn)算是因?yàn)樗鼈兊膽?yīng)用非常廣,有很大的復(fù)用價(jià)值,可以作為我們分析和解決問(wèn)題的基礎(chǔ)。比如,很多問(wèn)題都涉及到一個(gè)向量到另一個(gè)向量的投影或是求兩個(gè)向量的夾角,那么就會(huì)考慮專(zhuān)門(mén)定義點(diǎn)積(Dot Product)這個(gè)運(yùn)算:



點(diǎn)積概念的提出屬于設(shè)計(jì),有發(fā)揮創(chuàng)造的余地;一旦設(shè)計(jì)定了,具體公式就不能隨意發(fā)揮了,必須符合邏輯,保證它映射到初等數(shù)學(xué)模型的正確性。這就像一門(mén)高級(jí)語(yǔ)言可以定義很多概念,什么高階函數(shù)、閉包等等,但是它必須保證映射到底層實(shí)現(xiàn)時(shí)在執(zhí)行產(chǎn)生的效果符合其定義的規(guī)范。

線(xiàn)性代數(shù)好在哪里?

上面說(shuō)了,線(xiàn)性代數(shù)是一種高層次抽象模型,我們可以采用學(xué)習(xí)一門(mén)程序語(yǔ)言的方法去學(xué)習(xí)它的語(yǔ)法和語(yǔ)義,但是這一認(rèn)識(shí)不只針對(duì)線(xiàn)性代數(shù),它是對(duì)每一門(mén)數(shù)學(xué)學(xué)科通用的,可能有人會(huì)有疑問(wèn)

微積分、概率論也是高層次抽象,那么線(xiàn)性代數(shù)這種高層次抽象的特點(diǎn)在哪里呢?

這就問(wèn)到了根本上,線(xiàn)性代數(shù)的核心:向量模型。我們?cè)诔醯葦?shù)學(xué)中學(xué)習(xí)的坐標(biāo)系屬于笛卡爾所提出的解析模型,這個(gè)模型很有用,但同時(shí)也有很大的缺點(diǎn)。坐標(biāo)系是人為加上的虛擬參考系,但是我們要解決的問(wèn)題,比如求面積,圖形旋轉(zhuǎn)、拉伸等應(yīng)用都是和坐標(biāo)系無(wú)關(guān)的,建立一個(gè)虛擬的坐標(biāo)系往往無(wú)助于解決問(wèn)題,剛才三角形面積的例子就是這樣。

向量模型很好地克服了解析模型的缺點(diǎn),如果說(shuō)解析模型代表了某種“絕對(duì)性”的世界觀(guān),那么向量模型就代表了某種“相對(duì)性”的世界觀(guān),我推薦把向量模型和解析模型看作對(duì)立的兩種模型。

向量模型中定義了向量和標(biāo)量的概念。向量具有大小和方向,滿(mǎn)足線(xiàn)性組合法則;標(biāo)量是只有大小沒(méi)有方向的量(注:標(biāo)量的另一種更深刻的定義是在旋轉(zhuǎn)變換下保持不變的量)。向量模型的優(yōu)點(diǎn)之一是其坐標(biāo)系無(wú)關(guān)性,也就是相對(duì)性,它在定義向量和運(yùn)算規(guī)則的時(shí)候從一開(kāi)始就拋開(kāi)了坐標(biāo)系的束縛,不管你坐標(biāo)軸怎么旋轉(zhuǎn),我都能適應(yīng),向量的線(xiàn)性組合、內(nèi)積、叉積、線(xiàn)性變換等等運(yùn)算全部都是坐標(biāo)系無(wú)關(guān)的。注意,所謂坐標(biāo)系無(wú)關(guān)性不是說(shuō)就沒(méi)有坐標(biāo)系了,還是有的,剛才三角形例子的頂點(diǎn)就是用坐標(biāo)表示的,只是在解決問(wèn)題的時(shí)候不同的坐標(biāo)系不會(huì)構(gòu)成影響。用一個(gè)比喻,Java號(hào)稱(chēng)平臺(tái)無(wú)關(guān),不是說(shuō)Java就是空中樓閣,而是說(shuō)你用Java編程時(shí)底層是Linux還是Windows往往對(duì)你沒(méi)有影響。

向量模型有什么好處呢?除了剛才三角形面積問(wèn)題是一個(gè)例子,下面我再舉一個(gè)幾何的例子:

給定三維坐標(biāo)系中的一點(diǎn)(x0, y0, z0)和一個(gè)平面a*x + b*y + c*z + d = 0,求點(diǎn)到平面的垂直距離?



這個(gè)問(wèn)題如果是要從解析幾何的角度去解決幾乎復(fù)雜到?jīng)]法下手,除非是平面恰好是過(guò)坐標(biāo)軸的特殊情況,但是如果從向量模型考慮就很簡(jiǎn)單:根據(jù)平面方程,平面的法向量(Normal Vector)是v=(a, b, c),設(shè)從平面上任意一點(diǎn)(x, y, z)到(x0, y0, z0)的向量為w,那么通過(guò)點(diǎn)積dot_product(w, v)算出w到v的投影向量p,其大小就是(x0, y0, z0)到平面a*x + b*y + c*z + d = 0的垂直距離。這里用到了向量模型的基本概念:法向量,投影向量,點(diǎn)積,整個(gè)問(wèn)題解決過(guò)程簡(jiǎn)潔明快。

下面再給大家留一道相似的練習(xí)題(熟悉機(jī)器學(xué)習(xí)的朋友可能會(huì)發(fā)現(xiàn)這是線(xiàn)性代數(shù)在線(xiàn)性分類(lèi)中的應(yīng)用):

給定n維空間中的兩點(diǎn)(a1, a2, ... an),(b1, b2, ... bn)和一個(gè)超平面c1*x1 + c2*x2 ... + cn*xn + d = 0,請(qǐng)判斷兩點(diǎn)在超平面的同側(cè)或異側(cè)?

離開(kāi)向量,下面我們要請(qǐng)出線(xiàn)性代數(shù)的另一個(gè)主角:矩陣(Matrix)。

線(xiàn)性代數(shù)定義了矩陣和向量、矩陣和矩陣的乘法,運(yùn)算規(guī)則很復(fù)雜,用來(lái)做什么也不清楚,很多初學(xué)者都不能很好地理解,可以說(shuō)矩陣是學(xué)好線(xiàn)性代數(shù)的攔路虎。遇到復(fù)雜的東西,往往需要先避免一頭陷入細(xì)節(jié),先從整體上把握它。其實(shí),從程序的角度看,無(wú)論形式多么奇怪,它無(wú)非是一種語(yǔ)法,語(yǔ)法必然對(duì)應(yīng)了語(yǔ)義,所以理解矩陣的重點(diǎn)在于理解其語(yǔ)義。矩陣的語(yǔ)義不止一種,在不同的環(huán)境中有不同的語(yǔ)義,在同一環(huán)境中也可以有不同的解讀,最常見(jiàn)的包括:1)表示一個(gè)線(xiàn)性變換;2)表示列向量或行向量的集合;3)表示子矩陣的集合。

矩陣作為一個(gè)整體對(duì)應(yīng)的是線(xiàn)性變換語(yǔ)義:用矩陣A乘以一個(gè)向量v得到w,矩陣A就代表了v到w的線(xiàn)性變換。比如,如果想要把向量v0按逆時(shí)針?lè)较蛐D(zhuǎn)60度得到v',只需要用旋轉(zhuǎn)變換矩陣(Rotation Matrix)去乘v0就可以了。




除了旋轉(zhuǎn)變換,拉伸變換也是一種常見(jiàn)的變換,比如,我們可以通過(guò)一個(gè)拉伸矩陣把向量沿x軸拉伸2倍(請(qǐng)?jiān)囍约航o出拉伸矩陣的形式)。更重要的是,矩陣乘法有一個(gè)很好的性質(zhì):滿(mǎn)足結(jié)合率,這就意味著可以對(duì)線(xiàn)性變換進(jìn)行疊加。舉個(gè)例子,我們可以把“沿逆時(shí)針旋轉(zhuǎn)60度”的矩陣M和“沿x軸拉伸2倍”的矩陣N相乘,得到一個(gè)新矩陣T來(lái)代表“沿逆時(shí)針旋轉(zhuǎn)60度并沿x軸拉伸2倍”。這是不是很像我們Shell中把多個(gè)命令通過(guò)管道進(jìn)行疊加呢?

上面重點(diǎn)介紹了向量模型的坐標(biāo)系無(wú)關(guān)性,除此之外,向量模型的另一優(yōu)點(diǎn)是它能描述線(xiàn)性關(guān)系,下面我們來(lái)看一個(gè)熟悉的Fibonacci數(shù)列的例子:

Fibonacci數(shù)列定義為:f(n) = f(n-1) + f(n-2), f(0) = 0, f(1) = 1;問(wèn)題:輸入n,請(qǐng)給出求f(n)的時(shí)間復(fù)雜度不超過(guò)O(logn)的算法。

首先,我們構(gòu)造兩個(gè)向量v1=(f(n+1), f(n))和v2=(f(n+2), f(n+1)),根據(jù)Fibonacci數(shù)列性質(zhì),我們可以得到從v1到v2的遞推變換矩陣:



并進(jìn)一步得到:



這樣就把線(xiàn)性遞推問(wèn)題轉(zhuǎn)化為了矩陣的n次冪經(jīng)典問(wèn)題,在O(log n)時(shí)間復(fù)雜度內(nèi)解決。除了線(xiàn)性遞推數(shù)列,初等數(shù)學(xué)中著名的n元一次方程組問(wèn)題也可以轉(zhuǎn)化為矩陣和向量乘法形式更容易地解決。這個(gè)例子是想說(shuō)明,凡是滿(mǎn)足線(xiàn)性關(guān)系的系統(tǒng)都是向量模型的用武之地,我們往往可以把它轉(zhuǎn)化為線(xiàn)性代數(shù)得到簡(jiǎn)潔高效的解決方案。

總結(jié)

本文提出了一種觀(guān)點(diǎn):從應(yīng)用的角度,我們可以把線(xiàn)性代數(shù)視為一門(mén)特定領(lǐng)域的程序語(yǔ)言。線(xiàn)性代數(shù)在初等數(shù)學(xué)基礎(chǔ)上建立了向量模型,定義了一套語(yǔ)法和語(yǔ)義,符合程序語(yǔ)言的語(yǔ)言契約。向量模型具有坐標(biāo)系無(wú)關(guān)性和線(xiàn)性性,它是整個(gè)線(xiàn)性代數(shù)的核心,是解決線(xiàn)性空間問(wèn)題的好模型。向量的概念、性質(zhì)、關(guān)系、變換是掌握和運(yùn)用線(xiàn)性代數(shù)的重點(diǎn)。

網(wǎng)頁(yè)題目:人工智能基礎(chǔ)-算法工程師為什么要懂線(xiàn)性代數(shù)?
網(wǎng)站URL:http://www.muchs.cn/news/101232.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)手機(jī)網(wǎng)站建設(shè)、網(wǎng)站導(dǎo)航網(wǎng)站策劃、靜態(tài)網(wǎng)站、標(biāo)簽優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)